Browse Source

SCons: Preserve `Environment` values when updating `Variables`

Finally reading the docs for `SCons.Variables.Update` let me find this optional
parameter, which solves the hacks and pain we've dealt with for years:

> args (optional) – a dictionary of keys and values to update in env.
> If omitted, uses the variables from the commandline.

By passing the environment itself, we preserve the values we've overridden in
`SConstruct` or `detect.py`.
Rémi Verschelde 1 year ago
parent
commit
d4d0e34bb4
1 changed files with 33 additions and 41 deletions
  1. 33 41
      SConstruct

+ 33 - 41
SConstruct

@@ -300,12 +300,10 @@ if env["import_env_vars"]:
 
 # Platform selection: validate input, and add options.
 
-selected_platform = env["platform"]
+if env.scons_version < (4, 3) and not env["platform"]:
+    env["platform"] = env["p"]
 
-if env.scons_version < (4, 3) and not selected_platform:
-    selected_platform = env["p"]
-
-if selected_platform == "":
+if env["platform"] == "":
     # Missing `platform` argument, try to detect platform automatically
     if (
         sys.platform.startswith("linux")
@@ -314,62 +312,57 @@ if selected_platform == "":
         or sys.platform.startswith("netbsd")
         or sys.platform.startswith("openbsd")
     ):
-        selected_platform = "linuxbsd"
+        env["platform"] = "linuxbsd"
     elif sys.platform == "darwin":
-        selected_platform = "macos"
+        env["platform"] = "macos"
     elif sys.platform == "win32":
-        selected_platform = "windows"
+        env["platform"] = "windows"
 
-    if selected_platform != "":
-        print(f"Automatically detected platform: {selected_platform}")
+    if env["platform"] != "":
+        print(f'Automatically detected platform: {env["platform"]}')
 
-if selected_platform == "osx":
+if env["platform"] == "osx":
     # Deprecated alias kept for compatibility.
     print_warning('Platform "osx" has been renamed to "macos" in Godot 4. Building for platform "macos".')
-    selected_platform = "macos"
+    env["platform"] = "macos"
 
-if selected_platform == "iphone":
+if env["platform"] == "iphone":
     # Deprecated alias kept for compatibility.
     print_warning('Platform "iphone" has been renamed to "ios" in Godot 4. Building for platform "ios".')
-    selected_platform = "ios"
+    env["platform"] = "ios"
 
-if selected_platform in ["linux", "bsd", "x11"]:
-    if selected_platform == "x11":
+if env["platform"] in ["linux", "bsd", "x11"]:
+    if env["platform"] == "x11":
         # Deprecated alias kept for compatibility.
         print_warning('Platform "x11" has been renamed to "linuxbsd" in Godot 4. Building for platform "linuxbsd".')
     # Alias for convenience.
-    selected_platform = "linuxbsd"
+    env["platform"] = "linuxbsd"
 
-if selected_platform == "javascript":
+if env["platform"] == "javascript":
     # Deprecated alias kept for compatibility.
     print_warning('Platform "javascript" has been renamed to "web" in Godot 4. Building for platform "web".')
-    selected_platform = "web"
+    env["platform"] = "web"
 
-if selected_platform not in platform_list:
+if env["platform"] not in platform_list:
     text = "The following platforms are available:\n\t{}\n".format("\n\t".join(platform_list))
     text += "Please run SCons again and select a valid platform: platform=<string>."
 
-    if selected_platform == "list":
+    if env["platform"] == "list":
         print(text)
-    elif selected_platform == "":
+    elif env["platform"] == "":
         print_error("Could not detect platform automatically.\n" + text)
     else:
-        print_error(f'Invalid target platform "{selected_platform}".\n' + text)
-
-    Exit(0 if selected_platform == "list" else 255)
+        print_error(f'Invalid target platform "{env["platform"]}".\n' + text)
 
-# Make sure to update this to the found, valid platform as it's used through the buildsystem as the reference.
-# It should always be re-set after calling `opts.Update()` otherwise it uses the original input value.
-env["platform"] = selected_platform
+    Exit(0 if env["platform"] == "list" else 255)
 
 # Add platform-specific options.
-if selected_platform in platform_opts:
-    for opt in platform_opts[selected_platform]:
+if env["platform"] in platform_opts:
+    for opt in platform_opts[env["platform"]]:
         opts.Add(opt)
 
 # Update the environment to take platform-specific options into account.
-opts.Update(env)
-env["platform"] = selected_platform  # Must always be re-set after calling opts.Update().
+opts.Update(env, {**ARGUMENTS, **env})
 
 # Detect modules.
 modules_detected = OrderedDict()
@@ -418,7 +411,7 @@ for name, path in modules_detected.items():
 
     # Add module-specific options.
     try:
-        for opt in config.get_opts(selected_platform):
+        for opt in config.get_opts(env["platform"]):
             opts.Add(opt)
     except AttributeError:
         pass
@@ -429,8 +422,7 @@ for name, path in modules_detected.items():
 env.modules_detected = modules_detected
 
 # Update the environment again after all the module options are added.
-opts.Update(env)
-env["platform"] = selected_platform  # Must always be re-set after calling opts.Update().
+opts.Update(env, {**ARGUMENTS, **env})
 Help(opts.GenerateHelpText(env))
 
 # add default include paths
@@ -507,7 +499,7 @@ if not env["deprecated"]:
 if env["precision"] == "double":
     env.Append(CPPDEFINES=["REAL_T_IS_DOUBLE"])
 
-tmppath = "./platform/" + selected_platform
+tmppath = "./platform/" + env["platform"]
 sys.path.insert(0, tmppath)
 import detect
 
@@ -561,7 +553,7 @@ if env["build_profile"] != "":
 
 # Platform specific flags.
 # These can sometimes override default options.
-flag_list = platform_flags[selected_platform]
+flag_list = platform_flags[env["platform"]]
 for f in flag_list:
     if not (f[0] in ARGUMENTS) or ARGUMENTS[f[0]] == "auto":  # Allow command line to override platform flags
         env[f[0]] = f[1]
@@ -598,7 +590,7 @@ if env["scu_build"]:
 # are actually handled to change compile options, etc.
 detect.configure(env)
 
-print(f'Building for platform "{selected_platform}", architecture "{env["arch"]}", target "{env["target"]}".')
+print(f'Building for platform "{env["platform"]}", architecture "{env["arch"]}", target "{env["target"]}".')
 if env.dev_build:
     print("NOTE: Developer build, with debug optimization level and debug symbols (unless overridden).")
 
@@ -854,7 +846,7 @@ else:  # GCC, Clang
 if hasattr(detect, "get_program_suffix"):
     suffix = "." + detect.get_program_suffix()
 else:
-    suffix = "." + selected_platform
+    suffix = "." + env["platform"]
 
 suffix += "." + env["target"]
 if env.dev_build:
@@ -885,7 +877,7 @@ for name, path in modules_detected.items():
     env.current_module = name
     import config
 
-    if config.can_build(env, selected_platform):
+    if config.can_build(env, env["platform"]):
         # Disable it if a required dependency is missing.
         if not env.module_check_dependencies(name):
             continue
@@ -1037,7 +1029,7 @@ if env["tests"]:
     SConscript("tests/SCsub")
 SConscript("main/SCsub")
 
-SConscript("platform/" + selected_platform + "/SCsub")  # Build selected platform.
+SConscript("platform/" + env["platform"] + "/SCsub")  # Build selected platform.
 
 # Microsoft Visual Studio Project Generation
 if env["vsproj"]: