mirror of
https://github.com/godotengine/godot
synced 2024-09-16 01:12:42 +00:00
315636e77c
Some Linux distros use their distro name as the RID for directory names. If the .NET Host directory cannot be found with the generic RID, try to get the rid from `dotnet --info`. The generic RID should still be the first choice. Some platforms like Windows 10 define the RID as `win10-x64` but still use the generic `win-x64` for directory names. Co-authored-by: Lewis James <lewiji+github@gmail.com>
223 lines
7 KiB
Python
223 lines
7 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)
|
|
|
|
def get_runtime_path():
|
|
return os.path.join(
|
|
dotnet_root,
|
|
"packs",
|
|
"Microsoft.NETCore.App.Host." + runtime_identifier,
|
|
app_host_version,
|
|
"runtimes",
|
|
runtime_identifier,
|
|
"native",
|
|
)
|
|
|
|
app_host_dir = get_runtime_path()
|
|
|
|
# Some Linux distros use their distro name as the RID in these paths.
|
|
# If the initial generic path doesn't exist, try to get the RID from `dotnet --info`.
|
|
# The generic RID should still be the first choice. Some platforms like Windows 10
|
|
# define the RID as `win10-x64` but still use the generic `win-x64` for directory names.
|
|
if not app_host_dir or not os.path.isdir(app_host_dir):
|
|
runtime_identifier = find_dotnet_cli_rid(dotnet_cmd)
|
|
app_host_dir = get_runtime_path()
|
|
|
|
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 ""
|
|
|
|
|
|
def find_dotnet_cli_rid(dotnet_cmd):
|
|
import subprocess
|
|
|
|
try:
|
|
env = dict(os.environ, DOTNET_CLI_UI_LANGUAGE="en-US")
|
|
lines = subprocess.check_output([dotnet_cmd, "--info"], env=env).splitlines()
|
|
|
|
for line_bytes in lines:
|
|
line = line_bytes.decode("utf-8")
|
|
if not line.startswith(" RID:"):
|
|
continue
|
|
|
|
parts = line.split()
|
|
if len(parts) < 2:
|
|
continue
|
|
|
|
return parts[1]
|
|
except (subprocess.CalledProcessError, OSError) as e:
|
|
import sys
|
|
|
|
print(e, file=sys.stderr)
|
|
|
|
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 ""
|