From 0476e9b7499c7ad3ac0085045b36f5937e43a766 Mon Sep 17 00:00:00 2001 From: Lukas Tenbrink Date: Sun, 17 Nov 2024 22:48:34 +0100 Subject: [PATCH] Refactor SConstruct to separate library-specific options from those concerned with the build target. Add single compilation unit tool and option (scu_build). --- SConstruct | 86 +++++++++++++++------------- site_scons/site_tools/gdextension.py | 40 +++++++++++++ site_scons/site_tools/scu.py | 31 ++++++++++ 3 files changed, 116 insertions(+), 41 deletions(-) create mode 100644 site_scons/site_tools/gdextension.py create mode 100644 site_scons/site_tools/scu.py diff --git a/SConstruct b/SConstruct index 6f1b222..d4aedf8 100644 --- a/SConstruct +++ b/SConstruct @@ -5,60 +5,64 @@ import sys from methods import print_error -libname = "EXTENSION-NAME" -projectdir = "demo" - -localEnv = Environment(tools=["default"], PLATFORM="") - -customs = ["custom.py"] -customs = [os.path.abspath(path) for path in customs] - -opts = Variables(customs, ARGUMENTS) -opts.Update(localEnv) - -Help(opts.GenerateHelpText(localEnv)) - -env = localEnv.Clone() - -submodule_initialized = False -dir_name = 'godot-cpp' -if os.path.isdir(dir_name): - if os.listdir(dir_name): - submodule_initialized = True - -if not submodule_initialized: - print_error("""godot-cpp is not available within this folder, as Git submodules haven't been initialized. +if not (os.path.isdir("godot-cpp") and os.listdir("godot-cpp")): + print_error("""godot-cpp is not available within this folder, as Git submodules haven"t been initialized. Run the following command to download godot-cpp: git submodule update --init --recursive""") sys.exit(1) -env = SConscript("godot-cpp/SConstruct", {"env": env, "customs": customs}) -env.Append(CPPPATH=["src/"]) -sources = Glob("src/*.cpp") +# ============================= General Lib Info ============================= -if env["target"] in ["editor", "template_debug"]: - try: - doc_data = env.GodotCPPDocData("src/gen/doc_data.gen.cpp", source=Glob("doc_classes/*.xml")) - sources.append(doc_data) - except AttributeError: - print("Not including class reference as we're targeting a pre-4.3 baseline.") +libname = "EXTENSION-NAME" +projectdir = "demo" -file = "{}{}{}".format(libname, env["suffix"], env["SHLIBSUFFIX"]) +gdextension_tool = Tool("gdextension") + +# ============================= Setup Options ============================= + +# Load variables from custom.py, in case someone wants to store their own arguments. +# See https://scons.org/doc/production/HTML/scons-user.html#app-tools // search custom.py +customs = ["custom.py"] +customs = [os.path.abspath(path) for path in customs] +opts = Variables(customs, ARGUMENTS) + +gdextension_tool.options(opts) + +# Remove our custom options to avoid passing to godot-cpp; godot-cpp has its own check for unknown options. +for opt in opts.options: + ARGUMENTS.pop(opt.key, None) + +# ============================= Setup godot-cpp ============================= + +godot_cpp_env = SConscript("godot-cpp/SConstruct", {"customs": customs}) + +gdextension_env = godot_cpp_env.Clone() +opts.Update(gdextension_env) +Help(opts.GenerateHelpText(gdextension_env)) + +# ============================= Setup Targets ============================= + +sources = [] +targets = [] + +gdextension_tool.generate(gdextension_env, godot_cpp_env, sources) + +file = "{}{}{}".format(libname, godot_cpp_env["suffix"], godot_cpp_env["SHLIBSUFFIX"]) filepath = "" -if env["platform"] == "macos" or env["platform"] == "ios": - filepath = "{}.framework/".format(env["platform"]) - file = "{}.{}.{}".format(libname, env["platform"], env["target"]) +if godot_cpp_env["platform"] == "macos" or godot_cpp_env["platform"] == "ios": + filepath = "{}.framework/".format(godot_cpp_env["platform"]) + file = "{}.{}.{}".format(libname, godot_cpp_env["platform"], godot_cpp_env["target"]) -libraryfile = "bin/{}/{}{}".format(env["platform"], filepath, file) -library = env.SharedLibrary( +libraryfile = "bin/{}/{}{}".format(godot_cpp_env["platform"], filepath, file) +library = gdextension_env.SharedLibrary( libraryfile, source=sources, ) +targets.append(library) -copy = env.InstallAs("{}/bin/{}/{}lib{}".format(projectdir, env["platform"], filepath, file), library) +targets.append(gdextension_env.Install("{}/bin/{}/{}".format(projectdir, godot_cpp_env["platform"], filepath), library)) -default_args = [library, copy] -Default(*default_args) +Default(targets) diff --git a/site_scons/site_tools/gdextension.py b/site_scons/site_tools/gdextension.py new file mode 100644 index 0000000..ea038f9 --- /dev/null +++ b/site_scons/site_tools/gdextension.py @@ -0,0 +1,40 @@ +import pathlib +from SCons.Tool import Tool + + +def exists(env): + return True + +def options(opts): + # Add custom options here + # opts.Add( + # "custom_option", + # "Custom option help text", + # "default_value" + # ) + + scu_tool = Tool("scu") + scu_tool.options(opts) + +def generate(env, godot_cpp_env, sources): + scu_tool = Tool("scu") + + # read custom options values + # custom_option = env["custom_option"] + + env.Append(CPPPATH=["src/"]) + + sources.extend([ + f for f in env.Glob("src/*.cpp") + env.Glob("src/**/*.cpp") + # Generated files will be added selectively and maintained by tools. + if not "/gen/" in str(f.path) + ]) + + scu_tool.generate(env, sources) + + if godot_cpp_env["target"] in ["editor", "template_debug"]: + try: + doc_data = godot_cpp_env.GodotCPPDocData("src/gen/doc_data.gen.cpp", source=env.Glob("doc_classes/*.xml")) + sources.append(doc_data) + except AttributeError: + print("Not including class reference as we're targeting a pre-4.3 baseline.") diff --git a/site_scons/site_tools/scu.py b/site_scons/site_tools/scu.py new file mode 100644 index 0000000..af8153d --- /dev/null +++ b/site_scons/site_tools/scu.py @@ -0,0 +1,31 @@ +import pathlib +from SCons.Variables import BoolVariable + + +def exists(env): + return True + +def options(opts): + opts.Add( + BoolVariable( + "scu_build", + "Use single compilation unit build.", + False + ) + ) + +def generate(env, sources): + if not env.get('scu', False): + return + + scu_path = pathlib.Path('src/gen/scu.cpp') + scu_path.parent.mkdir(exist_ok=True) + + scu_path.write_text( + '\n'.join( + f'#include "{pathlib.Path(source.path).relative_to("src")}"' + for source in sources + ) + '\n' + ) + + sources[:] = [str(scu_path.absolute())]