Makefile. Ускоряй, упрощай!

Привет! Сегодня разберемся как не напрягаться и сохранить свое время избежав рутины.

Представим соревнование поваров - финал, очень сложное задание. Требуется приготовить 100 порций яичницы. Один повар знает где у него лежит каждый ингредиент, всё его рабочее пространство структурировано и везде царит порядок. Другой же повар - полная противоположность, у него хаос и разруха, сковородки лежат в разных местах, он каждый раз ищет подходящую тару и это постоянно отнимает у него ценные минуты.
Первый повар греет масло на сковороде нужного размера, а второй все ещё ищет яйца. Первый начинает разбивать яйца, а второй только сейчас понял, что ему нужна другая сковорода. Итог очевиден - первый победит. Также и у нас - мелкие вещи поглощают наше ценное время.

Omelette

При работе часто требуется выполнять разные команды, например:

Что делает разработчик? Варианта у него три:

  1. копирует откуда-то команду и вставляет в консоль
  2. жмет в консоли стрелочку вверх до посинения, и надеется найти требуемую команду
  3. вводит команду вручную по памяти

Sad Makefile

Хитрый и ленивый разработчик заведет файлик с командами и будет заглядывать в него, а если команда выполняется часто - будет еще и жать стрелочку вверх в консоли. Умный разработчик заведет Makefile, данный файл сможет использовать вся команда.

Что такое makefile и утилита Make? #

По своей сути данный файл - это набор инструкций для утилиты Make. Makefile хранится в корне проекта и является сразу как документацией, так и исполняемыми командами.

Изначально утилита Make использовалась для сборки программ и библиотек из исходного кода, она стала поставляться по умолчанию в большинстве Linux дистрибутивов и поэтому стала такой популярной. В итоге люди начали использовать make не только для сборки программ, но и для автоматизации различных процессов. Поэтому теперь мы можем встретить makefile в большом количестве проектов.

Структура Makefile-а #

Сам make-файл состоит из целей, которые содержат в себе команды:

#Makefile
засунуть_жирафа_в_холодильник: #имя цели
команда_открытия_холодильника #первая команда
команда_засовывания_жирафа #вторая команда
команда_закрытия_холодильника #третья команда

Команды будут выполняться в строгой последовательности: одна за другой. В случае если первая команда не выполнится - последующие не будут запущены. Важным замечанием является, что makefile чувствителен к табам, перед командой обязательно должен быть таб, а не четыре пробела (питонистам привет)!

Python tabs

Если нам понадобится засовывать в холодильник не только жирафа, но и других животных - мы можем не устоять перед желанием засунуть все команды в одну цель. В таком случае наш makefile будет представлять из себя одну бесполезную гору команд, которая не даст нам никаких плюсов. Чтобы этого избежать - мы можем накидать файл такого вида:

#Makefile
засунуть_всех_зверей: открытие_холодильника засовывание_жирафа засовывание_кукушки засовывание_дятла закрытие_холодильника

засунуть_птиц: открытие_холодильника засовывание_кукушки засовывание_дятла закрытие_холодильника

открытие_холодильника:
команда_открытия_холодильника

закрытие_холодильника:
команда_закрытия_холодильника

засовывание_жирафа:
команда_засовывания_жирафа

засовывание_кукушки:
команда_засовывания_кукушки

засовывание_дятла:
команда_засовывания_дятла

Таким образом мы можем комбинировать и запускать цели одну в другой. Наш файл теперь помогает другим разработчикам видеть список доступных целей. Если подходящая цель не найдена - можно добавить собственную!

Запуск целей #

Тут все просто, устанавливаем утилиту Make (как это сделать - легко гуглится), создаем файл с именем Makefile, заполняем его и в консоли выполняем команду **make** *имя_цели*.

Подводные камни #

У make и makefile есть много подводных камней, но самый популярный - это ошибка: make: <имя-цели> is up to date. Она может возникнуть в случае если имя цели совпадает с наименованием файла или каталога имеющегося в данной директории. Да, штука неприятная, но решается добавлением ключевого слова .PHONY:

#Makefile

.PHONY: имя_цели1
имя_цели1:
команда

Переменные #

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

#Makefile
pg_host = ${PG_HOST}
pg_user_name = ${PG_USER_NAME}
pg_password = ${PG_PASSWORD}
pg_database = ${PG_DATABASE}
host_port = ${HOST_PORT}

postgres_url="postgres://$(pg_user_name):$(pg_password)@$(pg_host):5432/$(pg_database)?sslmode=disable"

dbmate_migrations_folder="./Migrations"
dbmate_schema_folder="./schema.sql"
dbmate_options= -d $(dbmate_migrations_folder) -s $(dbmate_schema_folder) -u $(postgres_url)

.PHONY: db_up
db_up:
dbmate $(dbmate_options) --no-dump-schema up

В самом начале у нас объявляется пачка переменных, которые хранят в себе данные для подключения к Postgres. Их значения берутся из переменных окружения - это позволяет каждому разработчику локально изменять конфигурацию и запускать цели индивидуально!

Также можно заметить, что переменная postgres_url использует в себе значения переменных, объявленных ранее, сама же postgres_url используется в команде db_up.

Применение #

Makefile может пригодиться в самых разных задачах:

Makefile

А что еще? #

Я описал не все возможности и тонкости make-файла, за рамками статьи остались условные операторы, дополнительные функции и многое другое, но то, что мы сегодня рассмотрели может очень сильно облегчить жизнь! Подробнее про make можно почитать тут: GNU Make.

Итоги #

Думаю, что итог можно подвести нехитрыми вычислениями. Представим, что мы не пользуемся make-файлом и постоянно открываем файл с командами, ищем требуемую, копируем, вставляем, выполняем - все это занимает у нас ~30 секунд времени на команду (да, мы черепахи). В день мы выполняем 20 команд, 20 команд по 30 секунд = 600 секунд = 10 минут. 20 рабочих дней * 12 месяцев * 10 минут = 2400 минут = 40 часов! Сорок часов уходят на рутину. И это только для одного человека, а если над проектом работает большая команда?

Конечно, все это вычислено с ОЧЕНЬ большой натяжкой, но все же поиск и выполнение команд очень бесит и напрягает, с makefile-ом головной боли теперь будет меньше! Внедри его у себя и команда скажет: “Спасибо!”.

🙏🙏🙏

Поскольку ты зашел так далеко, я буду очень признателен, если ты поделишься этой статьей в своей любимой социальной сети 💖! Для обратной связи, пожалуйста, напиши в Telegram.

Опубликовано