Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix platform selection, custom tools overrides, and user overrides of use_mingw #81700

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
308 changes: 180 additions & 128 deletions SConstruct
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,6 @@ import gles3_builders
import scu_builders
from platform_methods import architectures, architecture_aliases, generate_export_icons

if ARGUMENTS.get("target", "editor") == "editor":
_helper_module("editor.editor_builders", "editor/editor_builders.py")
_helper_module("editor.template_builders", "editor/template_builders.py")

# Scan possible build platforms

Expand Down Expand Up @@ -98,73 +95,148 @@ for x in sorted(glob.glob("platform/*")):
if os.path.exists(x + "/api/api.cpp"):
platform_apis.append(platform_name)
if detect.can_build():
x = x.replace("platform/", "") # rest of world
x = x.replace("platform\\", "") # win32
platform_list += [x]
platform_opts[x] = detect.get_opts()
platform_flags[x] = detect.get_flags()
platform_list += [platform_name]
platform_opts[platform_name] = detect.get_opts()
platform_flags[platform_name] = detect.get_flags()
sys.path.remove(tmppath)
sys.modules.pop("detect")

custom_tools = ["default"]

platform_arg = ARGUMENTS.get("platform", ARGUMENTS.get("p", False))
# Environment initialization options.
customs = ["custom.py"]

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"]
profile = ARGUMENTS.get("profile", "")
if profile:
if os.path.isfile(profile):
customs.append(profile)
elif os.path.isfile(profile + ".py"):
customs.append(profile + ".py")

# 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"]
# Defaults.
defaults = {
"target": {"default": "editor", "converter": lambda v: v},
"use_mingw": {"default": False, "converter": BoolVariable("", "", False)[4]},
"custom_tools": {"default": ["default"], "converter": lambda v: v.split(",")},
}

env_base.disabled_modules = []
env_base.module_version_string = ""
env_base.msvc = False
# We'll parse these as strings first, so we can tell if they've been set explicitely.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo which makes the CI checks fail.

Suggested change
# We'll parse these as strings first, so we can tell if they've been set explicitely.
# We'll parse these as strings first, so we can tell if they've been set explicitly.

base_opts = Variables(customs, ARGUMENTS)
base_opts.Add(("platform", "p"), "Target platform (%s)" % ("|".join(platform_list),), "")
base_opts.Add(EnumVariable("target", "Compilation target", "", ("", "editor", "template_release", "template_debug")))
base_opts.Add("custom_tools", "Scons Environment toolset override", "")

env_base.__class__.disable_module = methods.disable_module
if os.name == "nt":
base_opts.Add("use_mingw", "Use the Mingw compiler, even if MSVC is installed.", ""),

env_base.__class__.add_module_version_string = methods.add_module_version_string
# We let SCons build a default environment so we can read environment-specific options
# from user and platform locations.
# We will then reinitialize the environment with the correct information.
env_base = Environment(tools="")
base_opts.Update(env_base)

env_base.__class__.add_source_files = methods.add_source_files
env_base.__class__.use_windows_spawn_fix = methods.use_windows_spawn_fix
# Convert the string values set by the user into our expected types.
for option in defaults:
if env_base[option]:
env_base[option] = defaults[option]["converter"](env_base[option])

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
# Platform selection.

env_base["x86_libtheora_opt_gcc"] = False
env_base["x86_libtheora_opt_vc"] = False
selected_platform = ""

# avoid issues when building with different versions of python out of the same directory
env_base.SConsignFile(".sconsign{0}.dblite".format(pickle.HIGHEST_PROTOCOL))
if env_base["platform"] != "":
selected_platform = env_base["platform"]
else:
# Missing `platform` argument, try to detect platform automatically
if (
sys.platform.startswith("linux")
or sys.platform.startswith("dragonfly")
or sys.platform.startswith("freebsd")
or sys.platform.startswith("netbsd")
or sys.platform.startswith("openbsd")
):
selected_platform = "linuxbsd"
elif sys.platform == "darwin":
selected_platform = "macos"
elif sys.platform == "win32":
selected_platform = "windows"
else:
print("Could not detect platform automatically. Supported platforms:")
for x in platform_list:
print("\t" + x)
print("\nPlease run SCons again and select a valid platform: platform=<string>")

# Build options
if selected_platform != "":
print("Automatically detected platform: " + selected_platform)

customs = ["custom.py"]
if selected_platform in ["macos", "osx"]:
if selected_platform == "osx":
# Deprecated alias kept for compatibility.
print('Platform "osx" has been renamed to "macos" in Godot 4. Building for platform "macos".')
# Alias for convenience.
selected_platform = "macos"

profile = ARGUMENTS.get("profile", "")
if profile:
if os.path.isfile(profile):
customs.append(profile)
elif os.path.isfile(profile + ".py"):
customs.append(profile + ".py")
if selected_platform in ["ios", "iphone"]:
if selected_platform == "iphone":
# Deprecated alias kept for compatibility.
print('Platform "iphone" has been renamed to "ios" in Godot 4. Building for platform "ios".')
# Alias for convenience.
selected_platform = "ios"

if selected_platform in ["linux", "bsd", "x11"]:
if selected_platform == "x11":
# Deprecated alias kept for compatibility.
print('Platform "x11" has been renamed to "linuxbsd" in Godot 4. Building for platform "linuxbsd".')
# Alias for convenience.
selected_platform = "linuxbsd"

if selected_platform not in platform_list:
if selected_platform == "list":
print("The following platforms are available:\n")
else:
print('Invalid target platform "' + selected_platform + '".')
print("The following platforms were detected:\n")

for x in platform_list:
print("\t" + x)

print("\nPlease run SCons again and select a valid platform: platform=<string>")

if selected_platform == "list":
# Exit early to suppress the rest of the built-in SCons messages
Exit()
else:
Exit(255)


# Platform specific flags.
if selected_platform in platform_flags:
platform_dict = dict(platform_flags[selected_platform])
for option in base_opts.options:
# Use the platform flag value if it's not set in the environment already (i.e. the user hasn't overridden it).
if not env_base[option.key] and option.key in platform_dict:
env_base[option.key] = platform_dict[option.key]

# Check for the use_mingw flag, but only replace custom_tools if they haven't been overridden yet.
if os.name == "nt" and env_base["use_mingw"] and not env_base["custom_tools"]:
env_base["custom_tools"] = ["mingw"]

# Set the default values if there's no overrides.
for option in defaults:
if not env_base[option]:
env_base[option] = defaults[option]["default"]

selected_target = env_base["target"]

# Determine the Scons toolset.
custom_tools = env_base["custom_tools"]

if selected_target == "editor":
_helper_module("editor.editor_builders", "editor/editor_builders.py")
_helper_module("editor.template_builders", "editor/template_builders.py")

# Prepare the real environment options list, now that we know what platform and toolset we're going to use.

# Build options
opts = Variables(customs, ARGUMENTS)

# Target build options
Expand Down Expand Up @@ -262,74 +334,70 @@ 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).
print(
'Initializing SCons environment for "'
+ selected_platform
+ '" with the following tools: "'
+ " ".join(custom_tools)
+ '".'
)

# We let SCons build its default ENV as it includes OS-specific things which we don't
# want to have to pull in manually.
# This lets us read the environment, command line, user and platform options and flags.
# Then we prepend PATH to make it take precedence, while preserving SCons' own entries.
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 with all general and platform-specific options.
opts.Update(env_base)

# Platform selection: validate input, and add options.
# 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

selected_platform = ""
# Make sure the target we've already parsed is set in this environment.
# The logic for merging platform flags into this environment happens later, and until then, we need
# to make sure this one is set properly
env_base["target"] = selected_target

if env_base["platform"] != "":
selected_platform = env_base["platform"]
elif env_base["p"] != "":
selected_platform = env_base["p"]
else:
# Missing `platform` argument, try to detect platform automatically
if (
sys.platform.startswith("linux")
or sys.platform.startswith("dragonfly")
or sys.platform.startswith("freebsd")
or sys.platform.startswith("netbsd")
or sys.platform.startswith("openbsd")
):
selected_platform = "linuxbsd"
elif sys.platform == "darwin":
selected_platform = "macos"
elif sys.platform == "win32":
selected_platform = "windows"
else:
print("Could not detect platform automatically. Supported platforms:")
for x in platform_list:
print("\t" + x)
print("\nPlease run SCons again and select a valid platform: platform=<string>")
# 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"]

if selected_platform != "":
print("Automatically detected platform: " + selected_platform)
env_base.disabled_modules = []
env_base.module_version_string = ""
env_base.msvc = False

if selected_platform in ["macos", "osx"]:
if selected_platform == "osx":
# Deprecated alias kept for compatibility.
print('Platform "osx" has been renamed to "macos" in Godot 4. Building for platform "macos".')
# Alias for convenience.
selected_platform = "macos"
env_base.__class__.disable_module = methods.disable_module

if selected_platform in ["ios", "iphone"]:
if selected_platform == "iphone":
# Deprecated alias kept for compatibility.
print('Platform "iphone" has been renamed to "ios" in Godot 4. Building for platform "ios".')
# Alias for convenience.
selected_platform = "ios"
env_base.__class__.add_module_version_string = methods.add_module_version_string

if selected_platform in ["linux", "bsd", "x11"]:
if selected_platform == "x11":
# Deprecated alias kept for compatibility.
print('Platform "x11" has been renamed to "linuxbsd" in Godot 4. Building for platform "linuxbsd".')
# Alias for convenience.
selected_platform = "linuxbsd"
env_base.__class__.add_source_files = methods.add_source_files
env_base.__class__.use_windows_spawn_fix = methods.use_windows_spawn_fix

# 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
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

# Add platform-specific options.
if selected_platform in platform_opts:
for opt in platform_opts[selected_platform]:
opts.Add(opt)
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))

# 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().

# Detect modules.
modules_detected = OrderedDict()
Expand Down Expand Up @@ -390,6 +458,8 @@ methods.write_modules(modules_detected)
# Update the environment again after all the module options are added.
opts.Update(env_base)
env_base["platform"] = selected_platform # Must always be re-set after calling opts.Update().
env_base["target"] = selected_target # Make sure this is set until the Platform specific flags section below.

Help(opts.GenerateHelpText(env_base))

# add default include paths
Expand Down Expand Up @@ -988,24 +1058,6 @@ if selected_platform in platform_list:
if conf.CheckCHeader(header[0]):
env.AppendUnique(CPPDEFINES=[header[1]])

elif selected_platform != "":
if selected_platform == "list":
print("The following platforms are available:\n")
else:
print('Invalid target platform "' + selected_platform + '".')
print("The following platforms were detected:\n")

for x in platform_list:
print("\t" + x)

print("\nPlease run SCons again and select a valid platform: platform=<string>")

if selected_platform == "list":
# Exit early to suppress the rest of the built-in SCons messages
Exit()
else:
Exit(255)

# The following only makes sense when the 'env' is defined, and assumes it is.
if "env" in locals():
# FIXME: This method mixes both cosmetic progress stuff and cache handling...
Expand Down
1 change: 1 addition & 0 deletions platform/android/detect.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ def get_flags():
return [
("arch", "arm64"), # Default for convenience.
("target", "template_debug"),
("custom_tools", ["clang", "clang++", "as", "ar", "link"]),
]


Expand Down
2 changes: 2 additions & 0 deletions platform/web/detect.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ def get_flags():
# 100 KiB over -Os, which does not justify the negative impact on
# run-time performance.
("optimize", "size"),
# Use generic POSIX build toolchain for Emscripten.
("custom_tools", ["cc", "c++", "ar", "link", "textfile", "zip"]),
]


Expand Down