Как проверить удобство использования библиотеки C++ в configure.in?

Я работаю над проектом C++ в GNU/Linux и ищу способ проверить существование и удобство использования библиотеки IBM Informix с помощью Autotools, а именно, отредактировав файл configure.in. У меня нет опыта работы с Autotools, поэтому в основном я беру из проекта configure.in et al. сценарии и копирую и изменяю то, что, по моему мнению, нужно изменить. IOW, я адаптировал существующий текст в configure.in.

До сих пор я успешно использовал AC_CHECK_LIB в configure.in, чтобы проверить, существует ли определенная библиотека и можно ли ее использовать. Но это работает только с библиотеками с функциями, а не, например. классы. А именно, это не удается при тестировании библиотеки Informix libifc++.so:

AC_CHECK_LIB(ifc++, ITString, 
        INFORMIX_LIB="-L$INFORMIX_LIB_LOCATION/c++ -lifc++ -L$INFORMIX_LIB_LOCATION -L$INFORMIX_LIB_LOCATION/dmi -L$INFORMIX_LIB_LOCATION/esql -lifdmi -lifsql -lifasf -lifgen -lifos -lifgls -lifglx $INFORMIX_LIB_LOCATION/esql/checkapi.o -lm -ldl -lcrypt -lnsl",
        echo "* WARNING: libifc++.so not found!"
        INFORMIX_INC=""
        INFORMIX_LIB=""
)

Я также пробовал использовать другие комбинации, например ITString::ITString и т. д.

Я не нашел "чистой" функции в API Informix (т. е. такой, которая не связана с контекстом в классе C++). Поэтому я надеюсь, что либо есть способ использовать AC_CHECK_LIB в этом контексте, либо есть другая "команда" autoconf/configure.in для этого конкретного использования.

Заранее благодарим за отзыв.


person jbatista    schedule 20.06.2009    source источник


Ответы (4)


Может быть более чистый способ добиться этого, но я думаю, что ваша проблема заключается в том, что методы С++ «искажаются», чтобы можно было закодировать дополнительную информацию о методе (типы аргументов и возвращаемых значений и т. д.). Например; метод int A::foo(void) превратится во что-то вроде __ZN1A3fooEv.

Итак, вам нужно найти искаженное имя метода в библиотеке. Это можно сделать с помощью nmкоманды в Unix-подобных ОС:

$ nm libifc++.so | grep ITString

Стоит отметить, что точный формат искажения зависит от разных компиляторов; и поэтому, встраивая определенный искаженный символ компилятора в ваш configure.in, он может не работать на других платформах - YMMV.

Примечание: вы можете использовать c++filt утилита для преобразования имени в удобочитаемую форму; поэтому для примера, который я привел ранее:

$ c++filt __ZN1A3fooEv
A::foo()

Дополнительную информацию см. в разделе Изменение имен в C++ в Википедии.

person DaveR    schedule 20.06.2009
comment
Работает на меня. Я думал о том, чтобы сделать что-то подобное, но это было похоже на взлом. Например, я не уверен, что произойдет, если код будет перекомпилирован с другой версией библиотеки Informix (я ожидаю, что искаженное имя изменится). Но эй, это работает! :-) - person jbatista; 20.06.2009
comment
Это должно продолжать работать с новой версией библиотеки (при условии, что имена классов и методов не меняются), но может сломаться, если изменится версия вашего компилятора, и почти наверняка сломается, если кто-то другой попытается скомпилировать ваш код на другом компиляторе или версии компилятора. . - person Tyler McHenry; 20.06.2009
comment
Слишком многословно, серьезно, поищите мой ответ внизу. - person rishta; 30.09.2013

Вы обнаружили недостаток автоинструментов, но с этим ничего не поделаешь. Autotools проверяет имена символов в двоичном файле библиотеки, и в отличие от C, где имена символов функций идентичны именам функций, C++ «искажает» имена символов функций для выполнения таких задач, как перегрузка функций. Что еще хуже, так это то, что C++ на самом деле даже не имеет «стандартного» соглашения об изменении, поэтому разные компиляторы C++ могут создавать разные имена символов для одной и той же функции. Таким образом, автоинструменты не могут надежно проверять имена символов C++.

Есть ли в библиотеке, которую вы пытаетесь использовать, какие-либо функции, объявленные с помощью extern "C"? Это заставляет компилятор C++ генерировать стандартизированные имена символов в стиле C, и автоинструменты смогут их найти.

Я столкнулся с этой проблемой, пытаясь обнаружить gtest и gmock (фреймворки Google для модульного тестирования и имитации объектов) с Autotools, и вот что у меня получилось:

# gtest has a main function in the gtest_main library with C linkage, we can test for that.
AC_CHECK_LIB([gtest_main], [main], [HAVE_GTEST=1] [TEST_LIBS="$TEST_LIBS -lgtest_main"], 
      AC_MSG_WARN([libgtest (Google C++ Unit Testing Framework) is not installed. Will not be able to make check.])) 

# gmock has no functions with C linkage, so this is a roundabout way of testing for it. We create a small test
# program that tries to instantiate one of gmock's objects, and try to link it with -lgmock and see if it works.
if test "$HAVE_GTEST"                                                                 
then                                                                                  
  saved_ldflags="${LDFLAGS}"                                                          
  LDFLAGS="${LDFLAGS} -lgtest -lgmock"                                                
  AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <gmock/gmock.h>], [testing::Cardinality dummy])],
    [TEST_LIBS="$TEST_LIBS -lgmock"] [HAVE_GMOCK=1],                                           
    [AC_MSG_WARN([libgmock (Google C++ Object Mocking Framework) is not installed. Will not be able to make check.])])
  LDFLAGS="${saved_ldflags}"                                                                                          
fi          
person Tyler McHenry    schedule 20.06.2009

Если библиотека, которую вы проверяете, поддерживает pkg-config, сделать это очень просто. Вот все, что я добавил в свой configure.in, чтобы проверить и включить gtest и gmock:

dnl ************************************
dnl Check for googletest and googlemock
dnl ************************************

PKG_CHECK_MODULES(gtestmock, libgtest >= 0.4.0, libgmock >= 0.4.0)
AC_SUBST(gtestmock_LIBS)
AC_SUBST(gtestmock_CFLAGS)

А потом где-то в моем Makefile.am:

sometarget_CXXFLAGS = $(gtestmock_CFLAGS) $(AM_CXXFLAGS)
sometarget_LDADD    = $(gtestmock_LIBS)

Довольно банально, а?

person Josh Glover    schedule 24.03.2010
comment
Однако есть проблемы с использованием pkg-config. И, что более важно, pkg-config и autotools работают по-разному. Autoconf проверяет функции, тогда как pkg-config проверяет версии пакетов. Если вы пытаетесь делать что-то с помощью автоинструментов, что должно дать вам максимальную совместимость между системами, я бы вообще не советовал использовать pkg-config. - person edam; 02.09.2014

AC_LANG_CPLUSPLUS
AC_CHECK_LIB(Sockets, main)

Предостережение: http://lists.gnu.org/archive/html/autoconf/2006-09/msg00019.html

person rishta    schedule 02.08.2012
comment
Еще немного пояснений не помешало бы. В вашем образце требуется, чтобы было указано именно main, и проверяется только наличие библиотеки. Но сгенерированная программа имеет UB, потому что в C++ main не разрешено вызывать main. Какой BTW упоминается в ссылке, которую вы предоставляете. - person Werner Henze; 23.01.2019
comment
Может быть, потому что ссылка была дана в качестве предостережения? Хм? - person rishta; 24.01.2019
comment
Так почему бы не перейти на AC_LANG_C, где main разрешено вызывать main? И, как уже было сказано: вы просто даете какой-то код без каких-либо объяснений, но объяснение действительно помогло бы. - person Werner Henze; 24.01.2019
comment
Так почему бы не отредактировать мой ответ, чтобы сделать его более информативным, а не ссориться? До свидания. - person rishta; 24.01.2019