3

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?

John McFarlane
  • 5,528
  • 4
  • 34
  • 38

2 Answers2

0

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!)

John McFarlane
  • 5,528
  • 4
  • 34
  • 38
0

I had similar problems even when the gtest library was built with a different GCC version.

Instead of using a pre-compiled library you could add some CMake code to your project to download and compile the library in the configure phase.

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

Instead of downloading the HEAD of the master branch you could modify CMakeLists.txt.in to get a tagged version.

Bodo
  • 9,287
  • 1
  • 13
  • 29
  • That's essentially what `ExternalProject_Add` does. It's a really simple way to pull a dependency into a CMake project ([example](https://github.com/hbe72/cdsp/blob/develop/test/CMakeLists.txt#L25)). The problem is that gtest will be built using the default tool-chain which causes similar issues to linking to a pre-built library. – John McFarlane Jun 20 '19 at 06:43