This page documents Godot's SCons-based build system: its entry point, option definitions, platform scanning, module discovery, and the SCsub compilation hierarchy. For details on individual platform detect.py scripts, see Platform Detection. For the module config.py and SCsub conventions, see Module System. For build options and the methods.py helper library, see Build Configuration.
Godot uses SCons as its build system. The build is driven by a single root SConstruct file which:
methods.py, platform_methods.py, etc.)platform/*/detect.py files to determine what platforms are buildablecustom.py or a profile fileSCsub scripts that compile each subsystem into static librariesbin/Minimum requirements: SCons 4.0, Python 3.9 (SConstruct4-5).
| File | Role |
|---|---|
SConstruct | Root build script; entry point for all SCons invocations |
methods.py | Helper functions attached to the SCons environment |
platform_methods.py | Architecture detection, cross-platform utilities |
platform_methods.py | Compatibility aliases for old platform names |
scu_builders.py | Single Compilation Unit (SCU) file generation |
glsl_builders.py | Builder for compiling GLSL shaders |
gles3_builders.py | Builder for GLES3 shader headers |
version.py | Engine version constants |
custom.py | Optional user-provided build option overrides (not tracked in git) |
Sources: SConstruct25-54 SConstruct47-65
The typical invocation pattern is:
scons platform=<platform> target=<target> [options...]
platform selects the target OS. If omitted, SCons auto-detects from sys.platform (SConstruct376-405). Valid aliases such as osx→macos, x11→linuxbsd, javascript→web are handled for backward compatibility (platform_methods.py12-17).
target selects one of three build modes:
| Target | Preprocessor Defines | Description |
|---|---|---|
editor | TOOLS_ENABLED, DEBUG_ENABLED | Full editor build |
template_debug | DEBUG_ENABLED | Export template with debug features |
template_release | (none of the above) | Stripped production export template |
Sources: SConstruct162-166 SConstruct526-555
Diagram: SConstruct Execution Flow
Sources: SConstruct25-109 SConstruct436-509 SConstruct694
The root SCons environment is created with no default tools (env = Environment(tools=[])) to avoid platform assumptions (SConstruct115). Tools are added later after the platform is known (SConstruct503-509).
Several methods from methods.py are patched directly onto the environment class:
| Method | Source function |
|---|---|
env.add_source_files() | methods.add_source_files |
env.add_library() | methods.add_library |
env.add_shared_library() | methods.add_shared_library |
env.add_program() | methods.add_program |
env.disable_warnings() | methods.disable_warnings |
env.module_add_dependencies() | methods.module_add_dependencies |
env.module_check_dependencies() | methods.module_check_dependencies |
env.CommandNoCache() | methods.CommandNoCache |
env.Run() | methods.Run |
Sources: SConstruct126-139
Each directory under platform/ must contain a detect.py with a defined interface. SCons scans platform/* at startup and calls can_build() to determine if the platform is available on the current host (SConstruct77-109).
Diagram: detect.py Interface
| Function | Called by | Purpose |
|---|---|---|
can_build() | SConstruct startup scan | Returns True if this platform can be built on the current host |
get_opts() | SConstruct after platform selection | Returns platform-specific Variables entries |
get_flags() | SConstruct after platform selection | Returns a dict of default option overrides for this platform |
get_tools(env) | SConstruct tool loading | Returns SCons tool names to activate (e.g. ["msvc", "mslink"]) |
configure(env) | SConstruct after all options resolved | Applies compiler paths, flags, and library settings to env |
Sources: SConstruct77-109 SConstruct499-509 SConstruct694
| Platform dir | get_name() | Build host requirement |
|---|---|---|
platform/windows | Windows | Native Windows, or POSIX with MinGW |
platform/linuxbsd | LinuxBSD | POSIX (not macOS) with pkg-config |
platform/macos | macOS | macOS or OSXCROSS_ROOT set |
platform/android | Android | ANDROID_HOME SDK with NDK |
platform/ios | iOS | macOS or OSXCROSS_IOS set |
platform/web | Web | Emscripten (emcc) in PATH |
Sources: platform/windows/detect.py49-61 platform/linuxbsd/detect.py17-26 platform/macos/detect.py20-24 platform/android/detect.py18-19 platform/ios/detect.py16-18 platform/web/detect.py29-30
Built-in modules are under modules/. Custom modules can be added via the custom_modules build option, which accepts a comma-separated list of directory paths.
The detect_modules() function in methods.py scans a directory and returns an OrderedDict of {module_name: module_path}. A directory is recognized as a module if it contains all three of: register_types.h, SCsub, and config.py (methods.py303-310).
Diagram: Module Detection
Sources: SConstruct436-492 methods.py240-310 modules/SCsub33-42
After all modules are discovered, modules/SCsub generates two files at build time:
modules/modules_enabled.gen.h — #define MODULE_<NAME>_ENABLED for each active modulemodules/register_module_types.gen.cpp — calls initialize_<name>_module() and uninitialize_<name>_module() for each levelSources: modules/modules_builders.py8-49 modules/SCsub18-28
Each major subsystem has its own SCsub file. The root SConstruct drives the top-level SConscript() calls. Each SCsub builds a static library with env.add_library() and prepends it to env LIBS so downstream link steps can find it.
Diagram: SCsub Library Dependency Chain
Sources: core/SCsub239-240 modules/SCsub57-63 editor/SCsub101-102 main/SCsub39-40 platform/SCsub29-30
The platform/<name>/SCsub (e.g. platform/windows/SCsub81-93 platform/linuxbsd/SCsub44-48) is responsible for the final env.add_program() call that produces the executable in bin/.
Options are declared with SCons Variables and can be set on the command line or in custom.py. A profile file can be specified with profile=<path> (SConstruct149-157).
| Option | Default | Description |
|---|---|---|
platform / p | (auto) | Target platform |
target | editor | editor, template_debug, or template_release |
arch | auto | CPU architecture |
dev_build | False | Enables DEV_ENABLED, no optimizations |
optimize | auto | none, debug, speed, speed_trace, size, size_extra |
debug_symbols | False | Embed debug symbols |
lto | none | Link-time optimization: none, auto, thin, full |
production | False | Alias enabling LTO, static C++, no debug symbols |
dev_mode | False | Alias enabling verbose, extra warnings, werror, tests |
Sources: SConstruct160-291
| Option | Default | Controls |
|---|---|---|
vulkan | True | Vulkan rendering driver |
opengl3 | True | GLES3/OpenGL rendering driver |
d3d12 | False | Direct3D 12 driver (Windows default: True) |
metal | False | Metal driver (macOS/iOS arm64 default: True) |
threads | True | Threading support |
deprecated | True | Compatibility code for removed features |
precision | single | Floating-point precision: single or double |
disable_3d | False | Strips 3D nodes for smaller binary |
disable_advanced_gui | False | Strips advanced GUI nodes |
modules_enabled_by_default | True | Whether unspecified modules are on |
Sources: SConstruct189-275
| Option | Default | Description |
|---|---|---|
scu_build | False | Single Compilation Unit build (faster full builds) |
ninja | False | Emit a build.ninja file and use Ninja |
num_jobs | (cpu_count-1) | Parallel compile jobs |
fast_unsafe | False | Implicit cache + max_drift for faster incremental builds |
compiledb | False | Emit compile_commands.json |
cache_path | (empty) | Directory for SCons build cache |
Sources: SConstruct233-294
Most bundled libraries have a corresponding builtin_<name> boolean option defaulting to True. Setting it to False makes the build use the system-installed version (via pkg-config where applicable). Examples: builtin_freetype, builtin_zlib, builtin_mbedtls, builtin_harfbuzz. The full list is declared at SConstruct312-341
After detect.configure(env) runs, SConstruct validates the detected compiler version. Minimum supported versions:
| Compiler | Minimum |
|---|---|
| GCC | 9 (with POSIX threads on MinGW) |
| Clang (upstream) | 6 |
| Apple Clang | 16 (Xcode 16) |
| MSVC | 15.9 (VS 2017), 16.11 (VS 2019) |
Sources: SConstruct705-772
Version detection is handled by methods.get_compiler_version(env) (methods.py687-802), which parses --version output or uses vswhere for MSVC.
Compiler identity helpers: methods.using_gcc(env), methods.using_clang(env), methods.using_emcc(env), methods.is_apple_clang(env) (methods.py811-821).
The final binary is placed in bin/ with a structured name:
bin/godot.<platform>.<target>.<arch>[.llvm][.double][.san][.<extra_suffix>]
Examples:
bin/godot.linuxbsd.editor.x86_64bin/godot.windows.template_release.x86_64.exebin/godot.android.template_debug.arm64Object files and intermediate static libraries are redirected to bin/obj/ when redirect_build_objects=yes (the default), keeping the source tree clean (methods.py88-112).
When scu_build=yes, the scu_builders.py script pre-generates .scu/scu_*.gen.cpp files that #include groups of source files. This reduces compilation time for full builds by merging translation units. The add_source_files() function in methods.py transparently uses SCU files when the option is active (methods.py55-85). The limit on includes per SCU file is controlled by scu_limit (SConstruct679-690).
Several build steps produce C++ headers or source files at compile time using env.CommandNoCache():
| Generated File | Generator | Content |
|---|---|---|
core/version_generated.gen.h | core_builders.version_info_builder | Version constants from version.py |
core/version_hash.gen.cpp | core_builders.version_hash_builder | Git commit hash |
core/disabled_classes.gen.h | core_builders.disabled_class_builder | Classes excluded by build_profile |
core/io/certs_compressed.gen.h | core_builders.make_certs_header | Compressed TLS certificate bundle |
modules/modules_enabled.gen.h | modules_builders.modules_enabled_builder | MODULE_<NAME>_ENABLED defines |
modules/register_module_types.gen.cpp | modules_builders.register_module_types_builder | Module init/deinit dispatcher |
editor/doc/doc_data_compressed.gen.h | editor_builders.make_doc_header | Compressed class reference |
editor/translations/*.gen.cpp | editor_builders.make_translations | Compiled translation data |
Sources: core/SCsub172-218 modules/SCsub18-28 editor/SCsub13-75
Refresh this wiki
This wiki was recently refreshed. Please wait 2 days to refresh again.