Files
blog/content/ru/makefiles.md
2021-12-10 11:54:53 +04:00

5.4 KiB
Raw Blame History

title, description, position, category
title description position category
Makefiles для чайников. Автоматизируем по старинке. 3 DevOps

Makefiles для чайников

Что такое мейкфайлы? Вы наверняка их встречали, если собирали проекты из ихсодных файлов. Если описывать в двух словах, то это просто описание команд для упрощения работы с проектом. Изначально делались для того, чтобы удобно компилировать всякие проекты на любых языках.

Как они работают?

Достаточно просто.

Вот пример Makefile:

# Сгенерируем простой файл
test.gen:
	@echo 'echo "Hi!"' > "test.gen"

# Команда для запуска файла test.gen
.PHONY: run
run: test.gen
	sh "test.gen"

До двоеточий обазначены команды (tagets). Например тут это: test.gen и run. Данные таргеты можно запускать через make ${target}.

Например, если ввести make run в папке с Makefile, то мы получим следующее:

$ sh "test.gen"  
Hi!

Как видно из выхлопа данной команды, у нас успешно запустился файл test.gen, хотя мы не запускали команду make test.gen. Что произошло? Давайте разбираться.

Зависимости таргетов

На строчке объявления таргета run видно, что объявлен test.gen. Это зависимость данного таргета и она будет вызвана до того, как выполнится скрипт описываемого таргета. Таких зависимостей может быть много, перечисляются они через пробел.

Например:

.PHONY: target1
target1:
	echo "1"

.PHONY: target2
target2: target1
	echo "2"

.PHONY: target3
target3: target1 target2
	echo "memes"

При вызове make target3 будет выведено:

$ make target3
echo "1"  
1  
echo "2"  
2  
echo "memes"  
memes

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

Сокрытие вывода команд

В предыдущем примере можно заметить, что он написал все команды в терминал. Для того, чтобы этого избежать следует добавить "@" в начало команды и она не будет напечатана.

.PHONY: target1
target1:
	@echo "1"

.PHONY: target2
target2: target1
	@echo "2"

.PHONY: target3
target3: target1 target2
	@echo "memes"

Теперь при вызое make target3 будет показано следующее:

$ make target3
1
2
memes

Валидация сгенерированных файлов

Зачастую Makefile используют для компиляции С и зачастую требуется собрать какую-либо часть проекта в файл и пропустить сборку этого файла, если он уже собран. Раскрою секрет, в Makefile это базовый функционал.

Давайте немного поменяем первый Makefile и запустим дважды.

# Сгенерируем простой файл
test.gen:
	echo 'echo "Hi!"' > "test.gen"

# Команда для запуска файла test.gen
.PHONY: run
run: test.gen
	sh "test.gen"

Теперь вызываемая команда таргета test.gen выводится на экран.

Позапускаем.

$ make run  
echo 'echo "Hi!"' > "test.gen"  # Наша командабыла вызвана.
sh "test.gen"  
Hi!  
$ make run  
sh "test.gen"  # Наша команда не вызвана.
Hi!

Дело в том, что названия таргетов - названия файлов, которые должны сгенерировать эти самые таргеты. То есть, в данном случае таргет test.gen должен сгенерировать файл test.gen по окончании выполнения. Если этот файл уже присутствует, то команда выполнена не будет. Именно поэтому у нас она не запустилась второй раз, так как в первый запуск был создан треубемый файл и его никто не удалял между запусками.

А что если я вот не хочу чтобы команда создавала и проверяла файлы? Для этого пишут .PHONY: ${target}. Например у нас так объявлен таргет run и, даже если файл с названием run будет присутствовать в директории цель не будет выполняться.