Skip to content

Commit 90208f7

Browse files
akien-mgaRepiteo
andcommitted
SCons: Fix handling of platform-specific tools, notably mingw
Add optional `detect.py` `get_tools` method to let platforms register SCons tools they need. This helps move this logic out of SConstruct, keeping platforms more self contained, and helping thirdparty platforms define their own custom tools. This logic was also unreliable (the `use_mingw` one would only work if passed manually on the command line, not in e.g. `get_flags`). Co-authored-by: Thaddeus Crews <repiteo@outlook.com>
1 parent b15b24b commit 90208f7

File tree

4 files changed

+41
-34
lines changed

4 files changed

+41
-34
lines changed

SConstruct

+25-30
Original file line numberDiff line numberDiff line change
@@ -107,22 +107,11 @@ for x in sorted(glob.glob("platform/*")):
107107
sys.path.remove(tmppath)
108108
sys.modules.pop("detect")
109109

110-
custom_tools = ["default"]
111-
112-
platform_arg = ARGUMENTS.get("platform", ARGUMENTS.get("p", False))
113-
114-
if platform_arg == "android":
115-
custom_tools = ["clang", "clang++", "as", "ar", "link"]
116-
elif platform_arg == "web":
117-
# Use generic POSIX build toolchain for Emscripten.
118-
custom_tools = ["cc", "c++", "ar", "link", "textfile", "zip"]
119-
elif os.name == "nt" and methods.get_cmdline_bool("use_mingw", False):
120-
custom_tools = ["mingw"]
121-
122110
# We let SCons build its default ENV as it includes OS-specific things which we don't
123-
# want to have to pull in manually.
111+
# want to have to pull in manually. However we enforce no "tools", which we register
112+
# further down after parsing our platform-specific configuration.
124113
# Then we prepend PATH to make it take precedence, while preserving SCons' own entries.
125-
env = Environment(tools=custom_tools)
114+
env = Environment(tools=[])
126115
env.PrependENVPath("PATH", os.getenv("PATH"))
127116
env.PrependENVPath("PKG_CONFIG_PATH", os.getenv("PKG_CONFIG_PATH"))
128117
if "TERM" in os.environ: # Used for colored output.
@@ -168,11 +157,7 @@ if profile:
168157
opts = Variables(customs, ARGUMENTS)
169158

170159
# Target build options
171-
if env.scons_version >= (4, 3):
172-
opts.Add(["platform", "p"], "Target platform (%s)" % "|".join(platform_list), "")
173-
else:
174-
opts.Add("platform", "Target platform (%s)" % "|".join(platform_list), "")
175-
opts.Add("p", "Alias for 'platform'", "")
160+
opts.Add((["platform", "p"], "Target platform (%s)" % "|".join(platform_list), ""))
176161
opts.Add(EnumVariable("target", "Compilation target", "editor", ("editor", "template_release", "template_debug")))
177162
opts.Add(EnumVariable("arch", "CPU architecture", "auto", ["auto"] + architectures, architecture_aliases))
178163
opts.Add(BoolVariable("dev_build", "Developer build with dev-only debugging code (DEV_ENABLED)", False))
@@ -312,10 +297,7 @@ if env["import_env_vars"]:
312297

313298
# Platform selection: validate input, and add options.
314299

315-
if env.scons_version < (4, 3) and not env["platform"]:
316-
env["platform"] = env["p"]
317-
318-
if env["platform"] == "":
300+
if not env["platform"]:
319301
# Missing `platform` argument, try to detect platform automatically
320302
if (
321303
sys.platform.startswith("linux")
@@ -330,7 +312,7 @@ if env["platform"] == "":
330312
elif sys.platform == "win32":
331313
env["platform"] = "windows"
332314

333-
if env["platform"] != "":
315+
if env["platform"]:
334316
print(f'Automatically detected platform: {env["platform"]}')
335317

336318
# Deprecated aliases kept for compatibility.
@@ -352,7 +334,7 @@ if env["platform"] not in platform_list:
352334

353335
if env["platform"] == "list":
354336
print(text)
355-
elif env["platform"] == "":
337+
elif not env["platform"]:
356338
print_error("Could not detect platform automatically.\n" + text)
357339
else:
358340
print_error(f'Invalid target platform "{env["platform"]}".\n' + text)
@@ -434,6 +416,23 @@ env.modules_detected = modules_detected
434416
opts.Update(env, {**ARGUMENTS, **env.Dictionary()})
435417
Help(opts.GenerateHelpText(env))
436418

419+
420+
# FIXME: Tool assignment happening at this stage is a direct consequence of getting the platform logic AFTER the SCons
421+
# environment was already been constructed. Fixing this would require a broader refactor where all options are setup
422+
# ahead of time with native validator/converter functions.
423+
tmppath = "./platform/" + env["platform"]
424+
sys.path.insert(0, tmppath)
425+
import detect
426+
427+
custom_tools = ["default"]
428+
try: # Platform custom tools are optional
429+
custom_tools = detect.get_tools(env)
430+
except AttributeError:
431+
pass
432+
for tool in custom_tools:
433+
env.Tool(tool)
434+
435+
437436
# add default include paths
438437

439438
env.Prepend(CPPPATH=["#"])
@@ -515,10 +514,6 @@ if not env["deprecated"]:
515514
if env["precision"] == "double":
516515
env.Append(CPPDEFINES=["REAL_T_IS_DOUBLE"])
517516

518-
tmppath = "./platform/" + env["platform"]
519-
sys.path.insert(0, tmppath)
520-
import detect
521-
522517
# Default num_jobs to local cpu count if not user specified.
523518
# SCons has a peculiarity where user-specified options won't be overridden
524519
# by SetOption, so we can rely on this to know if we should use our default.
@@ -587,7 +582,7 @@ if env["dev_mode"]:
587582
if env["production"]:
588583
env["use_static_cpp"] = methods.get_cmdline_bool("use_static_cpp", True)
589584
env["debug_symbols"] = methods.get_cmdline_bool("debug_symbols", False)
590-
if platform_arg == "android":
585+
if env["platform"] == "android":
591586
env["swappy"] = methods.get_cmdline_bool("swappy", True)
592587
# LTO "auto" means we handle the preferred option in each platform detect.py.
593588
env["lto"] = ARGUMENTS.get("lto", "auto")

platform/android/detect.py

+4
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ def can_build():
1919
return os.path.exists(get_env_android_sdk_root())
2020

2121

22+
def get_tools(env: "SConsEnvironment"):
23+
return ["clang", "clang++", "as", "ar", "link"]
24+
25+
2226
def get_opts():
2327
from SCons.Variables import BoolVariable
2428

platform/web/detect.py

+5
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ def can_build():
2828
return WhereIs("emcc") is not None
2929

3030

31+
def get_tools(env: "SConsEnvironment"):
32+
# Use generic POSIX build toolchain for Emscripten.
33+
return ["cc", "c++", "ar", "link", "textfile", "zip"]
34+
35+
3136
def get_opts():
3237
from SCons.Variables import BoolVariable
3338

platform/windows/detect.py

+7-4
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,13 @@ def detect_build_env_arch():
155155
return ""
156156

157157

158+
def get_tools(env: "SConsEnvironment"):
159+
if os.name != "nt" or env["use_mingw"]:
160+
return ["mingw"]
161+
else:
162+
return ["default"]
163+
164+
158165
def get_opts():
159166
from SCons.Variables import BoolVariable, EnumVariable
160167

@@ -326,10 +333,6 @@ def setup_mingw(env: "SConsEnvironment"):
326333
print_error("No valid compilers found, use MINGW_PREFIX environment variable to set MinGW path.")
327334
sys.exit(255)
328335

329-
env.Tool("mingw")
330-
env.AppendUnique(CCFLAGS=env.get("ccflags", "").split())
331-
env.AppendUnique(RCFLAGS=env.get("rcflags", "").split())
332-
333336
print("Using MinGW, arch %s" % (env["arch"]))
334337

335338

0 commit comments

Comments
 (0)