9
votes

I've just upgraded to Mountain Lion so I can use some of the C++11 features on the new version of Clang that comes with xcode. I'm using cmake 2.8.9 from Homebrew.

I've made a very simple CMake project which adds the compiler flags for C++11:

# CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
add_executable(test test.cxx)
add_definitions(-std=c++0x -stdlib=libc++)

where the C++ code in test.cxx is the following:

#include <iostream>

int main()
{
  std::cout << "Howdy" << std::endl;
  return 0;
}

When running cmake and make, the file compiles just fine but then the linker outputs the following errors:

Linking CXX executable test
Undefined symbols for architecture x86_64:
  "std::__1::locale::use_facet(std::__1::locale::id&) const", referenced from:
      std::__1::basic_ostream<char, std::__1::char_traits<char> >& std::__1::endl<char, std::__1::char_traits<char> >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) in test.cxx.o
  "std::__1::ios_base::getloc() const", referenced from:
      std::__1::basic_ostream<char, std::__1::char_traits<char> >& std::__1::endl<char, std::__1::char_traits<char> >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) in test.cxx.o
  "std::__1::basic_ostream<char, std::__1::char_traits<char> >::put(char)", referenced from:
      std::__1::basic_ostream<char, std::__1::char_traits<char> >& std::__1::endl<char, std::__1::char_traits<char> >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) in test.cxx.o
  "std::__1::basic_ostream<char, std::__1::char_traits<char> >::flush()", referenced from:
      std::__1::basic_ostream<char, std::__1::char_traits<char> >& std::__1::endl<char, std::__1::char_traits<char> >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) in test.cxx.o
  "std::__1::basic_ostream<char, std::__1::char_traits<char> >::sentry::sentry(std::__1::basic_ostream<char, std::__1::char_traits<char> >&)", referenced from:
      std::__1::basic_ostream<char, std::__1::char_traits<char> >& std::__1::operator<<<std::__1::char_traits<char> >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, char const*) in test.cxx.o
  "std::__1::basic_ostream<char, std::__1::char_traits<char> >::sentry::~sentry()", referenced from:
      std::__1::basic_ostream<char, std::__1::char_traits<char> >& std::__1::operator<<<std::__1::char_traits<char> >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, char const*) in test.cxx.o
  "std::__1::cout", referenced from:
      _main in test.cxx.o
  "std::__1::ctype<char>::id", referenced from:
      std::__1::basic_ostream<char, std::__1::char_traits<char> >& std::__1::endl<char, std::__1::char_traits<char> >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) in test.cxx.o
  "std::__1::locale::~locale()", referenced from:
      std::__1::basic_ostream<char, std::__1::char_traits<char> >& std::__1::endl<char, std::__1::char_traits<char> >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) in test.cxx.o
  "std::__1::ios_base::__set_badbit_and_consider_rethrow()", referenced from:
      std::__1::basic_ostream<char, std::__1::char_traits<char> >& std::__1::operator<<<std::__1::char_traits<char> >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, char const*) in test.cxx.o
  "std::__1::ios_base::clear(unsigned int)", referenced from:
      std::__1::basic_ostream<char, std::__1::char_traits<char> >& std::__1::operator<<<std::__1::char_traits<char> >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, char const*) in test.cxx.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [test] Error 1
make[1]: *** [CMakeFiles/test.dir/all] Error 2
make: *** [all] Error 2

I get no errors if I comment out the add_definitions line in the CMakeLists.txt file, and I can also avoid errors if I remove the std::cout line in test.cxx. Perhaps the weirdest part of all is that if I simply run

clang++ -std=c++0x -stdlib=libc++ test.cxx

it compiles just fine! So, following a commentor's advice, I checked the actual commands cmake is running for compiling and linking.

Compile:

/usr/bin/c++    -std=c++0x -stdlib=libc++ -o CMakeFiles/test.dir/test.cxx.o -c /Users/luis/test.cxx

Link:

/usr/bin/c++    -Wl,-search_paths_first -Wl,-headerpad_max_install_names   CMakeFiles/test.dir/test.cxx.o  -o test

The main issue now seems to be that the linker is not supplying the proper C++11 flags. Is there a better way to supply these flags so that both the compiler and the linker will use them?

5
Can you ask cmake to print out the commands it's running?Lily Ballard

5 Answers

12
votes

I'm not sure that ADD_DEFINITIONS is the right tool for this particular job.

Perhaps a better option is to set the value of CMAKE_CXX_FLAGS directly:

cmake_minimum_required(VERSION 2.8)
set (CMAKE_CXX_FLAGS "-std=c++0x -stdlib=libc++ -g3 -Wall -O0")
add_executable(test test.cxx)
8
votes

I saw this error when running gcc rather than g++. If I use g++, things compile correctly. Perhaps your Makefile is using the wrong compiler front end.

6
votes

Go to your project targets->Apple LLVM compiler 4.1 - Language->select c++library to

libc__(LLVM C++ stadard library with c++ 11 support);
1
votes

After getting this error recently (using Clang) the problem was in not passing -std=c++11 -stdlib=libc++ as linker flags too.

So they have to be passed both as compiler flags and as linker flags.

For GCC the first flag is -std=c++0x, instead of -std=c++11.

1
votes

For me the answer was simply using clang++ instead of clang.