auriamg / macdylibbundler

Utility to ease bundling libraries into executables for OSX
MIT License
546 stars 83 forks source link

Failed at a barebone example. #41

Open kakyoism opened 4 years ago

kakyoism commented 4 years ago

Coming from this issue: https://github.com/auriamg/macdylibbundler/issues/40

I've built a sanity-check example, which fails to find the dylib upon running:

After successfully building both projects, I then run

(12:44)me@mymac:~/Desktop/_learn/gtk/hello_dylib/build/Debug 
$ dylibbundler -od -b -x hello_dylib.app/Contents/MacOS/hello_dylib -d hello_dylib.app/Contents/Resources/lib/ -p @executable_path/../Resources/lib/
* Collecting dependencies...
/!\ WARNING : Library libmylib.dylib  has an incomplete name (location unknown)
Please specify now where this library can be found (or write 'quit' to abort): /Users/me/Desktop/_learn/gtk/mylib/build/Debug

/Users/me/Desktop/_learn/gtk/mylib/build/Debug/libmylib.dylib  was found. /!\MANUALLY CHECK THE EXECUTABLE WITH 'otool -L', DYLIBBUNDLDER MAY NOT HANDLE CORRECTLY THIS UNSTANDARD/ILL-FORMED DEPENDENCY
.......FOUND libmylib.dylib  in /Users/me/Desktop/_learn/gtk/mylib/build/Debug/

 * libmylib.dylib  from /Users/me/Desktop/_learn/gtk/mylib/build/Debug/

* Checking output directory hello_dylib.app/Contents/Resources/lib/
* Erasing old output directory hello_dylib.app/Contents/Resources/lib/
    rm -r hello_dylib.app/Contents/Resources/lib/
* Creating output directory hello_dylib.app/Contents/Resources/lib/
    mkdir -p hello_dylib.app/Contents/Resources/lib/
    cp -n /Users/me/Desktop/_learn/gtk/mylib/build/Debug/libmylib.dylib  hello_dylib.app/Contents/Resources/lib/libmylib.dylib 
    chmod +w hello_dylib.app/Contents/Resources/lib/libmylib.dylib 
    install_name_tool -id @executable_path/../Resources/lib/libmylib.dylib  hello_dylib.app/Contents/Resources/lib/libmylib.dylib 

* Fixing dependencies on hello_dylib.app/Contents/Resources/lib/libmylib.dylib 
    install_name_tool -change /Users/me/Desktop/_learn/gtk/mylib/build/Debug/libmylib.dylib  @executable_path/../Resources/lib/libmylib.dylib  hello_dylib.app/Contents/Resources/lib/libmylib.dylib 
    install_name_tool -change libmylib.dylib  @executable_path/../Resources/lib/libmylib.dylib  hello_dylib.app/Contents/Resources/lib/libmylib.dylib 

* Fixing dependencies on hello_dylib.app/Contents/MacOS/hello_dylib
    install_name_tool -change /Users/me/Desktop/_learn/gtk/mylib/build/Debug/libmylib.dylib  @executable_path/../Resources/lib/libmylib.dylib  hello_dylib.app/Contents/MacOS/hello_dylib
    install_name_tool -change libmylib.dylib  @executable_path/../Resources/lib/libmylib.dylib  hello_dylib.app/Contents/MacOS/hello_dylib

After this I simply run in Terminal:

/Users/me/Desktop/_learn/gtk/hello_dylib/build/Debug/hello_dylib.app/Contents/MacOS/hello_dylib

I got:

(12:45) me@mymac:~/Desktop/_learn/gtk/hello_dylib/build/Debug 
$ hello_dylib.app/Contents/MacOS/hello_dylib 
dyld: Library not loaded: /usr/local/lib/libmylib.dylib
  Referenced from: /Users/me/Desktop/_learn/gtk/hello_dylib/build/Debug/hello_dylib.app/Contents/MacOS/hello_dylib
  Reason: image not found
Abort trap: 6

I wonder where I did wrong.

kakyoism commented 4 years ago

The test projects are attached. Unzip, do not change their relative location, and build them both. Then you should be able to see what I see, hopefully. Archive.zip

kakyoism commented 4 years ago

I tried something new. After I see the Abort trap, I simply:

install_name_tool -change /usr/local/lib/libmylib.dylib @executable_path/../Resources/lib/libmylib.dylib hello_dylib.app/Contents/MacOS/hello_dylib

Then, run the executable as usual

/Users/me/Desktop/_learn/gtk/hello_dylib/build/Debug/hello_dylib.app/Contents/MacOS/hello_dylib

This gives me exactly what was in #40:

Killed: 9
kakyoism commented 4 years ago

After some digging, I solved my problem by doing the whole dance manually through otool and install_name_tool. macdylibbundler by design has a particular problem:

the last op:

install_name_tool -change libmylib.dylib  @exececutable_path/../Frameworks/lib/libmylib.dylib  hello_dylib.app/Contents/MacOS/hello_dylib

in my case should be corrected to:

install_name_tool -change /usr/local/lib/libmylib.dylib  @exececutable_path/../Frameworks/lib/libmylib.dylib  hello_dylib.app/Contents/MacOS/hello_dylib

which means on my machine, the dylibs are first searched under some system paths such as /usr/local/lib, instead of the working directory. The output of otool -L /path/to/hello_dylib gives me

otool -L "/Users/me/Desktop/_learn/gtk/hello_dylib/build/Debug/hello_dylib.app/Contents/MacOS/hello_dylib"
/Users/kakyo/Desktop/_learn/gtk/hello_dylib/build/Debug/hello_dylib.app/Contents/MacOS/hello_dylib:
    **/usr/local/lib/libmylib.dylib** (compatibility version 1.0.0, current version 1.0.0)
    /System/Library/Frameworks/Cocoa.framework/Versions/A/Cocoa (compatibility version 1.0.0, current version 23.0.0)
    /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (compatibility version 300.0.0, current version 1575.17.0)
    /usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
    /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 400.9.4)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.250.1)
    /System/Library/Frameworks/AppKit.framework/Versions/C/AppKit (compatibility version 45.0.0, current version 1671.60.107)
    /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 1575.17.0)

So the executable does assume that my lib to be under /usr/local/lib I don't know if this has anything to do with my custom $PATH, which has been modified by I don't know how many other apps. But I suspect that macdylibbundler should parse otool output faithfully.

auriamg commented 4 years ago

dylibbundler is a simple tools that works for most basic cases, but it was not meant to handle all the weird special cases. I actually no longer use a mac very often, so this project is a bit in search of a new maintainer.

One possibility is that your "libmylib" has an incorrect (or at least unusual) "internal name", dylibbundler will have trouble handling those

jpcima commented 4 years ago

I have a similar problem when I try to work with a dylib file.

My observation was that when I link as -dynamiclib, as opposed to -bundle, the library file is self-referring in the output of otool -L.

./string-machine.lv2/string-machine_ui.dylib:
    ../../bin/string-machine.lv2/string-machine_ui.dylib (compatibility version 0.0.0, current version 0.0.0)

And then dylibbundler fails, indicating that it can't find itself.

/!\ WARNING : Cannot resolve path '../../bin/string-machine.lv2/string-machine_ui.dylib'
/!\ WARNING : Library string-machine_ui.dylib has an incomplete name (location unknown)

This path is identical to the option -o of the compiler.

Do you think it's fine to ignore the first entry in case the file is a dylib?

jpcima commented 4 years ago

I found myself an answer, it's otool -L is showing the load command LC_ID_DYLIB.

For correctness, you have to get dylib ID (otool -D) and remove it from -L output.