Files
blog/content/ru/makefiles.md
Pavel Kirilin 68dcb8da74 Added k3s page.
Signed-off-by: Pavel Kirilin <win10@list.ru>
2021-12-09 15:38:19 +04:00

133 lines
5.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: Makefiles для чайников.
description: Автоматизируем по старинке.
position: 3
category: 'DevOps'
---
# Makefiles для чайников
Если описывать в двух словах, то это просто описание команд для упрощения работы с проектом. Изначально делались для того, чтобы удобно компилировать всякие проекты на любых языках.
## Как они работают
Достаточно просто.
Вот пример `Makefile`:
```makefile{}[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`, то мы получим следующее:
```console
$ sh "test.gen"
Hi!
```
Как видно из выхлопа данной команды, у нас успешно запустился файл `test.gen`, хотя мы не запускали команду `make test.gen`. Что произошло? Давайте разбираться.
## Зависимости таргетов
На строчке объявления таргета `run` видно, что объявлен `test.gen`. Это зависимость данного таргета и она будет вызвана до того, как выполнится скрипт описываемого таргета. Таких зависимостей может быть много, перечисляются они чере пробел.
Например:
```makefile{}[Makefile]
.PHONY: target1
target1:
echo "1"
.PHONY: target2
target2: target1
echo "2"
.PHONY: target3
target3: target1 target2
echo "memes"
```
При вызове `make target3` будет выведено:
```console
$ make target3
echo "1"
1
echo "2"
2
echo "memes"
memes
```
Как можно видеть, он построил граф зависимостей и не выполнил `target1` дважды.
## Сокрытие вывода команд
В предыдущем примере можно заметить, что он написал все команды в терминал. Для того, чтобы этого избежать следует добавить "@" в начало команды и она не будет напечатана.
```makefile{}[Makefile]
.PHONY: target1
target1:
@echo "1"
.PHONY: target2
target2: target1
@echo "2"
.PHONY: target3
target3: target1 target2
@echo "memes"
```
Теперь при вызое `make target3` будет показано следующее:
```cosole
$ make target3
1
2
memes
```
## Валидация сгенерированных файлов
Зачастую `Makefile` используют для компиляции С и зачастую требуется
собрать какую-либо часть проект и пропустить сборку этой части, если эта часть уже собрана.
Раскрою секрет, в Makefile это базовый функционал.
Давайте немного поменяем первый Makefile и запустим дважды.
```makefile{}[Makefile]
# Сгенерируем простой файл
test.gen:
echo 'echo "Hi!"' > "test.gen"
# Команда для запуска файла test.gen
.PHONY: run
run: test.gen
sh "test.gen"
```
Теперь вызываемая команда таргета `test.gen` выводится на экран.
Позапускаем.
```console
$ 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` будет присутствовать в директории цель не будет выполняться.