SCons: Refactor running commands through builders

A new `env.Run` method is added which allows to control the verbosity
of builders output automatically depending on whether the "verbose"
option is set. It also allows to optionally run any SCons commands in a
subprocess using the existing `run_in_subprocess` method, unifying
the interface. `Action` objects wrap all builder functions to include a
short build message associated with any action.

Notably, this removes quite verbose output generated by `make_doc_header`
and `make_editor_icons_action` builders.
This commit is contained in:
Andrii Doroshenko (Xrayez) 2020-07-27 21:00:26 +03:00
parent f93c04d8ef
commit d86de6c98e
11 changed files with 97 additions and 51 deletions

View File

@ -84,6 +84,7 @@ env_base.__class__.add_shared_library = methods.add_shared_library
env_base.__class__.add_library = methods.add_library env_base.__class__.add_library = methods.add_library
env_base.__class__.add_program = methods.add_program env_base.__class__.add_program = methods.add_program
env_base.__class__.CommandNoCache = methods.CommandNoCache env_base.__class__.CommandNoCache = methods.CommandNoCache
env_base.__class__.Run = methods.Run
env_base.__class__.disable_warnings = methods.disable_warnings env_base.__class__.disable_warnings = methods.disable_warnings
env_base.__class__.module_check_dependencies = methods.module_check_dependencies env_base.__class__.module_check_dependencies = methods.module_check_dependencies
@ -627,27 +628,24 @@ if selected_platform in platform_list:
methods.no_verbose(sys, env) methods.no_verbose(sys, env)
if not env["platform"] == "server": if not env["platform"] == "server":
env.Append( GLSL_BUILDERS = {
BUILDERS={ "GLES2_GLSL": env.Builder(
"GLES2_GLSL": env.Builder( action=env.Run(gles_builders.build_gles2_headers, 'Building GLES2_GLSL header: "$TARGET"'),
action=run_in_subprocess(gles_builders.build_gles2_headers), suffix="glsl.gen.h", src_suffix=".glsl" suffix="glsl.gen.h",
) src_suffix=".glsl",
} ),
) "RD_GLSL": env.Builder(
env.Append( action=env.Run(gles_builders.build_rd_headers, 'Building RD_GLSL header: "$TARGET"'),
BUILDERS={ suffix="glsl.gen.h",
"RD_GLSL": env.Builder( src_suffix=".glsl",
action=run_in_subprocess(gles_builders.build_rd_headers), suffix="glsl.gen.h", src_suffix=".glsl" ),
) "GLSL_HEADER": env.Builder(
} action=env.Run(gles_builders.build_raw_headers, 'Building GLSL header: "$TARGET"'),
) suffix="glsl.gen.h",
env.Append( src_suffix=".glsl",
BUILDERS={ ),
"GLSL_HEADER": env.Builder( }
action=run_in_subprocess(gles_builders.build_raw_headers), suffix="glsl.gen.h", src_suffix=".glsl" env.Append(BUILDERS=GLSL_BUILDERS)
)
}
)
scons_cache_path = os.environ.get("SCONS_CACHE") scons_cache_path = os.environ.get("SCONS_CACHE")
if scons_cache_path != None: if scons_cache_path != None:

View File

@ -149,28 +149,34 @@ env.Depends(
env.CommandNoCache( env.CommandNoCache(
"#core/io/certs_compressed.gen.h", "#core/io/certs_compressed.gen.h",
"#thirdparty/certs/ca-certificates.crt", "#thirdparty/certs/ca-certificates.crt",
run_in_subprocess(core_builders.make_certs_header), env.Run(core_builders.make_certs_header, "Building ca-certificates header."),
) )
# Make binders # Make binders
env.CommandNoCache( env.CommandNoCache(
["method_bind.gen.inc", "method_bind_ext.gen.inc", "method_bind_free_func.gen.inc"], ["method_bind.gen.inc", "method_bind_ext.gen.inc", "method_bind_free_func.gen.inc"],
"make_binders.py", "make_binders.py",
run_in_subprocess(make_binders.run), env.Run(make_binders.run, "Generating method binders."),
) )
# Authors # Authors
env.Depends("#core/authors.gen.h", "../AUTHORS.md") env.Depends("#core/authors.gen.h", "../AUTHORS.md")
env.CommandNoCache("#core/authors.gen.h", "../AUTHORS.md", run_in_subprocess(core_builders.make_authors_header)) env.CommandNoCache(
"#core/authors.gen.h", "../AUTHORS.md", env.Run(core_builders.make_authors_header, "Generating authors header."),
)
# Donors # Donors
env.Depends("#core/donors.gen.h", "../DONORS.md") env.Depends("#core/donors.gen.h", "../DONORS.md")
env.CommandNoCache("#core/donors.gen.h", "../DONORS.md", run_in_subprocess(core_builders.make_donors_header)) env.CommandNoCache(
"#core/donors.gen.h", "../DONORS.md", env.Run(core_builders.make_donors_header, "Generating donors header."),
)
# License # License
env.Depends("#core/license.gen.h", ["../COPYRIGHT.txt", "../LICENSE.txt"]) env.Depends("#core/license.gen.h", ["../COPYRIGHT.txt", "../LICENSE.txt"])
env.CommandNoCache( env.CommandNoCache(
"#core/license.gen.h", ["../COPYRIGHT.txt", "../LICENSE.txt"], run_in_subprocess(core_builders.make_license_header) "#core/license.gen.h",
["../COPYRIGHT.txt", "../LICENSE.txt"],
env.Run(core_builders.make_license_header, "Generating license header."),
) )
# Chain load SCsubs # Chain load SCsubs

View File

@ -16,7 +16,7 @@ env.Depends("#core/input/default_controller_mappings.gen.cpp", controller_databa
env.CommandNoCache( env.CommandNoCache(
"#core/input/default_controller_mappings.gen.cpp", "#core/input/default_controller_mappings.gen.cpp",
controller_databases, controller_databases,
run_in_subprocess(input_builders.make_default_controller_mappings), env.Run(input_builders.make_default_controller_mappings, "Generating default controller mappings."),
) )
env.add_source_files(env.core_sources, "*.cpp") env.add_source_files(env.core_sources, "*.cpp")

View File

@ -7,7 +7,6 @@ env.editor_sources = []
import os import os
import os.path import os.path
import glob import glob
from platform_methods import run_in_subprocess
import editor_builders import editor_builders
@ -61,7 +60,11 @@ if env["tools"]:
docs = sorted(docs) docs = sorted(docs)
env.Depends("#editor/doc_data_compressed.gen.h", docs) env.Depends("#editor/doc_data_compressed.gen.h", docs)
env.CommandNoCache("#editor/doc_data_compressed.gen.h", docs, run_in_subprocess(editor_builders.make_doc_header)) env.CommandNoCache(
"#editor/doc_data_compressed.gen.h",
docs,
env.Run(editor_builders.make_doc_header, "Generating documentation header."),
)
path = env.Dir(".").abspath path = env.Dir(".").abspath
@ -69,14 +72,18 @@ if env["tools"]:
tlist = glob.glob(path + "/translations/*.po") tlist = glob.glob(path + "/translations/*.po")
env.Depends("#editor/editor_translations.gen.h", tlist) env.Depends("#editor/editor_translations.gen.h", tlist)
env.CommandNoCache( env.CommandNoCache(
"#editor/editor_translations.gen.h", tlist, run_in_subprocess(editor_builders.make_editor_translations_header) "#editor/editor_translations.gen.h",
tlist,
env.Run(editor_builders.make_editor_translations_header, "Generating editor translations header."),
) )
# Documentation translations # Documentation translations
tlist = glob.glob(env.Dir("#doc").abspath + "/translations/*.po") tlist = glob.glob(env.Dir("#doc").abspath + "/translations/*.po")
env.Depends("#editor/doc_translations.gen.h", tlist) env.Depends("#editor/doc_translations.gen.h", tlist)
env.CommandNoCache( env.CommandNoCache(
"#editor/doc_translations.gen.h", tlist, run_in_subprocess(editor_builders.make_doc_translations_header) "#editor/doc_translations.gen.h",
tlist,
env.Run(editor_builders.make_doc_translations_header, "Generating translations header."),
) )
# Fonts # Fonts
@ -84,7 +91,11 @@ if env["tools"]:
flist.extend(glob.glob(path + "/../thirdparty/fonts/*.otf")) flist.extend(glob.glob(path + "/../thirdparty/fonts/*.otf"))
flist.sort() flist.sort()
env.Depends("#editor/builtin_fonts.gen.h", flist) env.Depends("#editor/builtin_fonts.gen.h", flist)
env.CommandNoCache("#editor/builtin_fonts.gen.h", flist, run_in_subprocess(editor_builders.make_fonts_header)) env.CommandNoCache(
"#editor/builtin_fonts.gen.h",
flist,
env.Run(editor_builders.make_fonts_header, "Generating builtin fonts header."),
)
env.add_source_files(env.editor_sources, "*.cpp") env.add_source_files(env.editor_sources, "*.cpp")

View File

@ -4,14 +4,14 @@ Import("env")
import os import os
from platform_methods import run_in_subprocess
import editor_icons_builders import editor_icons_builders
make_editor_icons_builder = Builder(
action=run_in_subprocess(editor_icons_builders.make_editor_icons_action), suffix=".h", src_suffix=".svg"
)
env["BUILDERS"]["MakeEditorIconsBuilder"] = make_editor_icons_builder env["BUILDERS"]["MakeEditorIconsBuilder"] = Builder(
action=env.Run(editor_icons_builders.make_editor_icons_action, "Generating editor icons header."),
suffix=".h",
src_suffix=".svg",
)
# Editor's own icons # Editor's own icons
icon_sources = Glob("*.svg") icon_sources = Glob("*.svg")

View File

@ -2,7 +2,6 @@
Import("env") Import("env")
from platform_methods import run_in_subprocess
import main_builders import main_builders
env.main_sources = [] env.main_sources = []
@ -15,15 +14,21 @@ if env["tests"]:
env_main.Append(CPPDEFINES=["TESTS_ENABLED"]) env_main.Append(CPPDEFINES=["TESTS_ENABLED"])
env_main.Depends("#main/splash.gen.h", "#main/splash.png") env_main.Depends("#main/splash.gen.h", "#main/splash.png")
env_main.CommandNoCache("#main/splash.gen.h", "#main/splash.png", run_in_subprocess(main_builders.make_splash)) env_main.CommandNoCache(
"#main/splash.gen.h", "#main/splash.png", env.Run(main_builders.make_splash, "Building splash screen header."),
)
env_main.Depends("#main/splash_editor.gen.h", "#main/splash_editor.png") env_main.Depends("#main/splash_editor.gen.h", "#main/splash_editor.png")
env_main.CommandNoCache( env_main.CommandNoCache(
"#main/splash_editor.gen.h", "#main/splash_editor.png", run_in_subprocess(main_builders.make_splash_editor) "#main/splash_editor.gen.h",
"#main/splash_editor.png",
env.Run(main_builders.make_splash_editor, "Building editor splash screen header."),
) )
env_main.Depends("#main/app_icon.gen.h", "#main/app_icon.png") env_main.Depends("#main/app_icon.gen.h", "#main/app_icon.png")
env_main.CommandNoCache("#main/app_icon.gen.h", "#main/app_icon.png", run_in_subprocess(main_builders.make_app_icon)) env_main.CommandNoCache(
"#main/app_icon.gen.h", "#main/app_icon.png", env.Run(main_builders.make_app_icon, "Building application icon."),
)
lib = env_main.add_library("main", env.main_sources) lib = env_main.add_library("main", env.main_sources)
env.Prepend(LIBS=[lib]) env.Prepend(LIBS=[lib])

View File

@ -4,6 +4,11 @@ import glob
import subprocess import subprocess
from collections import OrderedDict from collections import OrderedDict
# We need to define our own `Action` method to control the verbosity of output
# and whenever we need to run those commands in a subprocess on some platforms.
from SCons.Script import Action
from platform_methods import run_in_subprocess
def add_source_files(self, sources, files, warn_duplicates=True): def add_source_files(self, sources, files, warn_duplicates=True):
# Convert string to list of absolute paths (including expanding wildcard) # Convert string to list of absolute paths (including expanding wildcard)
@ -621,6 +626,14 @@ def CommandNoCache(env, target, sources, command, **args):
return result return result
def Run(env, function, short_message, subprocess=True):
output_print = short_message if not env["verbose"] else ""
if not subprocess:
return Action(function, output_print)
else:
return Action(run_in_subprocess(function), output_print)
def detect_darwin_sdk_path(platform, env): def detect_darwin_sdk_path(platform, env):
sdk_name = "" sdk_name = ""
if platform == "osx": if platform == "osx":

View File

@ -10,14 +10,28 @@ env_modules = env.Clone()
Export("env_modules") Export("env_modules")
# Header with MODULE_*_ENABLED defines. # Header with MODULE_*_ENABLED defines.
env.CommandNoCache("modules_enabled.gen.h", Value(env.module_list), modules_builders.generate_modules_enabled) env.CommandNoCache(
"modules_enabled.gen.h",
Value(env.module_list),
env.Run(
modules_builders.generate_modules_enabled,
"Generating enabled modules header.",
# NOTE: No need to run in subprocess since this is still executed serially.
subprocess=False,
),
)
# Header to be included in `tests/test_main.cpp` to run module-specific tests. # Header to be included in `tests/test_main.cpp` to run module-specific tests.
if env["tests"]: if env["tests"]:
env.CommandNoCache( env.CommandNoCache(
"modules_tests.gen.h", "modules_tests.gen.h",
Value(env.module_list), Value(env.module_list),
Action(modules_builders.generate_modules_tests, "Generating modules tests header."), env.Run(
modules_builders.generate_modules_tests,
"Generating modules tests header.",
# NOTE: No need to run in subprocess since this is still executed serially.
subprocess=False,
),
) )
env.AlwaysBuild("modules_tests.gen.h") env.AlwaysBuild("modules_tests.gen.h")

View File

@ -1,7 +1,6 @@
#!/usr/bin/env python #!/usr/bin/env python
import resource_to_cpp import resource_to_cpp
from platform_methods import run_in_subprocess
Import("env") Import("env")
Import("env_modules") Import("env_modules")

View File

@ -22,13 +22,12 @@ SConscript("pluginscript/SCsub")
SConscript("videodecoder/SCsub") SConscript("videodecoder/SCsub")
from platform_methods import run_in_subprocess
import gdnative_builders import gdnative_builders
_, gensource = env_gdnative.CommandNoCache( _, gensource = env_gdnative.CommandNoCache(
["include/gdnative_api_struct.gen.h", "gdnative_api_struct.gen.cpp"], ["include/gdnative_api_struct.gen.h", "gdnative_api_struct.gen.cpp"],
"gdnative_api.json", "gdnative_api.json",
run_in_subprocess(gdnative_builders.build_gdnative_api_struct), env.Run(gdnative_builders.build_gdnative_api_struct, "Generating GDNative API."),
) )
env_gdnative.add_source_files(env.modules_sources, [gensource]) env_gdnative.add_source_files(env.modules_sources, [gensource])

View File

@ -44,11 +44,12 @@ def run_in_subprocess(builder_function):
json.dump(data, json_file, indent=2) json.dump(data, json_file, indent=2)
json_file_size = os.stat(json_path).st_size json_file_size = os.stat(json_path).st_size
print( if env["verbose"]:
"Executing builder function in subprocess: " print(
"module_path=%r, parameter_file=%r, parameter_file_size=%r, target=%r, source=%r" "Executing builder function in subprocess: "
% (module_path, json_path, json_file_size, target, source) "module_path=%r, parameter_file=%r, parameter_file_size=%r, target=%r, source=%r"
) % (module_path, json_path, json_file_size, target, source)
)
try: try:
exit_code = subprocess.call([sys.executable, module_path, json_path], env=subprocess_env) exit_code = subprocess.call([sys.executable, module_path, json_path], env=subprocess_env)
finally: finally: