Make run command linux

Что такое Makefile и как начать его использовать

Что такое Makefile и как начать его использовать

В жизни многих разработчиков найдётся история про первый рабочий день с новым проектом. После клонирования основного репозитория проекта наступает этап, когда приходится вводить множество команд с определёнными флагами и в заданной последовательности. Без описания команд, в большинстве случаев, невозможно понять что происходит, например:

# Bash touch ~/.bash_history ufw allow 3035/tcp || echo 'cant configure ufw' ufw allow http || echo 'cant configure ufw' docker run \ -v /root/:/root/ \ -v /etc:/etc \ -v /var/run/docker.sock:/var/run/docker.sock \ -v /var/tmp:/var/tmp \ -v /tmp:/tmp \ -v $PWD:/app \ --network host \ -w /app \ --env-file .env \ ansible ansible-playbook ansible/development.yml -i ansible/development --limit =localhost -vv grep -qxF 'fs.inotify.max_user_watches=524288' /etc/sysctl.conf || echo fs.inotify.max_user_watches =524288 | tee -a /etc/sysctl.conf || echo 'cant set max_user_watches' && sysctl -p sudo systemctl daemon-reload && sudo systemctl restart docker 

Эти команды являются лишь частью того, что необходимо выполнить при разворачивании проекта. В приведённом примере видно, что команды сами по себе длинные, содержат много флагов, а значит, их трудно не только запомнить, но и вводить вручную. Постоянно вести документацию становится сложнее с ростом проекта, она неизбежно устаревает, а порог входа для новичков становится выше, ведь уже никто не в состоянии вспомнить всех деталей проекта. Некоторые такие команды необходимо использовать каждый день, и даже не один раз в день.

Со временем становится понятно, что нужен инструмент, способный объединить в себе подобные команды, предоставить к ним удобные шорткаты ( более короткие и простые команды) и обеспечить самодокументацию проекта. Именно таким инструментом стал Makefile и утилита make . Этот гайд расскажет, как использование этих инструментов позволит свести процесс разворачивания проекта к нескольким коротким и понятным командам:

# Bash make setup make start make test 

Что такое make и Makefile

Makefile — это файл, который хранится вместе с кодом в репозитории. Его обычно помещают в корень проекта. Он выступает и как документация, и как исполняемый код. Мейкфайл скрывает за собой детали реализации и раскладывает «по полочкам» команды, а утилита make запускает их из того мейкфайла, который находится в текущей директории.

Читайте также:  Linux cli on windows

Изначально make предназначалась для автоматизации сборки исполняемых программ и библиотек из исходного кода. Она поставлялась по умолчанию в большинство *nix дистрибутивов, что и привело к её широкому распространению и повсеместному использованию. Позже оказалось что данный инструмент удобно использовать и при разработке любых других проектов, потому что процесс в большинстве своём сводится к тем же задачам — автоматизация и сборка приложений.

Применение мейка в проектах стало стандартом для многих разработчиков, включая крупные проекты. Примеры мейкфайла можно найти у таких проектов, как Kubernetes, Babel, Ansible и, конечно же, повсеместно на Хекслете.

Синтаксис Makefile

make запускает цели из Makefile, которые состоят из команд:

# Makefile цель1: # имя цели, поддерживается kebab-case и snake_case команда1 # для отступа используется табуляция, это важная деталь команда2 # команды будут выполняться последовательно и только в случае успеха предыдущей 

Но недостаточно просто начать использовать мейкфайл в проекте. Чтобы получить эффект от его внедрения, понадобится поработать над разделением команд на цели, а целям дать семантически подходящие имена. Поначалу, перенос команд в Makefile может привести к свалке всех команд в одну цель с «размытым» названием:

# Makefile up: # разворачивание и запуск cp -n .env.example .env touch database/database.sqlite composer install npm install php artisan key:generate php artisan migrate --seed heroku local -f Procfile.dev # запуск проекта 

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

# Makefile env-prepare: # создать .env-файл для секретов cp -n .env.example .env sqlite-prepare: # подготовить локальную БД touch database/database.sqlite install: # установить зависимости composer install npm install key: # сгенерировать ключи php artisan key:generate db-prepare: # загрузить данные в БД php artisan migrate --seed start: # запустить приложение heroku local -f Procfile.dev 

Теперь, когда команды разбиты на цели, можно отдельно установить зависимости командой make install или запустить приложение через make start . Но остальные цели нужны только при первом разворачивании проекта и выполнять их нужно в определённой последовательности. Говоря языком мейкфайла, цель имеет пререквизиты:

# Makefile цель1: цель2 # такой синтаксис указывает на зависимость задач — цель1 зависит от цель2 команда2 # команда2 выполнится только в случае успеха команды из цель2 цель2: команда1 

Задачи будут выполняться только в указанной последовательности и только в случае успеха предыдущей задачи. Значит, можно добавить цель setup , чтобы объединить в себе все необходимые действия:

# Makefile setup: env-prepare sqlite-prepare install key db-prepare # можно ссылаться на цели, описанные ниже env-prepare: cp -n .env.example .env sqlite-prepare: touch database/database.sqlite install: composer install npm install key: php artisan key:generate db-prepare: php artisan migrate --seed start: heroku local -f Procfile.dev 

Теперь развернуть и запустить проект достаточно двумя командами:

# Bash make setup # выполнит последовательно: env-prepare sqlite-prepare install key db-prepare make start 

Благодаря проделанной работе Makefile, команды проекта вместе с флагами сведены в Makefile. Он обеспечивает правильный порядок выполнения и не важно, какие при этом задействованы языки и технологии.

Читайте также:  What is chmod command in linux

Продвинутое использование

Фальшивая цель

Использование make в проекте однажды может привести к появлению ошибки make: is up to date. , хотя всё написано правильно. Зачастую, её появление связано с наличием каталога или файла, совпадающего с именем цели. Например:

# Makefile test: # цель в мейкфайле php artisan test 
# Bash $ ls Makefile test # в файловой системе находится каталог с именем, как у цели в мейкфайле $ make test # попытка запустить тесты make: `test` is up to date. 

Как уже говорилось ранее, изначально make предназначалась для сборок из исходного кода. Поэтому она ищет каталог или файл с указанным именем, и пытается собрать из него проект. Чтобы изменить это поведение, необходимо в конце мейкфайла добавить .PHONY указатель на цель:

# Makefile test: php artisan test .PHONY: test 
# Bash $ make test ✓ All tests passed ! 

Последовательный запуск команд и игнорирование ошибок

Запуск команд можно производить по одной: make setup , make start , make test или указывать цепочкой через пробел: make setup start test . Последний способ работает как зависимость между задачами, но без описания её в мейкфайле. Сложности могут возникнуть, если одна из команд возвращает ошибку, которую нужно игнорировать. В примерах ранее такой командой было создание .env-файла при разворачивании проекта:

# Makefile env-prepare: cp -n .env.example .env # если файл уже создан, то повторный запуск этой команды вернёт ошибку 

Самый простой ( но не единственный) способ «заглушить» ошибку — это сделать логическое ИЛИ прямо в мейкфайле:

# Makefile env-prepare: cp -n .env.example .env || true # теперь любой исход выполнения команды будет считаться успешным 

Добавлять такие хаки стоит с осторожностью, чтобы не «выстрелить себе в ногу» в более сложных случаях.

Читайте также:  Lamp server kali linux

Переменные

Зачастую в команды подставляют параметры для конфигурации, указания путей, переменные окружения и make тоже позволяет этим управлять. Переменные можно прописать прямо в команде внутри мейкфайла и передавать их при вызове:

# Makefile say: echo "Hello, $(HELLO)!" 
# Bash $ make say HELLO=World echo "Hello, World!" Hello, World ! $ make say HELLO=Kitty echo "Hello, Kitty!" Hello, Kitty ! 

Переменные могут быть необязательными и содержать значение по умолчанию. Обычно их объявляют в начале мейкфайла.

# Makefile HELLO ?=World # знак вопроса указывает, что переменная опциональна. Значение после присвоения можно не указывать. say: echo "Hello, $(HELLO)!" 
# Bash $ make say echo "Hello, World!" Hello, World ! $ make say HELLO=Kitty echo "Hello, Kitty!" Hello, Kitty ! 

Некоторые переменные в Makefile имеют названия отличные от системных. Например, $PWD называется $CURDIR в мейкфайле:

# Makefile project-env-generate: docker run --rm -e RUNNER_PLAYBOOK =ansible/development.yml \ -v $(CURDIR)/ansible/development :/runner/inventory \ # $(CURDIR) - то же самое, что $PWD в терминале -v $(CURDIR) :/runner/project \ ansible/ansible-runner 

Заключение

В рамках данного гайда было рассказано об основных возможностях Makefile и утилиты make . Более плотное знакомство с данным инструментом откроет множество других его полезных возможностей: условия, циклы, подключение файлов. В компаниях, где имеется множество проектов, написанных разными командами в разное время, мейкфайл станет отличным подспорьем в стандартизации типовых команд: setup start test deploy . .

Возможность описывать в мейкфале последовательно многострочные команды позволяет использовать его как «универсальный клей» между менеджерами языков и другими утилитами. Широкая распространённость этого инструмента и общая простота позволяют внедрить его в свой проект достаточно легко, без необходимости доработок. Но мейкфайл может быть по-настоящему большим и сложным, это можно увидеть на примере реальных проектов:

Дополнительные материалы

Мейкфайлы, использованные при составлении гайда:

Источник

Оцените статью
Adblock
detector