Как известно, программный код
Один из таких инструментов, проверенных временем, — утилита Make. Ее стандарт
Утилита под названием Make возникла еще в далеком 1976 году в стенах компании Bell Labs. Появилась она в результате визита Стива Джонсона
Как-то раз он ворвался в офис, где работал Стюарт Фельдман, громко проклиная все на свете за то, что все утро у него ушло на отладку довольно простой программы.
Исполняемый файл с изменениями по какой-то причине не обновлялся . Поскольку за день до этого Фельдман столкнулся с аналогичной проблемой в своем проекте, ему пришла в голову идея создать универсальный инструмент для решения подобных задач.
Вначале это была просто продуманная идея анализатора зависимостей, но в конечном итоге программа стала более простой и дружелюбной. До появления системы компиляции Make в Unix использовались самописные кустарные сценарии командной строки, применяемые к исходному коду приложений.
Сейчас есть целый ряд программ автоматизаторов сборки, которые отслеживают зависимости в файлах, однако Make — одна из самых распространенных. В первую очередь по причине того, что она включена в дистрибутивы GNU/Linux.
Вообще есть две версии этой программы. Первая — написанная под платформу BSD
Для платформы Microsoft Windows имеется аналогичное приложение — nmake.
Программа Make может понадобиться, когда перед вами стоит задача обновления в сборке определенных данных.
Этот инструмент выполняет анализ файлов и идентифицирует, какие части большой программы необходимо перекомпилировать заново, и выдает соответствующие команды для их повторной сборки.
Для функционирования этой утилиты необходим специальный служебный файл, называемый Makefile (или makefile). Он описывает взаимосвязи между файлами в проекте, над которым вы работаете, и идентифицирует команды для обновления каждого файла. Makefile помещается вместе с кодом в репозиторий
Содержимое простого Makefile может иметь вид:
edit : main1.o kbd1.o command1.o display.o \
insert1.o search1.o files1.o utils1.o
cc -o edit main1.o kbd1.o command1.o display1.o \
insert1.o search1.o files1.o utils1.o
main1.o : main1.c defs1.h
cc -c main1.c
kbd1.o : kbd1.c defs.h command1.h
cc -c kbd1.c
command1.o : command1.c defs.h command1.h
cc -c command1.c
display1.o : display1.c defs1.h buffe1r.h
cc -c display1.c
insert1.o : insert1.c defs1.h buffer1.h
cc -c insert1.c
search1.o : search1.c defs1.h buffer1.h
cc -c search1.c
files1.o : files1.c defs1.h buffer1.h command1.h
cc -c files1.c
utils1.o : utils1.c defs.h
cc -c utils1.c
clean :
rm edit main1.o kbd1.o command1.o display1.o \
insert1.o search1.o files1.o utils1.o
После запуска GNU Make считывает файл с именем GNUmakefile, makefile или Makefile. Если необходимо изменить поведение программы при обработке файла по умолчанию, например, сделать так, чтобы открывался файл с другим именем, содержащий иной набор инструкций, следует указать команду make -f other_name_makefile.
Язык make-файлов — это полный по Тьюрингу декларативный язык. В нем описаны необходимые конечные условия, но порядок, в котором должны выполняться действия, не важен, что иногда сбивает с толку программистов, привыкших к императивному программированию.
Язык Make-файлов базируется на командах. Этими командами описываются цели. В качестве цели можно выбирать имя действия, которое необходимо осуществить, скажем, clean. Также под целью можно принимать имя исполняемого или объектного файла.
Суть построения такого файла состоит в грамотной группировке команд и в выборе понятных названий для целей. Общий синтаксис выглядит так:
# Makefile
цель1: # название_цели, поддерживается kebab-case (вариант при котором вместо символа подчеркивания используется дефис) и snake_case (стиль написания составных слов, при котором они разделяются символом подчеркивания)
команда1 # Обратите внимание — все команды, обязаны содержать в начале символ табуляции — так инструмент сборки отслеживает правила и другие цели
команда2 # если предыдущая команда была успешно выполнена, начинает выполняться следующая команда и так далее
Для команд применяются команды оболочки shell — они будут отображены в консоли. Когда необходимо, чтобы команды не показывались в командной строке, перед командой используется символ @. Если не вводить имя цели, то выполнится цель с именем all либо самая первая цель в сценарии. В качестве пререквизитов или зависимостей, как правило, используются другие цели, представляющие собой имена файлов.
Разберем вариант сборки простого приложения на Си. Предположим, наше приложение 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 defines.h cc -c lib.c defines.h cc -o program main.o lib.o
Если на каком-то этапе работы над приложением файл defines.h подвергнется редактированию, возникнет необходимость перекомпилирования обоих файлов и нового линкования. При изменении одного lib.c, перекомпиляцию main.о делать не нужно.
Следовательно, для каждого файла, который мы должны получить в процессе компиляции, нужно указать на основе каких файлов, а также с помощью какой команды он создается.
Make:Бывает, что при запуске утилиты Make цель явно не задана. В такой ситуации начнет выполняться первая цель, имя которой не начинается с точки “.“. Для нашей программы достаточно написать такой файл:
program: main.o lib.o
cc -o program main.o lib.o
main.o lib.o: defines.h
Есть ряд моментов, которые нужно обговорить относительно этого простого примера. В имени второй цели указаны два парных файла. Для этой же цели не указана команда компиляции. Кроме того, нигде явно не указана зависимость объектных файлов от файлов *.с.
Дело в том, что программа Make содержит встроенные правила для получения файлов с определенными расширениями. Так для цели – объектного файла (расширение *.o) при нахождении соответствующего файла с расширением *.с будет автоматически вызван компилятор «сс-с» .
Нередко команды могут задействовать различные параметры конфигурации, определять пути, устанавливать переменные окружения. С помощью Make можно всем этим управлять, прописав нужную переменную в команде. Формат описания переменной выглядит просто: переменная = значение. Переменные могут быть только строками.
Вы можете использовать любые символы, включая пробелы.
# Makefile
say:
echo "Hello, $(HELLO)!"
# Bash
$ make say HELLO=CRAZY
echo "Hello, CRAZY!"
Hello, CRAZY!
$ make say HELLO=HighloadToday
echo "Hello, HighloadToday!"
Hello, HighloadToday!
Теперь текст нашего примера можно модифицировать:
OBJ = main.o lib.o
program: $(OBJ)
cc -o program $(OBJ)
$(OBJ): defines.h
Обработка значения переменных выполняется исключительно в момент их задействования all на дисплей будет выведен текст «Ась?»:
foo = $(bar)
bar = $(ugh)
ugh = Ась?
all:
echo $(foo)
Если в наш проект был добавлен еще один заголовочный файл lib.h, включаемый только в lib.c, — структура make-файла изменится, будет дописана еще одна строка:
lib.o: lib.h
Таким образом, один целевой файл может быть указан сразу в нескольких целях. При этом полный список связей будет составлен из списков зависимостей всех целей, в которых он принимает участие, а создание файла будет выполняться только один раз.
Теперь вы знаете базовые принципы работы утилиты Make и можете автоматизировать процедуру сборки. Для закрепления навыков рекомендуем вам посмотреть видео, в котором показан процесс создания Make-файла на основе реального проекта:
На фоне роста спроса на ликвидность в бычьем рынке 2025 года, криптозаймы снова выходят на…
Прокси (proxy), или прокси-сервер — это программа-посредник, которая обеспечивает соединение между пользователем и интернет-ресурсом. Принцип…
Согласитесь, было бы неплохо соединить в одно сайт и приложение для смартфона. Если вы еще…
Повсеместное распространение смартфонов привело к огромному спросу на мобильные игры и приложения. Миллиарды пользователей гаджетов…
В перечне популярных чат-ботов с искусственным интеллектом Google Bard (Gemini) еще не пользуется такой популярностью…
Скрипт (англ. — сценарий), — это небольшая программа, как правило, для веб-интерфейса, выполняющая определенную задачу.…