2011-12-10 11 views
60

Compilare questo codice di esempio per boost :: program_options: http://svn.boost.org/svn/boost/trunk/libs/program_options/example/first.cppPerché non riesco a clangare con libC++ in modalità C++ 0x questo esempio boost :: program_options?

... su MacOS Lion (10.7.2), usare il boost-1.48.0 installato 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) 

Lo stesso codice compilato/collegato con g ++ 4.7 installato con MacPorts:

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

... funziona correttamente. Come usare clang senza libC++:

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

Cosa c'è che non va? Perché boost :: program_options e libC++ non funzionano insieme?

+3

Sembra che il linker non sia in grado di trovare le librerie a 64 bit appropriate. "ld: simbolo (i) non trovato per l'architettura x86_64" –

risposta

129

È necessario ricreare boost utilizzando clang ++ -stdlib = libC++.

libC++ non è compatibile binario con libstdC++ di gcc (eccetto per alcuni elementi di basso livello come l'operatore nuovo). Ad esempio lo std::string in libstdC++ di gcc viene reimpostato, mentre in libC++ viene utilizzato "l'ottimizzazione della stringa corta". Se dovessi mescolare accidentalmente queste due stringhe nello stesso programma (e scambiarle per la stessa struttura dati), inevitabilmente si verificherà un arresto anomalo.

Questo incidente è esattamente quello che è successo nel tuo caso.

Al fine di trasformare questo incidente fase di esecuzione in un errore di tempo di collegamento, libC++ usa una caratteristica del linguaggio C++ 11 chiamato inline namespace per cambiare il ABI di std::string senza impattare l'API di std::string. Cioè, per te std::string sembra lo stesso. Ma per il linker, std::string viene manomesso come se fosse nel namespace std::__1. Quindi il linker sa che std::basic_string e std::__1::basic_string sono due diverse strutture di dati (il primo proveniente da libstdC++ di gcc e quest'ultimo da libC++).

+5

P.S. Come ricompilare boost per clang/libC++: http://stackoverflow.com/questions/8486077/how-to-compile-link-boost-with-clang-libc –

+0

Grazie per l'ottima risposta! –

+0

Una domanda veloce. Se stavo facendo my_stdlib_str.c_str(), alla fine avrei risolto il problema, giusto? Intendo in questo caso che il trucco del linker sarebbe passato? – ShitalShah

Problemi correlati