浏览代码

Merge pull request #63278 from akien-mga/scons-linux-refactor-linker

Rémi Verschelde 3 年之前
父节点
当前提交
f37990ed77
共有 2 个文件被更改,包括 37 次插入20 次删除
  1. 4 4
      .github/workflows/linux_builds.yml
  2. 33 16
      platform/linuxbsd/detect.py

+ 4 - 4
.github/workflows/linux_builds.yml

@@ -31,12 +31,12 @@ jobs:
             proj-conv: true
             artifact: true
 
-          - name: Editor with doubles and GCC sanitizers (target=debug, tools=yes, float=64, tests=yes, use_asan=yes, use_ubsan=yes, ld.gold)
+          - name: Editor with doubles and GCC sanitizers (target=debug, tools=yes, float=64, tests=yes, use_asan=yes, use_ubsan=yes, linker=gold)
             cache-name: linux-editor-double-sanitizers
             target: debug
             tools: true
             tests: true
-            sconsflags: float=64 use_asan=yes use_ubsan=yes LINKFLAGS="-fuse-ld=gold"
+            sconsflags: float=64 use_asan=yes use_ubsan=yes linker=gold
             proj-test: true
             # Can be turned off for PRs that intentionally break compat with godot-cpp,
             # until both the upstream PR and the matching godot-cpp changes are merged.
@@ -46,12 +46,12 @@ jobs:
             # Skip 2GiB artifact speeding up action.
             artifact: false
 
-          - name: Editor with clang sanitizers (target=debug, tools=yes, use_asan=yes, use_ubsan=yes, use_llvm=yes, use_lld=yes)
+          - name: Editor with clang sanitizers (target=debug, tools=yes, use_asan=yes, use_ubsan=yes, use_llvm=yes, linker=lld)
             cache-name: linux-editor-llvm-sanitizers
             target: debug
             tools: true
             tests: true
-            sconsflags: use_asan=yes use_ubsan=yes use_llvm=yes use_lld=yes
+            sconsflags: use_asan=yes use_ubsan=yes use_llvm=yes linker=lld
             bin: "./bin/godot.linuxbsd.tools.64.llvm.san"
             build-mono: false
             # Skip 2GiB artifact speeding up action.

+ 33 - 16
platform/linuxbsd/detect.py

@@ -1,6 +1,7 @@
 import os
 import platform
 import sys
+from methods import get_compiler_version, using_gcc
 
 
 def is_active():
@@ -27,9 +28,9 @@ def get_opts():
     from SCons.Variables import BoolVariable, EnumVariable
 
     return [
+        EnumVariable("linker", "Linker program", "default", ("default", "bfd", "gold", "lld", "mold")),
         BoolVariable("use_llvm", "Use the LLVM compiler", False),
-        BoolVariable("use_lld", "Use the LLD linker", False),
-        BoolVariable("use_thinlto", "Use ThinLTO", False),
+        BoolVariable("use_thinlto", "Use ThinLTO (LLVM only, requires linker=lld, implies use_lto=yes)", False),
         BoolVariable("use_static_cpp", "Link libgcc and libstdc++ statically for better portability", True),
         BoolVariable("use_coverage", "Test Godot coverage", False),
         BoolVariable("use_ubsan", "Use LLVM/GCC compiler undefined behavior sanitizer (UBSAN)", False),
@@ -111,15 +112,32 @@ def configure(env):
             env["CXX"] = "clang++"
         env.extra_suffix = ".llvm" + env.extra_suffix
 
-    if env["use_lld"]:
-        if env["use_llvm"]:
-            env.Append(LINKFLAGS=["-fuse-ld=lld"])
-            if env["use_thinlto"]:
-                # A convenience so you don't need to write use_lto too when using SCons
-                env["use_lto"] = True
+    if env["linker"] != "default":
+        print("Using linker program: " + env["linker"])
+        if env["linker"] == "mold" and using_gcc(env):  # GCC < 12.1 doesn't support -fuse-ld=mold.
+            cc_version = get_compiler_version(env)
+            cc_semver = (int(cc_version["major"]), int(cc_version["minor"]))
+            if cc_semver < (12, 1):
+                found_wrapper = False
+                for path in ["/usr/libexec", "/usr/local/libexec", "/usr/lib", "/usr/local/lib"]:
+                    if os.path.isfile(path + "/mold/ld"):
+                        env.Append(LINKFLAGS=["-B" + path + "/mold"])
+                        found_wrapper = True
+                        break
+                if not found_wrapper:
+                    print("Couldn't locate mold installation path. Make sure it's installed in /usr or /usr/local.")
+                    sys.exit(255)
+            else:
+                env.Append(LINKFLAGS=["-fuse-ld=mold"])
         else:
-            print("Using LLD with GCC is not supported yet. Try compiling with 'use_llvm=yes'.")
+            env.Append(LINKFLAGS=["-fuse-ld=%s" % env["linker"]])
+
+    if env["use_thinlto"]:
+        if not env["use_llvm"] or env["linker"] != "lld":
+            print("ThinLTO is only compatible with LLVM and the LLD linker, use `use_llvm=yes linker=lld`.")
             sys.exit(255)
+        else:
+            env["use_lto"] = True  # ThinLTO implies LTO
 
     if env["use_coverage"]:
         env.Append(CCFLAGS=["-ftest-coverage", "-fprofile-arcs"])
@@ -164,16 +182,15 @@ def configure(env):
             env.Append(LINKFLAGS=["-fsanitize=memory"])
 
     if env["use_lto"]:
-        if not env["use_llvm"] and env.GetOption("num_jobs") > 1:
+        if env["use_thinlto"]:
+            env.Append(CCFLAGS=["-flto=thin"])
+            env.Append(LINKFLAGS=["-flto=thin"])
+        elif not env["use_llvm"] and env.GetOption("num_jobs") > 1:
             env.Append(CCFLAGS=["-flto"])
             env.Append(LINKFLAGS=["-flto=" + str(env.GetOption("num_jobs"))])
         else:
-            if env["use_lld"] and env["use_thinlto"]:
-                env.Append(CCFLAGS=["-flto=thin"])
-                env.Append(LINKFLAGS=["-flto=thin"])
-            else:
-                env.Append(CCFLAGS=["-flto"])
-                env.Append(LINKFLAGS=["-flto"])
+            env.Append(CCFLAGS=["-flto"])
+            env.Append(LINKFLAGS=["-flto"])
 
         if not env["use_llvm"]:
             env["RANLIB"] = "gcc-ranlib"