Build bsdtar that uses custom liblzma.dylib library - makefile

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

Related

How to link .dylib libraries after installing an application

This is my first time creating an installer for an application and I need some advice.
This application depends on A.dylib, and A.dylib depends on two other libraries: libstdc++.6.dylib and libgomp.1.dylib which all come from the gcc folder. When I do otool -L on A.dylib, this is what I get :
A.dylib (compatibility version 0.0.0, current version 0.0.0)
/opt/homebrew/opt/gcc/lib/gcc/10/libstdc++.6.dylib (compatibility version 7.0.0, current version 7.28.0)
/opt/homebrew/opt/gcc/lib/gcc/10/libgomp.1.dylib (compatibility version 2.0.0, current version 2.0.0)
Which means that if these two libraries aren't in there, the application won't launch at all. So my problem is with the installer, am I supposed to install libstdc++.6.dylib and libgomp.1.dylib in /opt/homebrew/opt/gcc/lib/gcc/10/ for the user? Even if they don't have a gcc installed there, or at all?
Another option is to install the libraries under say /Library/Application Support/, but then this would mean that the path A.dylib is linked to won't be correct anymore. How do I change the linking path automatically after I install those libraries? What is the best way to go beyond this?

Setting INSTALL_RPATH no longer works when I start using a custom toolchain file

To make my library target link with another dynamic library I am using the following commands:
set_target_properties(MyTarget PROPERTIES INSTALL_RPATH "${MyTargetRPaths}")
This works perfectly until I introduce a custom toolchain file.
I have read Mac OSX and the RPATH wiki and tried all possible combinations of settings suggested there (some of their descriptions are quite obscure) and still I am seeing:
dyld: Library not loaded: #rpath/libstd-a260b5db713b337f.dylib
Referenced from: /Users/Stanislaw/Projects/mull/BuildXcode/unittests/Debug/MullUnitTests
Reason: image not found
otool -L command shows me that rpaths to the libraries I need no longer expand to the full paths of these libraries and I see LD_RUNPATH_SEARCH_PATHS empty.
$ otool -L mylib.dylib
#rpath/libstd-a260b5db713b337f.dylib (compatibility version 0.0.0, current version 0.0.0)
#rpath/libtest-551a7b69d9c2ff2f.dylib (compatibility version 0.0.0, current version 0.0.0)
I still cannot find how presence of -DCMAKE_TOOLCHAIN_FILE=$(myfile) changes the setup of *RPATH* settings in CMake.

Cannot create dylib for distribution that works on OS X 10.5 (building in 10.6 environment)

I'm trying to distribute cairo (1.10.2) with my application. I can create the necessarily dylibs using Homebrew but they are dependent on versions of other dynamic libraries that aren't present in OS X 10.5 (libfontconfig, libfreetype, and others located primarily in /usr/X11/lib).
I assume to solve this I want it to be using the dylibs in /Developer/SDKs/MacOSX10.5.sdk/usr/X11/lib rather than the libraries in /usr/X11/lib. I've tried anything I could find for targeting cairo against the 10.5 SDK.
Setting MACOSX_DEPLOYMENT_TARGET environment variable to 10.5 (before calling brew or using Homebrew's ENV)
Setting SDKROOT environment variable to "/Developer/SDKs/MacOSX10.5.sdk" (before calling brew or using Homebrew's ENV)
Adding -mmacosx-version-min=10.5 to the CFLAGS, CXXFLAGS, and LDFLAGS in the Homebrew formula for cairo.
Adding -sysroot/-isysroot /Developer/SDKs/MacOSX10.5.sdk to the CFLAGS, CXXFLAGS, and LDFLAGS in the Homebrew formula for cairo.
Adding -I$(SDKROOT)/usr/X11/include and -I$(SDKROOT)/usr/X11R6/include to the CFLAGS and CXXFLAGS in the Homebrew formula for cairo.
Adding -L$(SDKROOT)/usr/X11/lib and -L$(SDKROOT)/usr/X11R6/lib to the LDFLAGS in the Homebrew formula for cairo.
While building cairo it has -I/usr/X11/lib on the gcc commands (with my options tacked on the end) so I imagine it's hitting that first. I'm not sure how to get rid of that so it uses my options. I thought isysroot would make it so the include and library paths were rerooted in the SDK but -isysroot doesn't seem to have any effect.
You should be able to use install_name_tool to change where cairo looks for its libraries. (I have no idea what cairo is. I'm assuming it's a dylib. If not, my confidence in this solution goes down considerably.)
Here's a made-up example that you should be able to adapt.
First, use otool -L to see which libraries cairo is using. In this example I'm working with libopencv_imgproc.2.3.1.dylib, but you'll use your cairo library's file name instead:
$ otool -L libopencv_imgproc.2.3.1.dylib
libopencv_imgproc.2.3.1.dylib:
lib/libopencv_imgproc.2.3.dylib (compatibility version 2.3.0, current version 2.3.1)
lib/libopencv_core.2.3.dylib (compatibility version 2.3.0, current version 2.3.1)
/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)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 125.2.11)
Then use install_name_tool -change to change whichever paths you need to change. The first parameter is the current library path, the second is the desired library path, and the third is the library file. I'm telling it to look for libz.1.dylib in /Developer/SDKs/MacOSX10.5.sdk/usr/X11/lib/ instead of /usr/lib:
$ install_name_tool -change /usr/lib/libz.1.dylib /Developer/SDKs/MacOSX10.5.sdk/usr/X11/lib/libz.1.dylib libopencv_imgproc.2.3.1.dylib
Repeat this for every library whose path you need to change. otool -L shows us that the change was made:
$ otool -L libopencv_imgproc.2.3.1.dylib
libopencv_imgproc.2.3.1.dylib:
lib/libopencv_imgproc.2.3.dylib (compatibility version 2.3.0, current version 2.3.1)
lib/libopencv_core.2.3.dylib (compatibility version 2.3.0, current version 2.3.1)
/Developer/SDKs/MacOSX10.5.sdk/usr/X11/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)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 125.2.11)
In my example (and perhaps in your application) my library expects to find itself somewhere other than my application bundle, so I need to change that as well with install_name_tool -id. I'm copying the library to my application bundle's Frameworks folder so I'm telling it to look there:
$install_name_tool -id #executable_path/../Frameworks/libopencv_imgproc.2.3.1.dylib libopencv_imgproc.2.3.1.dylib
You can put the install_name_tool invocations in a Run Script build phase. If you are copying the library into your application bundle's Frameworks folder, you should prepend the library name with $BUILT_PRODUCTS_DIR/$FRAMEWORKS_FOLDER_PATH/ to ensure that the script can find the library.

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