From d83d1134f858d1a81ed233eb680d7c290cd0a204 Mon Sep 17 00:00:00 2001 From: Andreia Gaita Date: Fri, 15 Sep 2023 15:30:35 +0200 Subject: [PATCH] Fix platform selection, let platforms override custom tools, and obey user overrides of use_mingw Let the platforms optionally override the default build tools with a `get_custom_tools` method, so the default SConstruct only needs to set the defaults and not worry about each individual platform requirements. Fix the order of initialization, so we can pick up the use_mingw option from all the different places where it can be set, and use it during environment initialization. This also fixes a related issue where, if a platform sets a default target in `get_flags`, if the platform doesn't support the `editor` target, and the user doesn't pass in the target in the command line, the `editor` target would be briefly selected during a portion of SConstruct execution, just long enough for some wrong variables to be set, and cause the build to fail, or include bad defines. Fixes #60719 --- SConstruct | 134 ++++++++++++++++++++++--------------- platform/android/detect.py | 4 ++ platform/web/detect.py | 5 ++ 3 files changed, 90 insertions(+), 53 deletions(-) diff --git a/SConstruct b/SConstruct index df750beae415cf..506cafd4c00c5a 100644 --- a/SConstruct +++ b/SConstruct @@ -73,6 +73,8 @@ platform_apis = [] time_at_start = time.time() +custom_tools = [] + for x in sorted(glob.glob("platform/*")): if not os.path.isdir(x) or not os.path.exists(x + "/detect.py"): continue @@ -103,56 +105,11 @@ for x in sorted(glob.glob("platform/*")): platform_list += [x] platform_opts[x] = detect.get_opts() platform_flags[x] = detect.get_flags() + if hasattr(detect, "get_custom_tools"): + custom_tools = detect.get_custom_tools() sys.path.remove(tmppath) sys.modules.pop("detect") -custom_tools = ["default"] - -platform_arg = ARGUMENTS.get("platform", ARGUMENTS.get("p", False)) - -if platform_arg == "android": - custom_tools = ["clang", "clang++", "as", "ar", "link"] -elif platform_arg == "web": - # Use generic POSIX build toolchain for Emscripten. - custom_tools = ["cc", "c++", "ar", "link", "textfile", "zip"] -elif os.name == "nt" and methods.get_cmdline_bool("use_mingw", False): - custom_tools = ["mingw"] - -# We let SCons build its default ENV as it includes OS-specific things which we don't -# want to have to pull in manually. -# Then we prepend PATH to make it take precedence, while preserving SCons' own entries. -env_base = Environment(tools=custom_tools) -env_base.PrependENVPath("PATH", os.getenv("PATH")) -env_base.PrependENVPath("PKG_CONFIG_PATH", os.getenv("PKG_CONFIG_PATH")) -if "TERM" in os.environ: # Used for colored output. - env_base["ENV"]["TERM"] = os.environ["TERM"] - -env_base.disabled_modules = [] -env_base.module_version_string = "" -env_base.msvc = False - -env_base.__class__.disable_module = methods.disable_module - -env_base.__class__.add_module_version_string = methods.add_module_version_string - -env_base.__class__.add_source_files = methods.add_source_files -env_base.__class__.use_windows_spawn_fix = methods.use_windows_spawn_fix - -env_base.__class__.add_shared_library = methods.add_shared_library -env_base.__class__.add_library = methods.add_library -env_base.__class__.add_program = methods.add_program -env_base.__class__.CommandNoCache = methods.CommandNoCache -env_base.__class__.Run = methods.Run -env_base.__class__.disable_warnings = methods.disable_warnings -env_base.__class__.force_optimization_on_debug = methods.force_optimization_on_debug -env_base.__class__.module_add_dependencies = methods.module_add_dependencies -env_base.__class__.module_check_dependencies = methods.module_check_dependencies - -env_base["x86_libtheora_opt_gcc"] = False -env_base["x86_libtheora_opt_vc"] = False - -# avoid issues when building with different versions of python out of the same directory -env_base.SConsignFile(".sconsign{0}.dblite".format(pickle.HIGHEST_PROTOCOL)) # Build options @@ -262,8 +219,25 @@ opts.Add("CFLAGS", "Custom flags for the C compiler") opts.Add("CXXFLAGS", "Custom flags for the C++ compiler") opts.Add("LINKFLAGS", "Custom flags for the linker") -# Update the environment to have all above options defined -# in following code (especially platform and custom_modules). + +recheck_mingw = False; + +# Set default tools, if the platform implementation didn't specify any +if not custom_tools: + custom_tools = ["default"] + + if os.name == "nt": + if methods.get_cmdline_bool("use_mingw", False): + custom_tools = ["mingw"] + else: + # At this point we aren't able to check other possible user overrides, + # we'll need an environment for that, so defer the check + recheck_mingw = True + +# We let SCons build its default ENV as it includes OS-specific things which we don't +# want to have to pull in manually. +# Then we prepend PATH to make it take precedence, while preserving SCons' own entries. +env_base = Environment(tools=custom_tools) opts.Update(env_base) # Platform selection: validate input, and add options. @@ -318,9 +292,6 @@ if selected_platform in ["linux", "bsd", "x11"]: # Alias for convenience. selected_platform = "linuxbsd" -# 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_base["platform"] = selected_platform # Add platform-specific options. if selected_platform in platform_opts: @@ -329,7 +300,64 @@ if selected_platform in platform_opts: # Update the environment to take platform-specific options into account. opts.Update(env_base) -env_base["platform"] = selected_platform # Must always be re-set after calling opts.Update(). + +# 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_base["platform"] = selected_platform + + +# MinGW is a special case, as it's a tool loaded as part of environment initialization +# but we need an environment in order to merge user option +# so we might have to recreate the environment +if recheck_mingw: + if env_base["use_mingw"] or ("use_mingw", False) in platform_flags[selected_platform]: + custom_tools = ["mingw"] + # rebuild the environment with the updated tools and reset everything + env_base = Environment(tools=custom_tools) + + # Add platform-specific options. + if selected_platform in platform_opts: + for opt in platform_opts[selected_platform]: + opts.Add(opt) + + # Update the environment to take platform-specific options into account. + opts.Update(env_base) + env_base["platform"] = selected_platform # Must always be re-set after calling opts.Update(). + + +# Now we're ready to set our PATHs +env_base.PrependENVPath("PATH", os.getenv("PATH")) +env_base.PrependENVPath("PKG_CONFIG_PATH", os.getenv("PKG_CONFIG_PATH")) +if "TERM" in os.environ: # Used for colored output. + env_base["ENV"]["TERM"] = os.environ["TERM"] + +env_base.disabled_modules = [] +env_base.module_version_string = "" +env_base.msvc = False + +env_base.__class__.disable_module = methods.disable_module + +env_base.__class__.add_module_version_string = methods.add_module_version_string + +env_base.__class__.add_source_files = methods.add_source_files +env_base.__class__.use_windows_spawn_fix = methods.use_windows_spawn_fix + +env_base.__class__.add_shared_library = methods.add_shared_library +env_base.__class__.add_library = methods.add_library +env_base.__class__.add_program = methods.add_program +env_base.__class__.CommandNoCache = methods.CommandNoCache +env_base.__class__.Run = methods.Run +env_base.__class__.disable_warnings = methods.disable_warnings +env_base.__class__.force_optimization_on_debug = methods.force_optimization_on_debug +env_base.__class__.module_add_dependencies = methods.module_add_dependencies +env_base.__class__.module_check_dependencies = methods.module_check_dependencies + +env_base["x86_libtheora_opt_gcc"] = False +env_base["x86_libtheora_opt_vc"] = False + +# avoid issues when building with different versions of python out of the same directory +env_base.SConsignFile(".sconsign{0}.dblite".format(pickle.HIGHEST_PROTOCOL)) + # Detect modules. modules_detected = OrderedDict() diff --git a/platform/android/detect.py b/platform/android/detect.py index 33c65657899d77..711126f1816ce7 100644 --- a/platform/android/detect.py +++ b/platform/android/detect.py @@ -71,6 +71,10 @@ def get_flags(): ] +def get_custom_tools(): + return ["clang", "clang++", "as", "ar", "link"] + + # Check if Android NDK version is installed # If not, install it. def install_ndk_if_needed(env): diff --git a/platform/web/detect.py b/platform/web/detect.py index 7b2e5646d6688f..bc150fb7654ba2 100644 --- a/platform/web/detect.py +++ b/platform/web/detect.py @@ -70,6 +70,11 @@ def get_flags(): ] +def get_custom_tools(): + # Use generic POSIX build toolchain for Emscripten. + return ["cc", "c++", "ar", "link", "textfile", "zip"] + + def configure(env: "Environment"): # Validate arch. supported_arches = ["wasm32"]