f9a67ee9da
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.
186 lines
5.8 KiB
Python
186 lines
5.8 KiB
Python
import os
|
|
import os.path
|
|
|
|
|
|
def is_desktop(platform):
|
|
return platform in ["windows", "macos", "linuxbsd", "server", "uwp", "haiku"]
|
|
|
|
|
|
def is_unix_like(platform):
|
|
return platform in ["macos", "linuxbsd", "server", "android", "haiku", "ios"]
|
|
|
|
|
|
def module_supports_tools_on(platform):
|
|
return is_desktop(platform)
|
|
|
|
|
|
def configure(env, env_mono):
|
|
# 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"]
|
|
|
|
if tools_enabled and not module_supports_tools_on(env["platform"]):
|
|
raise RuntimeError("This module does not currently support building for this platform with tools enabled")
|
|
|
|
if env["tools"] or env["target"] != "release":
|
|
env_mono.Append(CPPDEFINES=["GD_MONO_HOT_RELOAD"])
|
|
|
|
app_host_dir = find_dotnet_app_host_dir(env)
|
|
|
|
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)
|
|
|
|
# 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.
|
|
|
|
# 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")
|
|
|
|
env.Append(LIBPATH=[app_host_dir])
|
|
env_mono.Prepend(CPPPATH=app_host_dir)
|
|
|
|
libnethost_path = os.path.join(app_host_dir, "libnethost.lib" if os.name == "nt" else "libnethost.a")
|
|
|
|
if env["platform"] == "windows":
|
|
env_mono.Append(CPPDEFINES=["NETHOST_USE_AS_STATIC"])
|
|
|
|
if env.msvc:
|
|
env.Append(LINKFLAGS="libnethost.lib")
|
|
else:
|
|
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
|
|
|
|
# if is_ios and not is_ios_sim:
|
|
# env_mono.Append(CPPDEFINES=["IOS_DEVICE"])
|
|
|
|
if is_apple:
|
|
env.Append(LINKFLAGS=["-Wl,-force_load," + libnethost_path])
|
|
else:
|
|
env.Append(LINKFLAGS=["-Wl,-whole-archive", libnethost_path, "-Wl,-no-whole-archive"])
|
|
|
|
|
|
def find_dotnet_app_host_dir(env):
|
|
dotnet_root = env["dotnet_root"]
|
|
|
|
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")
|
|
|
|
print("Found .NET Core Sdk root directory: " + dotnet_root)
|
|
|
|
dotnet_cmd = os.path.join(dotnet_root, "dotnet.exe" if os.name == "nt" else "dotnet")
|
|
|
|
runtime_identifier = determine_runtime_identifier(env)
|
|
|
|
# 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)
|
|
|
|
app_host_dir = os.path.join(
|
|
dotnet_root,
|
|
"packs",
|
|
"Microsoft.NETCore.App.Host." + runtime_identifier,
|
|
app_host_version,
|
|
"runtimes",
|
|
runtime_identifier,
|
|
"native",
|
|
)
|
|
|
|
return app_host_dir
|
|
|
|
|
|
def determine_runtime_identifier(env):
|
|
names_map = {
|
|
"windows": "win",
|
|
"macos": "osx",
|
|
"linuxbsd": "linux",
|
|
"server": "linux", # FIXME: Is server linux only, or also macos?
|
|
}
|
|
|
|
# .NET RID architectures: x86, x64, arm, or arm64
|
|
|
|
platform = env["platform"]
|
|
|
|
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()
|
|
|
|
|
|
def find_app_host_version(dotnet_cmd, search_version):
|
|
import subprocess
|
|
|
|
try:
|
|
lines = subprocess.check_output([dotnet_cmd, "--list-runtimes"]).splitlines()
|
|
|
|
for line_bytes in lines:
|
|
line = line_bytes.decode("utf-8")
|
|
if not line.startswith("Microsoft.NETCore.App "):
|
|
continue
|
|
|
|
parts = line.split(" ")
|
|
if len(parts) < 2:
|
|
continue
|
|
|
|
version = parts[1]
|
|
|
|
# Look for 6.0.0 or 6.0.0-*
|
|
if version.startswith(search_version + "."):
|
|
return version
|
|
except (subprocess.CalledProcessError, OSError):
|
|
pass
|
|
return ""
|
|
|
|
|
|
ENV_PATH_SEP = ";" if os.name == "nt" else ":"
|
|
|
|
|
|
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
|
|
|
|
for dir in search_dirs:
|
|
path = os.path.join(dir, name)
|
|
|
|
if is_windows:
|
|
for extension in windows_exts:
|
|
path_with_ext = path + extension
|
|
|
|
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
|
|
|
|
return ""
|