Makefiles, "configure" файлы и другие инструменты компиляции - как они работают? Почему они работают так, как работают?
Я все еще новичок в мире UNIX/Linux и, в частности, в связанных инструментах, таких как компилятор GCC. А именно, я все еще новичок в make-файлах и подобных вещах (я использую MinGW в Windows), поскольку до сих пор большая часть моей разработки была с IDE, такими как Visual Studio и Eclipse.
Когда я открываю типичную папку проекта, я вижу такие файлы:
configure
make
INSTALL
install-sh (or a variant)
Здесь есть несколько вещей, которые я не понимаю, и мои основные вопросы таковы:
В чем разница между ними, и зачем нам каждый? (В мире IDE все, что у вас есть, это файл проекта; вот и все. Поэтому я запутался, почему у нас здесь больше, чем просто make-файл.)
Как создаются эти файлы? Для небольших проектов вы, вероятно, могли бы написать их вручную, но для больших проектов, таких как GCC, было бы даже смешно пытаться. Мне было трудно редактировать эти файлы, и я пришел к выводу, что я не должен изменять их вручную. Но если так, то какие инструменты люди обычно используют для добавления и изменения этих файлов?
Почему они не используют подстановочные знаки внутри make-файла? Почему для каждого отдельного объектного файла существует одна строка? Это из-за ограничения или в этом есть преимущество?
Какая разница между наличием сценария оболочки, который вызывает компилятор с каждым файлом, и наличием make-файла, который делает то же самое? В Windows мне очень хотелось бы просто создать командный файл внутри папки и скомпилировать все с этим - не нужно больше, чем один файл. Какая разница? Почему нет только одного
.sh
файл, чтобы скомпилировать все?
Бонусный вопрос:
- Существует ли "стандартный" формат make-файла? Я видел разные
make
инструменты, которые не принимают форматы друг друга... как я знаю, что использовать? GCC - просто обычный инструмент здесь, или есть какой-то стандарт, которому все должны следовать?
У меня, вероятно, будет больше вопросов, когда я узнаю больше о структуре подобных проектов, но сейчас это мои самые большие вопросы.:)
3 ответа
В вашем среднем пакете каждый из этих файлов имеет отдельную цель. Это соответствует философии Unix "каждая программа должна делать что-то одно и делать это хорошо". В большинстве проектов вы увидите такие файлы:
configure
configure.ac
Makefile
Makefile.in
Makefile.am
install-sh
INSTALL
configure
(обычно) сценарий оболочки, который проверяет вашу систему на наличие всех необходимых функций, прежде чем что-либо создавать.Makefile.in
это шаблон дляMakefile
, Результаты тестов конфигурации подставляются вMakefile.in
чтобы генерироватьMakefile
, Это относится к людям, имеющим вещи (компиляторы, заголовки, библиотеки) по непонятным путям, кросс-компиляцию (например, сборку для ARM на x86), дополнительную поддержку библиотек (некоторые программы имеют дополнительные функции, которые можно включать или выключать), компиляция с разными опциями и тд. Написание одного размера подходит всемMakefile
на самом деле очень сложно.Как вы заметили,
configure
Сам сценарий - беспорядок. Это не предназначено для того, чтобы быть увиденным смертными глазами, и не отредактировано смертными руками. Это на самом деле результат компиляцииconfigure.ac
, используя программу под названиемautoconf
,autoconf
это пакет макросов для и обертка вокругm4
макропроцессор, который был в то время единственным хорошим инструментом для такого рода вещей (autoconf
это действительно довольно старое программное обеспечение, но постарело на удивление хорошо).autoconf
позволяет разработчику легко писать тесты для проверки заголовков, библиотек или программ, необходимых для сборки программного обеспечения (и это меняется от программы к программе).Если вы будете копать немного глубже, вы заметите, что
Makefile.in
также имеет тенденцию быть немного уродливым. Это потому, что писать хорошоMakefile
S часто много шаблонного, и это вдохновило другой инструмент,automake
,automake
компилируетMakefile.am
(который часто короткий и декларативный) вMakefile.in
(который огромен), который затем компилируется вMakefile
отconfigure
(По существу).install-sh
это скрипт, который распространяется сautomake
но скопированы в другие пакеты. Он существует в качестве замены, если версияinstall
по системе это хрень (install
копирует файлы в каталог установки. У некоторых действительно старых систем были сломанные версииinstall
, а такжеautomake
довольно консервативен в отношении удаления предупреждений для старых систем). Некоторые другие сценарии, которые выполняют аналогичные ролиcompile
,depcomp
а такжеylwrap
,INSTALL
это просто документ, который описывает, как установить пакет. Обычно это стандартный контент, скопированный в пакетautomake
,Я ответил на этот пост выше, но вот резюме:
configure.ac ==[autoconf]=> configure
Makefile.am ==[automake]=> Makefile.in ==[configure]=> Makefile
Где ответственная программа находится внутри стрелки. Чтобы понять это в деталях, я рекомендую этот учебник по autotools. Не стоит откладывать подсчет страниц, большинство из них - диаграммы, появляющиеся по частям.
Подстановочные знаки в
Makefile
ы иногда используются. GNU Make, например, поддерживает$(wildcard)
функция, где вы можете написать что-то вроде:SOURCES := $(wildcard src/*.c)
Основные причины, такие как
$(wildcard)
не используются в том, что они являются расширениями, иautomake
очень старается генерироватьMakefile
s, которые будут работать с любым POSIX-совместимымmake
, После того, как проект становится зрелым, список файлов для компиляции все равно не сильно меняется.Вторая причина, по которой файлы перечислены явно, - это когда программы получают дополнительные функции. Подстановочные знаки больше не подходят, и вместо этого вам нужно перечислить условия, при которых должны компилироваться дополнительные функции.
Makefile
отслеживает зависимости между файлами, где сценарий оболочки не может (во всяком случае, не без значительных усилий).
Если у тебя есть Makefile
Правило как:
foo.out: foo.in
generate-foo foo.in
Оно говорит make
что если foo.in
новее чем foo.out
новый foo.out
может быть создан путем выполнения generate-foo foo.in
, Это экономит много лишней работы над большими проектами, где вы можете изменить только один или два файла между перекомпиляциями.
Ваш бонусный вопрос выглядит немного некорректным. Самый распространенный make
это, вероятно, GNU Make, хотя я бы предположил, что BSD make будет близка секунда, за которой следуют различные проприетарные make
версии, поставляемые с Solaris, AIX и т. д.
Все они принимают одну и ту же базовую структуру в Makefile
(потому что POSIX так говорит), но может иметь специфичные для поставщика расширения синтаксиса.
GCC не похож на инструмент сборки make
, GCC - это компилятор командной строки, родственный cl.exe
на окнах.
Есть много причин для разных вещей, но в итоге все сводится к переносимости. Во время Unix-войн все платформы были разными, и люди пытались создавать программное обеспечение, которое могло бы работать на максимально возможном количестве. Так что общие знаменатели должны были быть найдены. sh был одной из таких общностей, поэтому скрипты configure были написаны так, чтобы использовать максимально переносимый sh. Максимальная переносимость подразумевает использование минимального набора функций. Различные реализации make сильно различаются по функциям, которые они поддерживают, поэтому были написаны файлы Makefile, в которых использовалось как можно меньше функций. Сегодня все немного лучше, но проблемы с переносимостью по-прежнему определяют то, что вы видите.
configure
это скрипт, который устанавливает среду сборки и, возможно, генерирует make-файл. Сmake
Вы строите проект, сmake install
или жеinstall.sh
или аналогично, вы устанавливаете скомпилированные файлы. Если вы хотите проверить что-то локально, вы можете пропустить финальную часть, и она будет отдельной.- Вы можете использовать GNU autotools.
- Можете ли вы привести конкретные примеры? Makefiles поддерживают шаблоны, и они время от времени используются.
- Makefile обрабатывает зависимости и автоматическую перекомпиляцию только необходимых файлов, если вы что-то изменили в исходном файле, а затем решили пересобрать проект. С пакетным файлом вы будете перекомпилировать все, с Makefiles вы только компилируете то, что было изменено.