Browse Source

SCons: Sync `targets.py` fully with upstream Godot

- Reorders existing code to match Godot.
- Adds `NDEBUG` for non-dev builds.
- Adds `-gdwarf-4` for Clang debug symbols.
- Adds strip link flag for GCC/Clang builds without debug symbols.

(cherry picked from commit 600e749d9bbeb5bad58d2d6d097b2f6b52cbe241)
Rémi Verschelde 2 years ago
parent
commit
738ef9baf8
1 changed files with 61 additions and 9 deletions
  1. 61 9
      tools/targets.py

+ 61 - 9
tools/targets.py

@@ -1,10 +1,14 @@
 import os
+import subprocess
 import sys
 from SCons.Script import ARGUMENTS
 from SCons.Variables import *
 from SCons.Variables.BoolVariable import _text2bool
 
 
+# Helper methods
+
+
 def get_cmdline_bool(option, default):
     """We use `ARGUMENTS.get()` to check if options were manually overridden on the command line,
     and SCons' _text2bool helper to convert them to booleans, otherwise they're handled as strings.
@@ -16,6 +20,24 @@ def get_cmdline_bool(option, default):
         return default
 
 
+def using_clang(env):
+    return "clang" in os.path.basename(env["CC"])
+
+
+def is_vanilla_clang(env):
+    if not using_clang(env):
+        return False
+    try:
+        version = subprocess.check_output([env.subst(env["CXX"]), "--version"]).strip().decode("utf-8")
+    except (subprocess.CalledProcessError, OSError):
+        print("Couldn't parse CXX environment variable to infer compiler version.")
+        return False
+    return not version.startswith("Apple")
+
+
+# Main tool definition
+
+
 def options(opts):
     opts.Add(
         EnumVariable(
@@ -34,19 +56,21 @@ def exists(env):
 
 
 def generate(env):
-    env.dev_build = env["dev_build"]
-    env.debug_features = env["target"] in ["editor", "template_debug"]
-    env.editor_build = env["target"] == "editor"
+    # Configuration of build targets:
+    # - Editor or template
+    # - Debug features (DEBUG_ENABLED code)
+    # - Dev only code (DEV_ENABLED code)
+    # - Optimization level
+    # - Debug symbols for crash traces / debuggers
 
-    if env.editor_build:
-        env.AppendUnique(CPPDEFINES=["TOOLS_ENABLED"])
+    # Keep this configuration in sync with SConstruct in upstream Godot.
 
-    if env.debug_features:
-        env.AppendUnique(CPPDEFINES=["DEBUG_ENABLED", "DEBUG_METHODS_ENABLED"])
+    env.editor_build = env["target"] == "editor"
+    env.dev_build = env["dev_build"]
+    env.debug_features = env["target"] in ["editor", "template_debug"]
 
     if env.dev_build:
         opt_level = "none"
-        env.AppendUnique(CPPDEFINES=["DEV_ENABLED"])
     elif env.debug_features:
         opt_level = "speed_trace"
     else:  # Release
@@ -55,6 +79,26 @@ def generate(env):
     env["optimize"] = ARGUMENTS.get("optimize", opt_level)
     env["debug_symbols"] = get_cmdline_bool("debug_symbols", env.dev_build)
 
+    if env.editor_build:
+        env.Append(CPPDEFINES=["TOOLS_ENABLED"])
+
+    if env.debug_features:
+        # DEBUG_ENABLED enables debugging *features* and debug-only code, which is intended
+        # to give *users* extra debugging information for their game development.
+        env.Append(CPPDEFINES=["DEBUG_ENABLED"])
+        # In upstream Godot this is added in typedefs.h when DEBUG_ENABLED is set.
+        env.Append(CPPDEFINES=["DEBUG_METHODS_ENABLED"])
+
+    if env.dev_build:
+        # DEV_ENABLED enables *engine developer* code which should only be compiled for those
+        # working on the engine itself.
+        env.Append(CPPDEFINES=["DEV_ENABLED"])
+    else:
+        # Disable assert() for production targets (only used in thirdparty code).
+        env.Append(CPPDEFINES=["NDEBUG"])
+
+    # Set optimize and debug_symbols flags.
+    # "custom" means do nothing and let users set their own optimization flags.
     if env.get("is_msvc", False):
         if env["debug_symbols"]:
             env.Append(CCFLAGS=["/Zi", "/FS"])
@@ -71,13 +115,21 @@ def generate(env):
             env.Append(LINKFLAGS=["/OPT:REF"])
         elif env["optimize"] == "debug" or env["optimize"] == "none":
             env.Append(CCFLAGS=["/Od"])
-
     else:
         if env["debug_symbols"]:
+            # Adding dwarf-4 explicitly makes stacktraces work with clang builds,
+            # otherwise addr2line doesn't understand them.
+            env.Append(CCFLAGS=["-gdwarf-4"])
             if env.dev_build:
                 env.Append(CCFLAGS=["-g3"])
             else:
                 env.Append(CCFLAGS=["-g2"])
+        else:
+            if using_clang(env) and not is_vanilla_clang(env):
+                # Apple Clang, its linker doesn't like -s.
+                env.Append(LINKFLAGS=["-Wl,-S", "-Wl,-x", "-Wl,-dead_strip"])
+            else:
+                env.Append(LINKFLAGS=["-s"])
 
         if env["optimize"] == "speed":
             env.Append(CCFLAGS=["-O3"])