2009-06-20 19 views
10

我正在研究GNU/Linux上的C++项目,并且正在寻找一种方法来测试IBM Informix库的存在性和可用性,即使用Autotools - 即编辑configure.in。我没有Autotools的经验,所以基本上我从项目的configure.inet al。脚本和复制&改变我觉得需要改变的地方。 IOW,我一直在修改configure.in中的现有文本。如何在configure.in中测试C++库的可用性?

到目前为止,我一直在使用中的AC_CHECK_LIB来测试某个库是否存在并且可用。但是这只能用于具有函数而不是例如函数的函数库。类。也就是说,这个失败测试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,或者对于这种特定用途还有另一种“命令”。

在此先感谢您的意见。

回答

5

可能有一个更清晰的方式来实现这一点,但我认为你的问题是,C++方法得到'mangled',以允许有关方法的附加信息(参数&返回类型等)被编码。例如;方法int A::foo(void)将会被修改为__ZN1A3fooEv之类的东西。

因此,您需要在库中查找方法的名称。您可以通过在类Unix操作系统的nm command做到这一点:

$ nm libifc++.so | grep ITString 

值得一提的是,确切的mangling格式在不同的编译器而异;因此通过在您的configure.in中嵌入某个编译器的损坏符号,它可能无法在其他平台上工作 - YMMV。

注意:您可以使用c++filt实用工具将名称退回为人类可读的形式;所以对于例如我以前给:

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

有关更多信息,请参见Name Mangling in C++在维基百科上。

+0

作品-对于-ME。 我曾考虑过这样做,但它看起来像一个黑客。例如,我不确定如果代码使用不同的Informix库版本重新编译会发生什么情况(我期望改变的名称会发生​​更改)。 但是,嘿,它的作品! :-) – jbatista 2009-06-20 17:23:35

+2

这应该继续使用新的库版本(假设类和方法名称不会更改),但是如果您的编译器版本更改,则可能会中断,并且如果有人试图在另一个版本上编译您的代码,它几乎肯定会中断编译器或编译器版本。 – 2009-06-20 17:29:32

13

你发现了autotools的一个缺点,但是一个不能得到真正帮助的缺点。 Autotools检查库二进制文件中的符号名称,而不像C中函数的符号名称与函数名称相同,C++“mangles”函数的符号名称用于完成函数重载等操作。更糟糕的是,C++甚至没有真正的“标准”转换约定,因此不同的C++编译器可能会为同一个函数生成不同的符号名称。因此,autotools无法以可靠的方式检查C++符号名称。

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

我就遇到了这个问题,试图检测gtestgmock(在谷歌单元测试和对象嘲弄框架)与自动工具,这里就是我想出了:

# 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   
2

如果您检查库支持pkg-config,这变得很容易。这是我加入到我的configure.in检查并启用gtestgmock

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) 

很琐碎,不是吗?