How to distribute a Mac OS X with dependent libraries? - macos

I have a program (specifically my entry for the SO DevDays Countdown app challenge) which relies on several dynamic libraries, namely libSDL, libSDL_ttf, and others. I have these libraries installed under /opt/local/lib via MacPorts, and many people won't have these installed (and some might have them installed, but not at that location).
How do I distribute my program so that people without these libraries installed can run it out-of-the-box? Obviously I'll have to distribute the various .dylib files, but doing this is insufficient. The dynamic loader still looks for the libraries installed at the locations I have them installed at. Is there a way to tell the dynamic loader to look in the current directory of the executable, like what Windows does with DLLs? People shouldn't have to modify any environment variables (e.g. DYLD_LIBRARY_PATH), since again I want this to work out-of-the-box.

The basic approach to this is to ship them in the .app bundle. You'll then modify the location the linker looks for shared libraries to include this.
The steps are:
Create a new copy files build phase to your target that copies those files into the Frameworks directory of the .app bundle.
Edit the build configuration setting "Runpath Search Paths" to include #executable_path/../Frameworks
If you build your executable with these changes and then look, you should find that the dylibs exist in the Foo.app/Contents/Framework directory and running otool -L Foo.app/Contents/MacOS/Foo should yield and entry prefixed by #rpath for those dylibs.
From this Cocoabuilder post:
In general, #loader_path is preferred over #executable_path, as it
allows embedded frameworks to work in both an executable and a bundle,
plugin, or sub-framework. The only downside is that #loader_path
requires 10.4 or newer. If you're on 10.5 or newer, #rpath is even
better than #loader_path.

As you mentioned you're not using Xcode, so it's a bit difficult. Here are options in my order of preference:
Switch to Xcode. Use frameworks. The SDL libraries are available as frameworks already, and I've seen more than a couple commercial games with a libsdl.framework inside the app bundle.
Use frameworks, but keep your Makefiles. Download the framework versions of your SDL libraries (or build them yourself), and link with them with the -framework linker flag. Distribute the frameworks with your app or don't, and tell your users to put them in either ~/Library/Frameworks or in /Library/Frameworks. I wouldn't bother with an installer for this.
Statically link against SDL. In the Makefile, you'll have to list the path of the static libraries rather than use the -l flag, e.g., you run "ld blah blah /opt/local/lib/libsdl.a". There is no way that I know to tell -l to prefer static over shared libraries, and believe me, I've looked.

Statically link the libraries.

Related

dylib to dylib pathing on mac osx, how to make rpath work on mac?

We have a project which dynamically links against several dylibs. When copy the build to another mac. One need to run "otool" over the dylibs and executable in order to fix the shared library paths in them during "install".
Looks like OSX had some strange requirements for DLL to DLL pathing that made relative paths not work in them (i.e: using rpath). My questions here:
what is the the normal way to ship a software on mac? i.e: when running either a .pkg or .dmg installer, how one make sure the dylibs installed are able to link against each other in relative path? the dylib path must be fixed with either the rpath or some post install scripts
if we are not allowed to run a post install script to fix this, what are the other options?
Relative paths should work just fine. For example assume a macOS application bundle. The application lives in Contents/MacOS while the library lives in Contents/Frameworks. In this case you would relink the application's libraries to something like this #executable_path/../Frameworks/library.so. If you don't use an application bundle but have all files in the same directory simple using #executable_path should work too.
No need to use #rpath in these examples. you can use this too but it requires the application to define this path. This may be helpful if you want to distribute a library and people are supposed to link to your library. That way they can give an #rpath in their application to find the library without otool-ing them.
And you of course you make these changes before your package up your application into a .dmg or .pkg.

Can I use OpenFrameworks on OS X without having to use XCode?

I can't stand XCode, but really love OpenFrameworks, and I know it works on Linux+Win32 so I don't see why it should be XCode dependent. If I need to have XCode installed that's fine, I just don't want to use it at all.
Xcode internally uses gcc/llvm. in fact from the command line you can cd into a directory that contains an openFrameworks project and just type xcodebuild. but this won't allow you to edit the project file and add new source code, etc.
the Linux makefiles could be adapted to work on OSX as well. they already contain a lot of the information necessary about finding the correct source files, library paths etc. however Linux allows us to install many more components as shared system libraries, while on OSX we link most of the libs statically, so a number of extra library paths would need to be added. probably the biggest gotcha is that everything has to be compiled 32 bit, which means passing -arch i386 everywhere, so you can't just install dependant libs using Homebrew or MacPorts. we are in the process of transitioning to 64 bit but there are still some QuickTime calls that require us to stick with 32 bit, mainly around accessing legacy video capture devices that a lot of us still use for computer vision.
like #cdelacroix points out, we only maintain Xcode project files on OSX. this is mainly due to the lack of a decent alternative. there is a version of Code::Blocks for OSX but it is not very well supported, has some issues with native gui rendering and tends to lag behind the other platforms. Xcode is also the easiest way to install a toolchain on OSX so for most users installing Xcode is necessary.
if you do get a makefile based build system working, and would be interested in maintaining it medium to long term, please consider contributing it to the GitHub repository, it would be gladly accepted.
As of March 2013, openFrameworks has official makefile support for compiling the library itself. However, at the time of this writing, the changes haven't yet been merged into the stable release. You'll need to clone the Git repository and switch to the development branch.
git clone https://github.com/openframeworks/openFrameworks
cd openFrameworks && git checkout develop
cd libs/openFrameworksCompiled/project
make
As far as I can tell, we still need to use the unofficial solutions for compiling apps against the library.
You need Xcode, or at least a set of compilers (more information is available here), but otherwise, no, you can edit/work with the code in whatever editor or environment you want.
Here's a link to a makefile which will compile an OpenFrameworks application on OsX:
https://gist.github.com/labe-me/1190981
Place the makefile in the apps' directory and run make. Tested on OsX 10.6, but haven't tried with addons yet.
As #mipadi said, there is no requirement to actually use Xcode, you can do pretty much everything you do in Xcode with make or cake or any of your build system of choice. All you have to do is find the right set of command line options to pass to the usual tools (compiler, linker, strip, etc.), and sometimes the easier way is to... look in the Xcode build window how it is doing stuff (expand the lines with the small button on the right of each line).
For example you can link with your framework of choice with ld -framework Framework -FPathToFramework foo.o or your dynamic library with ld -lLib -LPathToDylib foo.o. You might have to learn about #rpath, #loader_path and install_name_tool to ship a self-contained packaged application.
As for OpenFrameworks, the "requirement" for Xcode is that the authors decided to maintain only Xcode project files. I just looked at how they do it, they ship source code and Xcode project files that build static libraries, so it will be even more simple for you (although you will need to link the library dependencies by hand). You will have to choose between compiling everything from source in your build system (if you want more customization power without touching Xcode), or just produce the 2 static libraries (openFrameworks.a and openFrameworksDebug.a) with Xcode once, then use them in your build system (recommended until you really need continuous customization).

How to compile a project including all Qt needed libraries, QtCreator, Linux?

First, I am sorry about my English. That's not my language.
I am developing an application in QtCreator, Linux. When the IDE asked me about the libraries I would use, I just leave the selected ones (they was not enabled for unchecking). Now, I have to run the compiled file in RedHat 5, but it doesn't run. It tells "Error while loading shared libraries: libQtGui.so.4: ...". So, how do I fix this problem?
I should not install Qt libraries in RedHat (it's a server). I prefer to compile the Qt project including needed Qt libraries (into self compiled file, or in the same directory).
Please, can you tell me some idea??
If you cannot install qt you have two main alternatives:
Deploy the libraries together with your application (how you do this depends on the way you deploy your application. It may suffice to do a manual copy.)
Statically link with the qt libraries. They will then be included in your executable (which will be much larger as a result). Static linking
Some pros and cons of static vs dynamic linking are discussed in this thread.

Is it possible to link some — but not all — libraries statically with libtool?

I am working on a project which is built using autoconf, automake and libtool. The project is distributed in both binary and source form.
On Linux, by default the build script links to all libraries dynamically. This makes sense since Linux users can rely on their distribution’s package manager to handle dependencies.
On Windows, by default the build script links to all libraries statically using libtool’s -all-static option. This makes sense since none of the dependencies are provided with Windows, and it’s helpful to be able to distribute a single binary containing all dependencies rather than mucking about distributing tons of DLLs.
On OSX, some of the dependencies are provided by the OS, and some are not. Therefore it would be helpful to link to the OS-provided libraries dynamically and to the other libraries statically. Unfortunately libtool’s all-or-nothing -all-static option is not helpful here.
Is there a good way to get libtool to link to some libraries statically, but not all?
Note: I realise I could carefully compile the dependencies so that only static builds are available. However, I’d rather the build system for my project were robust in the common case of static and dynamic builds of dependencies being available.
Note: Of course, I am not concerned with really low level dependencies like the C/C++ runtime libraries, which are always linked dynamically on all three of the above platforms.
After some research I have answered my own question.
If you have static and dynamic builds of a library installed, and you link to that library using the -l parameter, libtool links by preference to the dynamic build. It links to a static build if there is no dynamic build available, or if you pass the -static or -all-static options.
libtool can be forced to link to the static library by giving the full path to that library in place of the -l option.

Using frameworks in a command line tool

I've built a command-line utility (Foundation tool) in Xcode, using Cocoa. The tool makes use of a 3rd party framework.
Everything works OK in Xcode, but how do I deploy this program?
If I run the app from Finder, it can't find the library because it's looking in ../Frameworks/etc. Can I statically link in the 3rd party framework?
Unfortunately, there is no way to bundle a framework with a command-line Utility in OS X and I suspect that the framework you're linking to is expecting to be bundled in the app bundle's Frameworks/ directory. If you have access to the framework source code, you can compile a static library and statically link it to your application (or include the source in your application target directly). If you don't have the source code or you don't want to statically link the library for some reason, there are two remaining options:
If you have access to the system-wide /Library/Frameworks folder, you can install the 3rd party framework there. This require that the framework's Installation Path (the INSTALL_PATH build setting) be set to /Library/Frameworks at build time or that you use the install_name_tool to change the frameworks install path to /Library/Frameworks (if you don't have the framework's source code).
Build an application bundle (as if you were building a GUI app) with your command-line utility as the app bundle's executable (i.e. in AppBundle.app/Contents/MacOS/). You can then copy the 3rd party framework to the app bundle's frameworks directory. You can then put the app bundle anywhere you want and create a symbolic link to the command line utility.
Option 1 is definitely the more accepted approach, but I've used option 2 when there was a valid reason.
You can find more information on building, linking, and installing frameworks in Apple's Frameworks Programming Guide.
Another way, if you have the source code for the framework, is to add a static library target and build a static lib from it. Then you can statically link it into your command-line tool.
As of Xcode 9.3.1, I was able to have the framework added to the command line tool by setting the Mach-O Type to Static Library for the framework. Then in the command line target make sure to add the framework to the Target Dependencies & the Link Binary With Libraries Build Phases. The built executable was then able to run with no issues.
You can use marathon to manage dependencies
https://github.com/JohnSundell/Marathon
This would need more thought if you wanted to distribute app. (You would probably want to install into frameworks folder in that use case.) your mileage may vary with this solution.

Resources