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

Я работаю над проектом С++ на 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 и т.д.

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

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

Ответ 1

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

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

$ nm libifc++.so | grep ITString

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

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

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

Посмотрите Название Mangling в C++ в Википедии для получения дополнительной информации.

Ответ 2

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

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

Я столкнулся с этой проблемой, пытаясь обнаружить 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 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          

Ответ 3

Если библиотека, которую вы проверяете для поддержки 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)

Довольно тривиальный, eh?