Browse Source

SCons: Simplify Windows/MSVC detection

Thaddeus Crews 6 months ago
parent
commit
4505352021
2 changed files with 30 additions and 142 deletions
  1. 1 1
      methods.py
  2. 29 141
      platform/windows/detect.py

+ 1 - 1
methods.py

@@ -553,7 +553,7 @@ def glob_recursive(pattern, node="."):
 
 
 def precious_program(env, program, sources, **args):
-    program = env.ProgramOriginal(program, sources, **args)
+    program = env.Program(program, sources, **args)
     env.Precious(program)
     return program
 

+ 29 - 141
platform/windows/detect.py

@@ -47,14 +47,6 @@ def try_cmd(test, prefix, arch, check_clang=False):
 def can_build():
     if os.name == "nt":
         # Building natively on Windows
-        # If VCINSTALLDIR is set in the OS environ, use traditional Godot logic to set up MSVC
-        if os.getenv("VCINSTALLDIR"):  # MSVC, manual setup
-            return True
-
-        # Otherwise, let SCons find MSVC if installed, or else MinGW.
-        # Since we're just returning True here, if there's no compiler
-        # installed, we'll get errors when it tries to build with the
-        # null compiler.
         return True
 
     if os.name == "posix":
@@ -156,10 +148,13 @@ def detect_build_env_arch():
 
 
 def get_tools(env: "SConsEnvironment"):
-    if os.name != "nt" or env["use_mingw"]:
+    if os.name != "nt" or env.get("use_mingw"):
         return ["mingw"]
     else:
-        return ["default"]
+        msvc_arch_aliases = {"x86_32": "x86", "arm32": "arm"}
+        env["TARGET_ARCH"] = msvc_arch_aliases.get(env["arch"], env["arch"])
+        env["MSVC_VERSION"] = env["MSVS_VERSION"] = env.get("msvc_version")
+        return ["msvc", "mslink", "mslib"]
 
 
 def get_opts():
@@ -194,11 +189,7 @@ def get_opts():
             "0x0601",
         ),
         EnumVariable("windows_subsystem", "Windows subsystem", "gui", ("gui", "console")),
-        (
-            "msvc_version",
-            "MSVC version to use. Ignored if VCINSTALLDIR is set in shell env.",
-            None,
-        ),
+        ("msvc_version", "MSVC version to use. Handled automatically by SCons if omitted.", ""),
         BoolVariable("use_mingw", "Use the Mingw compiler, even if MSVC is installed.", False),
         BoolVariable("use_llvm", "Use the LLVM compiler", False),
         BoolVariable("use_static_cpp", "Link MinGW/MSVC C++ runtime libraries statically", True),
@@ -252,91 +243,7 @@ def get_flags():
     }
 
 
-def setup_msvc_manual(env: "SConsEnvironment"):
-    """Running from VCVARS environment"""
-
-    env_arch = detect_build_env_arch()
-    if env["arch"] != env_arch:
-        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(255)
-
-    print("Using VCVARS-determined MSVC, arch %s" % (env_arch))
-
-
-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.
-    # But we may want a different version or target arch.
-
-    # Valid architectures for MSVC's TARGET_ARCH:
-    # ['amd64', 'emt64', 'i386', 'i486', 'i586', 'i686', 'ia64', 'itanium', 'x86', 'x86_64', 'arm', 'arm64', 'aarch64']
-    # Our x86_64 and arm64 are the same, and we need to map the 32-bit
-    # architectures to other names since MSVC isn't as explicit.
-    # The rest we don't need to worry about because they are
-    # aliases or aren't supported by Godot (itanium & ia64).
-    msvc_arch_aliases = {"x86_32": "x86", "arm32": "arm"}
-    if env["arch"] in msvc_arch_aliases.keys():
-        env["TARGET_ARCH"] = msvc_arch_aliases[env["arch"]]
-    else:
-        env["TARGET_ARCH"] = env["arch"]
-
-    # The env may have already been set up with default MSVC tools, so
-    # reset a few things so we can set it up with the tools we want.
-    # (Ideally we'd decide on the tool config before configuring any
-    # environment, and just set the env up once, but this function runs
-    # on an existing env so this is the simplest way.)
-    env["MSVC_SETUP_RUN"] = False  # Need to set this to re-run the tool
-    env["MSVS_VERSION"] = None
-    env["MSVC_VERSION"] = None
-
-    if "msvc_version" in env:
-        env["MSVC_VERSION"] = env["msvc_version"]
-    env.Tool("msvc")
-    env.Tool("mssdk")  # we want the MS SDK
-
-    # Re-add potentially overwritten flags.
-    env.AppendUnique(CCFLAGS=env.get("ccflags", "").split())
-    env.AppendUnique(CXXFLAGS=env.get("cxxflags", "").split())
-    env.AppendUnique(CFLAGS=env.get("cflags", "").split())
-    env.AppendUnique(RCFLAGS=env.get("rcflags", "").split())
-
-    # Note: actual compiler version can be found in env['MSVC_VERSION'], e.g. "14.1" for VS2015
-    print("Using SCons-detected MSVC version %s, arch %s" % (env["MSVC_VERSION"], env["arch"]))
-
-
-def setup_mingw(env: "SConsEnvironment"):
-    """Set up env for use with mingw"""
-
-    env_arch = detect_build_env_arch()
-    if os.getenv("MSYSTEM") == "MSYS":
-        print_error(
-            "Running from base MSYS2 console/environment, use target specific environment instead (e.g., mingw32, mingw64, clang32, clang64)."
-        )
-        sys.exit(255)
-
-    if env_arch != "" and env["arch"] != env_arch:
-        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(255)
-
-    if not try_cmd("gcc --version", env["mingw_prefix"], env["arch"]) and not try_cmd(
-        "clang --version", env["mingw_prefix"], env["arch"]
-    ):
-        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: "SConsEnvironment", vcvars_msvc_config):
+def configure_msvc(env: "SConsEnvironment"):
     """Configure env to work with MSVC"""
 
     ## Build type
@@ -454,12 +361,6 @@ def configure_msvc(env: "SConsEnvironment", vcvars_msvc_config):
     # for notes on why this shouldn't be enabled for gcc
     env.AppendUnique(CCFLAGS=["/bigobj"])
 
-    if vcvars_msvc_config:  # should be automatic if SCons found it
-        if os.getenv("WindowsSdkDir") is not None:
-            env.Prepend(CPPPATH=[str(os.getenv("WindowsSdkDir")) + "/Include"])
-        else:
-            print_warning("Missing environment variable: WindowsSdkDir")
-
     validate_win_version(env)
 
     env.AppendUnique(
@@ -568,12 +469,6 @@ def configure_msvc(env: "SConsEnvironment", vcvars_msvc_config):
 
     env.Append(LINKFLAGS=[p + env["LIBSUFFIX"] for p in LIBS])
 
-    if vcvars_msvc_config:
-        if os.getenv("WindowsSdkDir") is not None:
-            env.Append(LIBPATH=[str(os.getenv("WindowsSdkDir")) + "/Lib"])
-        else:
-            print_warning("Missing environment variable: WindowsSdkDir")
-
     ## LTO
 
     if env["lto"] == "auto":  # No LTO by default for MSVC, doesn't help.
@@ -596,14 +491,6 @@ def configure_msvc(env: "SConsEnvironment", vcvars_msvc_config):
             env.AppendUnique(LINKFLAGS=["/LTCG"])
         env.AppendUnique(ARFLAGS=["/LTCG"])
 
-    if vcvars_msvc_config:
-        env.Prepend(CPPPATH=[p for p in str(os.getenv("INCLUDE")).split(";")])
-        env.Append(LIBPATH=[p for p in str(os.getenv("LIB")).split(";")])
-
-    # Incremental linking fix
-    env["BUILDERS"]["ProgramOriginal"] = env["BUILDERS"]["Program"]
-    env["BUILDERS"]["Program"] = methods.precious_program
-
     env.Append(LINKFLAGS=["/NATVIS:platform\\windows\\godot.natvis"])
 
     if env["use_asan"]:
@@ -679,6 +566,25 @@ def tempfile_arg_esc_func(arg):
 
 
 def configure_mingw(env: "SConsEnvironment"):
+    if os.getenv("MSYSTEM") == "MSYS":
+        print_error(
+            "Running from base MSYS2 console/environment, use target specific environment instead (e.g., mingw32, mingw64, clang32, clang64)."
+        )
+        sys.exit(255)
+
+    if (env_arch := detect_build_env_arch()) and env["arch"] != env_arch:
+        print_error(
+            f"Arch argument ({env['arch']}) is not matching MSYS2 console/environment that is being used to run SCons ({env_arch}).\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."
+        )
+        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_error("No valid compilers found, use MINGW_PREFIX environment variable to set MinGW path.")
+        sys.exit(255)
+
     # Workaround for MinGW. See:
     # https://www.scons.org/wiki/LongCmdLinesOnWin32
     env.use_windows_spawn_fix()
@@ -913,28 +819,10 @@ def configure(env: "SConsEnvironment"):
     # At this point the env has been set up with basic tools/compilers.
     env.Prepend(CPPPATH=["#platform/windows"])
 
-    if os.name == "nt":
-        env["ENV"] = os.environ  # this makes build less repeatable, but simplifies some things
-        env["ENV"]["TMP"] = os.environ["TMP"]
-
-    # First figure out which compiler, version, and target arch we're using
-    if os.getenv("VCINSTALLDIR") and detect_build_env_arch() and not env["use_mingw"]:
-        setup_msvc_manual(env)
-        env.msvc = True
-        vcvars_msvc_config = True
-    elif env.get("MSVC_VERSION", "") and not env["use_mingw"]:
-        setup_msvc_auto(env)
-        env.msvc = True
-        vcvars_msvc_config = False
-    else:
-        setup_mingw(env)
-        env.msvc = False
-
-    # Now set compiler/linker flags
+    env.msvc = "mingw" not in env["TOOLS"]
     if env.msvc:
-        configure_msvc(env, vcvars_msvc_config)
-
-    else:  # MinGW
+        configure_msvc(env)
+    else:
         configure_mingw(env)