install_name_tool om een ​​uitvoerbaar bestand bij te werken om te zoeken naar dylib in Mac OS X

Ik heb een dynamische libray libtest.dylib die is geïnstalleerd in /PATH/lib, en een uitvoerings-binary, myapp, die de dylib gebruikt die is geïnstalleerd in /PATH/bin.

Ik kan myappuitvoeren om de dylib als volgt te vinden (Is het OK om DYLD_LIBRARY_PATH op Mac OS X te gebruiken? En wat is het dynamische bibliotheekzoekalgoritme daarbij?):

DYLD_LIBRARY_PATH="/PATH/lib" myapp 

Ik denk dat ik install_name_toolkan gebruiken om de bibliotheek en het uitvoerbare bestand bij te werken, zodat de bibliotheek kan worden gevonden met rpath. Ik heb de hints in dit bericht gebruikt – Hoe kan ik het rpath specificeren in een dylib?.

In lib heb ik dit commando uitgevoerd om rpath toe te voegen.

install_name_tool -id "@rpath/libtest.dylib" libtest.dylib
install_name_tool -add_rpath "@executable_path/../lib/" libtest.dylib

In bin heb ik install_name_tool -add_rpath "@executable_path/../lib/" myappuitgevoerd.

Toen ik echter myappuitvoerde in de bin-directory, kreeg ik de foutmeldingen.

dyld: Library not loaded: libtest.dylib
  Referenced from: /PATH/bin/./myapp
  Reason: image not found
Trace/BPT trap: 5

otool -l myapplaat zien dat het rpath correct is bijgewerkt in mijnapp.

Load command 16
          cmd LC_RPATH
      cmdsize 40
         path @executable_path/../lib/ (offset 12)

Hetzelfde geldt voor libtest.dylib

Load command 13
          cmd LC_RPATH
      cmdsize 40
         path @executable_path/../lib/ (offset 12)

Wat kan er mis zijn?

TOEGEVOEGD

Natuurlijk kan ik cc -install_namegebruiken tijdens het compileren en koppelen, maar ik wilde weten hoe ik hetzelfde moest doen door de gegenereerde dylib en het uitvoerings-binaire bestand aan te passen.

Vanuit de bibliotheek:

cc -install_name "@loader_path/../lib/libtest.dylib" -dynamiclib -o libtest.dylib test.c

Of de installatienaam kan @rpath gebruiken:

cc -install_name "@rpath/libtest.dylib" -dynamiclib -o libtest.dylib test.c

Uit de prullenbak:

cc -I../lib -c main.c
cc -o main main.o ../lib/libtest.dylib -Wl,-rpath -Wl,@loader_path/../lib

Of slechts één regel:

cc -I../lib -L../lib -o main main.c -ltest -Wl,-rpath -Wl,@loader_path/../lib

Antwoord 1, autoriteit 100%

Van otool -lheb ik geanalyseerd wat er moet worden toegevoegd of gewijzigd vanuit de originele bibliotheek en binair.

Dylib

De wijziging is in id:

Load command 2 <-- OLD
          cmd LC_ID_DYLIB
      cmdsize 40
         name libtest.dylib (offset 24)
   time stamp 1 Wed Dec 31 18:00:01 1969
Load command 2 <-- NEW
          cmd LC_ID_DYLIB
      cmdsize 64
         name @loader_path/../lib/libtest.dylib (offset 24)

Dit is het commando om de verandering te bewerkstelligen:

install_name_tool -id "@loader_path/../lib/libtest.dylib" libtest.dylib 

Of gebruik rpath:

install_name_tool -id "@rpath/libtest.dylib" libtest.dylib

Het uitvoerbare bestand

Er zijn twee wijzigingen: rpath en load_dylib

Load command 12 <-- OLD
          cmd LC_LOAD_DYLIB
      cmdsize 40
         name libtest.dylib (offset 24)
Load command 12 <-- NEW
          cmd LC_LOAD_DYLIB
      cmdsize 64
         name @loader_path/../lib/libtest.dylib (offset 24)

Dit is het commando om de verandering te bewerkstelligen

install_name_tool -change libtest.dylib @loader_path/../lib/libtest.dylib myapp 

Ik moest ook het rpath toevoegen

Load command 14
          cmd LC_RPATH
      cmdsize 32
         path @loader_path/../lib (offset 12)

Dit is het commando om de toevoeging uit te voeren:

install_name_tool -add_rpath "@loader_path/../lib" myapp

Het idee

Het binaire bestand probeert de bibliotheek te vinden, het weet waar het zich bevindt van install_name_tool -add_rpath "@loader_path/../lib" myapp. Het laadt de bibliotheek en de id van de bibliotheek is @rpath/libtest.dylibwaarbij @rpathis ingesteld op @loader_path/../libin het uitvoerbare binaire bestand om de match te maken.

Referentie

Cmake

Bij gebruik van CMake kunnen we het proces automatiseren met de volgende toevoeging in het CMakeLists.txt-bestand.

Bibliotheek

De id moet worden toegevoegd.

# https://cmake.org/pipermail/cmake/2006-October/011530.html
SET_TARGET_PROPERTIES (test
  PROPERTIES BUILD_WITH_INSTALL_RPATH 1
             INSTALL_NAME_DIR "@rpath"
  )

Uitvoerbaar

Het rpath moet worden gespecificeerd:

SET(CMAKE_INSTALL_RPATH "@loader_path/../lib/libtest.dylib")

Other episodes