autoconf: лучший способ включения libftdi в configure.ac - PullRequest
1 голос
/ 30 мая 2020

Привет всем, кто использует GNU autoconf,

Как лучше всего искать libftdi и включать его в autoconf для компиляции программы C с его использованием?
Следующие фрагмент из файла configure.ac работает, но я не уверен, лучше ли это:

PKG_CHECK_MODULES([LIBFTDI], [libftdi])
#AC_CHECK_LIB([ftdi],[ftdi],[ftdi])  # Why doesn't this work?
#AC_SEARCH_LIBS([ftdi],[ftdi],[ftdi])  # Why doesn't this work?
#AC_CHECK_HEADERS([ftdi.h],[],[echo "error: missing libftdi header files" && exit 1])
LIBS="-lftdi $LIBS $LDFLAGS" # works, but is this the best way?

Я создаю программу с autoconf (GNU Autoconf) 2.69 и компилирую ее с gcc version 7.5.0 на Ubuntu 18.04.

Ответы [ 3 ]

1 голос
/ 30 мая 2020

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

Библиотечные тесты

Ваши закомментированные примеры AC_CHECK_LIB и AC_SEARCH_LIBS не демонстрируют правильного использования. Детали использования представлены в руководстве , но в итоге:

  • аргументы для AC_CHECK_LIB:

    1. Простое имя библиотеки, ie ftdi
    2. Имя характеристики c функция , предоставляемая библиотекой
    3. (необязательно) Код для configure, который будет выполняться в случае обнаружения библиотеки. По умолчанию к $LIBS добавляется параметр ссылки и определяется макрос препроцессора HAVE_LIB*.
    4. (необязательно) Код для configure, выполняемый в случае, если библиотека не найдена
    5. (необязательно) Дополнительные параметры ссылки на библиотеку (их нет в $LIBS), необходимые для компоновки программы, использующей проверяемую библиотеку.
  • аргументы AC_SEARCH_LIBS

    1. Имя функции для поиска
    2. Список из одного или нескольких имен библиотек для поиска
    3. (необязательно) Код для configure, выполняемый в случае обнаружения библиотеки, в дополнение к , добавление опции ссылки к $LIBS (но без определения макроса препроцессора)
    4. (необязательно) Код для configure, выполняемый в случае, если библиотека не найдена.
    5. (необязательно) Дополнительные параметры ссылки на библиотеку (которых еще нет в $LIBS, которые необходимы для компоновки программы, использующей проверяемая библиотека

Neit ни ваш пример AC_CHECK_LIB, ни ваш пример AC_SEARCH_LIBS правильно обозначают существующую функцию libftdi для проверки. Более того, третий аргумент в каждом случае вряд ли будет действительным кодом оболочки / Autoconf, поэтому в случае, если библиотека была найдена, configure, вероятно, взломал бы sh. Лучше может быть:

AC_CHECK_LIB([ftdi], [ftdi_init])

или

AC_SEARCH_LIBS([ftdi_init], [ftdi])

В зависимости от того, что именно вы хотите сделать, от деталей libftdi и от контекста configure.ac вам может потребоваться предоставить соответствующие значения для некоторых или всех необязательных аргументов.

Основными причинами сбоя проверки библиотеки, несмотря на то, что библиотека фактически установлена, являются:

  • библиотека, устанавливаемая в определенном месте который не находится в пути поиска по умолчанию
  • библиотека, имеющая зависимости ссылок на другие библиотеки, и которые (еще) не были учтены во время проверки

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

Обратите внимание, что libftdi предоставляет оба C и интерфейсы C ++. В ftdi_init я тщательно выбирал функцию с привязкой C, чтобы избежать проблем с изменением имен C ++ (см. Как проверить удобство использования библиотеки C ++ в configure.in?) . Вам также может потребоваться убедиться, что тесты выполняются с компилятором C (см. Выбор языка в руководстве Autoconf).

Тест заголовка

Ваш AC_CHECK_HEADERS использование, с другой стороны, не кажется неправильным по своей сути. Если результирующий сценарий configure не обнаруживает ftdi.h, это означает, что заголовок отсутствует в пути поиска заголовка по умолчанию компилятора. Это может произойти, например, если он установлен в подкаталоге, таком как /usr/include/ftdi. Это будет зависеть от соглашения об установке как ftdi, так и системы.

Если это соглашение ftdi для заголовков, устанавливаемых в подкаталог, тогда ваши исходные файлы должны указать это в своих #include директивы:

#include <ftdi/ftdi.h>

Если ваши исходные файлы действительно делают это, то это также должно быть то, что вы укажете Autoconf, чтобы искать:

AC_CHECK_HEADERS([ftdi/ftdi.h])

Независимо от того, ожидается ли префикс подкаталога или используется , рекомендуется учитывать возможность установки заголовков и / или библиотек в нестандартном месте. Хотя это всегда можно сделать, указав соответствующие флаги в переменной CPPFLAGS в среде configure, я предпочитаю и рекомендую использовать AC_ARG_WITH для обозначения аргумента --with или AC_ARG_VAR для обозначения переменной среды, которая configure проконсультируется по этому поводу. Например,

AC_ARG_WITH([ftdi-includedir],
  [AS_HELP_STRING([--with-ftdiincludedir=dir],
    [specifies a custom directory for the libftdi header files])],
  [CPPFLAGS="$CPPFLAGS -I$withval"]
)

Отображение аргумента или переменной среды для конкретной c цели подчеркивает (в выводе ./configure --help) тот факт, что это ручка, которую пользователю может потребоваться настроить. Кроме того, получение каталога include через целевой вектор иногда полезно для ограничения того, в каких компиляциях становится доступным указанный каталог include.

On PKG_CHECK_MODULES

Цель и философия Autotools для поддержки максимально широкого набора машин и сред для сборки за счет минимизации внешних зависимостей и написания максимально переносимой конфигурации и кода сборки. С этой целью Autotools спроектированы таким образом, что сами по себе не требуются для создания проектов в поддерживаемых системах. Напротив, Autoconf создает configure как автономный, очень переносимый сценарий оболочки, а Automake создает настраиваемые шаблоны для очень переносимых make-файлов. Они предназначены для включения в пакеты с исходным кодом для использования в каждой системе сборки «как есть». Зависимость сценария configure от установки pkg-config в каждой системе, в которой должен быть построен ваш проект, как и при использовании PKG_CHECK_MODULES, противоречит этим целям.

Насколько серьезной может быть проблема. предмет некоторого спора. Там, где это доступно, pkg-config может быть очень полезным, особенно для компонентов, требующих сложных флагов сборки. Таким образом, PKG_CHECK_MODULES очень удобен как для сопровождающего, так и для сборщика пакетов в тех системах, где он присутствует или легко доступен , для тех компонентов, которые предоставляют метаданные pkg-config.

Но pkg-config не обязательно доступен для каждой системы, на которую настроено ваше программное обеспечение. Его нельзя разумно считать присутствующим или доступным даже в тех системах, для которых он номинально доступен. И даже в системах, в которых он есть, метаданные pkg-config для интересующих библиотек не обязательно устанавливаются вместе с библиотеками.

Таким образом, я призываю вас избегать использования PKG_CHECK_MODULES в ваших проектах Autoconf. В любом случае вам нужно знать, как обойтись без него, потому что это не вариант для некоторых библиотек. Где возможно, предоставьте перехватчики, с помощью которых конструктор может предоставить соответствующие флаги, и позвольте им выбрать, использовать ли pkg-config вместе с ними. Разделение configure от pkg-config таким образом делает немного больше работы для вас, а в некоторых случаях и для строителей, но это более гибко.

Ваш PKG_CHECK_MODULES пример

Ваш пример вызова выглядит нормально сам по себе, предполагая, что "libftdi" - это соответствующее имя модуля pkg-config (вы должны знать соответствующее имя):

PKG_CHECK_MODULES([LIBFTDI], [libftdi])

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

  • не проверяет наличие и не тестирует использование библиотеки или заголовка
  • , хотя устанавливает некоторые выходные переменные, содержащие флаги компиляции и ссылки, вы, похоже, не используете эти
    • конкретно, если вы собираетесь полагаться на pkg-config, тогда вам следует использовать флаги ссылок, которые он сообщает вам вместо жесткого кодирования -lftdi, и только этого.

Более того, более типично использовать выходные переменные, созданные PKG_CHECK_MODULES в вашем make-файле, чем использовать их для update $LIBS или другие общие переменные внутри configure. Однако, если вы используете их в configure, то важно понимать, что LIBS и LDFLAGS имеют разные роли с небольшим перекрытием. Как правило, неуместно, не говоря уже о ненужности, включать LDFLAGS в LIBS. Если вы хотите обновить LIBS внутри configure, то это будет способ сделать это:

LIBS="$LIBFTDI_LIBS $LIBS"

И если вы собираетесь это сделать, то вам, вероятно, следует сделать то же самое с флаги компилятора, сообщаемые pkg-config, если есть:

CFLAGS="$CFLAGS $LIBFTDI_CFLAGS"
1 голос
/ 30 мая 2020

Вы можете проверить это так:

AC_CHECK_LIB([ftdi],[ftdi_init],[],[echo "error: missing libftdi library" && exit 1],[])
    LDFLAGS="-lftdi $LDFLAGS"

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

0 голосов
/ 30 мая 2020

Если libftdi использует pkg-config (и похоже, что, учитывая, что вы сказали, что фрагмент работает), PKG_CHECK_MODULES - это то, что вы хотите. По умолчанию для action-if-not-found выводится ошибка, поэтому, если это обязательная зависимость, это именно то, что вам нужно.

Но вы не должны использовать LIBS таким образом. Во-первых, потому что LDFLAGS не имеет той же семантики, что LIBS, во-вторых, потому что файл pkg-config мог предоставить вам дополнительные пути поиска, которые требуются.

Вместо этого вы должны добавить в свой Makefile.am флаги по мере необходимости:

mytarget_CFLAGS = $(LIBFTDI_CFLAGS)
mytarget_LDADD = $(LIBFTDI_LIBS)

Вы можете обратиться к моему Mythbuster Autotools - Dependency Discovery для получения дополнительных сведений о том, как использовать pkg-config для зависимостей. Здесь вы можете увидеть, как вы обычно используете AC_CHECK_LIB или AC_SEARCH_LIB, но если серьезно, если pkg-config работает, придерживайтесь этого, так как он более надежен и согласован.

...