## 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 [options] 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 authors 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>