summaryrefslogtreecommitdiff
path: root/modules/mono/build_scripts
diff options
context:
space:
mode:
Diffstat (limited to 'modules/mono/build_scripts')
-rwxr-xr-xmodules/mono/build_scripts/build_assemblies.py80
-rw-r--r--modules/mono/build_scripts/mono_configure.py299
2 files changed, 69 insertions, 310 deletions
diff --git a/modules/mono/build_scripts/build_assemblies.py b/modules/mono/build_scripts/build_assemblies.py
index 6f66ce9efa..0b91cda9b8 100755
--- a/modules/mono/build_scripts/build_assemblies.py
+++ b/modules/mono/build_scripts/build_assemblies.py
@@ -5,6 +5,7 @@ import os.path
import shlex
import subprocess
from dataclasses import dataclass
+from typing import Optional, List
def find_dotnet_cli():
@@ -150,10 +151,7 @@ def find_any_msbuild_tool(mono_prefix):
return None
-def run_msbuild(tools: ToolsLocation, sln: str, msbuild_args: [str] = None):
- if msbuild_args is None:
- msbuild_args = []
-
+def run_msbuild(tools: ToolsLocation, sln: str, msbuild_args: Optional[List[str]] = None):
using_msbuild_mono = False
# Preference order: dotnet CLI > Standalone MSBuild > Mono's MSBuild
@@ -169,7 +167,7 @@ def run_msbuild(tools: ToolsLocation, sln: str, msbuild_args: [str] = None):
args += [sln]
- if len(msbuild_args) > 0:
+ if msbuild_args:
args += msbuild_args
print("Running MSBuild: ", " ".join(shlex.quote(arg) for arg in args), flush=True)
@@ -195,7 +193,7 @@ def run_msbuild(tools: ToolsLocation, sln: str, msbuild_args: [str] = None):
return subprocess.call(args, env=msbuild_env)
-def build_godot_api(msbuild_tool, module_dir, output_dir, push_nupkgs_local, float_size):
+def build_godot_api(msbuild_tool, module_dir, output_dir, push_nupkgs_local, precision):
target_filenames = [
"GodotSharp.dll",
"GodotSharp.pdb",
@@ -216,7 +214,7 @@ def build_godot_api(msbuild_tool, module_dir, output_dir, push_nupkgs_local, flo
args = ["/restore", "/t:Build", "/p:Configuration=" + build_config, "/p:NoWarn=1591"]
if push_nupkgs_local:
args += ["/p:ClearNuGetLocalCache=true", "/p:PushNuGetToLocalSource=" + push_nupkgs_local]
- if float_size == "64":
+ if precision == "double":
args += ["/p:GodotFloat64=true"]
sln = os.path.join(module_dir, "glue/GodotSharp/GodotSharp.sln")
@@ -258,9 +256,59 @@ def build_godot_api(msbuild_tool, module_dir, output_dir, push_nupkgs_local, flo
return 0
-def build_all(msbuild_tool, module_dir, output_dir, godot_platform, dev_debug, push_nupkgs_local, float_size):
+def generate_sdk_package_versions():
+ # I can't believe importing files in Python is so convoluted when not
+ # following the golden standard for packages/modules.
+ import os
+ import sys
+ from os.path import dirname
+
+ # We want ../../../methods.py.
+ script_path = dirname(os.path.abspath(__file__))
+ root_path = dirname(dirname(dirname(script_path)))
+
+ sys.path.insert(0, root_path)
+ from methods import get_version_info
+
+ version_info = get_version_info("")
+ sys.path.remove(root_path)
+
+ version_str = "{major}.{minor}.{patch}".format(**version_info)
+ version_status = version_info["status"]
+ if version_status != "stable": # Pre-release
+ # If version was overridden to be e.g. "beta3", we insert a dot between
+ # "beta" and "3" to follow SemVer 2.0.
+ import re
+
+ match = re.search(r"[\d]+$", version_status)
+ if match:
+ pos = match.start()
+ version_status = version_status[:pos] + "." + version_status[pos:]
+ version_str += "-" + version_status
+
+ props = """<Project>
+ <PropertyGroup>
+ <PackageVersion_GodotSharp>{0}</PackageVersion_GodotSharp>
+ <PackageVersion_Godot_NET_Sdk>{0}</PackageVersion_Godot_NET_Sdk>
+ <PackageVersion_Godot_SourceGenerators>{0}</PackageVersion_Godot_SourceGenerators>
+ </PropertyGroup>
+</Project>
+""".format(
+ version_str
+ )
+
+ # We write in ../SdkPackageVersions.props.
+ with open(os.path.join(dirname(script_path), "SdkPackageVersions.props"), "w") as f:
+ f.write(props)
+ f.close()
+
+
+def build_all(msbuild_tool, module_dir, output_dir, godot_platform, dev_debug, push_nupkgs_local, precision):
+ # Generate SdkPackageVersions.props
+ generate_sdk_package_versions()
+
# Godot API
- exit_code = build_godot_api(msbuild_tool, module_dir, output_dir, push_nupkgs_local, float_size)
+ exit_code = build_godot_api(msbuild_tool, module_dir, output_dir, push_nupkgs_local, precision)
if exit_code != 0:
return exit_code
@@ -271,7 +319,7 @@ def build_all(msbuild_tool, module_dir, output_dir, godot_platform, dev_debug, p
)
if push_nupkgs_local:
args += ["/p:ClearNuGetLocalCache=true", "/p:PushNuGetToLocalSource=" + push_nupkgs_local]
- if float_size == "64":
+ if precision == "double":
args += ["/p:GodotFloat64=true"]
exit_code = run_msbuild(msbuild_tool, sln=sln, msbuild_args=args)
if exit_code != 0:
@@ -281,7 +329,7 @@ def build_all(msbuild_tool, module_dir, output_dir, godot_platform, dev_debug, p
args = ["/restore", "/t:Build", "/p:Configuration=Release"]
if push_nupkgs_local:
args += ["/p:ClearNuGetLocalCache=true", "/p:PushNuGetToLocalSource=" + push_nupkgs_local]
- if float_size == "64":
+ if precision == "double":
args += ["/p:GodotFloat64=true"]
sln = os.path.join(module_dir, "editor/Godot.NET.Sdk/Godot.NET.Sdk.sln")
exit_code = run_msbuild(msbuild_tool, sln=sln, msbuild_args=args)
@@ -306,7 +354,9 @@ def main():
parser.add_argument("--godot-platform", type=str, default="")
parser.add_argument("--mono-prefix", type=str, default="")
parser.add_argument("--push-nupkgs-local", type=str, default="")
- parser.add_argument("--float", type=str, default="32", choices=["32", "64"], help="Floating-point precision")
+ parser.add_argument(
+ "--precision", type=str, default="single", choices=["single", "double"], help="Floating-point precision level"
+ )
args = parser.parse_args()
@@ -315,6 +365,8 @@ def main():
output_dir = os.path.abspath(args.godot_output_dir)
+ push_nupkgs_local = os.path.abspath(args.push_nupkgs_local) if args.push_nupkgs_local else None
+
msbuild_tool = find_any_msbuild_tool(args.mono_prefix)
if msbuild_tool is None:
@@ -327,8 +379,8 @@ def main():
output_dir,
args.godot_platform,
args.dev_debug,
- args.push_nupkgs_local,
- args.float,
+ push_nupkgs_local,
+ args.precision,
)
sys.exit(exit_code)
diff --git a/modules/mono/build_scripts/mono_configure.py b/modules/mono/build_scripts/mono_configure.py
index c2d5452837..5cec8f41f5 100644
--- a/modules/mono/build_scripts/mono_configure.py
+++ b/modules/mono/build_scripts/mono_configure.py
@@ -20,300 +20,7 @@ def configure(env, env_mono):
# is_ios = env["platform"] == "ios"
# is_ios_sim = is_ios and env["arch"] in ["x86_32", "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"]:
+ if env.editor_build:
+ if not module_supports_tools_on(env["platform"]):
+ raise RuntimeError("This module does not currently support building for this platform for editor builds.")
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_mono.Prepend(CPPPATH=app_host_dir)
-
- env.Append(LIBPATH=[app_host_dir])
-
- # Only the editor build links nethost, which is needed to find hostfxr.
- # Exported games don't need this logic as hostfxr is bundled with them.
- if tools_enabled:
- 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_version = "6.0"
-
- dotnet_root = env["dotnet_root"]
-
- if not dotnet_root:
- dotnet_cmd = find_dotnet_executable(env["arch"])
- if dotnet_cmd:
- sdk_path = find_dotnet_sdk(dotnet_cmd, dotnet_version)
- if sdk_path:
- dotnet_root = os.path.abspath(os.path.join(sdk_path, os.pardir))
-
- if not dotnet_root:
- 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_version = find_app_host_version(dotnet_cmd, dotnet_version)
- if not app_host_version:
- raise RuntimeError("Cannot find .NET app host for version: " + dotnet_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):
- # The keys are Godot's names, the values are the Microsoft's names.
- # List: https://docs.microsoft.com/en-us/dotnet/core/rid-catalog
- names_map = {
- "windows": "win",
- "macos": "osx",
- "linuxbsd": "linux",
- }
- arch_map = {
- "x86_64": "x64",
- "x86_32": "x86",
- "arm64": "arm64",
- "arm32": "arm",
- }
- platform = env["platform"]
- if is_desktop(platform):
- return "%s-%s" % (names_map[platform], arch_map[env["arch"]])
- else:
- raise NotImplementedError()
-
-
-def find_app_host_version(dotnet_cmd, search_version_str):
- import subprocess
- from distutils.version import LooseVersion
-
- search_version = LooseVersion(search_version_str)
- found_match = False
-
- try:
- env = dict(os.environ, DOTNET_CLI_UI_LANGUAGE="en-US")
- lines = subprocess.check_output([dotnet_cmd, "--list-runtimes"], env=env).splitlines()
-
- for line_bytes in lines:
- line = line_bytes.decode("utf-8")
- if not line.startswith("Microsoft.NETCore.App "):
- continue
-
- parts = line.split(" ", 2)
- if len(parts) < 3:
- continue
-
- version_str = parts[1]
-
- version = LooseVersion(version_str)
-
- if version >= search_version:
- search_version = version
- found_match = True
- if found_match:
- return str(search_version)
- except (subprocess.CalledProcessError, OSError) as e:
- import sys
-
- print(e, file=sys.stderr)
-
- return ""
-
-
-def find_dotnet_arch(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")
-
- parts = line.split(":", 1)
- if len(parts) < 2:
- continue
-
- arch_str = parts[0].strip()
- if arch_str != "Architecture":
- continue
-
- arch_value = parts[1].strip()
- arch_map = {"x64": "x86_64", "x86": "x86_32", "arm64": "arm64", "arm32": "arm32"}
- return arch_map[arch_value]
- except (subprocess.CalledProcessError, OSError) as e:
- import sys
-
- print(e, file=sys.stderr)
-
- return ""
-
-
-def find_dotnet_sdk(dotnet_cmd, search_version_str):
- import subprocess
- from distutils.version import LooseVersion
-
- search_version = LooseVersion(search_version_str)
-
- try:
- env = dict(os.environ, DOTNET_CLI_UI_LANGUAGE="en-US")
- lines = subprocess.check_output([dotnet_cmd, "--list-sdks"], env=env).splitlines()
-
- for line_bytes in lines:
- line = line_bytes.decode("utf-8")
-
- parts = line.split(" ", 1)
- if len(parts) < 2:
- continue
-
- version_str = parts[0]
-
- version = LooseVersion(version_str)
-
- if version < search_version:
- continue
-
- path_part = parts[1]
- return path_part[1 : path_part.find("]")]
- except (subprocess.CalledProcessError, OSError) as e:
- import sys
-
- print(e, file=sys.stderr)
-
- 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_dotnet_executable(arch):
- 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 path_dirs:
- search_dirs += [
- os.path.join(dir, "x64"),
- os.path.join(dir, "x86"),
- os.path.join(dir, "arm64"),
- os.path.join(dir, "arm32"),
- ] # search subfolders for cross compiling
-
- # `dotnet --info` may not specify architecture. In such cases,
- # we fallback to the first one we find without architecture.
- sdk_path_unknown_arch = ""
-
- for dir in search_dirs:
- path = os.path.join(dir, "dotnet")
-
- 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):
- sdk_arch = find_dotnet_arch(path_with_ext)
- if sdk_arch == arch or arch == "":
- return path_with_ext
- elif sdk_arch == "":
- sdk_path_unknown_arch = path_with_ext
- else:
- if os.path.isfile(path) and os.access(path, os.X_OK):
- sdk_arch = find_dotnet_arch(path)
- if sdk_arch == arch or arch == "":
- return path
- elif sdk_arch == "":
- sdk_path_unknown_arch = path
-
- return sdk_path_unknown_arch