Error linking library built with ExternalProject_Add to project configured with CMAKE_CXX_COMPILER

Viewed 337

My CMake project uses the gtest library which I add using the ExternalProject module. This normally works but when I configure the project to use the Clang 3.8 tool chain, e.g.:

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

I receive the following linker errors under 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)

The problem appears to be that gtest is built with the system-wide compiler, GCC 5, and ignores CMAKE_CXX_COMPILER. What is the correct way to ensure all dependencies are build with the same tool chain?

2 Answers

You could pass the CMAKE_CXX_COMPILER value to ExternalProject_Add in the CONFIGURE_COMMAND parameter but this is not scalable. You could also set the _GLIBCXX_USE_CXX11_ABI flag to avoid this particular standard library mismatch — but again — this is a brittle solution.

Ultimately, you want to use the same compiler throughout the project for any given configuration. The best way to do this is to specify the compiler using the environment variable, CXX, rather than through the CMake variable, CMAKE_CXX_COMPILER:

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

Note that CXX needs to be set for both the configuration command and the build commands so if you don't want to pollute the environment with the change to CXX, prefix both commands:

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

(Better still, use a package manager such as Conan or Vcpkg!)

Related