Главная цель может быть прямо указана в командной строке при запуске make. В следующем примере make будет стремиться достичь цели edit (получить новую версию файла edit):
make edit
Если не указывать какой-либо цели в командной строке, то make выбирает в
качестве главной первую, встреченную в make-файле цель. Схематично
``верхний уровень'' алгоритма работы make можно представить так:
make()
{
главная_цель = Выбрать_Главную_Цель()
Достичь_Цели( главная_цель )
}
После того как главная цель выбрана, make запускает ``стандартную'' процедуру
достижения цели. Сначала в make-файле ищется правило, которое описывает способ
достижения этой цели (функция НайтиПравило). Затем, к найденному правилу
применяется обычный алгоритм обработки правил (функция ОбработатьПравило):
Достичь_Цели( Цель )
{
правило = Найти_Правило( Цель )
Обработать_Правило( правило )
}
Обработка правила разделяется на два основных этапа. На первом этапе
обрабатываются все зависимости, перечисленные в правиле (функция
ОбработатьЗависимости). На втором этапе принимается решение - нужно ли выполнять
указанные в правиле команды (функция НужноВыполнятьКоманды). При необходимости,
перечисленные в правиле команды выполняются (функция ВыполнитьКоманды):
Обработать_Правило( Правило )
{
Обработать_Зависимости( Правило )
если Нужно_Выполнять_Команды( Правило )
{
Выполнить_Команды( Правило )
}
}
Функция ОбработатьЗависимости поочередно проверяет все перечисленные в теле правила
зависимости. Некоторые из них могут оказаться целями каких-нибудь правил. Для
этих зависимостей выполняется обычная процедура достижения цели (функция
ДостичьЦели). Те зависимости, которые не являются целями, считаются именами
файлов. Для таких файлов проверяется факт их наличия. При их отсутствии make
аварийно завершает работу с сообщением об ошибке:
Обработать_Зависимости( Правило )
{
цикл от i=1 до Правило.число_зависимостей
{
если Есть_Такая_Цель( Правило.зависимость[i])
{
Достичь_Цели( Правило.зависимость[i])
}
иначе
{
Проверить_Наличие_Файла(Правило.зависимость[i])
}
}
}
На стадии обработки команд решается вопрос, нужно ли выполнять описанные в правиле команды или нет. Считается, что нужно выполнять команды если:
Нужно_Выполнять_Команды( Правило )
{
если Правило.Цель.Является_Абстрактной()
return true
// цель является именем файла
если Файл_Не_Существует( Правило.Цель )
return true
цикл от i=1 до Правило.Число_зависимостей
{
если Правило.Зависимость[i].Является_Абстрактной()
return true
иначе
// зависимость является именем файла
{
если Время_Модификации(Правило.Зависимость[i])
> Время_Модификации( Правило.Цель )
return true
}
}
return false
}
В указанном примере целью по умолчанию является edit. Первым шагом по его
обновлению будет обновление всех файлов объектов (.o), перечисленных как
зависимости. Обновление edit.o в свою очередь требует обновления edit.cc и
defs.h. Предполагается, что edit.cc является исходным файлом, из которого
создается edit.o, а defs.h является заголовочным файлом, который включается в
edit.cc. Правил, указывающих на эти файлы, нет; поэтому такие файлы, как минимум
должны просто существовать. Теперь edit.o считается готовым, если он изменен
позже, чем edit.cc или defs.h (если он старше их, это значит, что один из этих
файлов изменился со времени последней компиляции edit.o). Если edit.o старше
своих зависимостей, gmake выполняет действие OP ``gcc -g -c -Wall
edit.cc''
,
создавая новый edit.o. Когда edit.o и все другие файлы .o будут обновлены,
они будут собраны вместе действием
``gcc -g -o edit ...''
, чтобы создать
программу edit, если либо edit еще не существует, либо любой из файлов .o
новее, чем существующий файл edit.
Чтобы вызвать gmake для этого примера, используйте команду:
gmake -f <makefile-name> <target-names>,
где <target-names>
- это имена целей, которые вы хотите обновить, а
<makefile-name>
, заданное после ключа -f, является именем make-файла.
По умолчанию целью является первое правило в файле. Вы можете (обычно так и
делают) опустить -f makefile-name
, и в этом случае по умолчанию будет выбрано
имя makefile или Makefile, если любой из этих файлов существует.
Обычно каждый каталог содержит исходный код для простой части программы.
Принимая правило, что имя программы соответствует первой цели, и что make-файл
для каталога называется
makefile
, вы добьетесь того, что вызов команды gmake
без аргументов в любом каталоге приведет к обновлению части программы в этом
каталоге.
Для одной и той же цели может применяться несколько правил, но не более чем одно правило для цели должно иметь действия. Поэтому, мы может переписать последнюю часть примера следующим образом:
edit.o kbd.o commands.o display.o
edit.o : edit.cc
gcc -g -c -Wall edit.cc
kbd.o : kbd.cc
gcc -g -c -Wall kbd.cc
commands.o : command.cc
gcc -g -c -Wall commands.cc
display.o : display.cc
gcc -g -c -Wall display.cc
insert.o : insert.cc
gcc -g -c -Wall insert.cc
search.o : search.cc
gcc -g -c -Wall search.cc
files.o : files.cc
gcc -g -c -Wall files.cc
utils.o : utils.cc
gcc -g -c -Wall utils.cc
insert.o search.o files.o utils.o: defs.h
kbd.o commands.o files.o : command.h
display.o insert.o search.o files.o : buffer.h
Порядок, в котором записаны эти правила, не имеет значения. Скорее, он зависит от вашего вкуса и выбора порядка группировки файлов.