2015-11-13 9 views
7

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.

risposta

12

con C++ filt (o http://demangler.com) per decodifica i due simboli, il simbolo nella libreria Boost ha un prefisso std::__1::basic_string, mentre quello che manca nella follia ha std::string. Alcuni googling indicano che il subnamespace __1 viene utilizzato da libC++ (libreria standard C++ di clang) per evitare conflitti con libstdC++ (GNU). Questo indica che boost è stato compilato usando clang e libC++, che sono di default su OS X, mentre la follia è stata compilata con libstdC++ (usando g ++ o specificando flag diversi su clang).

Poiché le due librerie non dispongono di un ABI compatibile, la semplice correzione del nome del simbolo non è di aiuto, pertanto la soluzione dovrà implicare la ricompilazione in modo che entrambi condividano la stessa implementazione di libreria standard.

+0

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

Problemi correlati