When embedding Mono and distributing the libraries within a Cocoa application package, it is easy to overlook a small detail that means when attempting to run the code on another machine, you will come across a
library not found exception for the Mono dylib. As can likely be seen from the exception, the application is looking for the dylib at the absolute path of where Mono was built to despite there being no reference to this location in your code or build settings.
Referring to the developer documentation for dynamic libraries. It is apparent that:
The library specifies that the dynamic loader must resolve the library’s install name when it loads the executable that depends on the library.
A quick query with
otool on your dylib will show the install name of the library, quickly highlighting the problem:
$ otool -L libmonosgen-2.0.1.dylib libmono-2.0.dylib: /Users/adrianm/Projects/Mono/mono-4.0.1/Build/lib/libmonosgen-2.0.1.dylib (compatibility version 2.0.0, current version 2.0.0) ...
Well there's the absolute path culprit, and that certainly will not resolve on any machine other than the build machine.
Enter into the ring:
install_name_tool; an aptly named tool for configuring the install names of the library and its dependencies.
The solution is then very simple:
$ install_name_tool -id @executable_path/../Frameworks/libmonosgen-2.0.1.dylib libmonosgen-2.0.1.dylib
The library now has a relative, resolvable path - and the exception goes away.
You may also come across a related issue pop up later, an unhandled .NET exception stating that the
MonoPosixHelper.dll could not be found. Details for that can be found in Embedding Mono: libMonoPosixHelper.dylib.