…ccore@2668.
1. Mono changed dyld lookup to start looking in directories in
NATIVE_DLL_SEARCH_DIRECTORIES before the actual given path, even when the
given path is absolute [1].
2. This turned out to break Mac Catalyst, because when a DllImport says a
P/Invoke is in "/System/Library/Frameworks/SceneKit.framework/SceneKit",
Mono would try loading by prefixing the directories in
NATIVE_DLL_SEARCH_DIRECTORIES. We add the Contents/MonoBundle directory to
NATIVE_DLL_SEARCH_DIRECTORIES, so Mono would try to load
"/path/to/my.app/Contents/MonoBundle//System/Library/Frameworks/SceneKit.framework/SceneKit",
and things would go wrong.
3. We found a workaround: add "/" to NATIVE_DLL_SEARCH_DIRECTORIES. This works
on Ventura, but apparently not on older macOS version, because the actual
path we pass to dlopen ends up being "///System/Library/Frameworks/SceneKit.framework/SceneKit"
(note the three initial slashes instead of a single slash).
4. Add a second workaround, where we add a dll import resolver to load exactly
the path we want to load.
[1]: dotnet/runtime@5a1baeb
[2]: dotnet/runtime#85255
Technical sidenote:
Why trying to load "/path/to/my.app/Contents/MonoBundle//System/Library/Frameworks/SceneKit.framework/SceneKit"
turned out so bad on Mac Catalyst is not obvious. What happens is this:
* The app calls 'dlopen ("/path/to/my.app/Contents/MonoBundle//System/Library/Frameworks/SceneKit.framework/SceneKit")'
* dlopen checks if this is a Mac Catalyst override of a macOS system
framework, by prefixing "/System/iOSSupport" and trying to load that. So
dlopen would try to load "/System/iOSSupport/path/to/my.app/Contents/MonoBundle//System/Library/Frameworks/SceneKit.framework/SceneKit",
which would obviously fail.
* Then dlopen would try a few more fallbacks, eventually trying
"/System/Library/Frameworks/SceneKit.framework/SceneKit", and successfully
loading that library.
* Unfortunately "/System/Library/Frameworks/SceneKit.framework/SceneKit" is
the wrong library to load for Mac Catalyst ("/System/iOSSupport/System/Library/Frameworks/SceneKit.framework/SceneKit"
is the correct version). These two libraries are incompatible, and calling
one when you mean to call the other will do nasty things like corrupting the
stack.
This is a backport of xamarin#18159.