Sto cercando di creare & eseguire una piccola applicazione di esempio che utilizza Folly su OS X Yosemite utilizzando GCC 4.9.3. Ecco il codice sorgente:Perché la libreria condivisa di Folly fa riferimento al simbolo sbagliato di Boost? (GCC su OS X)
#include <folly/AtomicHashMap.h>
int main() {
folly::AtomicHashMap<int, int> map(256);
map.insert(std::make_pair(1, 1));
return 0;
}
ho costruito e installato sia Boost (1.59.0) e Folly (ultima testa GitHub) da fonti, assicurandosi GCC è stato utilizzato, e ora sono disponibili in /usr/local
loro librerie e intestazioni. GCC e altre dipendenze sono state installate utilizzando MacPorts. Posso generare l'esempio di cui sopra con successo utilizzando la seguente riga di comando:
$ g++-mp-4.9 main.cpp -std=c++11 -I/usr/local/include -L/opt/local/lib -lfolly -lglog
Tuttavia, quando provo a farlo funzionare, c'è il seguente errore:
$ ./a.out
dyld: Symbol not found: __ZNK5boost15program_options22error_with_option_name23substitute_placeholdersERKSs
Referenced from: /usr/local/lib/libfolly.57.dylib
Expected in: flat namespace
in /usr/local/lib/libfolly.57.dylib
Trace/BPT trap: 5
Da quello che ho capito, il modo in cui questo è dovrebbe funzionare è che /usr/local/lib/libfolly.57.dylib
inserisce automaticamente libboost_program_options.dylib
per riferimento al momento del caricamento. Posso vederlo elencato come una dipendenza quando corro otool -L
:
$ otool -L /usr/local/lib/libfolly.57.dylib
/usr/local/lib/libfolly.57.dylib:
/usr/local/lib/libfolly.57.dylib (compatibility version 58.0.0, current version 58.0.0)
libboost_context.dylib (compatibility version 0.0.0, current version 0.0.0)
libboost_program_options.dylib (compatibility version 0.0.0, current version 0.0.0)
...
libboost_program_options.dylib
si trova in /usr/local/lib
, e se rinominarlo in qualcos'altro, in esecuzione ./a.out
provoca il caricatore per lamentarsi di non essere in grado di trovare al posto ("dyld: Libreria non caricata: libboost_program_options.dylib"). Quindi sembra che il caricatore sia in grado di trovarlo, almeno.
Ho controllato i simboli esportati da questa libreria utilizzando nm -gU
:
$ nm -gU /usr/local/lib/libboost_program_options.dylib | grep program_options
...
0000000000023560 T __ZNK5boost15program_options22error_with_option_name23substitute_placeholdersERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE
...
per cui v'è un simbolo molto simile a quello che il caricatore si lamenta è mancante. Il nome storpiato ha solo un suffisso diverso.
[Edit: non è molto facile da vedere i nomi a meno che non si scorre verso destra, ecco sono di nuovo:
nm
dice il libreria contiene__ZNK5boost15program_options22error_with_option_name23substitute_placeholdersERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE
- Il "simbolo mancante" . in fase di carico è
__ZNK5boost15program_options22error_with_option_name23substitute_placeholdersERKSs
]
ho trovato la dichiarazione corrispondente /usr/local/include/boost/program_options/errors.hpp
:
namespace boost { namespace program_options {
...
class BOOST_PROGRAM_OPTIONS_DECL error_with_option_name : public error {
...
protected:
...
virtual void substitute_placeholders(const std::string& error_template) const;
Presumo che questo è il file di intestazione che Follia utilizzato quando ho costruito perché è l'unica occorrenza abbinamento di substitute_placeholders
in tutti /usr/include
, /usr/local/include
e /opt/local/include
. (Si noti che Follia non ha nemmeno chiamare direttamente questa funzione, ma lo fa #include <boost/program_options.hpp>
da folly/experimental/ProgramOptions.h
e utilizzare altri membri della boost::program_options
.)
Mi sembra che il nome più lungo mangled - l'unico che in realtà esportato da libboost_program_options.dylib
- - è quello corretto, poiché include l'argomento std::string
.
Quindi che cosa potrebbe causare libfolly.57.dylib
di fare riferimento a un nome diverso (più breve) con un nome diverso?
Altre note:
- Originariamente ho installato Boost da MacPorts invece di costruire da fonti, e hanno provocato lo stesso errore.
- Se creo il campione utilizzando
g++-mp-4.9 main.cpp -std=c++11 -I/usr/local/include -L/opt/local/lib /usr/local/lib/libfolly.a -lglog
, in altre parole, collego solo con la libreria statica di Folly, il problema scompare e l'esempio viene eseguito.
Hai ragione, non avevo effettivamente costruito Boost utilizzando MacPorts GCC come pensavo di aver fatto. Ho configurato Boost.Build correttamente questa volta e ora tutto va bene. – preshing