Interested Article - Make
- 2020-07-09
- 1
Make ( МФА [ m e ɪ k ]; с англ. — «сделать», «изготовить») — утилита , автоматизирующая процесс преобразования файлов из одной формы в другую. Чаще всего это компиляция исходного кода в объектные файлы и последующая компоновка в исполняемые файлы или библиотеки .
Утилита использует специальные make-файлы , в которых указаны зависимости файлов друг от друга и правила для их удовлетворения. На основе информации о времени последнего изменения каждого файла Make определяет и запускает необходимые программы.
Происхождение
До создания Make системы сборки (компиляции) ПО Unix обычно состояли из shell - скриптов сборки, сопровождавших исходный код программ.
Make была создана Стюартом Фельдманом ( Stuart Feldman ) в апреле 1976 года в Bell Labs .
В настоящее время существует множество утилит для отслеживания зависимостей, но Make — одна из самых широко распространённых, в первую очередь благодаря тому, что она включена в Unix , начиная с версии PWB/UNIX (англ. Programmer’s Workbench ), которая содержала инструменты для разработки программного обеспечения.
Современные версии
Существует несколько версий Make , основанных на оригинальной Make или написанных с нуля, использующих те же самые форматы файлов и базовые принципы и алгоритмы, а также содержащие некоторые улучшения и расширения. Например:
- BSD Make , основанная на работе Адама де Бура ( Adam de Boor ) над версией Make , с возможностью параллельной сборки; в той или иной форме перешла в FreeBSD , NetBSD и OpenBSD .
- GNU Make — входит в большинство дистрибутивов Linux и часто используется в сочетании с GNU build system .
POSIX включает в себя стандарт основных возможностей утилиты Make , с той или иной степенью совместимости реализованный в различных версиях Make . Как правило, простые make-файлы могут быть успешно обработаны различными версиями Make .
Использование
make [ -f make-файл ] [ цель ] ...
Файл ищется в текущем каталоге. Если ключ -f не указан, используется имя по умолчанию для make-файла — Makefile (однако в разных реализациях Make , кроме этого, могут проверяться и другие файлы, например GNUmakefile ).
Make открывает make-файл, считывает правила и выполняет команды, необходимые для создания указанной цели .
Стандартные цели для сборки дистрибутивов GNU:
- all — выполнить сборку пакета;
- install — установить пакет из дистрибутива (производит копирование исполняемых файлов, библиотек и документации в системные каталоги);
- uninstall — удалить пакет (производит удаление исполняемых файлов и библиотек из системных каталогов);
- clean — очистить дистрибутив (удалить из дистрибутива объектные и исполняемые файлы, созданные в процессе компиляции);
- distclean — очистить все созданные при компиляции файлы и все вспомогательные файлы, созданные утилитой ./configure в процессе настройки параметров компиляции дистрибутива.
По умолчанию Make использует самую первую цель в make-файле.
В процессе сборки приложений BSD часто применяют:
- depend — выполнить компиляцию/выстраивание зависимостей.
Make-файл
Программа Make выполняет команды согласно правилам, указанным в специальном файле. Этот файл называется make-файл (makefile, мейкфайл). Как правило, make-файл описывает, каким образом нужно компилировать и компоновать программу.
make-файл состоит из правил и переменных. Правила имеют следующий синтаксис:
цель1 цель2 ...: реквизит1 реквизит2 ...
команда1
команда2
...
Правило представляет собой набор команд, выполнение которых приведёт к сборке файлов- целей из файлов- реквизитов .
Правило сообщает Make , что файлы, получаемые в результате работы команд ( цели ), являются зависимыми от соответствующих файлов-реквизитов. Make никак не проверяет и не использует содержимое файлов-реквизитов, однако указание списка файлов-реквизитов требуется только для того, чтобы Make убедилась в наличии этих файлов перед началом выполнения команд и для отслеживания зависимостей между файлами.
Обычно цель представляет собой имя файла, который генерируется в результате работы указанных команд. Целью также может служить название некоторого действия, которое будет выполнено в результате выполнения команд (например, цель clean в make-файлах для компиляции программ обычно удаляет все файлы, созданные в процессе компиляции ).
Строки, в которых записаны команды , должны начинаться с символа табуляции .
Рассмотрим несложную программу на Си. Пусть программа program состоит из пары файлов кода — main.c и lib.c, а также из одного заголовочного файла — defines.h, который подключён в обоих файлах кода . Поэтому для создания program необходимо из пар (main.c defines.h) и (lib.c defines.h) создать объектные файлы main.o и lib.o, а затем скомпоновать их в program. При сборке вручную требуется исполнить следующие команды:
cc -c main.c
cc -c lib.c
cc -o program main.o lib.o
Если в процессе разработки программы в файл defines.h будут внесены изменения, потребуется перекомпиляция обоих файлов и линковка , а если изменим lib.c, то повторную компиляцию main.c можно не выполнять.
Таким образом, для каждого файла, который мы должны получить в процессе компиляции, нужно указать, на основе каких файлов и с помощью какой команды он создаётся. Программа Make на основе этих данных выполняет следующее:
- собирает из этой информации правильную последовательность команд для получения требуемых результирующих файлов;
- и инициирует создание требуемого файла только в случае, если такого файла не существует или он старше, чем файлы, от которых он зависит.
Если при запуске Make явно не указать цель, то будет обрабатываться первая цель в make-файле, имя которой не начинается с символа «.».
Для программы program достаточно написать следующий make-файл:
program: main.o lib.o
cc -o program main.o lib.o
main.o lib.o: defines.h
Стоит отметить ряд особенностей. В имени второй цели указаны два файла и для этой же цели не указана команда компиляции. Кроме того, нигде явно не указана зависимость объектных файлов от «*.c»-файлов. Дело в том, что программа Make имеет предопределённые правила для получения файлов с определёнными расширениями . Так, для цели- объектного файла (расширение «.o») при обнаружении соответствующего файла с расширением «.c» будет вызван компилятор «сс -с» с указанием в параметрах этого «.c»-файла и всех файлов-зависимостей.
Синтаксис для определения переменных :
переменная = значение
Значением может являться произвольная последовательность символов , включая пробелы и обращения к значениям других переменных . С учётом сказанного, можно модифицировать наш make-файл следующим образом:
OBJ = main.o lib.o
program: $(OBJ)
cc -o program $(OBJ)
$(OBJ): defines.h
Нужно отметить, что вычисление значений переменных происходит только в момент использования (используется так называемое ленивое вычисление ). Например, при сборке цели all из следующего make-файла на экран будет выведена строка «Huh?».
foo = $(bar)
bar = $(ugh)
ugh = Huh?
all:
echo $(foo)
Предположим, что к проекту добавился второй заголовочный файл lib.h, который включается только в lib.c. Тогда make-файл увеличится ещё на одну строчку:
lib.o: lib.h
Таким образом, один целевой файл может указываться в нескольких целях. При этом полный список зависимостей для файла будет составлен из списков зависимостей всех целей, в которых он участвует, создание файла будет производиться только один раз.
Многопоточное исполнение
Для ускорения длительных задач используют распараллеливание вычислений внутри make-программы. Распараллеливание делается автоматически make-интерпретатором. Для запуска make-файла в многопоточном режиме необходимо передать опцию -j <число потоков>.
make [ -j <число потоков> ] [ цель ]
См. также
Литература
- от 24 сентября 2006 на Wayback Machine и его переводы — не единственные документы, подходящие для обучения. Для того, чтобы изучить данный инструмент, можно воспользоваться и другими информационными источниками:
- от 11 июня 2018 на Wayback Machine
- от 9 июля 2016 на Wayback Machine
- от 9 февраля 2017 на Wayback Machine
- от 11 февраля 2017 на Wayback Machine
Ссылки
- от 24 сентября 2006 на Wayback Machine (англ.)
- от 12 июня 2011 на Wayback Machine (рус.)
- от 22 декабря 2013 на Wayback Machine (англ.)
- от 23 сентября 2007 на Wayback Machine
- от 24 февраля 2009 на Wayback Machine (рус.)
- 2020-07-09
- 1