How to make Unity find .dylib files?

Ok, I have 6 .dylib files built from OpenCV source code. These have respective .dll versions when deploying on Windows, which is already working without much effort.

However, I can't seem to understand how to make Unity find my .dylib files on OSX. The .NET wrapper fails with DllNotFoundException because it can't find the native OSX files, I guess.

The docs talk about .bundle files built with XCode. I have tried this, and even though I add the .dylib files as external frameworks, I seem to always end up with semi-empty .bundle files not containing the .dylib files that I added to the project. I read something about using install_name_tool to modify the bundles, but it's really confusing and I'm not quite sure about the interdependencies among these .dylib files. Do you really have to do this manually?

What's the simplest possible way to make Unity find the .dylib files? Can someone please shine some light on this seemingly super-obscure subject?

Is there not a tool to simply build a bundle with .dylib files that Unity will function with? Why is it so complex on OSX, when on Windows you just dump the dll files in the Plugins directory?

Ok I think I've worked out a solution. This might save some people a LOT of time and headaches:

Renaming a .dylib file to .bundle makes Unity find and load it, and it works! Weird? Yes.

Well, according to a post I found, on modern OSX, dylib and bundle are in practice interchangable, as they nowadays support mostly the same features (loading and unloading with dlopen() and dlclose()):

  • The modern dlopen implementation on the Mac (it wasn't there at all in 10.0) seems capable of loading both "bundles" (the file version I think) and regular Mac shared libraries. In 10.4, dlclose() couldn't unload a dynamic library but could unload a bundle; in 10.5, it can unload both. So it's unclear how relevant the distinction between "loadable objects" and "shared libraries" is any more, at least if you're targeting 10.5 or 10.6 as your minimum required OS version.

Sooo... the limitation seems to be a Unity one in that it simply does not consider .dylib files for loading - only .bundle files, but when it does load .bundle files which happen to be dylib files, OSX just swallows it.. It could also be that this only works in Unity 3.0 - haven't tried in older versions.

Happy coding! Feel free to comment!

AFAIK, there is no way to convert dylibs to bundles, and you are correct that Unity will need bundles to load native C++ code on Mac OS X. You need to have the XCode project used to generate the dylib files, and reconfigure that to output bundles.

I wrote a tutorial for this at my blog. Hope it helps :slight_smile:

Following up on Magnus Wolffelt’s IOException issue, we had the same issue occurring and added a UnityEditor.Callbacks.PostProcessScene script that, on !EditorApplication.isPlayingOrWillChangePlaymode, moves the bundle outside of the plugins directory and a UnityEditor.Callbacks.PostProcessBuild that moves it back to that directory and copies it into the app. It works well enough for us, could be better though.

Here’s how you can convert a dylib to a bundle:

lipo -create build-release/src/nvtt/libnvtt_x86.dylib build-release/src/nvtt/libnvtt_x86_64.dylib -output nvtt
mkdir -p ../../../UnityProject/Assets/Scripts/Editor/TextureImport/nvtt.bundle/Contents/MacOS/
cp nvtt ../../../UnityProject/Assets/Scripts/Editor/TextureImport/nvtt.bundle/Contents/MacOS/

Alternatively if you just want to ship 64-bit then skip the lipo step and copy the dylib (without extension) to the Contents/MacOS folder