Makefiles, "configure" файлы и другие инструменты компиляции - как они работают? Почему они работают так, как работают?

Я все еще новичок в мире UNIX/Linux и, в частности, в связанных инструментах, таких как компилятор GCC. А именно, я все еще новичок в make-файлах и подобных вещах (я использую MinGW в Windows), поскольку до сих пор большая часть моей разработки была с IDE, такими как Visual Studio и Eclipse.

Когда я открываю типичную папку проекта, я вижу такие файлы:

configure
make
INSTALL
install-sh  (or a variant)

Здесь есть несколько вещей, которые я не понимаю, и мои основные вопросы таковы:

  1. В чем разница между ними, и зачем нам каждый? (В мире IDE все, что у вас есть, это файл проекта; вот и все. Поэтому я запутался, почему у нас здесь больше, чем просто make-файл.)

  2. Как создаются эти файлы? Для небольших проектов вы, вероятно, могли бы написать их вручную, но для больших проектов, таких как GCC, было бы даже смешно пытаться. Мне было трудно редактировать эти файлы, и я пришел к выводу, что я не должен изменять их вручную. Но если так, то какие инструменты люди обычно используют для добавления и изменения этих файлов?

  3. Почему они не используют подстановочные знаки внутри make-файла? Почему для каждого отдельного объектного файла существует одна строка? Это из-за ограничения или в этом есть преимущество?

  4. Какая разница между наличием сценария оболочки, который вызывает компилятор с каждым файлом, и наличием make-файла, который делает то же самое? В Windows мне очень хотелось бы просто создать командный файл внутри папки и скомпилировать все с этим - не нужно больше, чем один файл. Какая разница? Почему нет только одного .sh файл, чтобы скомпилировать все?

Бонусный вопрос:

  • Существует ли "стандартный" формат make-файла? Я видел разные make инструменты, которые не принимают форматы друг друга... как я знаю, что использовать? GCC - просто обычный инструмент здесь, или есть какой-то стандарт, которому все должны следовать?

У меня, вероятно, будет больше вопросов, когда я узнаю больше о структуре подобных проектов, но сейчас это мои самые большие вопросы.:)

3 ответа

Решение
  1. В вашем среднем пакете каждый из этих файлов имеет отдельную цель. Это соответствует философии 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 также имеет тенденцию быть немного уродливым. Это потому, что писать хорошо MakefileS часто много шаблонного, и это вдохновило другой инструмент, automake, automake компилирует Makefile.am (который часто короткий и декларативный) в Makefile.in (который огромен), который затем компилируется в Makefile от configure (По существу).

    install-sh это скрипт, который распространяется с automake но скопированы в другие пакеты. Он существует в качестве замены, если версия install по системе это хрень (install копирует файлы в каталог установки. У некоторых действительно старых систем были сломанные версии install, а также automake довольно консервативен в отношении удаления предупреждений для старых систем). Некоторые другие сценарии, которые выполняют аналогичные роли compile, depcomp а также ylwrap,

    INSTALL это просто документ, который описывает, как установить пакет. Обычно это стандартный контент, скопированный в пакет automake,

  2. Я ответил на этот пост выше, но вот резюме:

    • configure.ac ==[autoconf]=> configure
    • Makefile.am ==[automake]=> Makefile.in ==[configure]=> Makefile

    Где ответственная программа находится внутри стрелки. Чтобы понять это в деталях, я рекомендую этот учебник по autotools. Не стоит откладывать подсчет страниц, большинство из них - диаграммы, появляющиеся по частям.

  3. Подстановочные знаки в Makefileы иногда используются. GNU Make, например, поддерживает $(wildcard) функция, где вы можете написать что-то вроде:

    SOURCES := $(wildcard src/*.c)

    Основные причины, такие как $(wildcard) не используются в том, что они являются расширениями, и automake очень старается генерировать Makefiles, которые будут работать с любым POSIX-совместимым make, После того, как проект становится зрелым, список файлов для компиляции все равно не сильно меняется.

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

  4. 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, в которых использовалось как можно меньше функций. Сегодня все немного лучше, но проблемы с переносимостью по-прежнему определяют то, что вы видите.

  1. configure это скрипт, который устанавливает среду сборки и, возможно, генерирует make-файл. С make Вы строите проект, с make install или же install.sh или аналогично, вы устанавливаете скомпилированные файлы. Если вы хотите проверить что-то локально, вы можете пропустить финальную часть, и она будет отдельной.
  2. Вы можете использовать GNU autotools.
  3. Можете ли вы привести конкретные примеры? Makefiles поддерживают шаблоны, и они время от времени используются.
  4. Makefile обрабатывает зависимости и автоматическую перекомпиляцию только необходимых файлов, если вы что-то изменили в исходном файле, а затем решили пересобрать проект. С пакетным файлом вы будете перекомпилировать все, с Makefiles вы только компилируете то, что было изменено.
Другие вопросы по тегам