Including custom dll and dylib in MonoMac app
bundle, dylib, mono, monomac
Solution
Have a look at my answer to this question: Setting path of the Native Library for DllImport on Mono for Mac
The binary launcher comes from monodevelop/main/build/MacOSX/monostub.m.
You can use either `MyApp.app/Contents/Frameworks` or some other path, the important part is not to use any path names in your `[DllImport]` but instead add the `<dllmap>` using `@executable_path` to your `app.config` like I explained in that other answer.
There's a also a link to a test app on github in there.
Detailed Instructions
Pick a path inside the `MyApp.app` to install your native dll, for instance `Contents/SharedSupport/sqlite3.0.8.6.dylib`.
Compute the relative path from the directory where the managed assembly is located to the native `.dll` and prepend `@executable_path` to it.
For instance, if your managed assembly is in `Contents/MonoBundle/MyApp.exe` and the native dll in `Contents/SharedSupport/sqlite3.0.8.6.dylib`, then it's `@executable_path/../SharedSupport/sqlite3.0.8.6.dylib`.
Change the installed name of the library to this relative path using `install_name_tool`.
Add a new `MyApp.exe.config` file to your project, containing
<configuration>
<dllmap dll="sqlite" target="@executable_path/../SharedSupport/sqlite3.0.8.6.dylib" />
</configuration>
Use the path that you computed in step 2. for the `target` field. Right-click the file in MonoDevelop, select "Quick Properties" from the context menu and enable "Copy to Output directory". This will copy the file into the `Contents/MonoBundle` directory, so it sits right next to your `MyApp.exe`.
Use `[DllImport ("sqlite")]` to reference this in your code.
When another library references it
When another library, for instance `Mono.Data.Sqlite.dll` references it, it get a little bit more complicated.
Use the same steps as above, but you need to figure out which name that other library is using in its `[DllImport]` to reference the native library and put that into the `<dllimport dll="..." />`. You can either look for the `[DllImport]` statements in the source code or run `monodis` on the assembly and search for `pinvokeimpl`, for instance:
// method line 679
.method assembly static hidebysig pinvokeimpl ("sqlite3" as "sqlite3_create_function" cdecl )
default int32 sqlite3_create_function (native int db, unsigned int8[] strName, int32 nArgs, int32 nType, native int pvUser, class Mono.Data.Sqlite.SQLiteCallback func, class Mono.Data.Sqlite.SQLiteCallback fstep, class Mono.Data.Sqlite.SQLiteFinalCallback ffinal) cil managed preservesig
{
// Method begins at RVA 0x0
} // end of method UnsafeNativeMethods::sqlite3_create_function
So `Mono.Data.Sqlite.dll` is using "sqlite3" to reference the native dll, so your `MyApp.exe.config` file will look like this:
<configuration>
<dllmap dll="sqlite3" target="@executable_path/../SharedSupport/sqlite3.0.8.6.dylib" />
</configuration>
Problem
Background: My MonoMac app uses a custom build of sqlite3.0.8.6.dylib. I need the exact steps to have MyApp.app use this dylib. Here are some steps I took: Copied the dylib to MyApp.app/Contents/SharedSupport. (Related question: is this the preferred location for 3rd party dylibs or is MyApp.app/Contents/Frameworks preferred?) Changed the installed name for the library so that it matches its new location. ``` MyApp.app/Contents/SharedSupport> otool -L libsqlite3.0.8.6.dylib libsqlite3.0.8.6.dylib: @executable_path/../SharedSupport/libsqlite3.0.8.6.dylib (compatibility version 9.0.0, current version 9.6.0) /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.1.0) ``` Problems - MyApp.app/Contents/MacOS/MyApp does not reference the dylib directly, so I can't use install_name_tool to point to the new library location. I believe that the library is referenced by System.Data.Sqlite.dll. - I thought of overriding DYLD_FALLBACK_LIBRARY_PATH in the launcher script but MonoMac now uses a binary launcher (MyApp.app/Contents/MacOS/MyApp), not a script, so I'm out of luck there. Would the MonoMac gods please help with what must be a simple solution? I've spent a couple of months, on and off, trying to get this to work. And please provide exact steps - this problem is all about the details.