2011-12-10 14 views
60

Compilar el código de ejemplo para impulsar :: program_options: http://svn.boost.org/svn/boost/trunk/libs/program_options/example/first.cpp¿Por qué no se puede chocar con libC++ en el modo C++ 0x? Este impulso :: ejemplo de program_options?

... en MacOS Lion (10.7.2), el uso de impulso-1.48.0 instalado con MacPorts:

$ clang++ -v 
Apple clang version 3.0 (tags/Apple/clang-211.12) (based on LLVM 3.0svn) 
Target: x86_64-apple-darwin11.2.0 
Thread model: posix 
$ clang++ -std=c++0x --stdlib=libc++ -lc++ -I/opt/local/include -L/opt/local/lib -lboost_program_options first.cpp -o first 
Undefined symbols for architecture x86_64: 
    "boost::program_options::options_description::options_description(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned int, unsigned int)", referenced from: 
     _main in cc-6QQcwm.o 
    "boost::program_options::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, boost::program_options::options_description const&)", referenced from: 
     _main in cc-6QQcwm.o 
    "boost::program_options::abstract_variables_map::operator[](std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) const", referenced from: 
     boost::program_options::variables_map::operator[](std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) const in cc-6QQcwm.o 
    "boost::program_options::detail::cmdline::set_additional_parser(boost::function1<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&>)", referenced from: 
     boost::program_options::basic_command_line_parser<char>::extra_parser(boost::function1<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&>) in cc-6QQcwm.o 
    "boost::program_options::detail::cmdline::cmdline(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&)", referenced from: 
     boost::program_options::basic_command_line_parser<char>::basic_command_line_parser(int, char const* const*) in cc-6QQcwm.o 
    "boost::program_options::to_internal(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)", referenced from: 
     std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > boost::program_options::to_internal<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&) in cc-6QQcwm.o 
    "boost::program_options::invalid_option_value::invalid_option_value(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)", referenced from: 
     void boost::program_options::validate<int, char>(boost::any&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, int*, long) in cc-6QQcwm.o 
    "boost::program_options::validation_error::validation_error(boost::program_options::validation_error::kind_t, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)", referenced from: 
     std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const& boost::program_options::validators::get_single_string<char>(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, bool) in cc-6QQcwm.o 
    "boost::program_options::value_semantic_codecvt_helper<char>::parse(boost::any&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, bool) const", referenced from: 
     vtable for boost::program_options::typed_value<int, char> in cc-6QQcwm.o 
ld: symbol(s) not found for architecture x86_64 
clang: error: linker command failed with exit code 1 (use -v to see invocation) 

El mismo código compilado/vinculado con g ++ 4.7 instalado con MacPorts:

$ g++-mp-4.7 -std=c++0x -I/opt/local/include -L/opt/local/lib -lboost_program_options -o first first.cpp 

... funciona bien. Al igual que el uso de clang sin libC++:

clang++ -std=c++0x -I/opt/local/include -L/opt/local/lib -lboost_program_options first.cpp -o first 

¿Qué pasa? ¿Por qué boost :: program_options y libC++ no funcionan juntos?

+3

Parece que su vinculador no puede encontrar las librerías apropiadas de 64 bits. "ld: símbolo (s) no encontrado (s) para la arquitectura x86_64" –

Respuesta

129

Necesita reconstruir el impulso utilizando clang ++ -stdlib = libC++.

libC++ no es compatible con binario con libstdC++ de gcc (excepto algunas cosas de bajo nivel como operador nuevo). Por ejemplo, el std::string en libstdC++ de gcc se vuelve a contabilizar, mientras que en libC++ se utiliza la "optimización de cadena corta". Si tuviera que mezclar accidentalmente estas dos cadenas en el mismo programa (y confundirlas con la misma estructura de datos), inevitablemente se produciría un fallo en el tiempo de ejecución.

Este accidente es exactamente lo que ocurrió en su caso.

Con el fin de convertir este accidente de tiempo de ejecución en un error de tiempo de enlace, libC++ utiliza una característica del lenguaje C++ 11 inline namespace llamada a cambiar el ABI de std::string sin afectar a la API de std::string. Es decir, para usted std::string tiene el mismo aspecto. Pero para el enlazador, std::string está siendo destrozado como si estuviera en el espacio de nombres std::__1. Por lo tanto, el vinculador sabe que std::basic_string y std::__1::basic_string son dos estructuras de datos diferentes (la primera proviene de gcc's libstdC++ y la última proviene de libC++).

+5

P.S. Cómo recompilar boost para clang/libC++: http://stackoverflow.com/questions/8486077/how-to-compile-link-boost-with-clang-libc –

+0

¡Gracias por la excelente respuesta! –

+0

Una pregunta rápida. Si estuviera haciendo my_stdlib_str.c_str(), eventualmente tendría un error establecido, ¿cierto? Quiero decir, en ese caso, ¿el truco anterior del enlazador sería pasado? – ShitalShah

Cuestiones relacionadas