summaryrefslogtreecommitdiff
path: root/modules/mono/build_scripts
diff options
context:
space:
mode:
authorIgnacio Roldán Etcheverry <ignalfonsore@gmail.com>2021-09-12 20:23:05 +0200
committerIgnacio Roldán Etcheverry <ignalfonsore@gmail.com>2022-08-22 03:35:59 +0200
commitf9a67ee9da1d6cc3562fa5a7443a2a66a673bd8c (patch)
tree724e3b0a0030cc0abc67710dcf9c4a14be5724f0 /modules/mono/build_scripts
parent513ee857a938c466e0f7146f66db771b9c6e2024 (diff)
C#: Begin move to .NET Core
We're targeting .NET 5 for now to make development easier while .NET 6 is not yet released. TEMPORARY REGRESSIONS --------------------- Assembly unloading is not implemented yet. As such, many Godot resources are leaked at exit. This will be re-implemented later together with assembly hot-reloading.
Diffstat (limited to 'modules/mono/build_scripts')
-rwxr-xr-xmodules/mono/build_scripts/build_assemblies.py6
-rw-r--r--modules/mono/build_scripts/make_android_mono_config.py55
-rw-r--r--modules/mono/build_scripts/mono_android_config.xml28
-rw-r--r--modules/mono/build_scripts/mono_configure.py624
-rw-r--r--modules/mono/build_scripts/mono_reg_utils.py112
5 files changed, 124 insertions, 701 deletions
diff --git a/modules/mono/build_scripts/build_assemblies.py b/modules/mono/build_scripts/build_assemblies.py
index dd96f40f6b..67c2f7f70e 100755
--- a/modules/mono/build_scripts/build_assemblies.py
+++ b/modules/mono/build_scripts/build_assemblies.py
@@ -203,6 +203,9 @@ def build_godot_api(msbuild_tool, module_dir, output_dir):
"GodotSharpEditor.dll",
"GodotSharpEditor.pdb",
"GodotSharpEditor.xml",
+ "GodotPlugins.dll",
+ "GodotPlugins.pdb",
+ "GodotPlugins.runtimeconfig.json",
]
for build_config in ["Debug", "Release"]:
@@ -223,6 +226,7 @@ def build_godot_api(msbuild_tool, module_dir, output_dir):
core_src_dir = os.path.abspath(os.path.join(sln, os.pardir, "GodotSharp", "bin", build_config))
editor_src_dir = os.path.abspath(os.path.join(sln, os.pardir, "GodotSharpEditor", "bin", build_config))
+ plugins_src_dir = os.path.abspath(os.path.join(sln, os.pardir, "GodotPlugins", "bin", build_config, "net5.0"))
if not os.path.isdir(editor_api_dir):
assert not os.path.isfile(editor_api_dir)
@@ -236,6 +240,8 @@ def build_godot_api(msbuild_tool, module_dir, output_dir):
src_path = os.path.join(core_src_dir, filename)
if not os.path.isfile(src_path):
src_path = os.path.join(editor_src_dir, filename)
+ if not os.path.isfile(src_path):
+ src_path = os.path.join(plugins_src_dir, filename)
print(f"Copying assembly to {target_path}...")
copy(src_path, target_path)
diff --git a/modules/mono/build_scripts/make_android_mono_config.py b/modules/mono/build_scripts/make_android_mono_config.py
deleted file mode 100644
index 3459244bc2..0000000000
--- a/modules/mono/build_scripts/make_android_mono_config.py
+++ /dev/null
@@ -1,55 +0,0 @@
-def generate_compressed_config(config_src, output_dir):
- import os.path
-
- # Source file
- with open(os.path.join(output_dir, "android_mono_config.gen.cpp"), "w") as cpp:
- with open(config_src, "rb") as f:
- buf = f.read()
- decompr_size = len(buf)
- import zlib
-
- # Use maximum zlib compression level to further reduce file size
- # (at the cost of initial build times).
- buf = zlib.compress(buf, zlib.Z_BEST_COMPRESSION)
- compr_size = len(buf)
-
- bytes_seq_str = ""
- for i, buf_idx in enumerate(range(compr_size)):
- if i > 0:
- bytes_seq_str += ", "
- bytes_seq_str += str(buf[buf_idx])
-
- cpp.write(
- """/* THIS FILE IS GENERATED DO NOT EDIT */
-#include "android_mono_config.h"
-
-#ifdef ANDROID_ENABLED
-
-#include "core/io/compression.h"
-
-
-namespace {
-
-// config
-static const int config_compressed_size = %d;
-static const int config_uncompressed_size = %d;
-static const unsigned char config_compressed_data[] = { %s };
-} // namespace
-
-String get_godot_android_mono_config() {
- Vector<uint8_t> data;
- data.resize(config_uncompressed_size);
- uint8_t* w = data.ptrw();
- Compression::decompress(w, config_uncompressed_size, config_compressed_data,
- config_compressed_size, Compression::MODE_DEFLATE);
- String s;
- if (s.parse_utf8((const char *)w, data.size()) != OK) {
- ERR_FAIL_V(String());
- }
- return s;
-}
-
-#endif // ANDROID_ENABLED
-"""
- % (compr_size, decompr_size, bytes_seq_str)
- )
diff --git a/modules/mono/build_scripts/mono_android_config.xml b/modules/mono/build_scripts/mono_android_config.xml
deleted file mode 100644
index e79670afd2..0000000000
--- a/modules/mono/build_scripts/mono_android_config.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<configuration>
- <dllmap wordsize="32" dll="i:cygwin1.dll" target="/system/lib/libc.so" />
- <dllmap wordsize="64" dll="i:cygwin1.dll" target="/system/lib64/libc.so" />
- <dllmap wordsize="32" dll="libc" target="/system/lib/libc.so" />
- <dllmap wordsize="64" dll="libc" target="/system/lib64/libc.so" />
- <dllmap wordsize="32" dll="intl" target="/system/lib/libc.so" />
- <dllmap wordsize="64" dll="intl" target="/system/lib64/libc.so" />
- <dllmap wordsize="32" dll="libintl" target="/system/lib/libc.so" />
- <dllmap wordsize="64" dll="libintl" target="/system/lib64/libc.so" />
- <dllmap dll="MonoPosixHelper" target="libMonoPosixHelper.so" />
- <dllmap dll="System.Native" target="libmono-native.so" />
- <dllmap wordsize="32" dll="i:msvcrt" target="/system/lib/libc.so" />
- <dllmap wordsize="64" dll="i:msvcrt" target="/system/lib64/libc.so" />
- <dllmap wordsize="32" dll="i:msvcrt.dll" target="/system/lib/libc.so" />
- <dllmap wordsize="64" dll="i:msvcrt.dll" target="/system/lib64/libc.so" />
- <dllmap wordsize="32" dll="sqlite" target="/system/lib/libsqlite.so" />
- <dllmap wordsize="64" dll="sqlite" target="/system/lib64/libsqlite.so" />
- <dllmap wordsize="32" dll="sqlite3" target="/system/lib/libsqlite.so" />
- <dllmap wordsize="64" dll="sqlite3" target="/system/lib64/libsqlite.so" />
- <dllmap wordsize="32" dll="liblog" target="/system/lib/liblog.so" />
- <dllmap wordsize="64" dll="liblog" target="/system/lib64/liblog.so" />
- <dllmap dll="i:kernel32.dll">
- <dllentry dll="__Internal" name="CopyMemory" target="mono_win32_compat_CopyMemory"/>
- <dllentry dll="__Internal" name="FillMemory" target="mono_win32_compat_FillMemory"/>
- <dllentry dll="__Internal" name="MoveMemory" target="mono_win32_compat_MoveMemory"/>
- <dllentry dll="__Internal" name="ZeroMemory" target="mono_win32_compat_ZeroMemory"/>
- </dllmap>
-</configuration>
diff --git a/modules/mono/build_scripts/mono_configure.py b/modules/mono/build_scripts/mono_configure.py
index e69904c54b..071693d758 100644
--- a/modules/mono/build_scripts/mono_configure.py
+++ b/modules/mono/build_scripts/mono_configure.py
@@ -1,65 +1,5 @@
import os
import os.path
-import subprocess
-
-from SCons.Script import Dir, Environment
-
-if os.name == "nt":
- from . import mono_reg_utils as monoreg
-
-
-android_arch_dirs = {
- "armv7": "armeabi-v7a",
- "arm64v8": "arm64-v8a",
- "x86": "x86",
- "x86_64": "x86_64",
-}
-
-
-def get_android_out_dir(env):
- return os.path.join(
- Dir("#platform/android/java/lib/libs").abspath,
- "release" if env["target"] == "release" else "debug",
- android_arch_dirs[env["android_arch"]],
- )
-
-
-def find_name_in_dir_files(directory, names, prefixes=[""], extensions=[""]):
- for extension in extensions:
- if extension and not extension.startswith("."):
- extension = "." + extension
- for prefix in prefixes:
- for curname in names:
- if os.path.isfile(os.path.join(directory, prefix + curname + extension)):
- return curname
- return ""
-
-
-def find_file_in_dir(directory, names, prefixes=[""], extensions=[""]):
- for extension in extensions:
- if extension and not extension.startswith("."):
- extension = "." + extension
- for prefix in prefixes:
- for curname in names:
- filename = prefix + curname + extension
- if os.path.isfile(os.path.join(directory, filename)):
- return filename
- return ""
-
-
-def copy_file(src_dir, dst_dir, src_name, dst_name=""):
- from shutil import copy
-
- src_path = os.path.join(Dir(src_dir).abspath, src_name)
- dst_dir = Dir(dst_dir).abspath
-
- if not os.path.isdir(dst_dir):
- os.makedirs(dst_dir)
-
- if dst_name:
- copy(src_path, os.path.join(dst_dir, dst_name))
- else:
- copy(src_path, dst_dir)
def is_desktop(platform):
@@ -71,504 +11,176 @@ def is_unix_like(platform):
def module_supports_tools_on(platform):
- return platform not in ["android", "javascript", "ios"]
-
-
-def find_wasm_src_dir(mono_root):
- hint_dirs = [
- os.path.join(mono_root, "src"),
- os.path.join(mono_root, "../src"),
- ]
- for hint_dir in hint_dirs:
- if os.path.isfile(os.path.join(hint_dir, "driver.c")):
- return hint_dir
- return ""
+ return is_desktop(platform)
def configure(env, env_mono):
- bits = env["bits"]
- is_android = env["platform"] == "android"
- is_javascript = env["platform"] == "javascript"
- is_ios = env["platform"] == "ios"
- is_ios_sim = is_ios and env["arch"] in ["x86", "x86_64"]
+ # is_android = env["platform"] == "android"
+ # is_javascript = env["platform"] == "javascript"
+ # is_ios = env["platform"] == "ios"
+ # is_ios_sim = is_ios and env["arch"] in ["x86", "x86_64"]
tools_enabled = env["tools"]
- mono_static = env["mono_static"]
- copy_mono_root = env["copy_mono_root"]
-
- mono_prefix = env["mono_prefix"]
- mono_bcl = env["mono_bcl"]
-
- mono_lib_names = ["mono-2.0-sgen", "monosgen-2.0"]
-
- if is_android and not env["android_arch"] in android_arch_dirs:
- raise RuntimeError("This module does not support the specified 'android_arch': " + env["android_arch"])
if tools_enabled and not module_supports_tools_on(env["platform"]):
- # TODO:
- # Android: We have to add the data directory to the apk, concretely the Api and Tools folders.
raise RuntimeError("This module does not currently support building for this platform with tools enabled")
- if is_android and mono_static:
- # FIXME: When static linking and doing something that requires libmono-native, we get a dlopen error as 'libmono-native'
- # seems to depend on 'libmonosgen-2.0'. Could be fixed by re-directing to '__Internal' with a dllmap or in the dlopen hook.
- raise RuntimeError("Statically linking Mono is not currently supported for this platform")
-
- if not mono_static and (is_javascript or is_ios):
- raise RuntimeError("Dynamically linking Mono is not currently supported for this platform")
-
- if not mono_prefix and (os.getenv("MONO32_PREFIX") or os.getenv("MONO64_PREFIX")):
- print(
- "WARNING: The environment variables 'MONO32_PREFIX' and 'MONO64_PREFIX' are deprecated; use the"
- " 'mono_prefix' SCons parameter instead"
- )
-
- # Although we don't support building with tools for any platform where we currently use static AOT,
- # if these are supported in the future, we won't be using static AOT for them as that would be
- # too restrictive for the editor. These builds would probably be made to only use the interpreter.
- mono_aot_static = (is_ios and not is_ios_sim) and not env["tools"]
-
- # Static AOT is only supported on the root domain
- mono_single_appdomain = mono_aot_static
-
- if mono_single_appdomain:
- env_mono.Append(CPPDEFINES=["GD_MONO_SINGLE_APPDOMAIN"])
-
- if (env["tools"] or env["target"] != "release") and not mono_single_appdomain:
+ if env["tools"] or env["target"] != "release":
env_mono.Append(CPPDEFINES=["GD_MONO_HOT_RELOAD"])
- if env["platform"] == "windows":
- mono_root = mono_prefix
-
- if not mono_root and os.name == "nt":
- mono_root = monoreg.find_mono_root_dir(bits)
-
- if not mono_root:
- raise RuntimeError(
- "Mono installation directory not found; specify one manually with the 'mono_prefix' SCons parameter"
- )
-
- print("Found Mono root directory: " + mono_root)
-
- mono_lib_path = os.path.join(mono_root, "lib")
-
- env.Append(LIBPATH=mono_lib_path)
- env_mono.Prepend(CPPPATH=os.path.join(mono_root, "include", "mono-2.0"))
+ app_host_dir = find_dotnet_app_host_dir(env)
- lib_suffixes = [".lib"]
+ def check_app_host_file_exists(file):
+ file_path = os.path.join(app_host_dir, file)
+ if not os.path.isfile(file_path):
+ raise RuntimeError("File not found: " + file_path)
- if not env.msvc:
- # MingW supports both '.a' and '.lib'
- lib_suffixes.insert(0, ".a")
+ # TODO:
+ # All libnethost does for us is provide a function to find hostfxr.
+ # If we could handle that logic ourselves we could void linking it.
- if mono_static:
- if env.msvc:
- mono_static_lib_name = "libmono-static-sgen"
- else:
- mono_static_lib_name = "libmonosgen-2.0"
+ # nethost file names:
+ # static: libnethost.a/lib
+ # shared: libnethost.a/dylib and nethost.dll
+ check_app_host_file_exists("libnethost.lib" if os.name == "nt" else "libnethost.a")
+ check_app_host_file_exists("nethost.h")
+ check_app_host_file_exists("hostfxr.h")
+ check_app_host_file_exists("coreclr_delegates.h")
- mono_static_lib_file = find_file_in_dir(mono_lib_path, [mono_static_lib_name], extensions=lib_suffixes)
+ env.Append(LIBPATH=[app_host_dir])
+ env_mono.Prepend(CPPPATH=app_host_dir)
- if not mono_static_lib_file:
- raise RuntimeError("Could not find static mono library in: " + mono_lib_path)
+ libnethost_path = os.path.join(app_host_dir, "libnethost.lib" if os.name == "nt" else "libnethost.a")
- if env.msvc:
- env.Append(LINKFLAGS=mono_static_lib_file)
-
- env.Append(LINKFLAGS="Mincore.lib")
- env.Append(LINKFLAGS="msvcrt.lib")
- env.Append(LINKFLAGS="LIBCMT.lib")
- env.Append(LINKFLAGS="Psapi.lib")
- else:
- mono_static_lib_file_path = os.path.join(mono_lib_path, mono_static_lib_file)
- env.Append(LINKFLAGS=["-Wl,-whole-archive", mono_static_lib_file_path, "-Wl,-no-whole-archive"])
+ if env["platform"] == "windows":
+ env_mono.Append(CPPDEFINES=["NETHOST_USE_AS_STATIC"])
- env.Append(LIBS=["psapi"])
- env.Append(LIBS=["version"])
+ if env.msvc:
+ env.Append(LINKFLAGS="libnethost.lib")
else:
- mono_lib_file = find_file_in_dir(mono_lib_path, mono_lib_names, extensions=lib_suffixes)
-
- if not mono_lib_file:
- raise RuntimeError("Could not find mono library in: " + mono_lib_path)
-
- if env.msvc:
- env.Append(LINKFLAGS=mono_lib_file)
- else:
- mono_lib_file_path = os.path.join(mono_lib_path, mono_lib_file)
- env.Append(LINKFLAGS=mono_lib_file_path)
-
- mono_bin_path = os.path.join(mono_root, "bin")
-
- mono_dll_file = find_file_in_dir(mono_bin_path, mono_lib_names, prefixes=["", "lib"], extensions=[".dll"])
-
- if not mono_dll_file:
- raise RuntimeError("Could not find mono shared library in: " + mono_bin_path)
-
- copy_file(mono_bin_path, "#bin", mono_dll_file)
+ env.Append(LINKFLAGS=["-Wl,-whole-archive", libnethost_path, "-Wl,-no-whole-archive"])
else:
is_apple = env["platform"] in ["macos", "ios"]
- is_macos = is_apple and not is_ios
-
- sharedlib_ext = ".dylib" if is_apple else ".so"
-
- mono_root = mono_prefix
- mono_lib_path = ""
- mono_so_file = ""
-
- if not mono_root and (is_android or is_javascript or is_ios):
- raise RuntimeError(
- "Mono installation directory not found; specify one manually with the 'mono_prefix' SCons parameter"
- )
-
- if not mono_root and is_macos:
- # Try with some known directories under macOS
- hint_dirs = ["/Library/Frameworks/Mono.framework/Versions/Current", "/usr/local/var/homebrew/linked/mono"]
- for hint_dir in hint_dirs:
- if os.path.isdir(hint_dir):
- mono_root = hint_dir
- break
-
- # We can't use pkg-config to link mono statically,
- # but we can still use it to find the mono root directory
- if not mono_root and mono_static:
- mono_root = pkgconfig_try_find_mono_root(mono_lib_names, sharedlib_ext)
- if not mono_root:
- raise RuntimeError(
- "Building with mono_static=yes, but failed to find the mono prefix with pkg-config; "
- + "specify one manually with the 'mono_prefix' SCons parameter"
- )
-
- if is_ios and not is_ios_sim:
- env_mono.Append(CPPDEFINES=["IOS_DEVICE"])
-
- if mono_root:
- print("Found Mono root directory: " + mono_root)
-
- mono_lib_path = os.path.join(mono_root, "lib")
-
- env.Append(LIBPATH=[mono_lib_path])
- env_mono.Prepend(CPPPATH=os.path.join(mono_root, "include", "mono-2.0"))
-
- mono_lib = find_name_in_dir_files(mono_lib_path, mono_lib_names, prefixes=["lib"], extensions=[".a"])
-
- if not mono_lib:
- raise RuntimeError("Could not find mono library in: " + mono_lib_path)
-
- env_mono.Append(CPPDEFINES=["_REENTRANT"])
-
- if mono_static:
- if not is_javascript:
- env.Append(LINKFLAGS=["-rdynamic"])
-
- mono_lib_file = os.path.join(mono_lib_path, "lib" + mono_lib + ".a")
-
- if is_apple:
- if is_macos:
- env.Append(LINKFLAGS=["-Wl,-force_load," + mono_lib_file])
- else:
- arch = env["arch"]
-
- def copy_mono_lib(libname_wo_ext):
- copy_file(
- mono_lib_path, "#bin", libname_wo_ext + ".a", "%s.ios.%s.a" % (libname_wo_ext, arch)
- )
-
- # Copy Mono libraries to the output folder. These are meant to be bundled with
- # the export templates and added to the Xcode project when exporting a game.
- copy_mono_lib("lib" + mono_lib)
- copy_mono_lib("libmono-native")
- copy_mono_lib("libmono-profiler-log")
-
- if not is_ios_sim:
- copy_mono_lib("libmono-ee-interp")
- copy_mono_lib("libmono-icall-table")
- copy_mono_lib("libmono-ilgen")
- else:
- assert is_desktop(env["platform"]) or is_android or is_javascript
- env.Append(LINKFLAGS=["-Wl,-whole-archive", mono_lib_file, "-Wl,-no-whole-archive"])
-
- if is_javascript:
- env.Append(LIBS=["mono-icall-table", "mono-native", "mono-ilgen", "mono-ee-interp"])
-
- wasm_src_dir = os.path.join(mono_root, "src")
- if not os.path.isdir(wasm_src_dir):
- raise RuntimeError("Could not find mono wasm src directory")
-
- # Ideally this should be defined only for 'driver.c', but I can't fight scons for another 2 hours
- env_mono.Append(CPPDEFINES=["CORE_BINDINGS"])
-
- env_mono.add_source_files(
- env.modules_sources,
- [
- os.path.join(wasm_src_dir, "driver.c"),
- os.path.join(wasm_src_dir, "zlib-helper.c"),
- os.path.join(wasm_src_dir, "corebindings.c"),
- ],
- )
-
- env.Append(
- LINKFLAGS=[
- "--js-library",
- os.path.join(wasm_src_dir, "library_mono.js"),
- "--js-library",
- os.path.join(wasm_src_dir, "binding_support.js"),
- "--js-library",
- os.path.join(wasm_src_dir, "dotnet_support.js"),
- ]
- )
- else:
- env.Append(LIBS=[mono_lib])
-
- if is_macos:
- env.Append(LIBS=["iconv", "pthread"])
- elif is_android:
- pass # Nothing
- elif is_ios:
- pass # Nothing, linking is delegated to the exported Xcode project
- elif is_javascript:
- env.Append(LIBS=["m", "rt", "dl", "pthread"])
- else:
- env.Append(LIBS=["m", "rt", "dl", "pthread"])
-
- if not mono_static:
- mono_so_file = find_file_in_dir(
- mono_lib_path, mono_lib_names, prefixes=["lib"], extensions=[sharedlib_ext]
- )
-
- if not mono_so_file:
- raise RuntimeError("Could not find mono shared library in: " + mono_lib_path)
- else:
- assert not mono_static
+ # is_macos = is_apple and not is_ios
- # TODO: Add option to force using pkg-config
- print("Mono root directory not found. Using pkg-config instead")
+ # if is_ios and not is_ios_sim:
+ # env_mono.Append(CPPDEFINES=["IOS_DEVICE"])
- env.ParseConfig("pkg-config monosgen-2 --libs")
- env_mono.ParseConfig("pkg-config monosgen-2 --cflags")
+ if is_apple:
+ env.Append(LINKFLAGS=["-Wl,-force_load," + libnethost_path])
+ else:
+ env.Append(LINKFLAGS=["-Wl,-whole-archive", libnethost_path, "-Wl,-no-whole-archive"])
- tmpenv = Environment()
- tmpenv.AppendENVPath("PKG_CONFIG_PATH", os.getenv("PKG_CONFIG_PATH"))
- tmpenv.ParseConfig("pkg-config monosgen-2 --libs-only-L")
- for hint_dir in tmpenv["LIBPATH"]:
- file_found = find_file_in_dir(hint_dir, mono_lib_names, prefixes=["lib"], extensions=[sharedlib_ext])
- if file_found:
- mono_lib_path = hint_dir
- mono_so_file = file_found
- break
+def find_dotnet_app_host_dir(env):
+ dotnet_root = env["dotnet_root"]
- if not mono_so_file:
- raise RuntimeError("Could not find mono shared library in: " + str(tmpenv["LIBPATH"]))
+ if not dotnet_root:
+ dotnet_exe = find_executable("dotnet")
+ if dotnet_exe:
+ dotnet_exe_realpath = os.path.realpath(dotnet_exe) # Eliminate symbolic links
+ dotnet_root = os.path.abspath(os.path.join(dotnet_exe_realpath, os.pardir))
+ else:
+ raise RuntimeError("Cannot find .NET Core Sdk")
- if not mono_static:
- libs_output_dir = get_android_out_dir(env) if is_android else "#bin"
- copy_file(mono_lib_path, libs_output_dir, mono_so_file)
+ print("Found .NET Core Sdk root directory: " + dotnet_root)
- if not tools_enabled:
- if is_desktop(env["platform"]):
- if not mono_root:
- mono_root = (
- subprocess.check_output(["pkg-config", "mono-2", "--variable=prefix"]).decode("utf8").strip()
- )
+ dotnet_cmd = os.path.join(dotnet_root, "dotnet.exe" if os.name == "nt" else "dotnet")
- make_template_dir(env, mono_root)
- elif is_android:
- # Compress Android Mono Config
- from . import make_android_mono_config
+ runtime_identifier = determine_runtime_identifier(env)
- module_dir = os.getcwd()
- config_file_path = os.path.join(module_dir, "build_scripts", "mono_android_config.xml")
- make_android_mono_config.generate_compressed_config(config_file_path, "mono_gd/")
+ # TODO: In the future, if it can't be found this way, we want to obtain it
+ # from the runtime.{runtime_identifier}.Microsoft.NETCore.DotNetAppHost NuGet package.
+ app_host_search_version = "5.0"
+ app_host_version = find_app_host_version(dotnet_cmd, app_host_search_version)
+ if not app_host_version:
+ raise RuntimeError("Cannot find .NET app host for version: " + app_host_search_version)
- # Copy the required shared libraries
- copy_mono_shared_libs(env, mono_root, None)
- elif is_javascript:
- pass # No data directory for this platform
- elif is_ios:
- pass # No data directory for this platform
+ app_host_dir = os.path.join(
+ dotnet_root,
+ "packs",
+ "Microsoft.NETCore.App.Host." + runtime_identifier,
+ app_host_version,
+ "runtimes",
+ runtime_identifier,
+ "native",
+ )
- if copy_mono_root:
- if not mono_root:
- mono_root = subprocess.check_output(["pkg-config", "mono-2", "--variable=prefix"]).decode("utf8").strip()
+ return app_host_dir
- if tools_enabled:
- # Only supported for editor builds.
- copy_mono_root_files(env, mono_root, mono_bcl)
+def determine_runtime_identifier(env):
+ names_map = {
+ "windows": "win",
+ "macos": "osx",
+ "linuxbsd": "linux",
+ "server": "linux", # FIXME: Is server linux only, or also macos?
+ }
-def make_template_dir(env, mono_root):
- from shutil import rmtree
+ # .NET RID architectures: x86, x64, arm, or arm64
platform = env["platform"]
- target = env["target"]
-
- template_dir_name = ""
-
- assert is_desktop(platform)
-
- template_dir_name = "data.mono.%s.%s.%s" % (platform, env["bits"], target)
-
- output_dir = Dir("#bin").abspath
- template_dir = os.path.join(output_dir, template_dir_name)
-
- template_mono_root_dir = os.path.join(template_dir, "Mono")
-
- if os.path.isdir(template_mono_root_dir):
- rmtree(template_mono_root_dir) # Clean first
- # Copy etc/mono/
-
- template_mono_config_dir = os.path.join(template_mono_root_dir, "etc", "mono")
- copy_mono_etc_dir(mono_root, template_mono_config_dir, platform)
-
- # Copy the required shared libraries
-
- copy_mono_shared_libs(env, mono_root, template_mono_root_dir)
-
-
-def copy_mono_root_files(env, mono_root, mono_bcl):
- from glob import glob
- from shutil import copy
- from shutil import rmtree
-
- if not mono_root:
- raise RuntimeError("Mono installation directory not found")
-
- output_dir = Dir("#bin").abspath
- editor_mono_root_dir = os.path.join(output_dir, "GodotSharp", "Mono")
-
- if os.path.isdir(editor_mono_root_dir):
- rmtree(editor_mono_root_dir) # Clean first
-
- # Copy etc/mono/
-
- editor_mono_config_dir = os.path.join(editor_mono_root_dir, "etc", "mono")
- copy_mono_etc_dir(mono_root, editor_mono_config_dir, env["platform"])
-
- # Copy the required shared libraries
-
- copy_mono_shared_libs(env, mono_root, editor_mono_root_dir)
+ if is_desktop(platform):
+ if env["arch"] in ["arm", "arm32"]:
+ rid = "arm"
+ elif env["arch"] == "arm64":
+ rid = "arm64"
+ else:
+ bits = env["bits"]
+ bit_arch_map = {"64": "x64", "32": "x86"}
+ rid = bit_arch_map[bits]
+ return "%s-%s" % (names_map[platform], rid)
+ else:
+ raise NotImplementedError()
- # Copy framework assemblies
- mono_framework_dir = mono_bcl or os.path.join(mono_root, "lib", "mono", "4.5")
- mono_framework_facades_dir = os.path.join(mono_framework_dir, "Facades")
+def find_app_host_version(dotnet_cmd, search_version):
+ import subprocess
- editor_mono_framework_dir = os.path.join(editor_mono_root_dir, "lib", "mono", "4.5")
- editor_mono_framework_facades_dir = os.path.join(editor_mono_framework_dir, "Facades")
+ try:
+ lines = subprocess.check_output([dotnet_cmd, "--list-runtimes"]).splitlines()
- if not os.path.isdir(editor_mono_framework_dir):
- os.makedirs(editor_mono_framework_dir)
- if not os.path.isdir(editor_mono_framework_facades_dir):
- os.makedirs(editor_mono_framework_facades_dir)
+ for line_bytes in lines:
+ line = line_bytes.decode("utf-8")
+ if not line.startswith("Microsoft.NETCore.App "):
+ continue
- for assembly in glob(os.path.join(mono_framework_dir, "*.dll")):
- copy(assembly, editor_mono_framework_dir)
- for assembly in glob(os.path.join(mono_framework_facades_dir, "*.dll")):
- copy(assembly, editor_mono_framework_facades_dir)
+ parts = line.split(" ")
+ if len(parts) < 2:
+ continue
+ version = parts[1]
-def copy_mono_etc_dir(mono_root, target_mono_config_dir, platform):
- from distutils.dir_util import copy_tree
- from glob import glob
- from shutil import copy
+ # Look for 6.0.0 or 6.0.0-*
+ if version.startswith(search_version + "."):
+ return version
+ except (subprocess.CalledProcessError, OSError):
+ pass
+ return ""
- if not os.path.isdir(target_mono_config_dir):
- os.makedirs(target_mono_config_dir)
- mono_etc_dir = os.path.join(mono_root, "etc", "mono")
- if not os.path.isdir(mono_etc_dir):
- mono_etc_dir = ""
- etc_hint_dirs = []
- if platform != "windows":
- etc_hint_dirs += ["/etc/mono", "/usr/local/etc/mono"]
- if "MONO_CFG_DIR" in os.environ:
- etc_hint_dirs += [os.path.join(os.environ["MONO_CFG_DIR"], "mono")]
- for etc_hint_dir in etc_hint_dirs:
- if os.path.isdir(etc_hint_dir):
- mono_etc_dir = etc_hint_dir
- break
- if not mono_etc_dir:
- raise RuntimeError("Mono installation etc directory not found")
+ENV_PATH_SEP = ";" if os.name == "nt" else ":"
- copy_tree(os.path.join(mono_etc_dir, "2.0"), os.path.join(target_mono_config_dir, "2.0"))
- copy_tree(os.path.join(mono_etc_dir, "4.0"), os.path.join(target_mono_config_dir, "4.0"))
- copy_tree(os.path.join(mono_etc_dir, "4.5"), os.path.join(target_mono_config_dir, "4.5"))
- if os.path.isdir(os.path.join(mono_etc_dir, "mconfig")):
- copy_tree(os.path.join(mono_etc_dir, "mconfig"), os.path.join(target_mono_config_dir, "mconfig"))
- for file in glob(os.path.join(mono_etc_dir, "*")):
- if os.path.isfile(file):
- copy(file, target_mono_config_dir)
+def find_executable(name):
+ is_windows = os.name == "nt"
+ windows_exts = os.environ["PATHEXT"].split(ENV_PATH_SEP) if is_windows else None
+ path_dirs = os.environ["PATH"].split(ENV_PATH_SEP)
+ search_dirs = path_dirs + [os.getcwd()] # cwd is last in the list
-def copy_mono_shared_libs(env, mono_root, target_mono_root_dir):
- from shutil import copy
+ for dir in search_dirs:
+ path = os.path.join(dir, name)
- def copy_if_exists(src, dst):
- if os.path.isfile(src):
- copy(src, dst)
+ if is_windows:
+ for extension in windows_exts:
+ path_with_ext = path + extension
- platform = env["platform"]
+ if os.path.isfile(path_with_ext) and os.access(path_with_ext, os.X_OK):
+ return path_with_ext
+ else:
+ if os.path.isfile(path) and os.access(path, os.X_OK):
+ return path
- if platform == "windows":
- src_mono_bin_dir = os.path.join(mono_root, "bin")
- target_mono_bin_dir = os.path.join(target_mono_root_dir, "bin")
-
- if not os.path.isdir(target_mono_bin_dir):
- os.makedirs(target_mono_bin_dir)
-
- mono_posix_helper_file = find_file_in_dir(
- src_mono_bin_dir, ["MonoPosixHelper"], prefixes=["", "lib"], extensions=[".dll"]
- )
- copy(
- os.path.join(src_mono_bin_dir, mono_posix_helper_file),
- os.path.join(target_mono_bin_dir, "MonoPosixHelper.dll"),
- )
-
- # For newer versions
- btls_dll_path = os.path.join(src_mono_bin_dir, "libmono-btls-shared.dll")
- if os.path.isfile(btls_dll_path):
- copy(btls_dll_path, target_mono_bin_dir)
- else:
- target_mono_lib_dir = (
- get_android_out_dir(env) if platform == "android" else os.path.join(target_mono_root_dir, "lib")
- )
-
- if not os.path.isdir(target_mono_lib_dir):
- os.makedirs(target_mono_lib_dir)
-
- lib_file_names = []
- if platform == "macos":
- lib_file_names = [
- lib_name + ".dylib"
- for lib_name in ["libmono-btls-shared", "libmono-native-compat", "libMonoPosixHelper"]
- ]
- elif is_unix_like(platform):
- lib_file_names = [
- lib_name + ".so"
- for lib_name in [
- "libmono-btls-shared",
- "libmono-ee-interp",
- "libmono-native",
- "libMonoPosixHelper",
- "libmono-profiler-aot",
- "libmono-profiler-coverage",
- "libmono-profiler-log",
- "libMonoSupportW",
- ]
- ]
-
- for lib_file_name in lib_file_names:
- copy_if_exists(os.path.join(mono_root, "lib", lib_file_name), target_mono_lib_dir)
-
-
-def pkgconfig_try_find_mono_root(mono_lib_names, sharedlib_ext):
- tmpenv = Environment()
- tmpenv.AppendENVPath("PKG_CONFIG_PATH", os.getenv("PKG_CONFIG_PATH"))
- tmpenv.ParseConfig("pkg-config monosgen-2 --libs-only-L")
- for hint_dir in tmpenv["LIBPATH"]:
- name_found = find_name_in_dir_files(hint_dir, mono_lib_names, prefixes=["lib"], extensions=[sharedlib_ext])
- if name_found and os.path.isdir(os.path.join(hint_dir, "..", "include", "mono-2.0")):
- return os.path.join(hint_dir, "..")
return ""
diff --git a/modules/mono/build_scripts/mono_reg_utils.py b/modules/mono/build_scripts/mono_reg_utils.py
deleted file mode 100644
index 43c1ec8f8a..0000000000
--- a/modules/mono/build_scripts/mono_reg_utils.py
+++ /dev/null
@@ -1,112 +0,0 @@
-import os
-import platform
-
-if os.name == "nt":
- import winreg
-
-
-def _reg_open_key(key, subkey):
- try:
- return winreg.OpenKey(key, subkey)
- except OSError:
- if platform.architecture()[0] == "32bit":
- bitness_sam = winreg.KEY_WOW64_64KEY
- else:
- bitness_sam = winreg.KEY_WOW64_32KEY
- return winreg.OpenKey(key, subkey, 0, winreg.KEY_READ | bitness_sam)
-
-
-def _reg_open_key_bits(key, subkey, bits):
- sam = winreg.KEY_READ
-
- if platform.architecture()[0] == "32bit":
- if bits == "64":
- # Force 32bit process to search in 64bit registry
- sam |= winreg.KEY_WOW64_64KEY
- else:
- if bits == "32":
- # Force 64bit process to search in 32bit registry
- sam |= winreg.KEY_WOW64_32KEY
-
- return winreg.OpenKey(key, subkey, 0, sam)
-
-
-def _find_mono_in_reg(subkey, bits):
- try:
- with _reg_open_key_bits(winreg.HKEY_LOCAL_MACHINE, subkey, bits) as hKey:
- value = winreg.QueryValueEx(hKey, "SdkInstallRoot")[0]
- return value
- except OSError:
- return None
-
-
-def _find_mono_in_reg_old(subkey, bits):
- try:
- with _reg_open_key_bits(winreg.HKEY_LOCAL_MACHINE, subkey, bits) as hKey:
- default_clr = winreg.QueryValueEx(hKey, "DefaultCLR")[0]
- if default_clr:
- return _find_mono_in_reg(subkey + "\\" + default_clr, bits)
- return None
- except OSError:
- return None
-
-
-def find_mono_root_dir(bits):
- root_dir = _find_mono_in_reg(r"SOFTWARE\Mono", bits)
- if root_dir is not None:
- return str(root_dir)
- root_dir = _find_mono_in_reg_old(r"SOFTWARE\Novell\Mono", bits)
- if root_dir is not None:
- return str(root_dir)
- return ""
-
-
-def find_msbuild_tools_path_reg():
- import subprocess
-
- vswhere = os.getenv("PROGRAMFILES(X86)")
- if not vswhere:
- vswhere = os.getenv("PROGRAMFILES")
- vswhere += r"\Microsoft Visual Studio\Installer\vswhere.exe"
-
- vswhere_args = ["-latest", "-products", "*", "-requires", "Microsoft.Component.MSBuild"]
-
- try:
- lines = subprocess.check_output([vswhere] + vswhere_args).splitlines()
-
- for line in lines:
- parts = line.decode("utf-8").split(":", 1)
-
- if len(parts) < 2 or parts[0] != "installationPath":
- continue
-
- val = parts[1].strip()
-
- if not val:
- raise ValueError("Value of `installationPath` entry is empty")
-
- # Since VS2019, the directory is simply named "Current"
- msbuild_dir = os.path.join(val, "MSBuild\\Current\\Bin")
- if os.path.isdir(msbuild_dir):
- return msbuild_dir
-
- # Directory name "15.0" is used in VS 2017
- return os.path.join(val, "MSBuild\\15.0\\Bin")
-
- raise ValueError("Cannot find `installationPath` entry")
- except ValueError as e:
- print("Error reading output from vswhere: " + e.message)
- except subprocess.CalledProcessError as e:
- print(e.output)
- except OSError as e:
- print(e)
-
- # Try to find 14.0 in the Registry
-
- try:
- subkey = r"SOFTWARE\Microsoft\MSBuild\ToolsVersions\14.0"
- with _reg_open_key(winreg.HKEY_LOCAL_MACHINE, subkey) as hKey:
- value = winreg.QueryValueEx(hKey, "MSBuildToolsPath")[0]
- return value
- except OSError:
- return ""