From 55558fb17574ddcbf0dcbba3f90a1aa880907f28 Mon Sep 17 00:00:00 2001 From: Riteo Date: Tue, 12 Mar 2024 22:51:19 +0100 Subject: [PATCH] SCons: Add an option to enable the experimental ninja build backend With this option turned on, if properly set up, SCons generates a `build.ninja` file and quits. To actually build the engine, the user can then call `ninja` with whatever options they might prefer (not everything is yet transferred properly to this new generated file). Ideally, the scons file should never be called again, as ninja automatically detects any SCons build script change and invokes the required commands to regenerate itself. This approach speeds up incremental builds considerably, as it limits SCons to code generation and uses ninja's extremely fast timestamp-based file change detector. --- .gitignore | 4 ++++ SConstruct | 23 ++++++++++++++++++++--- platform_methods.py | 1 - 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index d40f4d39486..46dcf84b43a 100644 --- a/.gitignore +++ b/.gitignore @@ -35,6 +35,10 @@ bin compile_commands.json platform/windows/godot_res.res +# Ninja build files +build.ninja +.ninja + # Generated by Godot binary .import/ /gdextension_interface.h diff --git a/SConstruct b/SConstruct index 753cea40e33..73ef420a0dc 100644 --- a/SConstruct +++ b/SConstruct @@ -203,6 +203,7 @@ opts.Add(BoolVariable("custom_modules_recursive", "Detect custom modules recursi opts.Add(BoolVariable("dev_mode", "Alias for dev options: verbose=yes warnings=extra werror=yes tests=yes", False)) opts.Add(BoolVariable("tests", "Build the unit tests", False)) opts.Add(BoolVariable("fast_unsafe", "Enable unsafe options for faster rebuilds", False)) +opts.Add(BoolVariable("ninja", "Use the ninja backend for faster rebuilds", False)) opts.Add(BoolVariable("compiledb", "Generate compilation DB (`compile_commands.json`) for external tools", False)) opts.Add(BoolVariable("verbose", "Enable verbose output for the compilation", False)) opts.Add(BoolVariable("progress", "Show a progress indicator during compilation", True)) @@ -956,7 +957,8 @@ if selected_platform in platform_list: env.vs_incs = [] env.vs_srcs = [] - # CompileDB + # CompileDB and Ninja are only available with certain SCons versions which + # not everybody might have yet, so we have to check. from SCons import __version__ as scons_raw_version scons_ver = env._get_major_minor_revision(scons_raw_version) @@ -968,6 +970,20 @@ if selected_platform in platform_list: env.Tool("compilation_db") env.Alias("compiledb", env.CompilationDatabase()) + if env["ninja"]: + if scons_ver < (4, 2, 0): + print("The `ninja=yes` option requires SCons 4.2 or later, but your version is %s." % scons_raw_version) + Exit(255) + + SetOption("experimental", "ninja") + + # By setting this we allow the user to run ninja by themselves with all + # the flags they need, as apparently automatically running from scons + # is way slower. + SetOption("disable_execute_ninja", True) + + env.Tool("ninja") + # Threads if env["threads"]: env.Append(CPPDEFINES=["THREADS_ENABLED"]) @@ -1041,9 +1057,10 @@ atexit.register(print_elapsed_time) def purge_flaky_files(): + paths_to_keep = ["ninja.build"] for build_failure in GetBuildFailures(): - path = build_failure.node.abspath - if os.path.isfile(path): + path = build_failure.node.path + if os.path.isfile(path) and path not in paths_to_keep: os.remove(path) diff --git a/platform_methods.py b/platform_methods.py index 92aefcc648b..56115db4a49 100644 --- a/platform_methods.py +++ b/platform_methods.py @@ -66,7 +66,6 @@ def generate_export_icons(platform_path, platform_name): svg_str += '";\n' - # NOTE: It is safe to generate this file here, since this is still executed serially. wf = export_path + "/" + name + "_svg.gen.h" methods.write_file_if_needed(wf, svg_str)