浏览代码

Merge pull request #98105 from Repiteo/scons/mingw-shenanigans

SCons: Extend `MinGW` support & checks
Thaddeus Crews 9 月之前
父节点
当前提交
fa65b70494
共有 2 个文件被更改,包括 51 次插入88 次删除
  1. 48 73
      platform/windows/detect.py
  2. 3 15
      platform/windows/platform_windows_builders.py

+ 48 - 73
platform/windows/detect.py

@@ -68,23 +68,23 @@ def can_build():
 
 
 def get_mingw_bin_prefix(prefix, arch):
-    if not prefix:
-        mingw_bin_prefix = ""
-    elif prefix[-1] != "/":
-        mingw_bin_prefix = prefix + "/bin/"
-    else:
-        mingw_bin_prefix = prefix + "bin/"
+    bin_prefix = (os.path.normpath(os.path.join(prefix, "bin")) + os.sep) if prefix else ""
+    ARCH_PREFIXES = {
+        "x86_64": "x86_64-w64-mingw32-",
+        "x86_32": "i686-w64-mingw32-",
+        "arm32": "armv7-w64-mingw32-",
+        "arm64": "aarch64-w64-mingw32-",
+    }
+    arch_prefix = ARCH_PREFIXES[arch] if arch else ""
+    return bin_prefix + arch_prefix
 
-    if arch == "x86_64":
-        mingw_bin_prefix += "x86_64-w64-mingw32-"
-    elif arch == "x86_32":
-        mingw_bin_prefix += "i686-w64-mingw32-"
-    elif arch == "arm32":
-        mingw_bin_prefix += "armv7-w64-mingw32-"
-    elif arch == "arm64":
-        mingw_bin_prefix += "aarch64-w64-mingw32-"
 
-    return mingw_bin_prefix
+def get_detected(env: "SConsEnvironment", tool: str) -> str:
+    checks = [
+        get_mingw_bin_prefix(env["mingw_prefix"], env["arch"]) + tool,
+        get_mingw_bin_prefix(env["mingw_prefix"], "") + tool,
+    ]
+    return str(env.Detect(checks))
 
 
 def detect_build_env_arch():
@@ -245,41 +245,6 @@ def get_flags():
     }
 
 
-def build_res_file(target, source, env: "SConsEnvironment"):
-    arch_aliases = {
-        "x86_32": "pe-i386",
-        "x86_64": "pe-x86-64",
-        "arm32": "armv7-w64-mingw32",
-        "arm64": "aarch64-w64-mingw32",
-    }
-    cmdbase = "windres --include-dir . --target=" + arch_aliases[env["arch"]]
-
-    mingw_bin_prefix = get_mingw_bin_prefix(env["mingw_prefix"], env["arch"])
-
-    for x in range(len(source)):
-        ok = True
-        # Try prefixed executable (MinGW on Linux).
-        cmd = mingw_bin_prefix + cmdbase + " -i " + str(source[x]) + " -o " + str(target[x])
-        try:
-            out = subprocess.Popen(cmd, shell=True, stderr=subprocess.PIPE).communicate()
-            if len(out[1]):
-                ok = False
-        except Exception:
-            ok = False
-
-        # Try generic executable (MSYS2).
-        if not ok:
-            cmd = cmdbase + " -i " + str(source[x]) + " -o " + str(target[x])
-            try:
-                out = subprocess.Popen(cmd, shell=True, stderr=subprocess.PIPE).communicate()
-                if len(out[1]):
-                    return -1
-            except Exception:
-                return -1
-
-    return 0
-
-
 def setup_msvc_manual(env: "SConsEnvironment"):
     """Running from VCVARS environment"""
 
@@ -361,6 +326,10 @@ def setup_mingw(env: "SConsEnvironment"):
         print_error("No valid compilers found, use MINGW_PREFIX environment variable to set MinGW path.")
         sys.exit(255)
 
+    env.Tool("mingw")
+    env.AppendUnique(CCFLAGS=env.get("ccflags", "").split())
+    env.AppendUnique(RCFLAGS=env.get("rcflags", "").split())
+
     print("Using MinGW, arch %s" % (env["arch"]))
 
 
@@ -706,6 +675,13 @@ def configure_mingw(env: "SConsEnvironment"):
     # https://www.scons.org/wiki/LongCmdLinesOnWin32
     env.use_windows_spawn_fix()
 
+    # HACK: For some reason, Windows-native shells have their MinGW tools
+    # frequently fail as a result of parsing path separators incorrectly.
+    # For some other reason, this issue is circumvented entirely if the
+    # `mingw_prefix` bin is prepended to PATH.
+    if os.sep == "\\":
+        env.PrependENVPath("PATH", os.path.join(env["mingw_prefix"], "bin"))
+
     # In case the command line to AR is too long, use a response file.
     env["ARCOM_ORIG"] = env["ARCOM"]
     env["ARCOM"] = "${TEMPFILE('$ARCOM_ORIG', '$ARCOMSTR')}"
@@ -760,29 +736,31 @@ def configure_mingw(env: "SConsEnvironment"):
 
     env.Append(CCFLAGS=["-ffp-contract=off"])
 
-    mingw_bin_prefix = get_mingw_bin_prefix(env["mingw_prefix"], env["arch"])
-
     if env["use_llvm"]:
-        env["CC"] = mingw_bin_prefix + "clang"
-        env["CXX"] = mingw_bin_prefix + "clang++"
-        if try_cmd("as --version", env["mingw_prefix"], env["arch"]):
-            env["AS"] = mingw_bin_prefix + "as"
-            env.Append(ASFLAGS=["-c"])
-        if try_cmd("ar --version", env["mingw_prefix"], env["arch"]):
-            env["AR"] = mingw_bin_prefix + "ar"
-        if try_cmd("ranlib --version", env["mingw_prefix"], env["arch"]):
-            env["RANLIB"] = mingw_bin_prefix + "ranlib"
+        env["CC"] = get_detected(env, "clang")
+        env["CXX"] = get_detected(env, "clang++")
+        env["AR"] = get_detected(env, "ar")
+        env["RANLIB"] = get_detected(env, "ranlib")
+        env.Append(ASFLAGS=["-c"])
         env.extra_suffix = ".llvm" + env.extra_suffix
     else:
-        env["CC"] = mingw_bin_prefix + "gcc"
-        env["CXX"] = mingw_bin_prefix + "g++"
-        if try_cmd("as --version", env["mingw_prefix"], env["arch"]):
-            env["AS"] = mingw_bin_prefix + "as"
-        ar = "ar" if os.name == "nt" else "gcc-ar"
-        if try_cmd(f"{ar} --version", env["mingw_prefix"], env["arch"]):
-            env["AR"] = mingw_bin_prefix + ar
-        if try_cmd("gcc-ranlib --version", env["mingw_prefix"], env["arch"]):
-            env["RANLIB"] = mingw_bin_prefix + "gcc-ranlib"
+        env["CC"] = get_detected(env, "gcc")
+        env["CXX"] = get_detected(env, "g++")
+        env["AR"] = get_detected(env, "gcc-ar" if os.name != "nt" else "ar")
+        env["RANLIB"] = get_detected(env, "gcc-ranlib")
+
+    env["RC"] = get_detected(env, "windres")
+    ARCH_TARGETS = {
+        "x86_32": "pe-i386",
+        "x86_64": "pe-x86-64",
+        "arm32": "armv7-w64-mingw32",
+        "arm64": "aarch64-w64-mingw32",
+    }
+    env.AppendUnique(RCFLAGS=f"--target={ARCH_TARGETS[env['arch']]}")
+
+    env["AS"] = get_detected(env, "as")
+    env["OBJCOPY"] = get_detected(env, "objcopy")
+    env["STRIP"] = get_detected(env, "strip")
 
     ## LTO
 
@@ -924,9 +902,6 @@ def configure_mingw(env: "SConsEnvironment"):
 
     env.Append(CPPDEFINES=["MINGW_ENABLED", ("MINGW_HAS_SECURE_API", 1)])
 
-    # resrc
-    env.Append(BUILDERS={"RES": env.Builder(action=build_res_file, suffix=".o", src_suffix=".rc")})
-
 
 def configure(env: "SConsEnvironment"):
     # Validate arch.

+ 3 - 15
platform/windows/platform_windows_builders.py

@@ -2,23 +2,11 @@
 
 import os
 
-from detect import get_mingw_bin_prefix, try_cmd
-
 
 def make_debug_mingw(target, source, env):
     dst = str(target[0])
     # Force separate debug symbols if executable size is larger than 1.9 GB.
     if env["separate_debug_symbols"] or os.stat(dst).st_size >= 2040109465:
-        mingw_bin_prefix = get_mingw_bin_prefix(env["mingw_prefix"], env["arch"])
-        if try_cmd("objcopy --version", env["mingw_prefix"], env["arch"]):
-            os.system(mingw_bin_prefix + "objcopy --only-keep-debug {0} {0}.debugsymbols".format(dst))
-        else:
-            os.system("objcopy --only-keep-debug {0} {0}.debugsymbols".format(dst))
-        if try_cmd("strip --version", env["mingw_prefix"], env["arch"]):
-            os.system(mingw_bin_prefix + "strip --strip-debug --strip-unneeded {0}".format(dst))
-        else:
-            os.system("strip --strip-debug --strip-unneeded {0}".format(dst))
-        if try_cmd("objcopy --version", env["mingw_prefix"], env["arch"]):
-            os.system(mingw_bin_prefix + "objcopy --add-gnu-debuglink={0}.debugsymbols {0}".format(dst))
-        else:
-            os.system("objcopy --add-gnu-debuglink={0}.debugsymbols {0}".format(dst))
+        os.system("{0} --only-keep-debug {1} {1}.debugsymbols".format(env["OBJCOPY"], dst))
+        os.system("{0} --strip-debug --strip-unneeded {1}".format(env["STRIP"], dst))
+        os.system("{0} --add-gnu-debuglink={1}.debugsymbols {1}".format(env["OBJCOPY"], dst))