12

我正在 GNU/Linux 上开发一个 C++ 项目,我正在寻找一种方法来使用 Autotools 测试 IBM Informix 库的存在性和可用性 - 即编辑一个configure.in. 我没有使用 Autotools 的经验,所以基本上我是从项目的configure.in et al 中学习的。脚本和复制和更改我觉得需要更改的地方。IOW,我一直在改编configure.in.

到目前为止,我一直在成功地使用AC_CHECK_LIBinconfigure.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 中找到“纯”函数(即,在 C++ 类中没有上下文的函数)。所以我希望要么有一种AC_CHECK_LIB在这种情况下使用的方法,要么有另一个autoconf/ configure.in“命令”用于这个特定用途。

提前感谢您的反馈。

4

4 回答 4

17

您已经发现了自动工具的一个缺点,但它确实无济于事。Autotools 检查库二进制文件中的符号名称,与 C 中函数的符号名称与函数名称相同的 C 不同,C++“修改”函数的符号名称以完成函数重载等事情。更糟糕的是,C++ 甚至没有真正的“标准”修改约定,因此不同的 C++ 编译器可能会为同一个函数生成不同的符号名称。因此,autotools 无法以可靠的方式检查 C++ 符号名称。

您尝试使用的库是否有任何用 声明的函数extern "C"?这会导致 C++ 编译器生成标准化的 C 样式符号名称,并且 autotools 将能够找到它们。

我在尝试使用 Autotools 检测gtestgmock(Google 单元测试和对象模拟框架)时遇到了这个问题,这就是我想出的:

# 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          
于 2009-06-20T16:48:26.830 回答
7

可能有一种更简洁的方法来实现这一点,但我认为您的问题是 C++ 方法被“破坏”以允许对有关方法(参数和返回类型等)的附加信息进行编码。例如; 该方法int A::foo(void)将被破坏为__ZN1A3fooEv.

因此,您需要在库中找到方法的错位名称。您可以通过在类 Unix 操作系统上使用以下nm命令来执行此操作:

$ nm libifc++.so | grep ITString

值得一提的是,不同的编译器的准确修饰格式会有所不同。因此,通过在您的中嵌入某个编译器的损坏符号,configure.in它可能无法在其他平台上运行 - YMMV。

注意:您可以使用该c++filt实用程序将名称恢复为人类可读的形式;所以对于我之前给出的例子:

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

有关更多信息,请参阅Wikipedia 上的 C++ 中的名称修饰。

于 2009-06-20T16:44:57.470 回答
3

如果您正在检查的库支持pkg-config,这将变得非常容易。这是我添加到我的所有内容configure.in以检查和启用gtestand 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)

很琐碎,嗯?

于 2010-03-24T08:31:16.883 回答
0
AC_LANG_CPLUSPLUS
AC_CHECK_LIB(Sockets, main)

警告: http: //lists.gnu.org/archive/html/autoconf/2006-09/msg00019.html

于 2012-08-02T13:28:06.427 回答