2011-01-13 16 views
31

Ho creato un'applicazione (un eseguibile) che chiama con successo alcuni dylib, tuttavia i file dylib e l'eseguibile si trovano in una directory diversa. Ho aggiunto che la directory contiene i file dylib nella variabile di ambiente $ PATH, tuttavia, non viene ancora caricata. Copio tutti i file dylib nell'eseguibile, il programma finalmente viene eseguito. Ciò conferma che i file dylib non hanno alcun problema. Tuttavia, come posso dire al sistema operativo di trovarlo? In Windows, ho solo bisogno di aggiungere il percorso della directory contiene i file dll in $ PATH. Cosa devo fare per Mac OS X? Grazie mille!Come usare dylib in Mac OS X (C++)

+4

Controllare le dipendenze della vostra app utilizzando 'otool -L app'. Se sono hardcoded come percorsi assoluti, modificali usando 'install_name_tool -change old new file' per diventarne uno relativo. Successivamente, il linker può trovare una libreria nella variabile di ambiente 'DYLD_LIBRARY_PATH'. – aponomarenko

risposta

2

Se il dylib si trova nel punto specificato da INSTALL_NAME della libreria, funzionerà semplicemente *.

Altrimenti, è possibile aggiungere la posizione del dylib a DYLD_LIBRARY_PATH. Si potrebbe voler leggere il dyld documentation.

*) per essere completamente precisi, è necessario che sia presente in DYLD_ROOT_PATH/INSTALL_NAME, ma il problema con DYLD_ROOT_PATH è piuttosto raro.

+0

Mi spiace, che cos'è "INSTALL_NAME della libreria"? Aggiungo DYLD_LIBRARY_PATH e non funziona, quindi confuso. –

+0

È necessario esportare la variabile: export DYLD_LIBRARY_PATH =/usr/local/lib' – Michel

13

È necessario impostare la variabile di ambiente DYLD_LIBRARY_PATH.

Dal dyld man page:

 This is a colon separated list of directories that contain libraries. The dynamic linker 
     searches these directories before it searches the default locations for libraries. It allows 
     you to test new versions of existing libraries. 

     For each library that a program uses, the dynamic linker looks for it in each directory in 
     DYLD_LIBRARY_PATH in turn. If it still can't find the library, it then searches DYLD_FALL- 
     BACK_FRAMEWORK_PATH and DYLD_FALLBACK_LIBRARY_PATH in turn. 
+0

grazie! Ho anche trovato questo da google, ho impostato il DYLD_LIBRARY_PATH, tuttavia, non funziona, il problema è ancora lì! Sono così confuso –

+0

Ho appena provato e funziona benissimo sul mio Mac. – EmeryBerger

+0

Ciao, EmeryBerger, sei la variabile DYLD_LIBRARY_PATH originariamente vuota. il mio è. Non so se questo è sbagliato in primo luogo. –

34

Dopo aver letto il link che Justin fornito, sono stato con successo in grado di utilizzare il @executable_path token per cambiare il mio dylib install_name per puntare alla stessa directory in cui si trova il mio eseguibile.

@executable_path I percorsi assoluti sono fastidiosi. A volte si desidera incorporare un framework in un'applicazione invece di dover installare il framework in/Library o in una posizione simile.

La soluzione del Mac per questo è @executable_path. Questo è un token magico che, quando collocato all'inizio del nome di installazione di una libreria, ottiene espanso nel percorso dell'eseguibile che lo sta caricando, meno l'ultimo componente . Ad esempio, supponiamo che i collegamenti Bar.app rispetto a Foo.framework. Se Bar.app è installato in/Applicazioni, @executable_path si espanderà in /Applications/Bar.app/Contents/MacOS. Se si intende incorporare il framework in Contents/Frameworks, è possibile impostare semplicemente il nome di installazione di Foo.framework su @executable_path /../ Frameworks/Foo.framework/Versions/A/Foo. Il linker dinamico che si espanderà a /Applications/Bar.app/Contents/MacOS/../Frameworks/Foo.framework/Versions/A/Foo e troverà il quadro lì.

http://www.mikeash.com/pyblog/friday-qa-2009-11-06-linking-and-install-names.html

dimostrerò con un esempio.

Diciamo che ho il seguente eseguibile /opt/local/bin/convertire e le sue dylibs sono in /opt/local/lib. Voglio copiarlo in un'altra directory e fargli caricare i suoi dylibs dalla stessa directory di dove ho copiato l'eseguibile.

> mkdir ~/tmp/bin 
> cp /opt/local/bin/convert ~/tmp/bin 

Ottenere un elenco di file eseguibili dylibs

> otool -L ~/tmp/bin/convert 
~/tmp/bin/convert: 
    /opt/local/lib/libtiff.3.dylib (compatibility version 13.0.0, current version 13.5.0) 
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.1.0) 
    /opt/local/lib/libjpeg.8.dylib (compatibility version 12.0.0, current version 12.0.0) 
    /opt/local/lib/libfontconfig.1.dylib (compatibility version 6.0.0, current version 6.4.0) 
    /opt/local/lib/libiconv.2.dylib (compatibility version 8.0.0, current version 8.1.0) 
    /opt/local/lib/libfreetype.6.dylib (compatibility version 15.0.0, current version 15.0.0) 
    /opt/local/lib/libexpat.1.dylib (compatibility version 7.0.0, current version 7.2.0) 
    /opt/local/lib/libbz2.1.0.dylib (compatibility version 1.0.0, current version 1.0.6) 
    /opt/local/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.6) 
    ... 

mi interessa solo i dylibs nella /opt/local/lib dir, quindi tiriamo fuori solo dylibs in /opt . Voglio mantenere intatti tutti gli altri riferimenti di dylib, in particolare su /usr/lib/libSystem.

> DYLIBS=`otool -L ~/tmp/bin/convert | grep "/opt" | awk -F' ' '{ print $1 }'` 

copiare tutti i dylibs che i riferimenti eseguibili allo stesso dir in cui l'eseguibile è stato copiato.

> for dylib in $DYLIBS; do cp $dylib ~/tmp/bin/; done; 

Utilizzare la install_name_tool di cambiare il nome di installazione di tutti i dylibs abbiamo tirato fuori nel passaggio precedente, e sostituirli anteponendo il @executable_path al nome dylib. Ciò farà sì che il linker dinamico cerchi il dylib nella stessa directory in cui si trova il file eseguibile.

> for dylib in $DYLIBS; do install_name_tool -change $dylib @executable_path/`basename $dylib` ~/tmp/bin/convert; done; 

Verificare che i nomi di installazione sono stati cambiati e che libSystem è ancora indicando /usr/lib/libSystem.

> otool -L ~/tmp/bin/convert 
~/tmp/bin/convert: 
    @executable_path/libtiff.3.dylib (compatibility version 13.0.0, current version 13.5.0) 
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.1.0) 
    @executable_path/libjpeg.8.dylib (compatibility version 12.0.0, current version 12.0.0) 
    @executable_path/libfontconfig.1.dylib (compatibility version 6.0.0, current version 6.4.0) 
    @executable_path/libiconv.2.dylib (compatibility version 8.0.0, current version 8.1.0) 
    @executable_path/libfreetype.6.dylib (compatibility version 15.0.0, current version 15.0.0) 
    @executable_path/libexpat.1.dylib (compatibility version 7.0.0, current version 7.2.0) 
    @executable_path/libbz2.1.0.dylib (compatibility version 1.0.0, current version 1.0.6) 
    @executable_path/libz.1.dylib (compatibility version 1.0.0, current version 1.2.6) 
    ... 
+0

Nota che sembra che devi farlo anche per ogni file di libreria, poiché possono anche contenere collegamenti a percorsi assoluti – Claudiu