如何用clang++编译boost单元测试模块

How to compile boost unit test module with clang++?

本文关键字:单元测试 模块 boost 编译 何用 clang++      更新时间:2023-10-16

我正试图用cmake和clang编译一个boost单元测试模块,但遇到了链接器错误。我能够生成以下最小的测试用例:

$ cat boost_test_test.cc
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE scanio
#include <boost/test/unit_test.hpp>
BOOST_AUTO_TEST_CASE(foo) { BOOST_CHECK(1); }

使用g++:

可以很好地编译
$ g++ boost_test_test.cc -lboost_unit_test_framework
$ echo $?
0

但是对于clang++则不是:

$ /usr/bin/clang++-3.7 boost_test_test.cc -lboost_unit_test_framework
/tmp/boost_test_test-7e4892.o: In function `boost::unit_test::make_test_case(boost::unit_test::callback0<boost::unit_test::ut_detail::unused> const&, boost::unit_test::basic_cstring<char const>)':
boost_test_test.cc:(.text._ZN5boost9unit_test14make_test_caseERKNS0_9callback0INS0_9ut_detail6unusedEEENS0_13basic_cstringIKcEE[_ZN5boost9unit_test14make_test_caseERKNS0_9callback0INS0_9ut_detail6unusedEEENS0_13basic_cstringIKcEE]+0x58): undefined reference to `boost::unit_test::ut_detail::normalize_test_case_name(boost::unit_test::basic_cstring<char const>)'
clang: error: linker command failed with exit code 1 (use -v to see invocation)

因此,在链接器阶段,我得到一个undefined reference错误,无论clang++参数的顺序如何,这个问题仍然存在。

因为它与g++工作得很好,我想这里有clang++特定的东西?

这是Debian Sid上的g++ 5.2.1, clang++ 3.7和boost 1.58。

在Ubuntu Willy中,Boost 1.58单元测试库是用GCC 5.0编译的。库文件libboost_unit_test_framework.a包含解析为boost::unit_test::ut_detail::normalize_test_case_name[abi:cxx11](boost::unit_test::basic_cstring<char const>)

的编译函数_ZN5boost9unit_test9ut_detail24normalize_test_case_nameB5cxx11ENS0_13basic_cstringIKcEE

然而,CLang似乎没有使用新的ABI,所以它搜索_ZN5boost9unit_test9ut_detail24normalize_test_case_nameENS0_13basic_cstringIKcEE,也就是boost::unit_test::ut_detail::normalize_test_case_name(boost::unit_test::basic_cstring<char const>)

为了克服这个问题,在测试文件中定义您自己的函数:
namespace boost { namespace unit_test { namespace ut_detail {
    std::string normalize_test_case_name(const_string name) {
        return ( name[0] == '&' ? std::string(name.begin()+1, name.size()-1) : std::string(name.begin(), name.size() ));
    }
}}}

这应该可以解决问题。如果使用与Boost相同版本的编译器进行编译,则应该没有问题,因为链接器将直接忽略函数的库版本。