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`.
This commit is contained in:
Rémi Verschelde 2024-05-10 12:32:27 +02:00
parent 2ba22d1554
commit d4d0e34bb4
No known key found for this signature in database
GPG Key ID: C3336907360768E1
1 changed files with 33 additions and 41 deletions

View File

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