Changing dylib library path with install_name_tool -id, nothing changes - xcode

I'm trying to put an executable together to send to another computer.
otool -L "exec_name" returns:
/usr/local/opt/glfw/lib/libglfw.3.dylib (compatibility version 3.0.0, current version 3.3.0)
trying to change it to my executable directory:
install_name_tool -id #executable_path/libglfw.3.3.dylib libglfw.3.3.dylib
it gives a warning:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/install_name_tool: warning: changes being made to the file will invalidate the code signature in: libglfw.3.3.dylib (for architecture x86_64)
but nothing changes, otool -L still shows:
/usr/local/opt/glfw/lib/libglfw.3.dylib (compatibility version 3.0.0, current version 3.3.0)
I also tried
install_name_tool -id #executable_path/libglfw.3.3.dylib libglfw.3.dylib
This gives an error:
error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/install_name_tool: can't open file: libglfw.3.dylib (No such file or directory)
Cannot understand why it would not change the path...

Two issues:
It's #executable_path, not #executive_path.
You need to change the install name both in the library and the binary that links against it:
install_name_tool -id #executable_path/libglfw.3.3.dylib libglfw.3.3.dylib
install_name_tool -change /usr/local/opt/glfw/lib/libglfw.3.dylib #executable_path/libglfw.3.3.dylib [exec_name]
For a deeper explanation of how install names work, see this answer of mine.

Related

Build bsdtar that uses custom liblzma.dylib library

Might be a very obvious thing to do, but I'm stuck on trying to build a bsdtar that uses a custom build version of liblzma.dylib, so I can share both the bsdtar binary and the liblzma.dylib library together.
Thanks to Tsyvarev comment, I'm building bsdtar with the custom the dylib, simply calling:
cmake -DCMAKE_PREFIX_PATH=customlib
No more need to use FIND_PACKAGE(liblzma HINTS customlib customlib/include) or similar. During the cmake process, the output looks like this:
-- Looking for lzma_auto_decoder in /libarchive-3.3.2/customlib/liblzma.dylib
-- Looking for lzma_auto_decoder in /libarchive-3.3.2/customlib/liblzma.dylib - found
-- Looking for lzma_easy_encoder in /libarchive-3.3.2/customlib/liblzma.dylib
-- Looking for lzma_easy_encoder in /libarchive-3.3.2/customlib/liblzma.dylib - found
-- Looking for lzma_lzma_preset in /libarchive-3.3.2/customlib/liblzma.dylib
-- Looking for lzma_lzma_preset in /libarchive-3.3.2/customlib/liblzma.dylib - found
-- Found LibLZMA: /libarchive-3.3.2/customlib/include (found version "5.2.3")
Anyway, the final build of bsdtar still looks for the system dylib, instead of the custom one:
aone$ otool -L libarchive-3.3.2/bin/bsdtar
libarchive-3.3.2/bin/bsdtar:
/usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.5)
/usr/lib/libbz2.1.0.dylib (compatibility version 1.0.0, current version 1.0.5)
/usr/local/lib/liblzma.5.dylib (compatibility version 8.0.0, current version 8.3.0)
...
The folder customlib contains liblzma.5.dylib, it's alias liblzma.dylib and liblzma.a. The folder customlib/import contains lzma.h and and lzma folder with the rest of the headers.
Anyone has any clue how to do it properly? Thanks in advance.
Just asked it here: https://github.com/libarchive/libarchive/issues/1014
Finally did it post compilation with install_name_tool (man):
install_name_tool -change "/usr/local/lib/liblzma.5.dylib" "customlib/liblzma.dylib" bsdtar

raco executables linked to invalid runtime

I have Racket installed via homebrew. When I attempt to create an executable with raco, per:
raco exe my_prog.rkt
...the resulting binary is linked to a Racket runtime with an invalid path. This can be seen with otool -L:
my_prog:
/usr/local/Cellar/racket/6.3/lib/racket/Racket.framework/Versions/6.3_3m/Racket (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1213.0.0)
The correct path doesn't contain racket/ after lib/. Thus, when you attempt to run the binary, dyld complains and aborts execution.
I can fix this, using install_name_tool:
chmod +w my_prog
install_name_tool -change /usr/local/Cellar/racket/6.3/lib/racket/Racket.framework/Versions/6.3_3m/Racket /usr/local/Cellar/racket/6.3/lib/Racket.framework/Versions/6.3_3m/Racket my_prog
...however, obviously this isn't something I want to have to do all the time!
Presumably raco is getting this invalid path from somewhere. Is there some way that I can configure this correctly?

install_name_tool reporting malformed object

Everytime I try to use install_name_tool on my machine it reports the following
install_name_tool: object: Abacate malformed object (unknown load command 4)
I read that it could be an error when building the binary. In order to check I create the simplest hello world c++ program and try to change something using install_name_tool. Didn't work. What Am I doing wrong?
Currently I have XCode 4.2 running Snow Leopard OS.
Apparently install_name_tool is not updated when XCode is updated. You need to install the Command Line Tools from XCode Preferences. See also install_name_tool on OS X Lion. This resolved the same error for me.
Managed to make it work with Mac OS 10.9.3
https://github.com/Homebrew/homebrew/issues/26544
$$:~ otool -L /usr/bin/install_name_tool
/usr/bin/install_name_tool: /usr/lib/libxcselect.dylib (compatibility
version 1.0.0, current version 1.0.0) /usr/lib/libSystem.B.dylib
(compatibility version 1.0.0, current version 1197.1.1)
$$:~ pkgutil --file-info /usr/bin/install_name_tool
volume: / path:
/usr/bin/install_name_tool
pkgid: com.apple.pkg.Essentials pkg-version: 10.9.0.1.1.1306847324
install-time: 1390577801 uid: 0 gid: 0 mode: 755
No more errors on wget:
$$:~ wget dyld: Library not loaded:
##HOMEBREW_PREFIX##/opt/openssl/lib/libssl.1.0.0.dylib Referenced
from: /usr/local/bin/wget Reason: image not found

How do I bundle a library within a Cocoa application?

I have the library libmysqlclient.16.dylib, which I need to have on the computer where my application is running, or I will get the following error:
Dyld Error Message: Library not
loaded:
/usr/local/mysql/lib/libmysqlclient_r.16.dylib
Referenced from: /Users/alex/snow
server 3.app/Contents/MacOS/snow
server Reason: image not found
This is very strange, because I linked the binary with this library.
If the same dylib exists on the target computer, but in a different version (for example, Snow Leopard Server), I get an error like the following:
Dyld Error Message: Library not
loaded:
/usr/local/mysql/lib/libmysqlclient_r.16.dylib
Referenced from: /Users/alex/snow
server 3.app/Contents/MacOS/snow
server Reason: no suitable image
found. Did find:
/usr/local/mysql/lib/libmysqlclient_r.16.dylib:
mach-o, but wrong architecture
I'd like to link against this library, but not have to use the local copy of it. Is this possible?
UPDATE - when i try to using install_name_tool i don't have any changes:
bash-3.2# otool -L
libmysqlclient.16.dylib
libmysqlclient.16.dylib:
libmysqlclient.16.dylib
(compatibility version 16.0.0, current
version 16.0.0)
/usr/lib/libSystem.B.dylib
(compatibility version 1.0.0, current
version 123.0.0)
/usr/lib/libz.1.dylib (compatibility
version 1.0.0, current version 1.2.3)
/usr/lib/libstdc++.6.dylib
(compatibility version 7.0.0, current
version 7.9.0) bash-3.2#
install_name_tool -change
libmysqlclient.16.dylib
#executable_path/../Frameworks/libmysqlclient.16.dylib
Usage: install_name_tool [-change old
new] ... [-rpath old new] ...
[-add_rpath new] ... [-delete_rpath
old] ... [-id name] input bash-3.2#
install_name_tool -change
libmysqlclient.16.dylib
#executable_path/../Frameworks/libmysqlclient.16.dylib
libmysqlclient.16.dylib bash-3.2#
otool -L libmysqlclient.16.dylib
libmysqlclient.16.dylib:
libmysqlclient.16.dylib
(compatibility version 16.0.0, current
version 16.0.0)
/usr/lib/libSystem.B.dylib
(compatibility version 1.0.0, current
version 123.0.0)
/usr/lib/libz.1.dylib (compatibility
version 1.0.0, current version 1.2.3)
/usr/lib/libstdc++.6.dylib
(compatibility version 7.0.0, current
version 7.9.0)
SOLUTION
i was add a script into build phase:
install_name_tool -change libmysqlclient.16.dylib #executable_path/../Frameworks/libmysqlclient.16.dylib $CONFIGURATION_BUILD_DIR/$PRODUCT_NAME.app/Contents/MacOS/$PRODUCT_NAME
this was fixed a libpath for executive product and working fine with lib in bundle.
First, you'll want to make sure that you're copying this library into your application bundle so that it will be available on the user's machine. To do this, add a new Copy Files build phase for your application to copy bundled frameworks. Within the properties of that build phase, make sure that the destination is Frameworks. Drag your library from your project into that build phase to make sure that it is packaged with your application.
You may also need to modify the library itself so that it points to the correct location within the application bundle. In the past, I've done this by making a copy of the library within my project's directory, then using the following command to modify where the library expects to find itself:
install_name_tool -id #executable_path/../Frameworks/libftd2xx.0.1.0.dylib libftd2xx.0.1.0.dylib
In this case, the library being modified was called libftd2xx.0.1.0.dylib.
You can use the command
otool -L [library filename]
to see the path where the library expects itself to be found and determine if this change needs to be made.
Make sure that you change the path on the library within your Xcode project so that you will be linking against this new, modified version of the library residing within your project directory.

Linking to a dynamic library on a Mac with full path

I am linking a (Python extension) library that embeds the Matlab engine with the following command (generated using cmake)
c++ -mmacosx-version-min=10.6 -bundle -headerpad_max_install_names -o library.so library.o /Applications/MATLAB_R2009b.app/bin/maci64/libeng.dylib /Applications/MATLAB_R2009b.app/bin/maci64/libmx.dylib -framework Python
resulting in
$ otool -L library.so
library.so:
#loader_path/libeng.dylib (compatibility version 0.0.0, current version 0.0.0)
#loader_path/libmx.dylib (compatibility version 0.0.0, current version 0.0.0)
/System/Library/Frameworks/Python.framework/Versions/2.6/Python (compatibility version 2.6.0, current version 2.6.1)
/opt/local/lib/gcc44/libstdc++.6.dylib (compatibility version 7.0.0, current version 7.13.0)
/opt/local/lib/gcc44/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 125.0.0)
However, when I try to use the library, I get an error message:
ImportError: dlopen(./library.so, 2): Library not loaded: #loader_path/libmex.dylib
Referenced from: ./library.so
Reason: image not found
I believe the problem stems from the fact that the linker includes the matlab dylib files in the form #loader_path/libeng.dylib rather than using the full path, even though I give the full path to g++. How can I force the linker to use the full path?
I know one solution is to use
export DYLD_LIBRARY_PATH=/Applications/MATLAB_R2009b.app/bin/maci64:$DYLD_LIBRARY_PATH
which is where those library files reside, but I'd like to avoid that as it causes some other problems.
Manually changing the files using install_name_tool
install_name_tool -change "#loader_path/libeng.dylib" "/Applications/MATLAB_R2009b.app/bin/maci64/libeng.dylib" library.so
install_name_tool -change "#loader_path/libmx.dylib" "/Applications/MATLAB_R2009b.app/bin/maci64/libmx.dylib" library.so
I could use this as a temporary fix, but I wonder if there isn't a better solution where the linker is given a setting to use the full paths.
Note that some of the problems with DYLD_LIBRARY_PATH can be prevented by using DYLD_FALLBACK_LIBRARY_PATH instead. This will only be used if the lib cannot be found in the default paths.
Look into the -rpath option to the ld command to control this. You might also be interested in the contents of https://github.com/bimargulies/jni-origin-testbed, which is a demonstration of some relevant technology.
The critical technique here is:
install_name_tool -change libsl2.so "#loader_path/libsl2.so" libsl1.so
You can also use symbolic link !

Resources