autoconf / automake: условная компиляция, основанная на наличии библиотеки? - PullRequest
13 голосов
/ 03 марта 2011

Мне нужно условно скомпилировать некоторый код, основываясь на наличии библиотеки. Похоже, это должно быть легко с autoconf / automake, но я не могу понять это.

Например, если есть библиотека PNG, я хочу включить код для ее использования. Мой файл configure.ac содержит:

AC_CHECK_LIB([png], [png_create_write_struct_2])

и мой Makefile.am имеет:

if USE_LIBPNG
libdev_la_SOURCES += png.c
endif

(который добавляет png.c в список источников для libdev, чтобы он компилировался).

Условный автомат, такой как USE_LIBPNG, требует, чтобы условное условие было определено в configure.ac, поэтому мне нужно:

AM_CONDITIONAL([USE_LIBPNG], [test SOMETHINGOROTHER])

Вопрос в том, что может быть ЧТО-ТО еще? Что определяет AC_CHECK_LIB, что я могу проверить?

По умолчанию AC_CHECK_LIB определяет символ (в config.h), который можно использовать в исходном коде, но это не помогает Makefile, поскольку AM_CONDITIONAL требуется тест оболочки

Я попытался переопределить поведение AC_CHECK_LIB по умолчанию следующим образом:

AC_CHECK_LIB([png], [png_create_write_struct_2], [HAS_LIBPNG=1])

после чего я могу проверить это:

AM_CONDITIONAL([USE_LIBPNG], [test "x$HAS_LIBPNG" = "x1"])

Это некрасиво, но работает для Makefile ... но создает новую проблему: поскольку он отбрасывает исходное поведение AC_CHECK_LIB, и я больше не получаю добавленный символ в config.h, который мне нужен.

Я, должно быть, упускаю что-то простое или, возможно, делаю неправильно. Копались в течение нескольких часов и не нашли ответа.

Любой

Ответы [ 3 ]

25 голосов
/ 03 марта 2011

Если библиотека, которую вы проверяете, предоставляет файл .pc для использования с pkg-config, тогда вам гораздо лучше использовать PKG_CHECK_MODULES для получения правильных флагов.libpng делает:

configure.ac)

PKG_CHECK_MODULES([libpng], [libpng12])

Это дает вам доступ к переменным $(libpng_CFLAGS) и $(libpng_LIBS), которые вы хотите добавить к Makefile.am (возможно,в AM_CFLAGS / AM_CXXFLAGS и LDADD, или их конкретных версиях).

Это также приведет к сбою configure с ошибкой, если libpng12.pc не найдено.Если вы хотите, чтобы configure продолжался, вам нужно будет указать третий и четвертый аргументы для PKG_CHECK_MODULES, которые ACTION-IF-FOUND и ACTION-IF-NOT-FOUND:

configure.ac)

PKG_CHECK_MODULES([libpng], [libpng12], [HAVE_LIBPNG=1], [HAVE_LIBPNG=0])

Теперь, если вам нужно условное automake, вы можете сделать что-то вроде:

configure.ac)

AM_CONDITIONAL([USE_LIBPNG], [test "$HAVE_LIBPNG" -eq 1])

Если вам также нужен препроцессоропределение, вы можете использовать AC_DEFINE, например, так:

configure.ac)

AS_IF([test "$USE_LIBPNG" -eq 1], [AC_DEFINE([USE_LIBPNG], [1], [Define if using libpng.])])

Возможно, лучше задать определение в Makefile.am:

Makefile.am)

AM_CPPFLAGS =
if USE_LIBPNG
AM_CPPFLAGS += -DUSE_LIBPNG
endif

Это загромождает вашу командную строку, тогда как AC_DEFINE может поместить определение в заголовок, если вы используете AC_CONFIG_HEADERS.Я думаю, это не имеет значения, если вы используете AM_SILENT_RULES([yes]) или вам не важно, чтобы ваша командная строка была аккуратной (и давайте будем честными, automake в любом случае генерирует довольно грубые командные строки).

Aпримечание о хорошем autoconf стиле

Считается плохой формой для создания дополнительной поддержки в зависимости от того, была ли успешной проверка (подробности см. в этом документе Gentoo ).Вот как я могу написать дополнительную поддержку libpng:

configure.ac)

# This is because the first PKG_CHECK_MODULES call is inside a conditional.
PKG_PROG_PKG_CONFIG

AC_ARG_WITH([libpng],
  [AS_HELP_STRING([--with-libpng],
    [support handling png files @<:@default=check@:>@])],
  [],
  [with_libpng=check])
AS_CASE(["$with_libpng"],
  [yes], [PKG_CHECK_MODULES([libpng], [libpng12], [HAVE_LIBPNG=1])],
  [no], [],
  [PKG_CHECK_MODULES([libpng], [libpng12], [HAVE_LIBPNG=1], [HAVE_LIBPNG=0])])
AM_CONDITIONAL([USE_LIBPNG], [test "$with_libpng" != no -a "$HAVE_LIBPNG" -eq 1])

Makefile.am)

if USE_LIBPNG
AM_CPPFLAGS += -DUSE_LIBPNG
AM_CFLAGS += $(libpng_CFLAGS)
LDADD += $(libpng_LIBS)
libdev_la_SOURCES += png.c
endif

Если ваша библиотекане имеет .pc файла

Для полноты, вот как я могу проверить библиотеку, в которой нет файла .pc.Я пропущу детали следующего хорошего стиля autoconf.AC_CHECK_LIB устанавливает переменную кэша, поэтому вы можете проверить, что вместо замены ACTION-IF-FOUND из AC_CHECK_LIB:

configure.ac)

AC_CHECK_LIB([png], [png_create_write_struct_2])

# Then test:
AS_IF([test "$ac_cv_lib_png_png_create_write_struct_2" = yes], [HAVE_LIBPNG=1], [HAVE_LIBPNG=0])

# Or set conditional:
AM_CONDITIONAL([USE_LIBPNG], [test "$ac_cv_lib_png_png_create_write_struct_2" = yes])

ИМХО, вам следуетделайте это только так, если у вас нет другого выбора.

1 голос
/ 03 марта 2011

Спасибо за ответы.

Джек: я пытаюсь добиться максимальной переносимости, поэтому не могу предположить, что библиотеки были установлены как часть пакета (они не находятся в моей собственной коробке!),это означает, что вы предложили решение «без других опций» - это то, что я уже пробовал - установка переменной оболочки вручную - но также вручную выполняет дополнительные шаги, которые были бы выполнены AC_CHECK_LIB: добавление библиотеки в LIBS и определение HAVE_LIBxxx.

Была одна загвоздка: autoheader жалуется на голое AC_DEFINE:

autoheader: warning: missing template: HAVE_LIBPNG
autoheader: Use AC_DEFINE([HAVE_LIBPNG], [], [Description])

Было бы неплохо, если бы autoheader работал в будущем, поэтому мне пришлось изменить AC_DEFINE на полную стоимость:

AC_CHECK_LIB([png], [png_create_write_struct_2],
    [HAS_LIBPNG=1
     LIBS="-lpng $LIBS"
     AC_DEFINE([HAVE_LIBPNG], 1, [Define to 1 if you have the `png' library (-lpng)])])

Это работает, но мне не очень нравится дублировать поведение AC_CHECK_LIB по умолчанию.

Уильям: Да, я могу найти определение символа в confdefs.h, чтотакже работает.

Оба решения имеют свои плюсы и минусы (что нет?).Не уверен, в какую сторону я пойду, но приятно иметь варианты.

Еще раз спасибо.

1 голос
/ 03 марта 2011

Я не соглашусь с Джеком по поводу его рекомендации использовать PKG_CHECK_MODULES.Вероятно, лучше избегать этого.Но я согласен с Джеком в том, чтобы избегать назначения LIBS в третьем аргументе AC_CHECK_LIB.Жизнь станет проще, если вы позволите AC_CHECK_LIB использовать настройки по умолчанию.

Хотя AC_CHECK_LIB не определяет переменную оболочки, указывающую, была ли найдена библиотека, вы можете сделать это в configure.ac:

AM_CONDITIONAL([USE_LIBPNG],[grep HAVE_LIBPNG confdefs.h > /dev/null])

Возможно, это зависит от внутренних деталей autoconf, но на практике будет работать надежно.

...