[ Страница назад | Страница вперед | Содержание | Индекс | Библиотека | Юридическая информация | Поиск ]

Программирование: Разработка и отладка программ


Глава 14. Команда make

В данной главе рассказано, как можно упростить процедуру повторной компиляции и компоновки с помощью команды make. Эта команда поможет вам сэкономить время при работе со своими проектами.

Программа make особенно полезна при создании программ среднего размера. Данная программа не предназначена для решения задач, связанных с поддержкой нескольких версий исходного кода и с описанием больших программ (см. описание команды sccs).

Команда make применяется для обслуживания набора программ, которые обычно относятся к одному проекту. Она предназначена для создания обновленных версий программ.

В любом проекте программы обычно компонуются из объектных файлов и библиотек. Следовательно, после изменения исходного файла вам необходимо заново перекомпилировать часть исходных модулей и заново перекомпоновать программу.

Команда make позволяет упростить процедуру повторной компиляции и компоновки программ. Связи между файлами достаточно определить только один раз. После этого команда make будет автоматически выполнять обновление.

С помощью команды make можно выполнить следующие задачи:

Для работы команде make необходимы файл описания, список имен файлов, а также правила, по которым программа make должна создавать стандартные типы файлов, и временные метки всех системных файлов.


Создание файла описания

Для создания целевого файла, содержащего весь исполняемый код, программа make использует информацию из пользовательского файла описания (целевого файла). На основе этой информации программа make определяет способ компоновки целевого файла, список файлов для компоновки и их связь с другими файлами. Файл описания содержит следующую информацию:

Программа make проверяет временные метки родительских файлов и на основе этой информации составляет список файлов, которые необходимо заново создать для получения обновленной копии целевого файла. Если какой-либо родительский файл был изменен уже после создания целевого файла, то команда make заново создаст все файлы, связанные с родительским, в том числе целевой файл.

Если файлу описания присвоено имя makefile или Makefile, и этот файл расположен в целевом каталоге, то для обновления целевого файла и его родительских файлов введите следующую команду:

make

Файлы будут обновлены независимо от того, сколько из них было изменено с момента последнего создания целевого файла программой make. В большинстве случаев файл описания имеет простую структуру, и его не требуется часто обновлять.

Если вы собираетесь хранить в одном каталоге несколько файлов описаний, присвойте им разные имена. Команда

make -f файл-описания

присваивает файлу описания имя, указанное в параметре файл-описания.

Формат записи файла описания

Ниже приведен общий формат записи:

целевой-файл-1 [целевой-файл-2..]:[:] [родительский-файл-1..][; команда]...
[(символ-табуляции) команды]

Элементы в квадратных скобках - необязательные. Имена целевых и родительских файлов - это символьные строки, которые могут содержать буквы, цифры, точки и символы косой черты. Команда make позволяет указывать символы подстановки, такие как * (звездочка) и ? (знак вопроса). Строка файла описания, содержащая имя целевого файла, называется строкой взаимосвязей. Строки, содержащие команды, должны начинаться с символа табуляции.

Примечание: в команде make символ $ (знак доллара) применяется для обозначения макроопределения. Не используйте этот символ в именах целевых или родительских файлов и в командах файла описания, если вы не применяете макроопределение make.

Комментарии в файле описания должны начинаться со знака фунта (#). Программа make игнорирует символ # и все следующие за ним символы. Кроме того, программа make игнорирует пустые строки.

Длина всех строк в файле описания, за исключением строк комментариев, может превышать ширину строки устройства ввода. Для переноса строки укажите в позиции переноса символ \ (обратная косая черта).

Применение команд в файле описания make

Команда - это любая строка символов, кроме строк, начинающихся с символа # (знака фунта) или с символа новой строки. Символ # можно использовать в команде только в кавычках. Команды могут задаваться либо в строке взаимосвязей после двоеточия, либо в строках, начинающихся с символа табуляции, которые следуют непосредственно за строкой взаимосвязей.

В файле описания для целевого файла может быть задана одна последовательность команд, либо несколько последовательностей для различных наборов зависимостей. Оба способа задания команд одновременно использовать нельзя.

Если для создания целевого файла будет применяться одна последовательность команд, укажите одно двоеточие после имени целевого файла в строке взаимосвязей. Например:

test:        список-взаимосвязей-1...
         список-команд...
            .
            .
            .
test:        список-взаимосвязей-2...

задается имя целевого файла (test), набор родительских файлов и набор команд для создания файла. Для целевого файла test может быть задан и другой список взаимосвязей.

Однако для этого имени нельзя будет указать другой список команд. Если будет изменен один из файлов, от которых зависит файл test, команда make создаст целевой файл test, выполнив команды из заданного списка.

Для задания нескольких последовательностей команд для создания одного и того же файла определите несколько списков взаимосвязей. В каждой строке взаимосвязей должно быть задано имя целевого файла, после которого должны быть указаны два двоеточия (::), список взаимосвязей и список команд, которые нужно выполнить команде make при изменении каких-либо файлов в списке взаимосвязей. Например:

test::      список-взаимосвязей-1...
         список-команд-1...
test::      список-взаимосвязей-2...
         список-команд-2...

Этот файл определяет два способа создания целевого файла с именем test. При изменении файлов из списка-взаимосвязей-1 команда make выполняет команды из списка-команд-1. При изменении файлов из списка-взаимосвязей-2 команда make выполняет команды из списка-команд-2. Во избежание конфликтов родительский файл не должен присутствовать ни в одном из списков взаимосвязей.

Примечание: команда make передает команды из каждой командной строки в новую оболочку. Будьте внимательны при использовании команд, которые зависят от процесса оболочки, например, команды cd и команд оболочки. Программа make не сохранит результат выполнения этих команд до выполнения команды, указанной в следующей строке файла описания.

Для объединения двух строк файла в одну командную строку, укажите в конце первой строки файла символ \ (обратную косую черту). Команда make объединит две строки в одну и передаст их в одну и ту же оболочку.

Вызов программы make из файла описания

Для создания вложенного вызова команды make в файле описания, укажите в командной строке этого файла макроопределение $(MAKE).

Если указан флаг -n и было найдено макроопределение $(MAKE), то новая копия команды make не будет выполнять никаких команд, за исключением другой команды макроопределения $(MAKE). Эту возможность можно использовать для тестирования набора файлов описания программы. Введите команду:

make -n

Эта команда make не выполняет никаких операций с программой. Однако она должна записать в стандартный вывод сведения обо всех этапах компиляции программы, в том числе вывод низкоуровневых вызовов команды make.

Подавление вывода команды make

Существует несколько способов подавления вывода команды make:

Предотвращение остановки программы make из-за ошибки

Если какая-либо программа передаст ненулевой код возврата, то программа make обычно завершает работу. Некоторые программы возвращают код возврата, который не сигнализирует об ошибке.

Для того чтобы предотвратить завершение программы make при возникновении ошибки, выполните одно из следующих действий:

Пример файла описания

Допустим, после компиляции и компоновки трех файлов на языке C (x.c, y.c и z.c) создается программа с именем prog. Общие объявления для файлов x.c и y.c заданы в файле с именем defs. В файле z.c эти объявления не используются. Ниже приведен пример файла описания, который создает программу prog:

# Создание программы prog из трех объектных файлов
prog: x.o y.o z.o
# Создание prog с помощью cc
    cc  x.o y.o z.o -o prog
# Создать x.o из двух других файлов
x.o:   x.c defs
# Создание x.o с помощью cc
    cc -c x.c
# Создание y.o из двух других файлов
y.o: y.c defs
# Создание y.o с помощью cc
    cc  -c y.c
# Создание z.o из z.c
z.o:   z.c
# Создание z.o с помощью cc
    cc  -c z.c

Если присвоить этому файлу имя makefile, то достаточно будет ввести следующую команду:

make

При этом в случае изменения одного из исходных файлов (x.c, y.c, z.c и defs) программа prog будет обновлена.

Упрощение файла описания

Для упрощения файла описания можно воспользоваться внутренними правилами программы make. В соответствии с соглашениями о присвоении имен в файловой системе, команда make распознает три файла .c, соответствующие нужным файлам .o. С помощью команды cc -c эта программа может создать объектный файл из исходного.

С учетом этих правил файл описания примет следующий вид:

# Создание программы prog из трех объектных файлов
prog:  x.o y.o z.o
# Создание prog с помощью cc
    cc  x.o y.o z.o -o prog
# Использование файлов defs и .c
# для создании x.o и y.o
x.o y.o:   defs

Внутренние правила программы make

Внутренние правила программы make хранятся в файле, аналогичном файлам описания. Если указать флаг -r, программа make не будет использовать файл внутренних правил. В этом случае необходимо определить правила создания файлов в файле описания. Файл внутренних правил содержит список расширений имен файлов (таких как .o или .a), которые распознаются командой make, и правила, указывающие команде make способ создания файла с одним расширением из файла с другим расширением. По умолчанию команда make распознает следующие расширения имен:

.a Архивная библиотека.
.C Исходный файл на языке C++.
.C\~ Файл SCCS, содержащий исходный файл на языке C++.
.c Исходный файл на языке C.
.c~ Файл системы управления исходным кодом (SCCS), содержащий исходный файл на языке C.
.f Исходный файл на языке FORTRAN.
.f~ Файл SCCS, содержащий исходный файл на языке FORTRAN.
.h Заголовочный файл на языке C.
.h~ Файл SCCS, содержащий заголовочный файл на языке C.
.l Исходная грамматика lex.
.l~ Файл SCCS, содержащий исходную грамматику lex.
.o Объектный файл.
.s Исходный файл на ассемблере.
.s~ Файл SCCS, содержащий исходный файл на ассемблере.
.sh Исходный файл команд оболочки.
.sh~ Файл SCCS, содержащий исходный файл команд оболочки.
.y Исходная грамматика yacc-c.
.y~ Файл SCCS, содержащий исходную грамматику yacc-c.

Список расширений имен файлов аналогичен списку взаимосвязей в файле описания и следует за фиктивным именем целевого файла .SUFFIXES. Команда make просматривает список расширений имен файлов слева направо, поэтому последовательность записей существенна.

Программа make будет использовать первую же запись из списка, которая удовлетворяет следующим двум требованиям:

Из двух расширений имен файлов, определяемых правилом, программа make создает имя правила. Например, имя правила для преобразования файла .c в файл .o - .c.o.

Для того чтобы добавить в список другие расширения имен файлов, добавьте в файл описания запись для фиктивного целевого имени .SUFFIXES. Если задать в файле описания строку .SUFFIXES без расширений имен файлов, команда make сотрет текущий список. Для изменения порядка имен в списке, сотрите текущий список, а затем укажите в строке .SUFFIXES новый набор значений.

Пример файла правил по умолчанию

Ниже приведен фрагмент файла правил, используемых по умолчанию:

# Определение расширений имен файлов, известных команде make.
.SUFFIXES:  .o .C .C\~ .c .c~ .f .f~ .y .y~ .l .l~ .s .s~ .sh .sh~ .h .h~ .a
 # Начало списка внутренних
# макроопределений
YACC=yacc
YFLAGS=
ASFLAGS=
LEX=lex
LFLAGS=
CC=cc
CCC=xlC
AS=as
CFLAGS=
CCFLAGS=
# Конец списка внутренних
# макроопределений
# Создание файла .o из файла .c
# с помощью программы cc.
c.o:
         $(CC) $(CFLAGS) -c $<

# Создание файла .o
# из файла .s с помощью ассемблера.
s.o:
         $(AS)$(ASFLAGS) -o $@ $<

.y.o:
# Создание промежуточного файла с помощью yacc
         $(YACC) $(YFLAGS) $<
# Вызов компилятора cc
         $(CC) $(CFLAGS) -c y.tab.c
# Удаление промежуточного файла
         rm y.tab.c
# Копирование в целевой файл
         mv y.tab.o $@.
.y.c:
# Создание промежуточного файла с помощью yacc
         $(YACC) $(YFLAGS) $<
# Копирование в целевой файл
         mv y.tab.c $@

Правило с одним расширением

В программе make существует набор правил с одним расширением, позволяющий создавать из исходного файла целевой файл без расширения (например, командный файл). Существуют также правила, в соответствии с которыми программа make создает объектные файлы с именами без расширений из следующих исходных файлов:

.C: Из исходного файла на языке C++.
.C\~: Из исходного файла SCCS на языке C++.
.c: Из исходного файла на языке C.
.c~: Из исходного файла SCCS на языке C.
.sh: Из файла команд оболочки.
.sh~: Из файла SCCS, содержащего команды оболочки.

Например, если все исходные файлы программы cat находятся в текущем каталоге, то команда

make cat

создаст исполняемый файл.

Создание библиотек с помощью команды make

С помощью команды make можно создавать библиотеки и библиотечные файлы. Файлы с расширением .a рассматриваются программой make как библиотечные файлы. Существуют следующие внутренние правила преобразования исходных файлов в библиотечные файлы:

.C.a Исходный файл C++ в архивный.
.C\~.a Исходный файл C++ SCCS в архивный.
.c.a Исходный файл C в архивный.
.c~.a Исходный файл C SCCS в архивный.
.s~.a Исходный ассемблерный файл SCCS в архивный.
.f.a Исходный файл на Фортране в архивный.
.f~.a Исходный файл SCCS на Фортране в архивный.

Изменение макроопределений в файле правил

Программа make использует макроопределения из файла правил. Для изменения этих макроопределений укажите новые определения в командной строке или в файле. Программа make применяет следующие имена макроопределений для компиляторов, которые она поддерживает:

AS Для Ассемблера.
CC Для компилятора C.
CCC Для компилятора C++.
YACC Для команды yacc.
LEX Для команды lex.

Программа make применяет для поддерживаемых компиляторов следующие макроопределения:

CFLAGS Для флагов компилятора C.
CCFLAGS Для флагов компилятора C++.
YFLAGS Для флагов команды yacc.
LFLAGS Для флагов команды lex.

Следовательно, команда

make "CC=NEWCC"

указывает программе make, что вместо обычного компилятора C необходимо вызвать программу NEWCC. Аналогично, команда

make "CFLAGS=-O"

указывает команде make, что объектный код, созданный компилятором C, должен быть оптимизирован.

Внутренние правила команды make хранятся в файле /usr/ccs/lib/make.cfg.

Определение команд по умолчанию в файле описания

Если при создании целевого файла команда make не может найти в файле описания необходимые команды или внутренние правила, она применяет указанные в файле команды по умолчанию. Команды, которые команда make будет выполнять в этом случае, перечисляются после целевого имени .DEFAULT:

.DEFAULT:
                команда
                команда
                   .
                   .
                   .

Поскольку целевой файл .DEFAULT реально не существует, он называется фиктивным. Фиктивный целевой файл .DEFAULT применяется для задания функции исправления ошибок или общей процедуры, которая применяется для создания всех файлов, не определенных во внутренних правилах программы make.

Добавление других файлов в файл описания

С помощью директивы include в файл описания можно включать другие файлы. Эту директиву можно указывать в любой строке файла. После слова include указывается пробел или символ табуляции, за которым должно следовать имя файла, который будет включен командой make.

Примечание: В директиве include можно задать только одно имя файла.

Например:

include /home/tom/temp

include /home/tom/sample

указывают команде make, что для создания целевого файла необходимо использовать файлы temp, sample и файл описания.

Не следует использовать файлы описания с уровнем вложенности больше 16.


Определение и использование макроопределений в файле описания

Макроопределение задает имя или метку, которая будет использоваться вместо нескольких других имен. Макроопределения позволяют кратко записывать длинные выражения. Для создания макроопределения:

  1. В начале новой строки введите имя макроопределения.
  2. После имени введите знак равенства (=).
  3. Справа от знака равенства (=) введите строку символов, которую должно заменять указанное имя.

До и после знака равенства (=) в макроопределении могут стоять пробелы; они ни на что не влияют. Перед знаком равенства не должно стоять двоеточие (:) или символ табуляции.

Ниже приведены примеры макроопределений:

# С константой "2" связывается значение "xyz"
2 = xyz
 
# С константой "abc" связывается значение "-ll -ly"
abc = -ll -ly
 
# С константой "LIBES" связывается пустое значение
LIBES =

Если задано имя макроопределения, но не указано его значение, то оно считается пустым.

Использование макроопределений в файле описания

После того как вы зададите макроопределение в файле описания, имя этого макроопределения можно использовать в командах файла описания, указывая перед ним символ $ (знак доллара). Если длина имени больше одного символа, его необходимо заключить в круглые () или фигурные {} скобки. Ниже приведены примеры использования макроопределений:

$(CFLAGS)
$2
$(xy)
$Z
$(Z)

Последние два примера в этом списке эквивалентны.

Ниже приведен пример файла описания, в котором задаются и используются макроопределения:

# OBJECTS  - это три файла x.o, y.o и
# z.o (откомпилированные ранее)
OBJECTS = x.o y.o z.o
# LIBES - это библиотека стандартных функций
LIBES = -lc
# prog зависит от x.o y.o и z.o
prog:  $(OBJECTS)
# Компоновка и загрузка 3 файлов и библиотеки стандартных
# функций для создания файла prog
      cc $(OBJECTS) $(LIBES) -o prog

С помощью этого файла описания программа make компонует и загружает три объектных файла (x.o, y.o и z.o) и библиотеку libc.a.

Макроопределение, которое вводится в командной строке, переопределяет макроопределение с тем же именем, заданное в файле описания. Следовательно, команда

make "LIBES= -ll"

загружает файлы и библиотеку lex(-11).

Примечание: Если внутри макроопределения есть пробелы, его необходимо заключить в двойные кавычки (" "). В противном случае оболочка будет воспринимать эти пробелы не как часть макроопределения, а как разделители параметров.

Команда make поддерживает до 10 уровней вложенности макроопределений. Например, если задать последовательность макроопределений:

macro1=value1

macro2=macro1

то значение выражения $($(macro2)) будет равно value1.

Значение в макроопределении вычисляется в момент его обработки. Оно не вычисляется в момент определения. Если макроопределение было задано, но ни разу не использовалось, то связанное с ним значение не будет ни разу вычислено. Это особенно важно в тех случаях, когда макроопределение создается для значений, интерпретируемых оболочкой, так как они могут изменяться. Результат подстановки макроопределения

OBJS = 'ls *.o'

может быть разным, если оно вызывается в разные моменты времени в процессе создания или удаления объектных файлов. Результат обработки такого макроопределения не совпадает с результатом вызова команды ls во время создания макроопределения OBJS.

Стандартные макроопределения

В программе make предусмотрены стандартные макроопределения, которые можно использовать в файле описания. В частности, они позволяют задавать переменные. Программа make выполняет следующие макроподстановки:

$@ Имя текущего целевого файла.
$$@ Имя метки в строке взаимосвязей.
$? Имена устаревших файлов (т.е. тех, которые были изменены уже после создания целевого файла).
$< Имя измененного родительского файла, из-за которого требуется повторно создать целевой файл.
$* Имя текущего родительского файла без расширения.
$% Имя компонента архивной библиотеки.

Имя целевого файла

Если в последовательности команд файла описания задано имя $@, то перед тем, как передать очередную команду оболочке, программа make заменит это имя на имя текущего целевого файла. Программа make выполняет такую подстановку только в том случае, если при создании целевого файла она выполняет команды из файла описания.

Имя метки

Если в строке взаимосвязей файла описания указано имя $$@, то программа make подставляет вместо него имя метки, которое стоит в этой строке слева от двоеточия. Например, строку взаимосвязей

cat:     $$@.c

программа make преобразует в

cat:     cat.c

после обработки. Это макроопределение можно использовать для создания группы файлов, каждому из которых соответствует только один исходный файл. Например, для обновления каталога системных команд можно создать такой файл описания:

# Макроопределение CMDS
# для замены имен команд
CMDS = cat dd echo date cc cmp comm ar ld chown
# Каждая команда зависит от файла .c
$(CMDS):      $$@.c
# Создание нового набора команд путем компиляции устаревших
# файлов ($?) и создания целевого файла с именем ($@)
         $(CC) -O $? -o $@

При выполнении программы make вместо $$(@F) будет подставлено $@. Это макроопределение можно использовать для обновления каталога usr/include, когда файл описания находится в другом каталоге. Ниже приведен пример такого файла описания:

# Макроопределение для имени каталога INCDIR
INCDIR = /usr/include
# Замена группы файлов каталога
# именем INCLUDES
INCLUDES = \
         $(INCDIR)/stdio.h \
         $(INCDIR)/pwd.h \
         $(INCDIR)/dir.h \
         $(INCDIR)/a.out.h \
# Все файлы в списке зависят от файла
# с тем же именем из текущего каталога
$(INCLUDES):       $$(@F)
# Копирует более свежие файлы из текущего
# каталога в /usr/include
         cp $? $@
# Устанавливает для целевых файлов права только на чтение
         chmod 0444 $@

Этот файл описания создает файл в каталоге /usr/include, если был изменен соответствующий файл в текущем каталоге.

Устаревшие файлы

Если в последовательности команд файла описания есть макроопределение $?, то команда make подставляет вместо него список родительских файлов, которые были изменены уже после создания целевого файла. Программа make выполняет такую подстановку только в том случае, если при создании целевого файла она выполняет команды из файла описания.

Первый устаревший файл

Если в последовательности команд файла описания задано макроопределение $<, то команда make подставляет вместо него имя файла, с которого начинается создание целевого файла. Это имя родительского файла, который был изменен после создания целевого файла, что и послужило причиной вызова команды make.

Если указать символ < (знак "меньше") с буквой D или F, то вместо этой конструкции будет подставлено имя каталога или имя первого устаревшего файла, соответственно. Например, если имя первого устаревшего файла

/home/linda/sample.c

то в результате подстановки, выполняемой командой make, он будет заменен на

$(<D)   =   /home/linda
$(<F)   =   sample.c
$<      =   /home/linda/sample.c

Программа make выполняет эту подстановку только в том случае, если она выполняет команды из своих внутренних правил или из списка .DEFAULT.

Расширение текущего файла

Если в последовательности команд файла описания задано макроопределение $*, то команда make подставляет вместо него имя текущего родительского файла (без расширения), который применяется для создания целевого файла. Например, если команда make использует файл

test.c

то вместо $* будет подставлено имя test.

Если после звездочки (*) указать букву D или F, то будет подставляться имя каталога или имя текущего файла, соответственно.

Допустим, что для создания целевого файла программа make использует несколько файлов (заданных в файле описания или во внутренних правилах). В каждый момент времени применяется только один из этих файлов (он называется текущим). Если этот текущий файл

/home/tom/sample.c

то результат подстановки, выполняемой командой make, будет выглядеть так:

$(*D)  =  /home/tom
$(*F)  =  sample
$*     =  /home/tom/sample

Программа make выполняет эту подстановку только в том случае, если она выполняет команды из своих внутренних правил или из списка .DEFAULT, а не из файла описания.

Компонент архивной библиотеки

Если в последовательности команд файла описания задано макроопределение $%, а целевой файл представляет собой компонент архивной библиотеки, то программа make подставляет имя библиотечного компонента. Например, если целевой файл - это

lib(file.o)

то команда make подставляет вместо $% имя компонента, то есть file.o.

Изменение макроопределений в команде

Если в командах оболочки файла описания применяются макроопределения, то вы можете изменить текст, который будет подставлен вместо них командой make. Для изменения текста замещения после имени макроопределения нужно поставить двоеточие (:), а затем указать новый текст. Ниже приведен общий вид этой команды:

$(имя:строка1=строка2)

Когда команда make обнаруживает имя макроопределения, вместо строки1 она подставляет строку2. Например, если файл описания содержит макроопределение

FILES=test.o sample.o form.o defs

то с помощью макроопределения в команде файла описания можно заменить файл form.o на input.o:

cc -o $(FILES:form.o=input.o)

Такое изменение макроопределения можно использовать при обновлении архивных библиотек. Дополнительная информация приведена в описании команды ar.


Процедура создания целевого файла командой make

Программа make создает целевой файл поэтапно.

Программа make выполняет следующие действия:

  1. Находит имя целевого файла в файле описания или в команде вызова программы make
  2. Проверяет, существуют ли файлы, от которых зависит целевой файл, и не устарели ли они
  3. Проверяет, совпадает ли версия целевого файла с версией файлов, от которых он зависит.

Если целевой файл или один из родительских файлов устарел, программа make создает целевой файл с помощью одного из следующих наборов команд:

Если все файлы уже были обработаны программой make, то она выдаст сообщение о том, что ни один файл не изменен, и завершит свою работу. Если после последнего запуска команды make некоторые файлы были изменены, то команда make обновит только устаревшие файлы. Файлы, которые не были изменены, заново не создаются.

При выполнении команд, предназначенных для создания целевого файла, программа make обрабатывает макроопределения, записывает каждую командную строку и передает команду в новую копию оболочки.


Применение команды make к файлам Системы контроля исходного кода (SCCS)

Команды и файлы SCCS применяются для управления доступом к файлу и отслеживания изменений, внесенных в файл. Файл SCCS - это любой текстовый файл, который применяется командами SCCS. При обработке файлов SCCS командами, отличными от SCCS, эти файлы могут быть повреждены. Дополнительная информация об SCCS приведена в разделе Глава 23, Система контроля исходного кода (SCCS).

У всех файлов SCCS есть префикс s., отличающий их от обычных текстовых файлов. Программа make не распознает ссылки на префиксы имен файлов. Из-за этого в файле описания команды make нельзя ссылаться на файлы SCCS напрямую. Для представления файлов SCCS программа make использует расширение ~ (тильду). Следовательно, .c~.o - это имя правила, которое преобразует файл SCCS, содержащий исходный код на языке C, в объектный файл. Ниже приведено внутреннее представление этого правила:

.c~.o:
         $(GET) $(GFLAGS) -p  $<  >$*.c
         $(CC) $(CFLAGS) -c $*.c
         -rm -f $*.c

Добавление символа ~ (тильды) к расширению имени файла приводит к тому, что вместо обычного файла будет найден файл SCCS с фактическим расширением (включающим все символы, стоящие между точкой (.) и тильдой). С помощью макроопределения GFLAGS в SCCS передаются флаги, задающие версию файла SCCS.

Программа make распознает следующие расширения имен SCCS:

.C\~ Исходный файл C++
.c~ Исходный файл c
.y~ Исходная грамматика yacc
.s~ Исходный файл ассемблера
.sh~ Файл команд оболочки
.h~ Заголовочный файл
.f~ Файл на Фортране
.l~ Исходная грамматика lex

В программе make применяются следующие правила преобразования файлов SCCS:

.C\~.a:

.C\~.c:

.C\~.o:

.c~:

.c~.a:

.c~.c:

.c~.o:

.f~:

.f~.a:

.f~.o:

.f~.f:

.h~.h:

.l~.o:

.s~.a:

.sh~:

.s~.o:

.y~.c:

.y~.o:

Файлы описания, хранящиеся в SCCS

Если в текущем каталоге хранится файл описания (файл с именем makefile или Makefile), то команда make не будет искать файл описания в SCCS. Если в текущем каталоге нет файла описания, то команда make попытается найти в SCCS файл с именем s.makefile или s.Makefile. Если команда make найдет один из этих файлов, она вызовет команду get для создания файла описания на базе найденного файла с помощью SCCS. После того как SCCS создаст файл описания, он будет обработан командой make как обычный файл описания. Когда команда make завершит свою работу, она удалит из текущего каталога созданный файл описания.


Применение команды make другими файлами

Запустите программу make из каталога, в котором находится файл описания для создаваемого файла. Имя этого файла описания указывается в параметре файл-описания. Введите команду

make -f файл-описания

в командной строке. Если файл описания называется makefile или Makefile, флаг -f указывать не нужно. Введите в командной строке вместе с командой make макроопределения, флаги, имена файлов описания и имена целевых файлов:

make [флаги] [макроопределения] [целевые-файлы]

С помощью параметров, заданных в командной строке, программа make определяет, что ей нужно сделать. Во-первых, она просматривает все макроопределения, указанные в командной строке (т.е. записи, которые заключены в кавычки и содержат знак равенства), и выполняет макроподстановку. Если программа make обнаружит одно и то же макроопределение в командной строке и в файле описания, то она будет применять макроопределение, заданное в командной строке.

После этого программа make просматривает флаги. Для получения дополнительной информации просмотрите список флагов, поддерживаемых командой make.

Все остальные записи в командной строке рассматриваются программой make как имена целевых файлов. Команда make выполняет все команды оболочки, заключенные в обратные кавычки, которые генерируют имена целевых файлов. После этого программа make создает целевые файлы (слева направо). Если имя целевого файла в командной строке не указано, то программа make создает целевой файл с первым же обнаруженным в файле описания именем, которое не начинается с точки. Если задано несколько файлов описания, команда make определяет имя целевого файла из первого файла описания.


Применение переменных среды командой make

При запуске программа make считывает текущие значения переменных среды и добавляет их в свои макроопределения. С помощью макроопределений MAKEFLAGS и MFLAGS пользователь может задать флаги, которые должны быть переданы команде make. Если заданы оба макроопределения, то MAKEFLAGS переопределяет значения MFLAGS. С флагами, заданными с помощью этих переменных, в команду make передаются все опции из командной строки. Если команда make вызывается рекурсивно с помощью макроопределения $(MAKE) в файле описания, то при каждом вызове make передает все флаги.

Программа make выполняет макроподстановку в следующем порядке:

  1. Считывает переменную среды MAKEFLAGS.

    Если переменная среды MAKEFLAGS не задана, команда make проверяет значение переменной среды MFLAGS. Если для одной из этих переменных задано непустое значение, команда make рассматривает каждый символ этого значения как входной флаг. Эти флаги (кроме флагов -f, -p и -d, которые нельзя задать с помощью MAKEFLAGS и MFLAGS), задают среду выполнения команды make.

  2. Считывает и устанавливает флаги, заданные в командной строке. Эти флаги добавляются к флагам, установленным ранее с помощью переменной среды MAKEFLAGS или MFLAGS.
  3. Считывает макроопределения, заданные в командной строке. Все другие макроопределения с таким же именем команда make будет игнорировать.
  4. Считывает внутренние макроопределения.
  5. Считывает значения переменных среды. Программа make рассматривает переменные среды как макроопределения и передает их в другие программы оболочки.

Пример файла описания

Ниже приведен файл описания для обновления программы make. Исходный код команды make включает несколько файлов на языке C и грамматику yacc.

# Файл описания для программы make
# Макроопределение: вывод на печать
P = qprt
#  Макроопределение: имена исходных файлов
    FILES = Makefile version.c defs main.c \
            doname.c misc.c files.c \
            dosy.c gram.y lex.c gcos.c
    #Макроопределение: имена объектных файлов
    OBJECTS = version.o main.o doname.o \
              misc.o files.o dosys.o \
              gram.o
    # Макроопределение: программа lint и флаги
    LINT = lint -p
    # Макроопределение: флаги компилятора C
    CFLAGS = -O
    # make зависит от файлов, указанных
    # в макроопределении OBJECTS
    make:    $(OBJECTS)
    # Компоновка make с помощью программы cc
             cc $(CFLAGS) $(OBJECTS) -o make
    # Выводит размер файлов
             @size make

# Объектные файлы зависят от файла
 # с именем defs
    $(OBJECTS):  defs
    # Файл gram.o зависит от lex.c
    # Для создания gram.o применяются внутренние правила:
    gram.o:  lex.c
    # Удаление промежуточных файлов
    clean:
             -rm *.o gram.c
             -du
    # Копирование вновь созданной программы в каталог
    # /usr/bin и удаление программы
    # из текущего каталога
    install:
             @size make /usr/bin/make
             cp make /usr/bin/make ; rm make
    # Пустой файл "print" зависит от файлов,
    # включенных в макроопределение FILES
    print:   $(FILES)
    # Печать измененных файлов
             pr $? | $P
    # Изменение даты в пустом файле
    # print на дату последней
    # печати
             touch print

# Сравнение даты старого
    # файла с датой вновь
    # созданного файла
    test:
             make -dp | grep -v TIME >1zap
             /usr/bin/make -dp | grep -v TIME >2zap
             diff 1zap 2zap
             rm 1zap 2zap
    # Программа lint зависит
    # от перечисленных файлов
    lint:    dosys.c doname.c files.c main.c misc.c \
             version.c gram.c
    # Вызов lint с перечисленными файлами
    # LINT - это внутреннее макроопределение
             $(LINT) dosys. doname.c files.c main.c \
             misc.c version.c gram.c
             rm gram.c
    # Архивация файлов, из которых создается make
    arch:
             ar uv /sys/source/s2/make.a $(FILES)

Обычно перед выполнением команды программа make отправляет ее на стандартное устройство вывода.

Ниже показан пример вывода, полученного при вызове простой команды make из каталога, содержащего только исходный файл и файл описания:

cc -O -c version.c
cc -O -c main.c
cc -O -c doname.c
cc -O -c misc.c
cc -O -c files.c
cc -O -c dosys.c
yacc  gram.y
mv y.tab.c gram.c
cc -O -c gram.c
cc version.o main.o doname.o misc.o files.o dosys.o
   gram.o -o make
make: 63620 + 13124 + 764 + 4951 = 82459

В файле описания не задано ни одного исходного файла или файла грамматики. Для их определения команда make использует свои правила расширения имен, а затем выполняет необходимые команды. Числа в последней строке приведенного примера - это результат выполнения команды size make. Поскольку в файле описания перед командой size стоит символ @, то вывод самой команды подавляется, а выводятся только ее результаты (размеры файлов).

Вывод можно отправить на принтер или в файл, изменив макроопределение P в командной строке. Например:

make print "P = print -sp"

или

make print "P = cat >zap"


[ Страница назад | Страница вперед | Содержание | Индекс | Библиотека | Юридическая информация | Поиск ]