Make-файл является хранилищем информации, указывающей программе make, каким образом нужно перекомпилировать проект.
Из чего состоят make-файлы
Make-файл может состоять из конструкций пяти видов: явные правила, неявные правила, определения переменных, директивы и комментарии. Правила, переменные и директивы подробно рассматриваются в следующих главах.
Явное правило (explicit rule) описывает, когда и каким образом следует обновлять файлы, называемые целями правила. В этом правиле перечисляются файлы, от которых зависит цель правила (так называемые пререквизиты), а также могут быть заданы команды, которые следует использовать для создания или обновления цели.
Неявное правило (implicit rule) описывает, когда и каким образом нужно обновлять некоторую группу файлов, имена которых подходят под определенный шаблон. Такое правило описывает, как цель может зависеть от файла со "сходным" именем и задает команды для обновления целей.
Определение переменной (variable definition) - это строка make-файла, в которой переменной присваивается определенное текстовое значение. Далее, это значение может быть "подставлено" в нужном месте текста. В нашем примере make-файла, переменная objects определялась как список объектных файлов программы.
Директива указывает программе make на необходимость произведения некоторого специального действия во время чтения make-файла. Возможны, в частности, следующие действия:
Чтение другого make-файла.
Решение (на основе значения переменных) об использовании или игнорировании части make-файла.
Определение многострочной переменной, состоящей из нескольких строк.
Символ `#' обозначает начало комментария. Весь текст, начиная с этого символа и до конца строки, будет игнорирован. Комментарий может быть продолжен на следущую строку с помощью одиночного символа обратной косой черты, находящегося в конце строки. Комментарии могут находиться практически в любом месте make-файла за несколькими исключениями. Они не могут находится внутри директивы define и, возможно, внутри команд (поскольку, здесь уже интерпретатор командной строки будет решать - что именно является комментарием). Строка make-файла, целиком состоящая из комментария, рассматривается как пустая и игнорируется.
Имена make-файлов
По умолчанию, когда make ищет make-файл для обработки, она поочередно пробует найти файлы со следующими именами (в указанном порядке): `GNUmakefile', `makefile' и `Makefile'.
Обычно, вам имеет смысл давать своему make-файлу имя `makefile', либо `Makefile'. Мы рекомендуем использовать имя `Makefile', потому что при выводе содержимого каталога, файл с таким именем будет находится в начале списка, наряду с такими важными файлами как `README'. Первое из проверяемых имен - `GNUmakefile' - не может быть рекомендовано для большинсства make-файлов. Это имя можно использовать, если ваш make-файл специфичен для GNU make и не будет обрабатываться другими версиями make. Другие версии программы make ищут make-файлы с именами `makefile' и `Makefile', но не `GNUmakefile'.
В том случае, если make не может найти файлов с перечисленными выше именами, то она пробует продолжить работу без использования make-файла. В таком случае, при вызове make вы должны явно указать главную цель и утилита попробует достичь этой цели, используя только "встроенные" в нее неявные правила.
Если вы хотите использовать "нестандартное" имя для вашего make-файла, вы можете указать его в командной строке, используя опции `-f' или `--file'. Аргументы `-f имя_файла' или `--file=имя_файла', указывают программе make на необходимость использования файла с именем имя_файла в качестве make-файла. Вы можете задать обработку сразу нескольких make-файлов, перечислив их в командной строке с помощь нескольких опций `-f' или `--file'. Все указанные таким образом make-файлы логически "объединяются" в том порядке, как они были заданы в командной строке. При наличии в командной строке опций `-f' или `--file', автоматического поиска make-файлов с именами `GNUmakefile', `makefile' и `Makefile', не производится.
Составление правил
Правила (rules) содержатся в make-файле и описывают, когда и каким образом должны быть обновлены или созданы некоторые файлы, называемые целями (targets). Чаще всего, каждое правило содержит только одну цель. В правиле перечисляются файлы, которые являются пререквизитами (prerequisites) для этой цели и команды, которые должны быть выполнены для создания или обновления цели.
Порядок следования правил внутри make-файле не имеет значения. Исключение составляет лишь выбор главной цели по умолчанию (default goal) - цели, к которой стремиться make, если вы не задали ее явно. По умолчанию, главной целью становиться цель из первого правила в первом обрабатываемом make-файле. Если это правило содержит несколько целей, то только первая из них становится главной целью. Здесь есть два исключения. Во-первых, главными целями, выбираемыми по умолчанию, не могут стать цели, имя которых начинается с точки (если только они не содержат по крайней мере одного символа `/'). И, во-вторых, из процесса выбора главной цели исключаются шаблонные правила.
Поэтому, мы обычно пишем make-файлы таким образом, чтобы первое правило описывало процесс сборки готовой программы, или всех программ, описываемых в этом make-файле (часто, для этого используется цель с именем `all').
Синтаксис правил
В общем виде, правило выглядит так:
цели : пререквизиты
команда
...
или так:
цели : пререквизиты ; команда
команда
...
Цели (targets) - это имена файлов, разделенные пробелами. В именах целей могут быть использованы шаблонные символы. Для файлов, содержащихся в архиве, может быть использована специальная форма записи: `a(m)', где a - это имя архивного файла, а m - имя содержащегося в нем файла . Обычно, в правиле содержится только одна цель, однако, иногда имеет смысл задать несколько целей в одном правиле.
Строки, содержащие команды, должны начинаться с символа табуляции. Первая команда может располагаться либо в строке с пререквизитами (и отделяться от них точкой с запятой), либо в следующей строке после пререквизитов (эта строка должна начинаться с символа табуляции). В обоих случаях, результат будет один и тот же.
Поскольку знак доллара используется для ссылки на переменные, для использования его в правилах, нужно писать `$$'. Длинные строки make-файла могут быть разделены на части с помощью символа '\', находящегося в конце строки. Это может повысить удобочитаемость make-файла, но "технической" необходимости в этом нет - make никак не ограничивает длину строк make-файла.
Правило содержит информацию о двух вещах: когда следует считать, что цель "устарела", и каким образом она может быть обновлена при возникновении такой необходимости.
Критерий "устаревания" вычисляется по отношению к пререквизитам, которые представляют из себя имена файлов, разделенные пробелами. В именах пререквизитов могут использоваться шаблонные символы. Пререквизиты также могут быть файлами, находящимися в архивах. Цель считается "устаревшей", если такого файла не существует, либо он "старше", чем какой-либо из пререквизитов (проверяется время последней модефикации файла). Смысл здесь в том, что, поскольку целевой файл строится на основе информации из файлов-пререквизитов, то изменение хотя бы одного из них может привести к тому, что содержимое целевого файла уже не будет "правильным".
Команды указывают на то, каким образом следует обновлять цель. Это - просто строки (с некоторыми дополнительными возможностями), исполняемые интерпретатором командной строки (обычно `sh').
Использование шаблонных символов (wildcard characters) в именах файлов.
При использованием шаблонных символов (wildcard characters), с помощью одного имени можно задать целую группу файлов. В make шаблонными символами являются `*', `?' и `[...]' (как в оболочке Bourne). Например, шаблон `*.c' будет соответствовать всем файлам с суффиксом `.c', находящимся в текущей директории.
Символ `~' в начале имени файла, также имеет специальное значение. Одиночный символ `~' или сочетание `~/' означает ваш домашний каталог. Например, выражение `~/bin' будет означать `/home/you/bin'. Если сразу за символом `~' следует некоторое имя, такая строка будет представлять собой домашнюю директорию пользователя с этим именем. Например, строка `~john/bin' будет означать `/home/john/bin'. В системах, где пользователи не имеют своего домашнего каталога (таких как MS-DOS или MS-Windows), такое поведение может эмулироваться с помощью установки переменной окружения HOME.
Раскрытие шаблонных имен (замена их конкретным списком файлов, удовлетворяющих шаблону) автоматически производится в именах целей, именах пререквизитов и командах (в командах этим занимается интерпретатор командной строки). В других случаях, раскрытие шаблона производится только при явном запросе с помощью функции wildcard.
Специальное значение шаблонных символов может быть "отключено" с помощью предшествующего им символа '\'. Таким образом, строка `foo\*bar' будет ссылаться на довольно странное имя, состоящее из семи символов - начального `foo', звездочки и `bar'.