[Scons] Implement module dependency sorting.
Modules can now call: env.module_add_dependencies(name: str, deps: list, optional: bool) To add required or optional dependencies during the "can_build" step. Required dependencies will be checked and the module will be not be enabled when they are missing, printing a warning to notify the user.
This commit is contained in:
parent
bed2482ce2
commit
951a1016d3
16
SConstruct
16
SConstruct
|
@ -138,6 +138,7 @@ env_base.__class__.CommandNoCache = methods.CommandNoCache
|
||||||
env_base.__class__.Run = methods.Run
|
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__.force_optimization_on_debug = methods.force_optimization_on_debug
|
env_base.__class__.force_optimization_on_debug = methods.force_optimization_on_debug
|
||||||
|
env_base.__class__.module_add_dependencies = methods.module_add_dependencies
|
||||||
env_base.__class__.module_check_dependencies = methods.module_check_dependencies
|
env_base.__class__.module_check_dependencies = methods.module_check_dependencies
|
||||||
|
|
||||||
env_base["x86_libtheora_opt_gcc"] = False
|
env_base["x86_libtheora_opt_gcc"] = False
|
||||||
|
@ -699,6 +700,7 @@ if selected_platform in platform_list:
|
||||||
sys.modules.pop("detect")
|
sys.modules.pop("detect")
|
||||||
|
|
||||||
modules_enabled = OrderedDict()
|
modules_enabled = OrderedDict()
|
||||||
|
env.module_dependencies = {}
|
||||||
env.module_icons_paths = []
|
env.module_icons_paths = []
|
||||||
env.doc_class_path = {}
|
env.doc_class_path = {}
|
||||||
|
|
||||||
|
@ -710,6 +712,10 @@ if selected_platform in platform_list:
|
||||||
import config
|
import config
|
||||||
|
|
||||||
if config.can_build(env, selected_platform):
|
if config.can_build(env, selected_platform):
|
||||||
|
# Disable it if a required dependency is missing.
|
||||||
|
if not env.module_check_dependencies(name):
|
||||||
|
continue
|
||||||
|
|
||||||
config.configure(env)
|
config.configure(env)
|
||||||
# Get doc classes paths (if present)
|
# Get doc classes paths (if present)
|
||||||
try:
|
try:
|
||||||
|
@ -732,6 +738,7 @@ if selected_platform in platform_list:
|
||||||
sys.modules.pop("config")
|
sys.modules.pop("config")
|
||||||
|
|
||||||
env.module_list = modules_enabled
|
env.module_list = modules_enabled
|
||||||
|
methods.sort_module_list(env)
|
||||||
|
|
||||||
methods.update_version(env.module_version_string)
|
methods.update_version(env.module_version_string)
|
||||||
|
|
||||||
|
@ -794,15 +801,6 @@ if selected_platform in platform_list:
|
||||||
if env["minizip"]:
|
if env["minizip"]:
|
||||||
env.Append(CPPDEFINES=["MINIZIP_ENABLED"])
|
env.Append(CPPDEFINES=["MINIZIP_ENABLED"])
|
||||||
|
|
||||||
editor_module_list = []
|
|
||||||
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)."
|
|
||||||
)
|
|
||||||
Exit(255)
|
|
||||||
|
|
||||||
if not env["verbose"]:
|
if not env["verbose"]:
|
||||||
methods.no_verbose(sys, env)
|
methods.no_verbose(sys, env)
|
||||||
|
|
||||||
|
|
46
methods.py
46
methods.py
|
@ -1,5 +1,6 @@
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
import sys
|
||||||
import glob
|
import glob
|
||||||
import subprocess
|
import subprocess
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
@ -336,7 +337,20 @@ def disable_module(self):
|
||||||
self.disabled_modules.append(self.current_module)
|
self.disabled_modules.append(self.current_module)
|
||||||
|
|
||||||
|
|
||||||
def module_check_dependencies(self, module, dependencies, silent=False):
|
def module_add_dependencies(self, module, dependencies, optional=False):
|
||||||
|
"""
|
||||||
|
Adds dependencies for a given module.
|
||||||
|
Meant to be used in module `can_build` methods.
|
||||||
|
"""
|
||||||
|
if module not in self.module_dependencies:
|
||||||
|
self.module_dependencies[module] = [[], []]
|
||||||
|
if optional:
|
||||||
|
self.module_dependencies[module][1].extend(dependencies)
|
||||||
|
else:
|
||||||
|
self.module_dependencies[module][0].extend(dependencies)
|
||||||
|
|
||||||
|
|
||||||
|
def module_check_dependencies(self, module):
|
||||||
"""
|
"""
|
||||||
Checks if module dependencies are enabled for a given module,
|
Checks if module dependencies are enabled for a given module,
|
||||||
and prints a warning if they aren't.
|
and prints a warning if they aren't.
|
||||||
|
@ -344,23 +358,41 @@ def module_check_dependencies(self, module, dependencies, silent=False):
|
||||||
Returns a boolean (True if dependencies are satisfied).
|
Returns a boolean (True if dependencies are satisfied).
|
||||||
"""
|
"""
|
||||||
missing_deps = []
|
missing_deps = []
|
||||||
for dep in dependencies:
|
required_deps = self.module_dependencies[module][0] if module in self.module_dependencies else []
|
||||||
|
for dep in required_deps:
|
||||||
opt = "module_{}_enabled".format(dep)
|
opt = "module_{}_enabled".format(dep)
|
||||||
if not opt in self or not self[opt]:
|
if not opt in self or not self[opt]:
|
||||||
missing_deps.append(dep)
|
missing_deps.append(dep)
|
||||||
|
|
||||||
if missing_deps != []:
|
if missing_deps != []:
|
||||||
if not silent:
|
print(
|
||||||
print(
|
"Disabling '{}' module as the following dependencies are not satisfied: {}".format(
|
||||||
"Disabling '{}' module as the following dependencies are not satisfied: {}".format(
|
module, ", ".join(missing_deps)
|
||||||
module, ", ".join(missing_deps)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
)
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def sort_module_list(env):
|
||||||
|
out = OrderedDict()
|
||||||
|
deps = {k: v[0] + list(filter(lambda x: x in env.module_list, v[1])) for k, v in env.module_dependencies.items()}
|
||||||
|
|
||||||
|
frontier = list(env.module_list.keys())
|
||||||
|
explored = []
|
||||||
|
while len(frontier):
|
||||||
|
cur = frontier.pop()
|
||||||
|
deps_list = deps[cur] if cur in deps else []
|
||||||
|
if len(deps_list) and any([d not in explored for d in deps_list]):
|
||||||
|
# Will explore later, after its dependencies
|
||||||
|
frontier.insert(0, cur)
|
||||||
|
continue
|
||||||
|
explored.append(cur)
|
||||||
|
for k in explored:
|
||||||
|
env.module_list.move_to_end(k)
|
||||||
|
|
||||||
|
|
||||||
def use_windows_spawn_fix(self, platform=None):
|
def use_windows_spawn_fix(self, platform=None):
|
||||||
|
|
||||||
if os.name != "nt":
|
if os.name != "nt":
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
def can_build(env, platform):
|
def can_build(env, platform):
|
||||||
|
env.module_add_dependencies("gdscript", ["jsonrpc", "websocket"], True)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
def can_build(env, platform):
|
def can_build(env, platform):
|
||||||
return env.module_check_dependencies("msdfgen", ["freetype"])
|
env.module_add_dependencies("msdfgen", ["freetype"])
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def configure(env):
|
def configure(env):
|
||||||
|
|
|
@ -36,8 +36,8 @@ def make_icu_data(target, source, env):
|
||||||
# Thirdparty source files
|
# Thirdparty source files
|
||||||
|
|
||||||
thirdparty_obj = []
|
thirdparty_obj = []
|
||||||
freetype_enabled = env.module_check_dependencies("text_server_adv", ["freetype"], True)
|
freetype_enabled = "freetype" in env.module_list
|
||||||
msdfgen_enabled = env.module_check_dependencies("text_server_adv", ["msdfgen"], True)
|
msdfgen_enabled = "msdfgen" in env.module_list
|
||||||
|
|
||||||
if env["builtin_harfbuzz"]:
|
if env["builtin_harfbuzz"]:
|
||||||
env_harfbuzz = env_modules.Clone()
|
env_harfbuzz = env_modules.Clone()
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
Import("env")
|
Import("env")
|
||||||
Import("env_modules")
|
Import("env_modules")
|
||||||
|
|
||||||
freetype_enabled = env.module_check_dependencies("text_server_fb", ["freetype"], True)
|
freetype_enabled = "freetype" in env.module_list
|
||||||
msdfgen_enabled = env.module_check_dependencies("text_server_fb", ["msdfgen"], True)
|
msdfgen_enabled = "msdfgen" in env.module_list
|
||||||
|
|
||||||
env_text_server_fb = env_modules.Clone()
|
env_text_server_fb = env_modules.Clone()
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
def can_build(env, platform):
|
def can_build(env, platform):
|
||||||
if env["arch"].startswith("rv"):
|
if env["arch"].startswith("rv"):
|
||||||
return False
|
return False
|
||||||
return env.module_check_dependencies("theora", ["ogg", "vorbis"])
|
env.module_add_dependencies("theora", ["ogg", "vorbis"])
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def configure(env):
|
def configure(env):
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
def can_build(env, platform):
|
def can_build(env, platform):
|
||||||
return env.module_check_dependencies("vorbis", ["ogg"])
|
env.module_add_dependencies("vorbis", ["ogg"])
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def configure(env):
|
def configure(env):
|
||||||
|
|
Loading…
Reference in New Issue