## Abstract
For some circumstances the linker provided by Xcode writes absolute paths of dependent libraries. If you have an executable which uses /opt/local/lib/something.dylib.0.0 for example, then you’ll need to put that library in /opt/local/lib/ every time you want to run that executable, otherwise it will fail.
## Problem
So if you plan to distribute your executable and all the relative libraries with less pain, try Freely! It will copy libraries on which your software depends (with dependencies for that libs, I mean recursive resolving) in the specified directory (./lib/ by default) and relocate their paths by modifying the target executable.
## Installation
% gem install freely
## Example
### Compiling
Okay, let’s get some libs to link with:
% pkg-config --libs gio-2.0
-L/opt/local/lib -lgio-2.0 -lgobject-2.0 -lglib-2.0 -lintl
Linking our dummy test binary:
% gcc -L/opt/local/lib -lgio-2.0 -lgobject-2.0 -lglib-2.0 -lintl test.c -o test
Checking with ‘otool -L`:
% otool -L test
test:
/opt/local/lib/libgio-2.0.0.dylib (compatibility version 3201.0.0, current version 3201.4.0)
/opt/local/lib/libgobject-2.0.0.dylib (compatibility version 3201.0.0, current version 3201.4.0)
/opt/local/lib/libglib-2.0.0.dylib (compatibility version 3201.0.0, current version 3201.4.0)
/opt/local/lib/libintl.8.dylib (compatibility version 10.0.0, current version 10.1.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 169.3.0)
Oh noes! Hard references all the way! It’s okay if these libs are in the /opt/local/ path, but what about that case:
afroditetest:
/Users/xlab/Documents/Coding/Vala/afrodite/out/libafrodite-1.0.dylib (compatibility version 0.0.0, current version 0.0.0)
.............
It’s in the temporary place which is going to disappear when I run ‘make clean` etc. How to avoid that hard referencing and produce executable which refers only on neary placed ./lib?
### The Freely
Just before running freely:
% tree
.
├── test
Okay, let’s give it a chance:
% freely ./test
# Loading test
# Looking for dependencies
libiconv.2.dylib
libintl.8.dylib
libglib-2.0.0.dylib
libgthread-2.0.0.dylib
libffi.6.dylib
libgobject-2.0.0.dylib
libgmodule-2.0.0.dylib
libz.1.dylib
libgio-2.0.0.dylib
# Copying dependencies into ./lib
# Relinking dependencies
/opt/local/lib/libiconv.2.dylib => lib/libiconv.2.dylib
/opt/local/lib/libintl.8.dylib => lib/libintl.8.dylib
..replacing subsequent dependencies
/opt/local/lib/libglib-2.0.0.dylib => lib/libglib-2.0.0.dylib
..replacing subsequent dependencies
/opt/local/lib/libgthread-2.0.0.dylib => lib/libgthread-2.0.0.dylib
..replacing subsequent dependencies
/opt/local/lib/libffi.6.dylib => lib/libffi.6.dylib
/opt/local/lib/libgobject-2.0.0.dylib => lib/libgobject-2.0.0.dylib
..replacing subsequent dependencies
/opt/local/lib/libgmodule-2.0.0.dylib => lib/libgmodule-2.0.0.dylib
..replacing subsequent dependencies
/opt/local/lib/libz.1.dylib => lib/libz.1.dylib
/opt/local/lib/libgio-2.0.0.dylib => lib/libgio-2.0.0.dylib
..replacing subsequent dependencies
Wow!
% tree
.
├── lib
So, here we have a complete dependecy collection in a single ./lib directory! And what about hard links of the test executable?
% otool -L test
test:
lib/libgio-2.0.0.dylib (compatibility version 3201.0.0, current version 3201.4.0)
lib/libgobject-2.0.0.dylib (compatibility version 3201.0.0, current version 3201.4.0)
lib/libglib-2.0.0.dylib (compatibility version 3201.0.0, current version 3201.4.0)
lib/libintl.8.dylib (compatibility version 10.0.0, current version 10.1.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 169.3.0)
Awesome, subsequent references are cleaned too:
% otool -L lib/libintl.8.dylib
lib/libintl.8.dylib:
lib/libiconv.2.dylib (compatibility version 8.0.0, current version 8.1.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 169.3.0)
/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 744.0.0)
### Happy end
And now you can distribute your application! The executable will look only for ./lib directory and libs in it. Referenced system libs will stay unchanged, since they’re built-in or redistributable.
### Another options
Freely - make your OSX executable very portable.
Usage: freely [] executable
-p, --prefix DIR Directory name to store dependencies ("./lib" by default)
-s, --silent Don't echo re-linking info
-h, --help Show this help message
## License
Copyright (C) 2012 Maxim Kouprianov
This software is provided 'as-is', without any express or implied
warranty. In no event will the be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
Maxim Kouprianov <me@kc.vc>