summaryrefslogtreecommitdiffstats
path: root/platform/windows/detect.py
diff options
context:
space:
mode:
Diffstat (limited to 'platform/windows/detect.py')
-rw-r--r--platform/windows/detect.py230
1 files changed, 185 insertions, 45 deletions
diff --git a/platform/windows/detect.py b/platform/windows/detect.py
index bdacdbb9ba..93eb34001e 100644
--- a/platform/windows/detect.py
+++ b/platform/windows/detect.py
@@ -2,12 +2,13 @@ import methods
import os
import subprocess
import sys
+from methods import print_warning, print_error
from platform_methods import detect_arch
from typing import TYPE_CHECKING
if TYPE_CHECKING:
- from SCons import Environment
+ from SCons.Script.SConscript import SConsEnvironment
# To match other platforms
STACK_SIZE = 8388608
@@ -164,6 +165,22 @@ def get_opts():
mingw = os.getenv("MINGW_PREFIX", "")
+ # Direct3D 12 SDK dependencies folder.
+ d3d12_deps_folder = os.getenv("LOCALAPPDATA")
+ if d3d12_deps_folder:
+ d3d12_deps_folder = os.path.join(d3d12_deps_folder, "Godot", "build_deps")
+ else:
+ # Cross-compiling, the deps install script puts things in `bin`.
+ # Getting an absolute path to it is a bit hacky in Python.
+ try:
+ import inspect
+
+ caller_frame = inspect.stack()[1]
+ caller_script_dir = os.path.dirname(os.path.abspath(caller_frame[1]))
+ d3d12_deps_folder = os.path.join(caller_script_dir, "bin", "build_deps")
+ except: # Give up.
+ d3d12_deps_folder = ""
+
return [
("mingw_prefix", "MinGW prefix", mingw),
# Targeted Windows version: 7 (and later), minimum supported version
@@ -186,7 +203,35 @@ def get_opts():
BoolVariable("use_asan", "Use address sanitizer (ASAN)", False),
BoolVariable("debug_crt", "Compile with MSVC's debug CRT (/MDd)", False),
BoolVariable("incremental_link", "Use MSVC incremental linking. May increase or decrease build times.", False),
+ BoolVariable("silence_msvc", "Silence MSVC's cl/link stdout bloat, redirecting any errors to stderr.", True),
("angle_libs", "Path to the ANGLE static libraries", ""),
+ # Direct3D 12 support.
+ (
+ "mesa_libs",
+ "Path to the MESA/NIR static libraries (required for D3D12)",
+ os.path.join(d3d12_deps_folder, "mesa"),
+ ),
+ (
+ "dxc_path",
+ "Path to the DirectX Shader Compiler distribution (required for D3D12)",
+ os.path.join(d3d12_deps_folder, "dxc"),
+ ),
+ (
+ "agility_sdk_path",
+ "Path to the Agility SDK distribution (optional for D3D12)",
+ os.path.join(d3d12_deps_folder, "agility_sdk"),
+ ),
+ BoolVariable(
+ "agility_sdk_multiarch",
+ "Whether the Agility SDK DLLs will be stored in arch-specific subdirectories",
+ False,
+ ),
+ BoolVariable("use_pix", "Use PIX (Performance tuning and debugging for DirectX 12) runtime", False),
+ (
+ "pix_path",
+ "Path to the PIX runtime distribution (optional for D3D12)",
+ os.path.join(d3d12_deps_folder, "pix"),
+ ),
]
@@ -205,10 +250,11 @@ def get_flags():
return [
("arch", arch),
+ ("supported", ["mono"]),
]
-def build_res_file(target, source, env):
+def build_res_file(target, source, env: "SConsEnvironment"):
arch_aliases = {
"x86_32": "pe-i386",
"x86_64": "pe-x86-64",
@@ -243,24 +289,22 @@ def build_res_file(target, source, env):
return 0
-def setup_msvc_manual(env):
+def setup_msvc_manual(env: "SConsEnvironment"):
"""Running from VCVARS environment"""
env_arch = detect_build_env_arch()
if env["arch"] != env_arch:
- print(
- """
- Arch argument (%s) is not matching Native/Cross Compile Tools Prompt/Developer Console (or Visual Studio settings) that is being used to run SCons (%s).
- Run SCons again without arch argument (example: scons p=windows) and SCons will attempt to detect what MSVC compiler will be executed and inform you.
- """
+ print_error(
+ "Arch argument (%s) is not matching Native/Cross Compile Tools Prompt/Developer Console (or Visual Studio settings) that is being used to run SCons (%s).\n"
+ "Run SCons again without arch argument (example: scons p=windows) and SCons will attempt to detect what MSVC compiler will be executed and inform you."
% (env["arch"], env_arch)
)
- sys.exit(200)
+ sys.exit(255)
- print("Found MSVC, arch %s" % (env_arch))
+ print("Using VCVARS-determined MSVC, arch %s" % (env_arch))
-def setup_msvc_auto(env):
+def setup_msvc_auto(env: "SConsEnvironment"):
"""Set up MSVC using SCons's auto-detection logic"""
# If MSVC_VERSION is set by SCons, we know MSVC is installed.
@@ -293,45 +337,37 @@ def setup_msvc_auto(env):
env.Tool("mssdk") # we want the MS SDK
# Note: actual compiler version can be found in env['MSVC_VERSION'], e.g. "14.1" for VS2015
- print("Found MSVC version %s, arch %s" % (env["MSVC_VERSION"], env["arch"]))
+ print("Using SCons-detected MSVC version %s, arch %s" % (env["MSVC_VERSION"], env["arch"]))
-def setup_mingw(env):
+def setup_mingw(env: "SConsEnvironment"):
"""Set up env for use with mingw"""
env_arch = detect_build_env_arch()
if os.getenv("MSYSTEM") == "MSYS":
- print(
- """
- Running from base MSYS2 console/environment, use target specific environment instead (e.g., mingw32, mingw64, clang32, clang64).
- """
+ print_error(
+ "Running from base MSYS2 console/environment, use target specific environment instead (e.g., mingw32, mingw64, clang32, clang64)."
)
- sys.exit(201)
+ sys.exit(255)
if env_arch != "" and env["arch"] != env_arch:
- print(
- """
- Arch argument (%s) is not matching MSYS2 console/environment that is being used to run SCons (%s).
- Run SCons again without arch argument (example: scons p=windows) and SCons will attempt to detect what MSYS2 compiler will be executed and inform you.
- """
+ print_error(
+ "Arch argument (%s) is not matching MSYS2 console/environment that is being used to run SCons (%s).\n"
+ "Run SCons again without arch argument (example: scons p=windows) and SCons will attempt to detect what MSYS2 compiler will be executed and inform you."
% (env["arch"], env_arch)
)
- sys.exit(202)
+ sys.exit(255)
if not try_cmd("gcc --version", env["mingw_prefix"], env["arch"]) and not try_cmd(
"clang --version", env["mingw_prefix"], env["arch"]
):
- print(
- """
- No valid compilers found, use MINGW_PREFIX environment variable to set MinGW path.
- """
- )
- sys.exit(202)
+ print_error("No valid compilers found, use MINGW_PREFIX environment variable to set MinGW path.")
+ sys.exit(255)
print("Using MinGW, arch %s" % (env["arch"]))
-def configure_msvc(env, vcvars_msvc_config):
+def configure_msvc(env: "SConsEnvironment", vcvars_msvc_config):
"""Configure env to work with MSVC"""
## Build type
@@ -348,6 +384,39 @@ def configure_msvc(env, vcvars_msvc_config):
## Compile/link flags
+ env["MAXLINELENGTH"] = 8192 # Windows Vista and beyond, so always applicable.
+
+ if env["silence_msvc"]:
+ from tempfile import mkstemp
+
+ old_spawn = env["SPAWN"]
+
+ def spawn_capture(sh, escape, cmd, args, env):
+ # We only care about cl/link, process everything else as normal.
+ if args[0] not in ["cl", "link"]:
+ return old_spawn(sh, escape, cmd, args, env)
+
+ tmp_stdout, tmp_stdout_name = mkstemp()
+ os.close(tmp_stdout)
+ args.append(f">{tmp_stdout_name}")
+ ret = old_spawn(sh, escape, cmd, args, env)
+
+ try:
+ with open(tmp_stdout_name, "rb") as tmp_stdout:
+ # First line is always bloat, subsequent lines are always errors. If content
+ # exists after discarding the first line, safely decode & send to stderr.
+ tmp_stdout.readline()
+ content = tmp_stdout.read()
+ if content:
+ sys.stderr.write(content.decode(sys.stdout.encoding, "replace"))
+ os.remove(tmp_stdout_name)
+ except OSError:
+ pass
+
+ return ret
+
+ env["SPAWN"] = spawn_capture
+
if env["debug_crt"]:
# Always use dynamic runtime, static debug CRT breaks thread_local.
env.AppendUnique(CCFLAGS=["/MDd"])
@@ -374,9 +443,13 @@ def configure_msvc(env, vcvars_msvc_config):
if vcvars_msvc_config: # should be automatic if SCons found it
if os.getenv("WindowsSdkDir") is not None:
- env.Prepend(CPPPATH=[os.getenv("WindowsSdkDir") + "/Include"])
+ env.Prepend(CPPPATH=[str(os.getenv("WindowsSdkDir")) + "/Include"])
else:
- print("Missing environment variable: WindowsSdkDir")
+ print_warning("Missing environment variable: WindowsSdkDir")
+
+ if int(env["target_win_version"], 16) < 0x0601:
+ print_error("`target_win_version` should be 0x0601 or higher (Windows 7).")
+ sys.exit(255)
env.AppendUnique(
CPPDEFINES=[
@@ -426,10 +499,42 @@ def configure_msvc(env, vcvars_msvc_config):
LIBS += ["psapi", "dbghelp"]
if env["vulkan"]:
- env.AppendUnique(CPPDEFINES=["VULKAN_ENABLED"])
+ env.AppendUnique(CPPDEFINES=["VULKAN_ENABLED", "RD_ENABLED"])
if not env["use_volk"]:
LIBS += ["vulkan"]
+ if env["d3d12"]:
+ # Check whether we have d3d12 dependencies installed.
+ if not os.path.exists(env["mesa_libs"]):
+ print_error(
+ "The Direct3D 12 rendering driver requires dependencies to be installed.\n"
+ "You can install them by running `python misc\\scripts\\install_d3d12_sdk_windows.py`.\n"
+ "See the documentation for more information:\n\t"
+ "https://docs.godotengine.org/en/latest/contributing/development/compiling/compiling_for_windows.html"
+ )
+ sys.exit(255)
+
+ env.AppendUnique(CPPDEFINES=["D3D12_ENABLED", "RD_ENABLED"])
+ LIBS += ["dxgi", "dxguid"]
+ LIBS += ["version"] # Mesa dependency.
+
+ # Needed for avoiding C1128.
+ if env["target"] == "release_debug":
+ env.Append(CXXFLAGS=["/bigobj"])
+
+ # PIX
+ if not env["arch"] in ["x86_64", "arm64"] or env["pix_path"] == "" or not os.path.exists(env["pix_path"]):
+ env["use_pix"] = False
+
+ if env["use_pix"]:
+ arch_subdir = "arm64" if env["arch"] == "arm64" else "x64"
+
+ env.Append(LIBPATH=[env["pix_path"] + "/bin/" + arch_subdir])
+ LIBS += ["WinPixEventRuntime"]
+
+ env.Append(LIBPATH=[env["mesa_libs"] + "/bin"])
+ LIBS += ["libNIR.windows." + env["arch"]]
+
if env["opengl3"]:
env.AppendUnique(CPPDEFINES=["GLES3_ENABLED"])
if env["angle_libs"] != "":
@@ -443,13 +548,16 @@ def configure_msvc(env, vcvars_msvc_config):
LIBS += ["dxgi", "d3d9", "d3d11"]
env.Prepend(CPPPATH=["#thirdparty/angle/include"])
+ if env["target"] in ["editor", "template_debug"]:
+ LIBS += ["psapi", "dbghelp"]
+
env.Append(LINKFLAGS=[p + env["LIBSUFFIX"] for p in LIBS])
if vcvars_msvc_config:
if os.getenv("WindowsSdkDir") is not None:
- env.Append(LIBPATH=[os.getenv("WindowsSdkDir") + "/Lib"])
+ env.Append(LIBPATH=[str(os.getenv("WindowsSdkDir")) + "/Lib"])
else:
- print("Missing environment variable: WindowsSdkDir")
+ print_warning("Missing environment variable: WindowsSdkDir")
## LTO
@@ -458,7 +566,7 @@ def configure_msvc(env, vcvars_msvc_config):
if env["lto"] != "none":
if env["lto"] == "thin":
- print("ThinLTO is only compatible with LLVM, use `use_llvm=yes` or `lto=full`.")
+ print_error("ThinLTO is only compatible with LLVM, use `use_llvm=yes` or `lto=full`.")
sys.exit(255)
env.AppendUnique(CCFLAGS=["/GL"])
env.AppendUnique(ARFLAGS=["/LTCG"])
@@ -468,8 +576,8 @@ def configure_msvc(env, vcvars_msvc_config):
env.AppendUnique(LINKFLAGS=["/LTCG"])
if vcvars_msvc_config:
- env.Prepend(CPPPATH=[p for p in os.getenv("INCLUDE").split(";")])
- env.Append(LIBPATH=[p for p in os.getenv("LIB").split(";")])
+ env.Prepend(CPPPATH=[p for p in str(os.getenv("INCLUDE")).split(";")])
+ env.Append(LIBPATH=[p for p in str(os.getenv("LIB")).split(";")])
# Sanitizers
if env["use_asan"]:
@@ -481,11 +589,11 @@ def configure_msvc(env, vcvars_msvc_config):
env["BUILDERS"]["ProgramOriginal"] = env["BUILDERS"]["Program"]
env["BUILDERS"]["Program"] = methods.precious_program
- env.Append(LINKFLAGS=["/NATVIS:platform\windows\godot.natvis"])
+ env.Append(LINKFLAGS=["/NATVIS:platform\\windows\\godot.natvis"])
env.AppendUnique(LINKFLAGS=["/STACK:" + str(STACK_SIZE)])
-def configure_mingw(env):
+def configure_mingw(env: "SConsEnvironment"):
# Workaround for MinGW. See:
# https://www.scons.org/wiki/LongCmdLinesOnWin32
env.use_windows_spawn_fix()
@@ -575,6 +683,10 @@ def configure_mingw(env):
## Compile flags
+ if int(env["target_win_version"], 16) < 0x0601:
+ print_error("`target_win_version` should be 0x0601 or higher (Windows 7).")
+ sys.exit(255)
+
if not env["use_llvm"]:
env.Append(CCFLAGS=["-mwindows"])
@@ -619,10 +731,38 @@ def configure_mingw(env):
env.Append(LIBS=["psapi", "dbghelp"])
if env["vulkan"]:
- env.Append(CPPDEFINES=["VULKAN_ENABLED"])
+ env.Append(CPPDEFINES=["VULKAN_ENABLED", "RD_ENABLED"])
if not env["use_volk"]:
env.Append(LIBS=["vulkan"])
+ if env["d3d12"]:
+ # Check whether we have d3d12 dependencies installed.
+ if not os.path.exists(env["mesa_libs"]):
+ print_error(
+ "The Direct3D 12 rendering driver requires dependencies to be installed.\n"
+ "You can install them by running `python misc\\scripts\\install_d3d12_sdk_windows.py`.\n"
+ "See the documentation for more information:\n\t"
+ "https://docs.godotengine.org/en/latest/contributing/development/compiling/compiling_for_windows.html"
+ )
+ sys.exit(255)
+
+ env.AppendUnique(CPPDEFINES=["D3D12_ENABLED", "RD_ENABLED"])
+ env.Append(LIBS=["dxgi", "dxguid"])
+
+ # PIX
+ if not env["arch"] in ["x86_64", "arm64"] or env["pix_path"] == "" or not os.path.exists(env["pix_path"]):
+ env["use_pix"] = False
+
+ if env["use_pix"]:
+ arch_subdir = "arm64" if env["arch"] == "arm64" else "x64"
+
+ env.Append(LIBPATH=[env["pix_path"] + "/bin/" + arch_subdir])
+ env.Append(LIBS=["WinPixEventRuntime"])
+
+ env.Append(LIBPATH=[env["mesa_libs"] + "/bin"])
+ env.Append(LIBS=["libNIR.windows." + env["arch"]])
+ env.Append(LIBS=["version"]) # Mesa dependency.
+
if env["opengl3"]:
env.Append(CPPDEFINES=["GLES3_ENABLED"])
if env["angle_libs"] != "":
@@ -644,15 +784,15 @@ def configure_mingw(env):
env.Append(BUILDERS={"RES": env.Builder(action=build_res_file, suffix=".o", src_suffix=".rc")})
-def configure(env: "Environment"):
+def configure(env: "SConsEnvironment"):
# Validate arch.
supported_arches = ["x86_32", "x86_64", "arm32", "arm64"]
if env["arch"] not in supported_arches:
- print(
+ print_error(
'Unsupported CPU architecture "%s" for Windows. Supported architectures are: %s.'
% (env["arch"], ", ".join(supported_arches))
)
- sys.exit()
+ sys.exit(255)
# At this point the env has been set up with basic tools/compilers.
env.Prepend(CPPPATH=["#platform/windows"])