123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- 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 ""
|