Selaa lähdekoodia

SCons: Refactor handling of `production` flag and per-platform LTO defaults

Fixup to #63288.
See #65583 for the bug report.

Co-authored-by: Cyberrebell <[email protected]>
(cherry picked from commit 35a15e619161798820b2bd6ff46178c5b7ccebcf)
Rémi Verschelde 3 vuotta sitten
vanhempi
commit
d5c1baa288

+ 29 - 32
SConstruct

@@ -123,7 +123,7 @@ opts.Add("arch", "Platform-dependent architecture (arm/arm64/x86/x64/mips/...)",
 opts.Add(EnumVariable("bits", "Target platform bits", "default", ("default", "32", "64")))
 opts.Add(EnumVariable("bits", "Target platform bits", "default", ("default", "32", "64")))
 opts.Add(EnumVariable("optimize", "Optimization type", "speed", ("speed", "size", "none")))
 opts.Add(EnumVariable("optimize", "Optimization type", "speed", ("speed", "size", "none")))
 opts.Add(BoolVariable("production", "Set defaults to build Godot for use in production", False))
 opts.Add(BoolVariable("production", "Set defaults to build Godot for use in production", False))
-opts.Add(EnumVariable("lto", "Link-time optimization (for production builds)", "none", ("none", "thin", "full")))
+opts.Add(EnumVariable("lto", "Link-time optimization (production builds)", "none", ("none", "auto", "thin", "full")))
 
 
 # Components
 # Components
 opts.Add(BoolVariable("deprecated", "Enable deprecated features", True))
 opts.Add(BoolVariable("deprecated", "Enable deprecated features", True))
@@ -411,58 +411,55 @@ if selected_platform in platform_list:
     env["LINKFLAGS"] = ""
     env["LINKFLAGS"] = ""
     env.Append(LINKFLAGS=str(LINKFLAGS).split())
     env.Append(LINKFLAGS=str(LINKFLAGS).split())
 
 
-    # Platform specific flags
+    # Platform specific flags.
+    # These can sometimes override default options.
     flag_list = platform_flags[selected_platform]
     flag_list = platform_flags[selected_platform]
     for f in flag_list:
     for f in flag_list:
         if not (f[0] in ARGUMENTS):  # allow command line to override platform flags
         if not (f[0] in ARGUMENTS):  # allow command line to override platform flags
             env[f[0]] = f[1]
             env[f[0]] = f[1]
 
 
-    # Must happen after the flags definition, so that they can be used by platform detect
-    detect.configure(env)
-
-    # Set our C and C++ standard requirements.
-    # Prepending to make it possible to override
-    # This needs to come after `configure`, otherwise we don't have env.msvc.
-    if not env.msvc:
-        # Specifying GNU extensions support explicitly, which are supported by
-        # both GCC and Clang. This mirrors GCC and Clang's current default
-        # compile flags if no -std is specified.
-        env.Prepend(CFLAGS=["-std=gnu11"])
-        env.Prepend(CXXFLAGS=["-std=gnu++14"])
-    else:
-        # MSVC doesn't have clear C standard support, /std only covers C++.
-        # We apply it to CCFLAGS (both C and C++ code) in case it impacts C features.
-        env.Prepend(CCFLAGS=["/std:c++14"])
-
-    # 'dev' and 'production' are aliases to set default options if they haven't been set
-    # manually by the user.
+    # 'dev' and 'production' are aliases to set default options if they haven't been
+    # set manually by the user.
+    # These need to be checked *after* platform specific flags so that different
+    # default values can be set (e.g. to keep LTO off for `production` on some platforms).
     if env["dev"]:
     if env["dev"]:
         env["verbose"] = methods.get_cmdline_bool("verbose", True)
         env["verbose"] = methods.get_cmdline_bool("verbose", True)
         env["warnings"] = ARGUMENTS.get("warnings", "extra")
         env["warnings"] = ARGUMENTS.get("warnings", "extra")
         env["werror"] = methods.get_cmdline_bool("werror", True)
         env["werror"] = methods.get_cmdline_bool("werror", True)
     if env["production"]:
     if env["production"]:
         env["use_static_cpp"] = methods.get_cmdline_bool("use_static_cpp", True)
         env["use_static_cpp"] = methods.get_cmdline_bool("use_static_cpp", True)
-        env["lto"] = ARGUMENTS.get("lto", "full")
         env["debug_symbols"] = methods.get_cmdline_bool("debug_symbols", False)
         env["debug_symbols"] = methods.get_cmdline_bool("debug_symbols", False)
+        # LTO "auto" means we handle the preferred option in each platform detect.py.
+        env["lto"] = ARGUMENTS.get("lto", "auto")
         if not env["tools"] and env["target"] == "debug":
         if not env["tools"] and env["target"] == "debug":
             print(
             print(
                 "WARNING: Requested `production` build with `tools=no target=debug`, "
                 "WARNING: Requested `production` build with `tools=no target=debug`, "
                 "this will give you a full debug template (use `target=release_debug` "
                 "this will give you a full debug template (use `target=release_debug` "
                 "for an optimized template with debug features)."
                 "for an optimized template with debug features)."
             )
             )
-        if env.msvc:
-            print(
-                "WARNING: For `production` Windows builds, you should use MinGW with GCC "
-                "or Clang instead of Visual Studio, as they can better optimize the "
-                "GDScript VM in a very significant way. MSVC LTO also doesn't work "
-                "reliably for our use case."
-                "If you want to use MSVC nevertheless for production builds, set "
-                "`debug_symbols=no lto=none` instead of the `production=yes` option."
-            )
-            Exit(255)
+
+    # Must happen after the flags' definition, as configure is when most flags
+    # are actually handled to change compile options, etc.
+    detect.configure(env)
+
+    # Needs to happen after configure to handle "auto".
     if env["lto"] != "none":
     if env["lto"] != "none":
         print("Using LTO: " + env["lto"])
         print("Using LTO: " + env["lto"])
 
 
+    # Set our C and C++ standard requirements.
+    # Prepending to make it possible to override
+    # This needs to come after `configure`, otherwise we don't have env.msvc.
+    if not env.msvc:
+        # Specifying GNU extensions support explicitly, which are supported by
+        # both GCC and Clang. This mirrors GCC and Clang's current default
+        # compile flags if no -std is specified.
+        env.Prepend(CFLAGS=["-std=gnu11"])
+        env.Prepend(CXXFLAGS=["-std=gnu++14"])
+    else:
+        # MSVC doesn't have clear C standard support, /std only covers C++.
+        # We apply it to CCFLAGS (both C and C++ code) in case it impacts C features.
+        env.Prepend(CCFLAGS=["/std:c++14"])
+
     # Handle renamed options.
     # Handle renamed options.
     if "use_lto" in ARGUMENTS or "use_thinlto" in ARGUMENTS:
     if "use_lto" in ARGUMENTS or "use_thinlto" in ARGUMENTS:
         print("Error: The `use_lto` and `use_thinlto` boolean options have been unified to `lto=<none|thin|full>`.")
         print("Error: The `use_lto` and `use_thinlto` boolean options have been unified to `lto=<none|thin|full>`.")

+ 4 - 3
platform/android/detect.py

@@ -48,9 +48,6 @@ def get_ndk_version():
 def get_flags():
 def get_flags():
     return [
     return [
         ("tools", False),
         ("tools", False),
-        # Benefits of LTO for Android (size, performance) haven't been clearly established yet.
-        # So for now we override the default value which may be set when using `production=yes`.
-        ("lto", "none"),
     ]
     ]
 
 
 
 
@@ -141,6 +138,10 @@ def configure(env):
         env.Append(CPPFLAGS=["-UNDEBUG"])
         env.Append(CPPFLAGS=["-UNDEBUG"])
 
 
     # LTO
     # LTO
+
+    if env["lto"] == "auto":  # LTO benefits for Android (size, performance) haven't been clearly established yet.
+        env["lto"] = "none"
+
     if env["lto"] != "none":
     if env["lto"] != "none":
         if env["lto"] == "thin":
         if env["lto"] == "thin":
             env.Append(CCFLAGS=["-flto=thin"])
             env.Append(CCFLAGS=["-flto=thin"])

+ 5 - 4
platform/iphone/detect.py

@@ -42,9 +42,6 @@ def get_opts():
 def get_flags():
 def get_flags():
     return [
     return [
         ("tools", False),
         ("tools", False),
-        # Disable by default even if production is set, as it makes linking in Xcode
-        # on exports very slow and that's not what most users expect.
-        ("lto", "none"),
     ]
     ]
 
 
 
 
@@ -67,7 +64,11 @@ def configure(env):
         env.Append(CCFLAGS=["-gdwarf-2", "-O0"])
         env.Append(CCFLAGS=["-gdwarf-2", "-O0"])
         env.Append(CPPDEFINES=["_DEBUG", ("DEBUG", 1)])
         env.Append(CPPDEFINES=["_DEBUG", ("DEBUG", 1)])
 
 
-    # LTO
+    ## LTO
+
+    if env["lto"] == "auto":  # Disable by default as it makes linking in Xcode very slow.
+        env["lto"] = "none"
+
     if env["lto"] != "none":
     if env["lto"] != "none":
         if env["lto"] == "thin":
         if env["lto"] == "thin":
             env.Append(CCFLAGS=["-flto=thin"])
             env.Append(CCFLAGS=["-flto=thin"])

+ 4 - 0
platform/javascript/detect.py

@@ -100,6 +100,10 @@ def configure(env):
     env["ENV"] = os.environ
     env["ENV"] = os.environ
 
 
     # LTO
     # LTO
+
+    if env["lto"] == "auto":  # Full LTO for production.
+        env["lto"] = "full"
+
     if env["lto"] != "none":
     if env["lto"] != "none":
         if env["lto"] == "thin":
         if env["lto"] == "thin":
             env.Append(CCFLAGS=["-flto=thin"])
             env.Append(CCFLAGS=["-flto=thin"])

+ 7 - 5
platform/osx/detect.py

@@ -35,11 +35,7 @@ def get_opts():
 
 
 
 
 def get_flags():
 def get_flags():
-    return [
-        # Benefits of LTO for macOS (size, performance) haven't been clearly established yet.
-        # So for now we override the default value which may be set when using `production=yes`.
-        ("lto", "none"),
-    ]
+    return []
 
 
 
 
 def configure(env):
 def configure(env):
@@ -132,6 +128,10 @@ def configure(env):
         env.Append(CPPDEFINES=["__MACPORTS__"])  # hack to fix libvpx MM256_BROADCASTSI128_SI256 define
         env.Append(CPPDEFINES=["__MACPORTS__"])  # hack to fix libvpx MM256_BROADCASTSI128_SI256 define
 
 
     # LTO
     # LTO
+
+    if env["lto"] == "auto":  # LTO benefits for macOS (size, performance) haven't been clearly established yet.
+        env["lto"] = "none"
+
     if env["lto"] != "none":
     if env["lto"] != "none":
         if env["lto"] == "thin":
         if env["lto"] == "thin":
             env.Append(CCFLAGS=["-flto=thin"])
             env.Append(CCFLAGS=["-flto=thin"])
@@ -140,6 +140,8 @@ def configure(env):
             env.Append(CCFLAGS=["-flto"])
             env.Append(CCFLAGS=["-flto"])
             env.Append(LINKFLAGS=["-flto"])
             env.Append(LINKFLAGS=["-flto"])
 
 
+    # Sanitizers
+
     if env["use_ubsan"] or env["use_asan"] or env["use_lsan"] or env["use_tsan"]:
     if env["use_ubsan"] or env["use_asan"] or env["use_lsan"] or env["use_tsan"]:
         env.extra_suffix += "s"
         env.extra_suffix += "s"
 
 

+ 8 - 0
platform/windows/detect.py

@@ -281,6 +281,9 @@ def configure_msvc(env, manual_msvc_config):
 
 
     ## LTO
     ## LTO
 
 
+    if env["lto"] == "auto":  # No LTO by default for MSVC, doesn't help.
+        env["lto"] = "none"
+
     if env["lto"] != "none":
     if env["lto"] != "none":
         if env["lto"] == "thin":
         if env["lto"] == "thin":
             print("ThinLTO is only compatible with LLVM, use `use_llvm=yes` or `lto=full`.")
             print("ThinLTO is only compatible with LLVM, use `use_llvm=yes` or `lto=full`.")
@@ -395,6 +398,11 @@ def configure_mingw(env):
 
 
     env["x86_libtheora_opt_gcc"] = True
     env["x86_libtheora_opt_gcc"] = True
 
 
+    ## LTO
+
+    if env["lto"] == "auto":  # Full LTO for production with MinGW.
+        env["lto"] = "full"
+
     if env["lto"] != "none":
     if env["lto"] != "none":
         if env["lto"] == "thin":
         if env["lto"] == "thin":
             if not env["use_llvm"]:
             if not env["use_llvm"]:

+ 4 - 0
platform/x11/detect.py

@@ -204,6 +204,10 @@ def configure(env):
             env.Append(LINKFLAGS=["-fsanitize=memory"])
             env.Append(LINKFLAGS=["-fsanitize=memory"])
 
 
     # LTO
     # LTO
+
+    if env["lto"] == "auto":  # Full LTO for production.
+        env["lto"] = "full"
+
     if env["lto"] != "none":
     if env["lto"] != "none":
         if env["lto"] == "thin":
         if env["lto"] == "thin":
             if not env["use_llvm"]:
             if not env["use_llvm"]: