summaryrefslogtreecommitdiff
path: root/SConstruct
diff options
context:
space:
mode:
Diffstat (limited to 'SConstruct')
-rw-r--r--SConstruct288
1 files changed, 150 insertions, 138 deletions
diff --git a/SConstruct b/SConstruct
index 9496595a26..b006dddbe6 100644
--- a/SConstruct
+++ b/SConstruct
@@ -12,9 +12,7 @@ from collections import OrderedDict
# Local
import methods
-import gles_builders
-import version
-from platform_methods import run_in_subprocess
+import glsl_builders
# Scan possible build platforms
@@ -57,22 +55,24 @@ custom_tools = ["default"]
platform_arg = ARGUMENTS.get("platform", ARGUMENTS.get("p", False))
-if os.name == "nt" and (platform_arg == "android" or ARGUMENTS.get("use_mingw", False)):
+if os.name == "nt" and (platform_arg == "android" or methods.get_cmdline_bool("use_mingw", False)):
custom_tools = ["mingw"]
elif platform_arg == "javascript":
# Use generic POSIX build toolchain for Emscripten.
custom_tools = ["cc", "c++", "ar", "link", "textfile", "zip"]
+# 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)
-if "TERM" in os.environ:
+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.AppendENVPath("PATH", os.getenv("PATH"))
-env_base.AppendENVPath("PKG_CONFIG_PATH", os.getenv("PKG_CONFIG_PATH"))
+
env_base.disabled_modules = []
-env_base.use_ptrcall = False
env_base.module_version_string = ""
env_base.msvc = False
-env_base.stable_release = version.status == "stable"
env_base.__class__.disable_module = methods.disable_module
@@ -85,6 +85,7 @@ 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__.module_check_dependencies = methods.module_check_dependencies
@@ -98,7 +99,7 @@ env_base.SConsignFile(".sconsign{0}.dblite".format(pickle.HIGHEST_PROTOCOL))
customs = ["custom.py"]
-profile = ARGUMENTS.get("profile", False)
+profile = ARGUMENTS.get("profile", "")
if profile:
if os.path.isfile(profile):
customs.append(profile)
@@ -108,44 +109,47 @@ if profile:
opts = Variables(customs, ARGUMENTS)
# Target build options
-opts.Add("arch", "Platform-dependent architecture (arm/arm64/x86/x64/mips/...)", "")
-opts.Add(EnumVariable("bits", "Target platform bits", "default", ("default", "32", "64")))
opts.Add("p", "Platform (alias for 'platform')", "")
opts.Add("platform", "Target platform (%s)" % ("|".join(platform_list),), "")
+opts.Add(BoolVariable("tools", "Build the tools (a.k.a. the Godot editor)", True))
opts.Add(EnumVariable("target", "Compilation target", "debug", ("debug", "release_debug", "release")))
+opts.Add("arch", "Platform-dependent architecture (arm/arm64/x86/x64/mips/...)", "")
+opts.Add(EnumVariable("bits", "Target platform bits", "default", ("default", "32", "64")))
opts.Add(EnumVariable("optimize", "Optimization type", "speed", ("speed", "size")))
-
-opts.Add(BoolVariable("tools", "Build the tools (a.k.a. the Godot editor)", True))
+opts.Add(BoolVariable("production", "Set defaults to build Godot for use in production", False))
opts.Add(BoolVariable("use_lto", "Use link-time optimization", False))
-opts.Add(BoolVariable("use_precise_math_checks", "Math checks use very precise epsilon (debug option)", False))
# Components
opts.Add(BoolVariable("deprecated", "Enable deprecated features", True))
opts.Add(BoolVariable("minizip", "Enable ZIP archive support using minizip", True))
opts.Add(BoolVariable("xaudio2", "Enable the XAudio2 audio driver", False))
opts.Add("custom_modules", "A list of comma-separated directory paths containing custom modules to build.", "")
+opts.Add(BoolVariable("custom_modules_recursive", "Detect custom modules recursively for each specified path.", True))
# Advanced options
-opts.Add(BoolVariable("verbose", "Enable verbose output for the compilation", False))
+opts.Add(BoolVariable("dev", "If yes, alias for verbose=yes warnings=extra werror=yes", False))
opts.Add(BoolVariable("progress", "Show a progress indicator during compilation", True))
+opts.Add(BoolVariable("tests", "Build the unit tests", False))
+opts.Add(BoolVariable("verbose", "Enable verbose output for the compilation", False))
opts.Add(EnumVariable("warnings", "Level of compilation warnings", "all", ("extra", "all", "moderate", "no")))
-opts.Add(BoolVariable("werror", "Treat compiler warnings as errors", not env_base.stable_release))
-opts.Add(BoolVariable("dev", "If yes, alias for verbose=yes warnings=extra werror=yes", False))
+opts.Add(BoolVariable("werror", "Treat compiler warnings as errors", False))
opts.Add("extra_suffix", "Custom extra suffix added to the base filename of all generated binary files", "")
opts.Add(BoolVariable("vsproj", "Generate a Visual Studio solution", False))
-opts.Add(EnumVariable("macports_clang", "Build using Clang from MacPorts", "no", ("no", "5.0", "devel")))
opts.Add(BoolVariable("disable_3d", "Disable 3D nodes for a smaller executable", False))
opts.Add(BoolVariable("disable_advanced_gui", "Disable advanced GUI nodes and behaviors", False))
opts.Add(BoolVariable("no_editor_splash", "Don't use the custom splash screen for the editor", False))
opts.Add("system_certs_path", "Use this path as SSL certificates default for editor (for package maintainers)", "")
+opts.Add(BoolVariable("use_precise_math_checks", "Math checks use very precise epsilon (debug option)", False))
# Thirdparty libraries
-# opts.Add(BoolVariable('builtin_assimp', "Use the built-in Assimp library", True))
opts.Add(BoolVariable("builtin_bullet", "Use the built-in Bullet library", True))
opts.Add(BoolVariable("builtin_certs", "Use the built-in SSL certificates bundles", True))
opts.Add(BoolVariable("builtin_enet", "Use the built-in ENet library", True))
opts.Add(BoolVariable("builtin_freetype", "Use the built-in FreeType library", True))
opts.Add(BoolVariable("builtin_glslang", "Use the built-in glslang library", True))
+opts.Add(BoolVariable("builtin_graphite", "Use the built-in Graphite library", True))
+opts.Add(BoolVariable("builtin_harfbuzz", "Use the built-in HarfBuzz library", True))
+opts.Add(BoolVariable("builtin_icu", "Use the built-in ICU library", True))
opts.Add(BoolVariable("builtin_libogg", "Use the built-in libogg library", True))
opts.Add(BoolVariable("builtin_libpng", "Use the built-in libpng library", True))
opts.Add(BoolVariable("builtin_libtheora", "Use the built-in libtheora library", True))
@@ -175,16 +179,54 @@ 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")
-# add platform specific options
+# Update the environment to have all above options defined
+# in following code (especially platform and custom_modules).
+opts.Update(env_base)
+
+# Platform selection: validate input, and add options.
+
+selected_platform = ""
+
+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"):
+ selected_platform = "linuxbsd"
+ elif sys.platform == "darwin":
+ selected_platform = "osx"
+ 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>")
+
+ if selected_platform != "":
+ print("Automatically detected platform: " + selected_platform)
+
+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.0. Building for platform "linuxbsd".')
+ # Alias for convenience.
+ selected_platform = "linuxbsd"
-for k in platform_opts.keys():
- opt_list = platform_opts[k]
- for o in opt_list:
- opts.Add(o)
+# 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
-# Update the environment now as the "custom_modules" option may be
-# defined in a file rather than specified via the command line.
+# 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().
# Detect modules.
modules_detected = OrderedDict()
@@ -200,8 +242,14 @@ if env_base["custom_modules"]:
Exit(255)
for path in module_search_paths:
+ if path == "modules":
+ # Built-in modules don't have nested modules,
+ # so save the time it takes to parse directories.
+ modules = methods.detect_modules(path, recursive=False)
+ else: # External.
+ modules = methods.detect_modules(path, env_base["custom_modules_recursive"])
# Note: custom modules can override built-in ones.
- modules_detected.update(methods.detect_modules(path))
+ modules_detected.update(modules)
include_path = os.path.dirname(path)
if include_path:
env_base.Prepend(CPPPATH=[include_path])
@@ -224,6 +272,7 @@ 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().
Help(opts.GenerateHelpText(env_base))
# add default include paths
@@ -250,47 +299,16 @@ if env_base["target"] == "debug":
# http://scons.org/doc/production/HTML/scons-user/ch06s04.html
env_base.SetOption("implicit_cache", 1)
+if not env_base["tools"]:
+ # Export templates can't run unit test tool.
+ env_base["tests"] = False
+
if env_base["no_editor_splash"]:
env_base.Append(CPPDEFINES=["NO_EDITOR_SPLASH"])
if not env_base["deprecated"]:
env_base.Append(CPPDEFINES=["DISABLE_DEPRECATED"])
-env_base.platforms = {}
-
-selected_platform = ""
-
-if env_base["platform"] != "":
- selected_platform = env_base["platform"]
-elif env_base["p"] != "":
- selected_platform = env_base["p"]
- env_base["platform"] = selected_platform
-else:
- # Missing `platform` argument, try to detect platform automatically
- if sys.platform.startswith("linux"):
- selected_platform = "linuxbsd"
- elif sys.platform == "darwin":
- selected_platform = "osx"
- 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>")
-
- if selected_platform != "":
- print("Automatically detected platform: " + selected_platform)
- env_base["platform"] = selected_platform
-
-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.0. Building for platform "linuxbsd".')
- # Alias for convenience.
- selected_platform = "linuxbsd"
- env_base["platform"] = selected_platform
-
if selected_platform in platform_list:
tmppath = "./platform/" + selected_platform
sys.path.insert(0, tmppath)
@@ -301,43 +319,43 @@ if selected_platform in platform_list:
else:
env = env_base.Clone()
- # Compilation DB requires SCons 3.1.1+.
+ # Generating the compilation DB (`compile_commands.json`) requires SCons 4.0.0 or later.
from SCons import __version__ as scons_raw_version
scons_ver = env._get_major_minor_revision(scons_raw_version)
- if scons_ver >= (3, 1, 1):
- env.Tool("compilation_db", toolpath=["misc/scons"])
- env.Alias("compiledb", env.CompilationDatabase("compile_commands.json"))
- if env["dev"]:
- env["verbose"] = True
- env["warnings"] = "extra"
- env["werror"] = True
+ if scons_ver >= (4, 0, 0):
+ env.Tool("compilation_db")
+ env.Alias("compiledb", env.CompilationDatabase())
- if env["vsproj"]:
- env.vs_incs = []
- env.vs_srcs = []
-
- def AddToVSProject(sources):
- for x in sources:
- if type(x) == type(""):
- fname = env.File(x).path
- else:
- fname = env.File(x)[0].path
- pieces = fname.split(".")
- if len(pieces) > 0:
- basename = pieces[0]
- basename = basename.replace("\\\\", "/")
- if os.path.isfile(basename + ".h"):
- env.vs_incs = env.vs_incs + [basename + ".h"]
- elif os.path.isfile(basename + ".hpp"):
- env.vs_incs = env.vs_incs + [basename + ".hpp"]
- if os.path.isfile(basename + ".c"):
- env.vs_srcs = env.vs_srcs + [basename + ".c"]
- elif os.path.isfile(basename + ".cpp"):
- env.vs_srcs = env.vs_srcs + [basename + ".cpp"]
-
- env.AddToVSProject = AddToVSProject
+ # 'dev' and 'production' are aliases to set default options if they haven't been set
+ # manually by the user.
+ if env["dev"]:
+ env["verbose"] = methods.get_cmdline_bool("verbose", True)
+ env["warnings"] = ARGUMENTS.get("warnings", "extra")
+ env["werror"] = methods.get_cmdline_bool("werror", True)
+ if env["tools"]:
+ env["tests"] = methods.get_cmdline_bool("tests", True)
+ if env["production"]:
+ env["use_static_cpp"] = methods.get_cmdline_bool("use_static_cpp", True)
+ env["use_lto"] = methods.get_cmdline_bool("use_lto", True)
+ env["debug_symbols"] = methods.get_cmdline_bool("debug_symbols", False)
+ if not env["tools"] and env["target"] == "debug":
+ print(
+ "WARNING: Requested `production` build with `tools=no target=debug`, "
+ "this will give you a full debug template (use `target=release_debug` "
+ "for an optimized template with debug features)."
+ )
+ if env.msvc:
+ print(
+ "WARNING: For `production` Windows builds, you should use MinGW with GCC "
+ "or Clang instead of Visual Studio, as they can better optimize the "
+ "GDScript VM in a very significant way. MSVC LTO also doesn't work "
+ "reliably for our use case."
+ "If you want to use MSVC nevertheless for production builds, set "
+ "`debug_symbols=no use_lto=no` instead of the `production=yes` option."
+ )
+ Exit(255)
env.extra_suffix = ""
@@ -433,7 +451,7 @@ if selected_platform in platform_list:
Exit(255)
# Configure compiler warnings
- if env.msvc:
+ if env.msvc: # MSVC
# Truncations, narrowing conversions, signed/unsigned comparisons...
disable_nonessential_warnings = ["/wd4267", "/wd4244", "/wd4305", "/wd4018", "/wd4800"]
if env["warnings"] == "extra":
@@ -446,20 +464,17 @@ if selected_platform in platform_list:
env.Append(CCFLAGS=["/w"])
# Set exception handling model to avoid warnings caused by Windows system headers.
env.Append(CCFLAGS=["/EHsc"])
+
if env["werror"]:
env.Append(CCFLAGS=["/WX"])
- # Force to use Unicode encoding
- env.Append(MSVC_FLAGS=["/utf8"])
- else: # Rest of the world
- shadow_local_warning = []
- all_plus_warnings = ["-Wwrite-strings"]
+ else: # GCC, Clang
+ gcc_common_warnings = []
if methods.using_gcc(env):
- if cc_version_major >= 7:
- shadow_local_warning = ["-Wshadow-local"]
+ gcc_common_warnings += ["-Wshadow-local", "-Wno-misleading-indentation"]
if env["warnings"] == "extra":
- env.Append(CCFLAGS=["-Wall", "-Wextra", "-Wno-unused-parameter"] + all_plus_warnings + shadow_local_warning)
+ env.Append(CCFLAGS=["-Wall", "-Wextra", "-Wwrite-strings", "-Wno-unused-parameter"] + gcc_common_warnings)
env.Append(CXXFLAGS=["-Wctor-dtor-privacy", "-Wnon-virtual-dtor"])
if methods.using_gcc(env):
env.Append(
@@ -475,14 +490,15 @@ if selected_platform in platform_list:
env.Append(CXXFLAGS=["-Wplacement-new=1"])
if cc_version_major >= 9:
env.Append(CCFLAGS=["-Wattribute-alias=2"])
- if methods.using_clang(env):
+ elif methods.using_clang(env):
env.Append(CCFLAGS=["-Wimplicit-fallthrough"])
elif env["warnings"] == "all":
- env.Append(CCFLAGS=["-Wall"] + shadow_local_warning)
+ env.Append(CCFLAGS=["-Wall"] + gcc_common_warnings)
elif env["warnings"] == "moderate":
- env.Append(CCFLAGS=["-Wall", "-Wno-unused"] + shadow_local_warning)
+ env.Append(CCFLAGS=["-Wall", "-Wno-unused"] + gcc_common_warnings)
else: # 'no'
env.Append(CCFLAGS=["-w"])
+
if env["werror"]:
env.Append(CCFLAGS=["-Werror"])
# FIXME: Temporary workaround after the Vulkan merge, remove once warnings are fixed.
@@ -549,13 +565,13 @@ if selected_platform in platform_list:
doc_path = config.get_doc_path()
for c in doc_classes:
env.doc_class_path[c] = path + "/" + doc_path
- except:
+ except Exception:
pass
# Get icon paths (if present)
try:
icons_path = config.get_icons_path()
env.module_icons_paths.append(path + "/" + icons_path)
- except:
+ except Exception:
# Default path for module icons
env.module_icons_paths.append(path + "/" + "icons")
modules_enabled[name] = path
@@ -582,8 +598,6 @@ if selected_platform in platform_list:
env["LIBSUFFIX"] = suffix + env["LIBSUFFIX"]
env["SHLIBSUFFIX"] = suffix + env["SHLIBSUFFIX"]
- if env.use_ptrcall:
- env.Append(CPPDEFINES=["PTRCALL_ENABLED"])
if env["tools"]:
env.Append(CPPDEFINES=["TOOLS_ENABLED"])
if env["disable_3d"]:
@@ -607,11 +621,12 @@ if selected_platform in platform_list:
if env["minizip"]:
env.Append(CPPDEFINES=["MINIZIP_ENABLED"])
- editor_module_list = ["regex"]
+ editor_module_list = ["freetype", "regex"]
if env["tools"] and not env.module_check_dependencies("tools", editor_module_list):
print(
- "Build option 'module_" + x + "_enabled=no' cannot be used with 'tools=yes' (editor), "
- "only with 'tools=no' (export template)."
+ "Build option 'module_"
+ + x
+ + "_enabled=no' cannot be used with 'tools=yes' (editor), only with 'tools=no' (export template)."
)
Exit(255)
@@ -619,37 +634,32 @@ if selected_platform in platform_list:
methods.no_verbose(sys, env)
if not env["platform"] == "server":
- env.Append(
- BUILDERS={
- "GLES2_GLSL": env.Builder(
- action=run_in_subprocess(gles_builders.build_gles2_headers), suffix="glsl.gen.h", src_suffix=".glsl"
- )
- }
- )
- env.Append(
- BUILDERS={
- "RD_GLSL": env.Builder(
- action=run_in_subprocess(gles_builders.build_rd_headers), suffix="glsl.gen.h", src_suffix=".glsl"
- )
- }
- )
- env.Append(
- BUILDERS={
- "GLSL_HEADER": env.Builder(
- action=run_in_subprocess(gles_builders.build_raw_headers), suffix="glsl.gen.h", src_suffix=".glsl"
- )
- }
- )
+ GLSL_BUILDERS = {
+ "RD_GLSL": env.Builder(
+ action=env.Run(glsl_builders.build_rd_headers, 'Building RD_GLSL header: "$TARGET"'),
+ suffix="glsl.gen.h",
+ src_suffix=".glsl",
+ ),
+ "GLSL_HEADER": env.Builder(
+ action=env.Run(glsl_builders.build_raw_headers, 'Building GLSL header: "$TARGET"'),
+ suffix="glsl.gen.h",
+ src_suffix=".glsl",
+ ),
+ }
+ env.Append(BUILDERS=GLSL_BUILDERS)
scons_cache_path = os.environ.get("SCONS_CACHE")
if scons_cache_path != None:
CacheDir(scons_cache_path)
print("Scons cache enabled... (path: '" + scons_cache_path + "')")
- Export("env")
+ if env["vsproj"]:
+ env.vs_incs = []
+ env.vs_srcs = []
- # build subdirs, the build order is dependent on link order.
+ Export("env")
+ # Build subdirs, the build order is dependent on link order.
SConscript("core/SCsub")
SConscript("servers/SCsub")
SConscript("scene/SCsub")
@@ -658,9 +668,11 @@ if selected_platform in platform_list:
SConscript("platform/SCsub")
SConscript("modules/SCsub")
+ if env["tests"]:
+ SConscript("tests/SCsub")
SConscript("main/SCsub")
- SConscript("platform/" + selected_platform + "/SCsub") # build selected platform
+ SConscript("platform/" + selected_platform + "/SCsub") # Build selected platform.
# Microsoft Visual Studio Project Generation
if env["vsproj"]: