【问题标题】:Error linking library built with ExternalProject_Add to project configured with CMAKE_CXX_COMPILER将使用 ExternalProject_Add 构建的库链接到使用 CMAKE_CXX_COMPILER 配置的项目时出错
【发布时间】:2019-11-01 07:53:09
【问题描述】:

我的 CMake 项目使用我使用 ExternalProject 模块添加的 gtest 库。这通常有效,但是当我将项目配置为使用 Clang 3.8 工具链时,例如:

cmake -DCMAKE_CXX_COMPILER=clang++-3.8 ..
cmake --build .

我在 Ubuntu 16.04 下收到以下链接器错误:

../lib/libgtest.a(gtest-all.cc.o): In function `testing::Message::Message()':
gtest-all.cc:(.text+0x2194): undefined reference to `std::__cxx11::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >::basic_stringstream()'
../lib/libgtest.a(gtest-all.cc.o): In function `testing::internal::edit_distance::CreateUnifiedDiff(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, unsigned long)':
gtest-all.cc:(.text+0x3596): undefined reference to `std::__cxx11::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >::basic_stringstream()'
../lib/libgtest.a(gtest-all.cc.o): In function `testing::internal::WideStringToUtf8[abi:cxx11](wchar_t const*, int)':
gtest-all.cc:(.text+0x53d7): undefined reference to `std::__cxx11::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >::basic_stringstream()'
../lib/libgtest.a(gtest-all.cc.o): In function `testing::internal::String::FormatIntWidth2[abi:cxx11](int)':
gtest-all.cc:(.text+0x59f8): undefined reference to `std::__cxx11::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >::basic_stringstream()'
../lib/libgtest.a(gtest-all.cc.o): In function `testing::internal::String::FormatHexInt[abi:cxx11](int)':
gtest-all.cc:(.text+0x5ac4): undefined reference to `std::__cxx11::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >::basic_stringstream()'
../lib/libgtest.a(gtest-all.cc.o):gtest-all.cc:(.text+0x5b80): more undefined references to `std::__cxx11::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >::basic_stringstream()' follow
clang: error: linker command failed with exit code 1 (use -v to see invocation)

问题似乎是 gtest 是使用系统范围的编译器 GCC 5 构建的,并且忽略了 CMAKE_CXX_COMPILER。确保所有依赖项都使用相同的工具链构建的正确方法是什么?

【问题讨论】:

    标签: c++ linux cmake clang++ external-project


    【解决方案1】:

    您可以在CONFIGURE_COMMAND 参数中将CMAKE_CXX_COMPILER 值传递给ExternalProject_Add,但这不可扩展。您还可以设置 _GLIBCXX_USE_CXX11_ABI 标志来避免这种特定的标准库不匹配 - 但同样 - 这是一个脆弱的解决方案。

    最终,您希望在整个项目中为任何给定配置使用相同的编译器。最好的方法是使用环境变量 CXX 指定编译器,而不是通过 CMake 变量 CMAKE_CXX_COMPILER

    export CXX=clang++-3.8
    cmake ..
    cmake --build .
    

    请注意,配置命令和构建命令都需要设置CXX,因此如果您不想通过更改为CXX而污染环境,请在两个命令前加上前缀:

    CXX=clang++-3.8 cmake ..
    CXX=clang++-3.8 cmake --build .
    

    (更好的是,使用包管理器,例如 ConanVcpkg!)

    【讨论】:

      【解决方案2】:

      即使 gtest 库是使用不同的 GCC 版本构建的,我也遇到了类似的问题。

      您可以将一些 CMake 代码添加到您的项目中,以在配置阶段下载并编译该库,而不是使用预编译的库。

      https://github.com/google/googletest/tree/master/googletest#incorporating-into-an-existing-cmake-project

      您可以修改 CMakeLists.txt.in 以获取标记版本,而不是下载 master 分支的 HEAD。

      【讨论】:

      • 这基本上就是ExternalProject_Add 所做的。这是将依赖项拉入 CMake 项目 (example) 的一种非常简单的方法。问题是 gtest 将使用默认工具链构建,这会导致与链接到预构建库类似的问题。
      猜你喜欢
      • 1970-01-01
      • 2012-10-06
      • 2015-12-26
      • 1970-01-01
      • 2017-04-19
      • 1970-01-01
      • 2018-03-05
      • 2019-09-04
      • 1970-01-01
      相关资源
      最近更新 更多