0

I want to include the GNU Scientific Library (GSL) in my Cocoa app so that the user needs not installing it locally first. Like most GNU packages, it's the standard configure / make / make install routine. But this won't work:

./configure --prefix ~/libgsl
make
make install

Since the prefix is local to my computer. And neither is this:

./configure --prefix (path to build folder)/libgsl
make
make install

What I want is essentially the GSL being contained entirely in my application, and I can call its functions without the users downloading anything else.

I'm rather new to Xcode 4 and the build system for Clang/GCC, having coming over from .NET. Any help is much appreciated.

Code Different
  • 90,614
  • 16
  • 144
  • 163
  • I think it's sufficient to generate the `config.h` header by running `./configure` only, then copy-pasta all the source files (with their directory structure preserved, preferably) into your app/Xcode project. –  Jul 01 '13 at 12:29

1 Answers1

1

Assuming there is not a framework-style build of the library, the way this is typically done when bundling with 3rd party libraries is to build the package as normal, install it in /usr/local, and configure your project to include and link from there. Building is the easy part though.

The tricky part is bundling up the .app correctly. You need to add a custom build stage (after the others) which first copies all the dependent .dylib files into your app bundle's Frameworks folder (using the environment variables to help; see Xcode docs). Then you need to use install_name_tool to get the app binary to look in the framework dir (as the embedded soname still thinks it is in /usr/local). This part is very fiddly and not well documented.

I've just extracted this from a working project where I use GSL. Just add this as an extra build phase in your XCode project as a Custom Script:

# Framework folder for Example.app
FRAMEWORKS_DIR=${TARGET_BUILD_DIR}/Example.app/Contents/Frameworks

# Create path if it doesn't exsit
mkdir -p ${FRAMEWORKS_DIR}

# Find the original linked path for libgsl
GSLLIB=`otool -L ${TARGET_BUILD_DIR}/Example.app/Contents/MacOS/Example | grep libgsl | cut -d" " -f1`
GSLPATH=`dirname $GSLLIB`

# Copy the dylibs into your app
cp /usr/local/lib/lib{gsl,gslcblas}.0.dylib ${FRAMEWORKS_DIR}

# Update embedded paths
install_name_tool \
    -change ${GSLPATH}/libgsl.0.dylib \
    @executable_path/../Frameworks/libgsl.0.dylib \
    ${TARGET_BUILD_DIR}/Example.app/Contents/MacOS/Example

This should work with a simple substitution of your app name.

This is basically the same as what you need to do to build a standalone Qt app, so the docs here are very relevant:

It is worth reading up on bundles, frameworks and packaging. For example:

This post is also relevant:

Note that GSL is published under the GPL, so your app would need to be similarly published in order to respect the license. Shipping the source is necessary, but not sufficient for compliance.

Community
  • 1
  • 1
gavinb
  • 19,278
  • 3
  • 45
  • 60
  • Thanks for the tips @gavinb, I'm going through Nokia's documentation and will post the result here for all future Googler. BTW, it's a school project for my Master thesis so GPL isn't a problem. – Code Different Jul 02 '13 at 01:34
  • I've just found an old project of mine that does just this (embedding GSL), so I've pasted above some working code that does just what you need. By using this, you can build and install GSL in whatever directory you like, and just link as you normally would, leaving the script to fix up the references so you have a self-contained app (that only uses relative paths). – gavinb Jul 03 '13 at 01:53