How do I make Godot Mono use the bundled Mono instead of system Mono?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By alexp

I’ve been trying to build Godot Mono for OSX, and figured out I can get it to work on arm64 by bundling the binaries so that they run under Rosetta. However, I’m getting a particularly disappointing error, where two Mono version numbers are the same, but one of them has a datetime at the end, so they are not equal strings:

Mono: Prepared to set up assembly 'mscorlib' (/Library/Frameworks/Mono.framework/Versions/Current/lib/mono/4.5/mscorlib.dll)
Mono: AOT: module /Library/Frameworks/Mono.framework/Versions/Current/lib/mono/4.5/mscorlib.dll.dylib is unusable: compiled against runtime version '6.12.0.182 (2020-02/6051b710727 Tue Jun 14 15:01:21 EDT 2022)' while this runtime has version '6.12.0.182 (2020-02/6051b710727)'.

The below paragraph from the docs tells me that I need to use copy_mono_root=yes, so I rebuilt with that, but I’m still having the same problem.

The Mono subdirectory is optional. It can be used to bundle the Mono framework assemblies and configuration files with the Godot editor, as well as some shared library dependencies like MonoPosixHelper. This is important to avoid issues that might arise when the installed Mono version in the user’s system may not be the same as the one the Godot editor was built with. You can make SCons copy these files to this subdirectory by passing the option copy_mono_root=yes when building the editor.

I pasted the output of ls -lR for the Godot.app folder at this pastebin to confirm that the files are there. I’m hoping that someone here can tell me about an environment variable or something in Info.plists I can set so that the executable only looks in the GodotSharp folders. I’m also unsure about this paragraph:

If you’re not linking the Mono runtime statically, the build script will place the Mono runtime shared library (monosgen-2.0) next to the Godot binary in the output directory. Make sure to include this library when distributing Godot.

I do see that library in the bin folder, but I don’t know where I’m supposed to include it. Should I just put it in Godot.app/Contents/MacOS right next to the binary?

My build script:

PLAT=osx
ARCH=x86_64
TARGET=release_debug
scons platform=$PLAT arch=$ARCH target=$TARGET tools=yes module_mono_enabled=yes mono_glue=no

rm -Rf bin/GodotGlue.app
rm -Rf bin/GodotMono.app
cp -R misc/dist/osx_tools.app bin/GodotGlue.app
mkdir -p bin/GodotGlue.app/Contents/MacOS
cp bin/godot.$PLAT.opt.tools.$ARCH.mono bin/GodotGlue.app/Contents/MacOS/Godot
chmod +x bin/GodotGlue.app/Contents/MacOS/Godot
open -n -W bin/GodotGlue.app --stderr /tmp/test.err --stdout /tmp/test.out --args --generate-mono-glue $(pwd)/modules/mono/glue

scons platform=$PLAT arch=$ARCH --jobs=$NUM_JOBS custom_modules=$MODULES target=$TARGET tools=yes module_mono_enabled=yes mono_glue=yes copy_mono_root=yes
cp -R misc/dist/osx_tools.app bin/GodotMono.app
mkdir -p bin/GodotMono.app/Contents/MacOS
mkdir -p bin/GodotMono.app/Frameworks/GodotSharp/Mono
mkdir -p bin/GodotMono.app/Resources/GodotSharp/Mono
cp bin/godot.$PLAT.opt.tools.$ARCH.mono bin/GodotMono.app/Contents/MacOS/Godot
cp -R bin/GodotSharp/Tools bin/GodotMono.app/Frameworks/GodotSharp
cp -R bin/GodotSharp/Api bin/GodotMono.app/Frameworks/GodotSharp
cp -R bin/GodotSharp/Mono/lib bin/GodotMono.app/Frameworks/GodotSharp/Mono
cp -R bin/GodotSharp/Mono/etc bin/GodotMono.app/Resources/GodotSharp/Mono
chmod +x bin/GodotMono.app/Contents/MacOS/Godot

I went as far as to clone mono/mono and godotengine/godot-mono-builds so I could make my mono installation as Godot-centric as possible, but because I’m on an arm64 processor, I ran into trouble where the build tool apparently relies on some x86-only SIMD instructions. This is from running ./osx.py make --target=x86_64:

 [ 89%] Linking C shared library libmono-btls-shared.dylib
Undefined symbols for architecture arm64:
  "_ChaCha20_ctr32", referenced from:
      _CRYPTO_chacha_20 in chacha.c.o
  "_bn_mul_mont", referenced from:
      _BN_mod_mul_montgomery in montgomery.c.o
  "_sha1_block_data_order", referenced from:
      _SHA1_Update in sha1.c.o
      _SHA1_Final in sha1.c.o
      _SHA1_Transform in sha1.c.o
  "_sha256_block_data_order", referenced from:
      _SHA256_Update in sha256.c.o
      _SHA256_Final in sha256.c.o
      _SHA256_Transform in sha256.c.o
  "_sha512_block_data_order", referenced from:
      _SHA512_Update in sha512.c.o
      _SHA512_Final in sha512.c.o
      _SHA512_Transform in sha512.c.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[6]: *** [libmono-btls-shared.dylib] Error 1
make[5]: *** [CMakeFiles/mono-btls-shared.dir/all] Error 2
make[4]: *** [all] Error 2
make[3]: *** [build-shared/libmono-btls-shared.dylib] Error 2
make[2]: *** [all-recursive] Error 1
make[1]: *** [all-recursive] Error 1
make: *** [all] Error 2

I tried building with mono_static=yes too, seeing no changes

alexp | 2022-10-16 19:52

:bust_in_silhouette: Reply From: alexp

The problem was that I was putting Resources and Frameworks in the top level app directory, rather than under Contents. I also noticed the official release doesn’t use a Frameworks folder and just puts all of GodotSharp under Contents/Resources, so I followed suit. It works fine now.