2012-10-16 15 views
23

Ho una grande libreria statica in C++ con bit di Objective-C originariamente costruiti per iOS (armv7).Errore linker STD con Apple LLVM 4.1

Ho creato una versione OS X (64-bit Intel x86_64) di esso, ma non appena ho provato a utilizzarlo in un progetto di app OS X (indirizzato a Lion 10.7), sono apparsi decine di errori del linker, la maggior parte loro su simboli di libreria standard.

So come risolvere i "miei" problemi di linker, ma quelli STD copiati di seguito mi infastidiscono.

"std::basic_filebuf<char, std::char_traits<char> >::is_open() const" 
"std::basic_stringbuf<char, std::char_traits<char>, std::allocator<char> >::str() const" 
"std::basic_ios<char, std::char_traits<char> >::widen(char) const" 
"std::istream& std::istream::_M_extract<double>(double&)" 
"std::ostream::put(char)" 
"std::ostream::flush()" 
"std::ostream& std::ostream::_M_insert<void const*>(void const*)" 
"std::ostream& std::ostream::_M_insert<bool>(bool)" 
"std::ostream& std::ostream::_M_insert<double>(double)" 
"std::ostream& std::ostream::_M_insert<unsigned long>(unsigned long)" 
"std::ostream::operator<<(int)" 
"std::ostream::operator<<(short)" 
"std::string::_Rep::_M_destroy(std::allocator<char> const&)" 
"std::string::_Rep::_S_terminal" 
"std::string::_Rep::_S_empty_rep_storage" 
"std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&)" 
"std::string::append(char const*, unsigned long)" 
"std::string::append(std::string const&)" 
"std::string::assign(std::string const&)" 
"std::string::reserve(unsigned long)" 
"std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&)" 
"std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::string const&)" 
"std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()" 
"std::basic_ofstream<char, std::char_traits<char> >::open(char const*, std::_Ios_Openmode)" 
"std::basic_ofstream<char, std::char_traits<char> >::close()" 
"std::basic_ofstream<char, std::char_traits<char> >::basic_ofstream()" 
"std::basic_ofstream<char, std::char_traits<char> >::~basic_ofstream()" 
"std::_List_node_base::hook(std::_List_node_base*)" 
"std::_List_node_base::unhook()" 
"std::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >::basic_stringstream(std::string const&, std::_Ios_Openmode)" 
"std::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >::basic_stringstream(std::_Ios_Openmode)" 
"std::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >::~basic_stringstream()" 
"std::basic_ostringstream<char, std::char_traits<char>, std::allocator<char> >::basic_ostringstream(std::_Ios_Openmode)" 
"std::basic_ostringstream<char, std::char_traits<char>, std::allocator<char> >::~basic_ostringstream()" 
"std::ios_base::Init::Init()" 
"std::ios_base::Init::~Init()" 
"std::basic_ios<char, std::char_traits<char> >::clear(std::_Ios_Iostate)" 
"std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)" 
"std::_Rb_tree_decrement(std::_Rb_tree_node_base*)" 
"std::_Rb_tree_increment(std::_Rb_tree_node_base const*)" 
"std::_Rb_tree_increment(std::_Rb_tree_node_base*)" 
"std::__throw_logic_error(char const*)" 
"std::__throw_length_error(char const*)" 
"std::__throw_out_of_range(char const*)" 
"std::_Rb_tree_rebalance_for_erase(std::_Rb_tree_node_base*, std::_Rb_tree_node_base&)" 
"std::_Rb_tree_insert_and_rebalance(bool, std::_Rb_tree_node_base*, std::_Rb_tree_node_base*, std::_Rb_tree_node_base&)" 
"std::cerr" 
"std::cout" 

ho controllato il mio impostazioni di generazione, il mio link di progetto alla libreria standard (-stdlib=libc++) e posso usare std :: cout senza alcun problema nella mia main.cpp.

Ho modificato il compilatore nelle impostazioni di generazione da Apple LLVM 4.1 a LLVM GCC 4.2 e il problema è scomparso. Voglio continuare a utilizzare Apple LLVM 4.1. Come posso ripararlo?

Grazie!

+0

Come ha detto @gzfrancisco, Link stdC++. 6.dylib risolverà questo problema. – aksani56

risposta

44

Modificare la libreria standard che viene legata ad utilizzare libstdc++ invece di libc++ - il problema è che l'altra libreria è stata compilata utilizzando la modalità g++ che usa la libreria libstdc++.

Si consideri il seguente codice di esempio:

dhcp-191:~/Development/testy/fred% cat fred.cpp 
#include <iostream> 
#include <string> 
#include "fred.h" 

using namespace std; 

bool dofred(string &x) 
{ 
    cout << x << endl; 
    return true; 
} 
dhcp-191:~/Development/testy/fred% cat fred.h 

#include <iostream> 
#include <string> 

bool dofred(std::string &x); 

dhcp-191:~/Development/testy/fred% clang++ -stdlib=libc++ -shared -o fred.dylib fred.cpp 
dhcp-191:~/Development/testy/fred% nm fred.dylib | c++filt | grep dofred 
0000000000000fa0 T dofred(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&) 
dhcp-191:~/Development/testy/fred% clang++ -stdlib=libstdc++ -shared -o fred.dylib fred.cpp 
dhcp-191:~/Development/testy/fred% nm fred.dylib | c++filt | grep dofred      
0000000000000e30 T dofred(std::string&) 

È possibile ottenere due completamente diversi simboli esportati. Quando si tenta di utilizzare il simbolo, l'app che utilizza lo stesso flag -stdlib sarà in grado di collegarsi, mentre l'app che non visualizza un errore di collegamento.

+9

Puoi dire la differenza perché libC++ usa uno spazio dei nomi incorporato all'interno di std, quindi i simboli in libC++ sono come 'std :: __ 1 :: cout'. – bames53

+0

@ bames53 Questo è un ottimo consiglio per rintracciare questi tipi di errori di collegamento! – Petesh

+0

OK grazie! Non mi rendevo conto che c'erano 2 implementazioni di libreria standard disponibili. Capisco che hanno internals diversi, ma non capisco perché questo porta a problemi di linker su cose come 'std :: cout'. /modifica: risposta di @ bames53. Adesso lo so. Un po 'confuso _why_ though :) – antho

11

Ho avuto questo problema dopo aver inserito tutti i file C++ in una libreria separata. Ho impostato le impostazioni di tutti i progetti per utilizzare libC++, ma il linker non si collega a libC++. Se aggiungo un file C++ al progetto principale, il problema scompare. Per risolvere questo problema, puoi aggiungere '-lC++' nella sezione "Altri linker flag" del progetto principale. Ciò costringerebbe XCode a collegarsi a libC++.

MODIFICA: Come ha detto l'altro poster, XCode potrebbe comportarsi correttamente. Mi aspettavo che sapesse di aggiungere il collegamento C++ perché il codice sorgente lib C++ si trova nello stesso spazio di lavoro.

0

In risposta a jlukanta: Ho avuto lo stesso problema. Sono stato attento a scegliere il giusto STD ma ho ancora ricevuto quegli errori. Ma questo non è un bug, in realtà ha senso: perché Xcode dovrebbe collegarsi con lo stdlib C++ se non hai alcun codice C++ nel tuo progetto?

Ovviamente, questo è un problema quando non si ha codice C++ nel progetto ma ancora librerie C++.

44

In iOS 7 uso una libreria per grafici e ho lo stesso problema. In questo caso, lib stdC++ non risolve il problema.

Aggiungo lo stdC++. 6.dylib alla fase di compilazione e vengono trovati i simboli.

+0

Grazie! Risparmiami un sacco di volte! – liuyaodong

+4

Questo ha funzionato anche per me. Qualcuno sa perché 'libstdC++. Dylib' fallisce e' libstdC++. 6.dylib' funziona? – simeon

+1

Grazie, ho trovato questo prima che tutti i miei capelli fossero stati estratti :) –

3

Ho appena avuto un problema simile, e ho dovuto andare su "Impostazioni Build" e quindi su "Apple LLVM 5.1 - Language - C++" e quindi modificare "Libreria standard C++" in libstdC++.

1

potresti anche provare ad aggiungere un file .cpp vuoto al tuo progetto.Ciò ingannerà xcode nel caricamento delle librerie std C++

+1

Grazie! Questa è l'unica soluzione che ha funzionato per me. Ho provato il collegamento con libC++ e libstdC++ (specificato in LLVM C++ e "altre impostazioni di linker flag"), ma senza fortuna ... ho aggiunto un file "foo.cpp" vuoto al progetto e, voilà, non ci sono più errori di linker! Grazie! –