Ожидаемая структура проекта/каталога для Automake?

Я разрабатываю статическую библиотеку C и использую простой Makefile. Теперь нам нужно поддерживать удаленные установки и все такое, и пришло время перейти к более надежному стандарту сборки. Я действительно хочу, чтобы это были автоинструменты — мне нравится автоматическое соответствие системе сборки GNU, и я также обнаружил, что с ней довольно легко работать.

Тем не менее, у меня есть проблема.

Вот грубый план того, как был структурирован проект:

project/
    common/
       pkg/
    inc/
    src/
       submodule1/
           some_thing/
           some_other_thing/
       submodule2/
        . . .

common содержит файлы заголовков, которые будут установлены в целевой системе — один заголовок непосредственно в файле common и некоторые другие файлы в файле common/pkg. (Ну, на самом деле это не pkg, это просто пример.) Все, что ниже common, равно .h.

inc содержит внутренние включаемые файлы, которые строго связаны с реализацией и не должны открываться. Все, что ниже inc, равно .h.

src имеет директорию для каждого из множества подмодулей, и каждый из подмодулей может быть разделен на части (или не разделен на части) (подподмодули, если хотите). Все, что ниже src, равно .c.

Исходный make-файл устанавливает переменную SOURCES, состоящую из каждого файла .c, рекурсивно найденного в src, добавляет -I./common -I./inc, создает объектные файлы и архивирует их в библиотеку. Довольно просто.

Что ж, с automake не все так просто. Я разобрался с добавлением флагов к цели сборки, например, `project_CPPFLAGS=-I./inc -I./common — это решает часть проблемы, но мне кажется, что я почему-то делаю что-то не так.

С этими (субоптимальными?) настройками я могу получить автоматическую сборку и компоновку библиотеки, что уже достаточно интересно, но настоящая причина, по которой я здесь, это make install.

Основная проблема заключается в следующем:

common содержит публичный интерфейс к библиотеке, если хотите. Он необходим для сборки исходников, но его также необходимо установить. Если я включу его из project/, то automake увидит такие пути, как common/thing.h и common/pkg/other.h, и при установке получит неверные пути в includedir. Я думал о том, чтобы он рекурсировал в этот каталог, чтобы построить проект, который имеет только установочные заголовки, но это не только плохо пахнет, но и не сработало, когда я пробовал. Заголовки библиотек нуждаются в определенной древовидной структуре -- как поддерживать древовидную структуру заголовков библиотеки, сделать их доступными для всех исходных файлов и установить их с корнем из common?

Кроме того, есть ли более элегантный способ обработки включений, чем форсирование -I? Я знаю, что мне нужно указать их как HEADERS, чтобы получить их в дистрибутивных пакетах, но на самом деле это не делает их доступными для включения, что оставляет меня немного потерянным.

Я чувствую, что automake (и, возможно, GNU в целом) ожидает какой-то структуры моего проекта, которую я просто не вижу. Если это так, скажите мне -- я готов потратить некоторое время на рефакторинг/реорганизацию проекта. Я действительно чувствую, что мне не хватает какой-то философии — текущая структура была разработана без руководства или опыта, и я никоим образом не привязан к ней.

Любая помощь приветствуется.


person shanef22    schedule 25.02.2012    source источник
comment
Не используйте автозапуск. Просто не надо. Все, что он делает, является обратным и противоречит передовой практике. Autoconf не так уж и плох, но нет причин использовать automake. Просто изучите make и напишите свой make-файл.   -  person R.. GitHub STOP HELPING ICE    schedule 25.02.2012
comment
Р., можно подробнее? Я очень опытный кодер (и хорошо знаком с make), но новичок в управлении развертыванием и сборкой; какие лучшие практики, по вашему мнению, он нарушает? Действительно ли лучше написать, например. устанавливать, удалять, распространять, очищать, очищать и т. д. вручную?   -  person shanef22    schedule 25.02.2012
comment
Make — очень простая, но мощная система разрешения зависимостей, а automake выбрасывает большую часть этой мощности и использует ее как тупую систему сценариев. Лучшее описание проблемы, которое я видел (не конкретно для automake, а для неправильного использования make в целом), — это «Рекурсивное создание считается вредным»: miller.emu.id.au/pmiller/books/rmch   -  person R.. GitHub STOP HELPING ICE    schedule 25.02.2012
comment
Те, кто не понимает automake, обречены отвергать его, а иногда и изобретать заново.. плохо.   -  person jørgensen    schedule 25.02.2012
comment
Автоинструменты пытаются инкапсулировать почти 20-летние несоответствия платформ, причуды и отсутствующие функции. Некрасивые проблемы иногда требуют некрасивых решений.   -  person Brett Hale    schedule 26.02.2012
comment
@R..: Modern automake поддерживает нерекурсивные make-файлы, JSYK. Добавьте subdir-objects к вызову AM_INIT_AUTOMAKE и добавьте AM_PROG_CC_C_O (при использовании C). Оба входят в configure.ac.   -  person Jack Kelly    schedule 04.03.2012
comment
@Brett: 20 лет назад это могло быть полезно, но в наши дни то, что они делают, гораздо больше вредит, чем помогает. Особенно gnulib, который хотя и не обязателен, но часто используется вместе с проектами automake. Идея переносимости gnulib состоит в том, чтобы иметь уродливые хаки, которые проникают во внутренности каждой известной реализации Unix 1980-х годов и современных внутренностей BSD и glibc, и прерывают сборку с помощью #error в любой другой системе.   -  person R.. GitHub STOP HELPING ICE    schedule 04.03.2012
comment
@Jack: Это хорошо, но причина, по которой я процитировал эту статью, заключалась не только в традиционном использовании рекурсивной make (или, что еще хуже, рекурсивной конфигурации) с automake, но и в том, что она очень хорошо объясняет, как make должен работать и как почти все, кто его использует, не могут воспользоваться его основной функцией и вместо этого используют его как тупой язык сценариев. Automake виновен в этом далеко за пределами рекурсивного вызова make.   -  person R.. GitHub STOP HELPING ICE    schedule 04.03.2012


Ответы (1)


Не вижу ничего плохого в использовании -I. Это даже позволяет последовательно использовать нотацию #include <pkg/foo.h> как в вашем дереве, так и в сторонних проектах, использующих pkg/foo.h.

AM_CPPFLAGS = -I${top_srcdir}/common -I${top_srcdir}/inc

Чтобы установить файлы в common, вы можете либо использовать SUBDIRS = common (начиная с верхнего уровня Makefile.am),

# <top>/common/Makefile.am
nobase_include_HEADERS = pkg/foo.h pkg2/bar.h

или, если вы решите использовать нерекурсивный подход, что-то вроде

# <top>/Makefile.am
xxxpkgdir = ${includedir}/pkg
xxxpkg_HEADERS = common/pkg/foo.h
xxxpkg2dir = ${includedir}/pkg2
xxxpkg2_HEADERS = common/pkg2/bar.h
person jørgensen    schedule 25.02.2012
comment
Ах! Я смотрел на кусок в руководстве по automake, объясняющий, как вы можете назвать новые каталоги для использования слева, и моя интуиция кричала на меня, но я не соединил это с разделением пути справа, пока вы так услужливо не продемонстрировали . Я пробовал рекурсивный SUBDIR, и у меня были проблемы с ним, но я только что настроил что-то вроде вашего последнего примера, и он отлично работает. Спасибо! - person shanef22; 26.02.2012