CMake не работает с С++ 11 на OSX

Я только что обновился до Mountain Lion, поэтому я могу использовать некоторые из возможностей С++ 11 в новой версии Clang, которая поставляется с xcode. Я использую cmake 2.8.9 из Homebrew.

Я создал очень простой проект CMake, который добавляет флаги компилятора для С++ 11:

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

где код С++ в test.cxx следующий:

#include <iostream>

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

При запуске cmake и make файл компилируется просто отлично, но тогда компоновщик выводит следующие ошибки:

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

Я не получаю ошибок, если я прокомментирую строку add_definitions в файле CMakeLists.txt, и я также могу избежать ошибок, если я удалю строку std:: cout в test.cxx. Возможно, самая странная часть всего заключается в том, что если я просто запустил

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

он компилируется просто отлично! Итак, после рекомендации комментатора, я проверил фактические команды cmake для компиляции и компоновки.

Compile:

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

Ссылка

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

Теперь основная проблема заключается в том, что компоновщик не снабжает правильные флаги С++ 11. Есть ли лучший способ предоставить эти флаги, чтобы использовать их как компилятор, так и компоновщик?

Ответ 1

Я не уверен, что ADD_DEFINITIONS является правильным инструментом для этой конкретной работы.

Возможно, лучшим вариантом является прямое значение CMAKE_CXX_FLAGS:

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

Ответ 2

Я видел эту ошибку при запуске gcc, а не g++. Если я использую g++, все будет правильно составлено. Возможно, ваш Makefile использует неправильный внешний интерфейс компилятора.

Ответ 3

Перейдите в целевые объекты проекта → Apple LLVM-компилятор 4.1 - Язык- > выберите библиотеку С++ для

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

Ответ 4

После получения этой ошибки в последнее время (используя Clang) проблема заключалась в том, что не пропускал -std=c++11 -stdlib=libc++ в качестве флагов компоновщика.

Поэтому они должны передаваться как в качестве флагов компилятора , так и в качестве флагов компоновщика.

Для GCC первый флаг -std=c++0x вместо -std=c++11.

Ответ 5

Для меня ответ был просто использованием clang++ вместо clang.