Как создать makefile в linux
Make-файлы используются, чтобы помочь решить, какие части большой программы должны быть перекомпилированы.
Другие языки обычно имеют свои собственные инструменты, которые служат той же цели, что и Make.
Его можно использовать и за пределами программ, когда вам нужна серия инструкций для запуска в зависимости от того, какие файлы изменились.
В этой статье вы узнаете про использование компиляции C/C++.
Вот пример графика зависимостей, который вы можете построить с помощью Make.
Граф зависимостей
wikipedia.org
Формат
target: prerequisites recipe
Типичное применение: какая-то зависимость изменилась → выполнятеся действие в результате которого создаётся таргет файл.
Как и в статье Configure, make, install в примере выше используются стандартные цели (target)
.PHONY
Рассмотрим следующий Makefile
.PHONY: site site: echo «HeiHei.ru»
Если теперь выполнить
Удалите site из первой строки, а всё остальное не трогайте
Вроде бы ничего не изменилось, но теперь создайте файл site рядом с Makefile
touch site
make site
make: ‘site’ is up to date.
Так как таргет теперь реальный make не нашёл изменений и ничего не сделал. Из-за такого простого совпадения имени цели (target) и какого-то файла в директории может перестать работать скрипт.
Для защиты от таких неприятностей и применяют PHONY
Также PHONY удобен тем, что перечисляет все цели в самом начале файла. Это улучшает читаемость кода. (если пользоваться правильно)
Пример из C++
Functions.cpp Functions.h Main.cpp
#include #include «Functions.h» int main()
double add( double x, double y)
#pragma once double add(double x, double y);
Эта команда сначала вызывает компиляцию, затем линковку
Создайте Makefile и откройте его в текстовом редакторе. Например, в Vim
touch Makefile
vi Makefile
Makefile будет выглядеть следующим образом
Теперь для компиляции достаточно выполнить
В результате появится исполняемый файл output
To запустить скрипт, достаточно выполнить
Если нужно скомпилировать Main execute
Появится файл Main.o но не появятся остальные (Functions.o, output)
Functions.cpp Functions.h Main.cpp Main.o Makefile
На примере команды make Main.o можно понять почему в Make-файлах используется термин цели (target)
Если теперь выполнить make Main.o не будет перекомпилироваться. Будут выполнены только последние два шага.
Выполните make если ещё не выполняли и не делайте после этого clean
Добавим ещё одну функцию в наш проект. Нужно указать её в файлах Functions.*
Вызывать пока не будет, поэтому Main.cpp остаётся без изменений
Обратите внимание: Main.cpp не был перекомпилирован так как в нём нет изменений.
Таже посмотрите на время изменения файла output оно должно измениться.
Не вносите никаких изменений в файлы и execute
make: ‘output’ is up to date.
Перекомпиляция не нужна и поэтому не выполнена
Переменные
Запустить Docker container из Makefile
Читайте также статью
Параметризация Make
?= позволяет переменным быть перезаписанными на существующие переменные окружения
:= перезаписывает значение переменной
BUILD_ID
To добавить переменным уникальности используют BUILD_ID
USER_ID
To получить ID пользователя запустившего GNUmakefile
Какие альтернативы Make существуют
Для Java есть Ant, Maven и Gradle.
Другие языки, такие как Go и Rust, имеют свои собственные инструменты сборки.
Цель Makefile состоит в том, чтобы скомпилировать любые файлы, которые должны быть скомпилированы, основываясь на том, какие файлы изменились.
Но когда файлы на интерпретируемых языках меняются, ничего не нужно перекомпилировать.
При запуске программы используется самая последняя версия файла.
Существует несколько общедоступных компиляторов C
В этой статье использовался gcc
-c это опция, которую разбирали здесь
whoami
В Make файле это может не получиться. Есть два варианта решить проблему
Инструментарий программиста в Linux: MAKE
Утилита make автоматически определяет, какие части программы должны быть перекомпилированы и вызывает команды для их перекомпиляции. Наиболее часто make используется для компиляции C-программ и содержит особенности, ориентированные именно на такие задачи, но можно использовать make с любым языком программирования. Более того, применение утилиты make не ограничивается программами. Можно использовать еe для автоматизации любой задачи, где некоторые файлы должны автоматически порождаться из других.
Makefile
Прежде чем использовать make, необходимо создать файл, называемый make-файлом, который описывает отношения зависимости между исходными и результирующими файлами и содержит команды для пересборки результирующих файлов. В C++ исполняемый файл зависит от объектных файлов, которые, в свою очередь, зависят от исходных файлов и файлов заголовков.
Для make-файлов зарезервированы имена GNUmakefile, makefile и Makefile, причем поиск идет в указанном порядке. Если необходимо использовать нестандартное имя, то его можно передать явно через опцию -f.
Когда make-файл уже написан, для сборки проекта достаточно выполнить в каталоге, где он находится, команду make.
Простой make-файл состоит из правил (инструкций) следующего вида:
Запуск make
Квадратные скобки означают необязательность присутствия данной части.
Более сложные способы применения MAKE
Правила написания Makefile
Автоматические переменные
В КОМАНДАХ можно использовать автоматические переменные. Эти переменные заново вычисляются для каждого выполняемого правила на основе цели и зависимостей правила.
Автоматическая переменная | Назначение |
$@ | Имя файла цели правила. В шаблонном правиле с несколькими целями,имя той цели, которая вызвала выполнение команд правила. |
$ make clean Для сокращения записи можно использовать переменные и действия по умолчанию (неявные правила) Переменная objects позволила использовать единожды написанный список объектных файлов, а для объектных файлов в make встроено неявное правило по умолчанию Специальная цель .PHONY является встроенной в make и определяет свои зависимости как цели-имена, которым нет соответствия в виде файлов. Если данное правило пропустить, то создание в текущем каталоге файла с именем clean заблокирует выполнение make clean. Использование правил по умолчанию позволяет изменить стиль записей зависимостей: Makefile для самых маленькихНе очень строгий перевод материала mrbook.org/tutorials/make Мне в свое время очень не хватило подобной методички для понимания базовых вещей о make. Думаю, будет хоть кому-нибудь интересно. Хотя эта технология и отмирает, но все равно используется в очень многих проектах. Статья будет интересная прежде всего изучающим программирование на C/C++ в UNIX-подобных системах от самых корней, без использования IDE. Компилировать проект ручками — занятие весьма утомительное, особенно когда исходных файлов становится больше одного, и для каждого из них надо каждый раз набивать команды компиляции и линковки. Но не все так плохо. Сейчас мы будем учиться создавать и использовать Мейкфайлы. Makefile — это набор инструкций для программы make, которая помогает собирать программный проект буквально в одно касание. Для практики понадобится создать микроскопический проект а-ля Hello World из четырех файлов в одном каталоге: Все скопом можно скачать отсюда Программа makeПроцесс сборкиКомпилятор берет файлы с исходным кодом и получает из них объектные файлы. Затем линковщик берет объектные файлы и получает из них исполняемый файл. Сборка = компиляция + линковка. Компиляция рукамиСамый простой МейкфайлВ нем должны быть такие части: Для нашего примера мейкфайл будет выглядеть так: Использование зависимостейИспользовать несколько целей в одном мейкфайле полезно для больших проектов. Это связано с тем, что при изменении одного файла не понадобится пересобирать весь проект, а можно будет обойтись пересборкой только измененной части. Пример: Это надо сохранить под именем Makefile-2 все в том же каталоге Использование переменных и комментариевПеременные широко используются в мейкфайлах. Например, это удобный способ учесть возможность того, что проект будут собирать другим компилятором или с другими опциями. Что делать дальшеПосле этого краткого инструктажа уже можно пробовать создавать простые мейкфайлы самостоятельно. Дальше надо читать серьезные учебники и руководства. Как финальный аккорд можно попробовать самостоятельно разобрать и осознать такой универсальный мейкфайл, который можно в два касания адаптировать под практически любой проект: Просто о makeМеня всегда привлекал минимализм. Идея о том, что одна вещь должна выполнять одну функцию, но при этом выполнять ее как можно лучше, вылилась в создание UNIX. И хотя UNIX давно уже нельзя назвать простой системой, да и минимализм в ней узреть не так то просто, ее можно считать наглядным примером количество- качественной трансформации множества простых и понятных вещей в одну весьма непростую и не прозрачную. В своем развитии make прошел примерно такой же путь: простота и ясность, с ростом масштабов, превратилась в жуткого монстра (вспомните свои ощущения, когда впервые открыли мэйкфайл). Мое упорное игнорирование make в течении долгого времени, было обусловлено удобством используемых IDE, и нежеланием разбираться в этом ‘пережитке прошлого’ (по сути — ленью). Однако, все эти надоедливые кнопочки, менюшки ит.п. атрибуты всевозможных студий, заставили меня искать альтернативу тому методу работы, который я практиковал до сих пор. Нет, я не стал гуру make, но полученных мною знаний вполне достаточно для моих небольших проектов. Данная статья предназначена для тех, кто так же как и я еще совсем недавно, желают вырваться из уютного оконного рабства в аскетичный, но свободный мир шелла. Make- основные сведенияmake — утилита предназначенная для автоматизации преобразования файлов из одной формы в другую. Правила преобразования задаются в скрипте с именем Makefile, который должен находиться в корне рабочей директории проекта. Сам скрипт состоит из набора правил, которые в свою очередь описываются: 1) целями (то, что данное правило делает); В общем виде синтаксис makefile можно представить так: То есть, правило make это ответы на три вопроса: Несложно заметить что процессы трансляции и компиляции очень красиво ложатся на эту схему: Простейший MakefileПредположим, у нас имеется программа, состоящая всего из одного файла: Для его компиляции достаточно очень простого мэйкфайла: Компиляция из множества исходниковПредположим, что у нас имеется программа, состоящая из 2 файлов: Makefile, выполняющий компиляцию этой программы может выглядеть так: Он вполне работоспособен, однако имеет один значительный недостаток: какой — раскроем далее. Инкрементная компиляцияПредставим, что наша программа состоит из десятка- другого исходных файлов. Мы вносим изменения в один из них, и хотим ее пересобрать. Использование подхода описанного в предыдущем примере приведет к тому, что все без исключения исходные файлы будут снова скомпилированы, что негативно скажется на времени перекомпиляции. Решение — разделить компиляцию на два этапа: этап трансляции и этап линковки. Теперь, после изменения одного из исходных файлов, достаточно произвести его трансляцию и линковку всех объектных файлов. При этом мы пропускаем этап трансляции не затронутых изменениями реквизитов, что сокращает время компиляции в целом. Такой подход называется инкрементной компиляцией. Для ее поддержки make сопоставляет время изменения целей и их реквизитов (используя данные файловой системы), благодаря чему самостоятельно решает какие правила следует выполнить, а какие можно просто проигнорировать: Попробуйте собрать этот проект. Для его сборки необходимо явно указать цель, т.е. дать команду make hello. После запуска make попытается сразу получить цель hello, но для ее создания необходимы файлы main.o и hello.o, которых пока еще нет. Поэтому выполнение правила будет отложено и make станет искать правила, описывающие получение недостающих реквизитов. Как только все реквизиты будут получены, make вернется к выполнению отложенной цели. Отсюда следует, что make выполняет правила рекурсивно. Фиктивные целиНа самом деле, в качестве make целей могут выступать не только реальные файлы. Все, кому приходилось собирать программы из исходных кодов должны быть знакомы с двумя стандартными в мире UNIX командами: Командой make производят компиляцию программы, командой make install — установку. Такой подход весьма удобен, поскольку все необходимое для сборки и развертывания приложения в целевой системе включено в один файл (забудем на время о скрипте configure). Обратите внимание на то, что в первом случае мы не указываем цель, а во втором целью является вовсе не создание файла install, а процесс установки приложения в систему. Проделывать такие фокусы нам позволяют так называемые фиктивные (phony) цели. Вот краткий список стандартных целей: Теперь мы можем собрать нашу программу, произвести ее инсталлцию/деинсталляцию, а так же очистить рабочий каталог, используя для этого стандартные make цели. Обратите внимание на то, что в цели all не указаны команды; все что ей нужно — получить реквизит hello. Зная о рекурсивной природе make, не сложно предположить как будет работать этот скрипт. Так же следует обратить особое внимание на то, что если файл hello уже имеется (остался после предыдущей компиляции) и его реквизиты не были изменены, то команда make ничего не станет пересобирать. Это классические грабли make. Так например, изменив заголовочный файл, случайно не включенный в список реквизитов, можно получить долгие часы головной боли. Поэтому, чтобы гарантированно полностью пересобрать проект, нужно предварительно очистить рабочий каталог: Для выполнения целей install/uninstall вам потребуются использовать sudo. ПеременныеВсе те, кто знакомы с правилом DRY (Don’t repeat yourself), наверняка уже заметили неладное, а именно — наш Makefile содержит большое число повторяющихся фрагментов, что может привести к путанице при последующих попытках его расширить или изменить. В императивных языках для этих целей у нас имеются переменные и константы; make тоже располагает подобными средствами. Переменные в make представляют собой именованные строки и определяются очень просто: Существует негласное правило, согласно которому следует именовать переменные в верхнем регистре, например: Ниже представлен мэйкфайл, использующий две переменные: TARGET — для определения имени целевой программы и PREFIX — для определения пути установки программы в систему. Это уже посимпатичней. Думаю, теперь вышеприведенный пример для вас в особых комментариях не нуждается. Автоматические переменныеАвтоматические переменные предназначены для упрощения мейкфайлов, но на мой взгляд негативно сказываются на их читабельности. Как бы то ни было, я приведу здесь несколько наиболее часто используемых переменных, а что с ними делать (и делать ли вообще) решать вам: Что такое Makefile и как начать его использоватьВведениеВ жизни многих разработчиков найдётся история про первый рабочий день с новым проектом. После клонирования основного репозитория проекта наступает этап, когда приходится вводить множество команд с определёнными флагами и в заданной последовательности. Без описания команд, в большинстве случаев, невозможно понять что происходит, например: Эти команды являются лишь частью того, что необходимо выполнить при разворачивании проекта. В приведённом примере видно, что команды сами по себе длинные, содержат много флагов, а значит, их трудно не только запомнить, но и вводить вручную. Постоянно вести документацию становится сложнее с ростом проекта, она неизбежно устаревает, а порог входа для новичков становится выше, ведь уже никто не в состоянии вспомнить всех деталей проекта. Некоторые такие команды необходимо использовать каждый день, и даже не один раз в день. Что такое make и MakefileMakefile — это файл, который хранится вместе с кодом в репозитории. Его обычно помещают в корень проекта. Он выступает и как документация, и как исполняемый код. Мейкфайл скрывает за собой детали реализации и раскладывает “по полочкам” команды, а утилита make запускает их из того мейкфайла, который находится в текущей директории. Изначально make предназначалась для автоматизации сборки исполняемых программ и библиотек из исходного кода. Она поставлялась по умолчанию в большинство *nix дистрибутивов, что и привело к её широкому распространению и повсеместному использованию. Позже оказалось что данный инструмент удобно использовать и при разработке любых других проектов, потому что процесс в большинстве своём сводится к тем же задачам — автоматизация и сборка приложений. Применение мейка в проектах стало стандартом для многих разработчиков, включая крупные проекты. Примеры мейкфайла можно найти у таких проектов, как Kubernetes, Babel, Ansible и, конечно же, повсеместно на Хекслете. Синтаксис Makefilemake запускает цели из Makefile, которые состоят из команд: Но недостаточно просто начать использовать мейкфайл в проекте. Чтобы получить эффект от его внедрения, понадобится поработать над разделением команд на цели, а целям дать семантически подходящие имена. Поначалу, перенос команд в Makefile может привести к свалке всех команд в одну цель с «размытым» названием: Здесь происходит сразу несколько действий: создание файла с переменными окружения, подготовка базы данных, генерация ключей, установка зависимостей и запуск проекта. Это невозможно понять из комментариев и названия цели, поэтому будет правильно разделить эти независимые команды на разные цели: Теперь развернуть и запустить проект достаточно двумя командами: Благодаря проделанной работе Makefile, команды проекта вместе с флагами сведены в Makefile. Он обеспечивает правильный порядок выполнения и не важно, какие при этом задействованы языки и технологии. Продвинутое использованиеФальшивая цельПоследовательный запуск команд и игнорирование ошибокСамый простой (но не единственный) способ «заглушить» ошибку — это сделать логическое ИЛИ прямо в мейкфайле: Добавлять такие хаки стоит с осторожностью, чтобы не «выстрелить себе в ногу» в более сложных случаях. ПеременныеЗачастую в команды подставляют параметры для конфигурации, указания путей, переменные окружения и make тоже позволяет этим управлять. Переменные можно прописать прямо в команде внутри мейкфайла и передавать их при вызове: Переменные могут быть необязательными и содержать значение по умолчанию. Обычно их объявляют в начале мейкфайла. ЗаключениеВозможность описывать в мейкфале последовательно многострочные команды позволяет использовать его как «универсальный клей» между менеджерами языков и другими утилитами. Широкая распространённость этого инструмента и общая простота позволяют внедрить его в свой проект достаточно легко, без необходимости доработок. Но мейкфайл может быть по-настоящему большим и сложным, это можно увидеть на примере реальных проектов: Дополнительные материалыМейкфайлы, использованные при составлении гайда: Не пропустите наши новые статьи: Подписаться авторизуйтесь 0 комментариев Старые |