2
0
Эх сурвалжийг харах

[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.
Fabio Alessandrelli 3 жил өмнө
parent
commit
951a1016d3

+ 7 - 9
SConstruct

@@ -138,6 +138,7 @@ env_base.__class__.CommandNoCache = methods.CommandNoCache
 env_base.__class__.Run = methods.Run
 env_base.__class__.disable_warnings = methods.disable_warnings
 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["x86_libtheora_opt_gcc"] = False
@@ -699,6 +700,7 @@ if selected_platform in platform_list:
     sys.modules.pop("detect")
 
     modules_enabled = OrderedDict()
+    env.module_dependencies = {}
     env.module_icons_paths = []
     env.doc_class_path = {}
 
@@ -710,6 +712,10 @@ if selected_platform in platform_list:
         import config
 
         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)
             # Get doc classes paths (if present)
             try:
@@ -732,6 +738,7 @@ if selected_platform in platform_list:
         sys.modules.pop("config")
 
     env.module_list = modules_enabled
+    methods.sort_module_list(env)
 
     methods.update_version(env.module_version_string)
 
@@ -794,15 +801,6 @@ if selected_platform in platform_list:
     if env["minizip"]:
         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"]:
         methods.no_verbose(sys, env)
 

+ 39 - 7
methods.py

@@ -1,5 +1,6 @@
 import os
 import re
+import sys
 import glob
 import subprocess
 from collections import OrderedDict
@@ -336,7 +337,20 @@ def disable_module(self):
     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,
     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).
     """
     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)
         if not opt in self or not self[opt]:
             missing_deps.append(dep)
 
     if missing_deps != []:
-        if not silent:
-            print(
-                "Disabling '{}' module as the following dependencies are not satisfied: {}".format(
-                    module, ", ".join(missing_deps)
-                )
+        print(
+            "Disabling '{}' module as the following dependencies are not satisfied: {}".format(
+                module, ", ".join(missing_deps)
             )
+        )
         return False
     else:
         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):
 
     if os.name != "nt":

+ 1 - 0
modules/gdscript/config.py

@@ -1,4 +1,5 @@
 def can_build(env, platform):
+    env.module_add_dependencies("gdscript", ["jsonrpc", "websocket"], True)
     return True
 
 

+ 2 - 1
modules/msdfgen/config.py

@@ -1,5 +1,6 @@
 def can_build(env, platform):
-    return env.module_check_dependencies("msdfgen", ["freetype"])
+    env.module_add_dependencies("msdfgen", ["freetype"])
+    return True
 
 
 def configure(env):

+ 2 - 2
modules/text_server_adv/SCsub

@@ -36,8 +36,8 @@ def make_icu_data(target, source, env):
 # Thirdparty source files
 
 thirdparty_obj = []
-freetype_enabled = env.module_check_dependencies("text_server_adv", ["freetype"], True)
-msdfgen_enabled = env.module_check_dependencies("text_server_adv", ["msdfgen"], True)
+freetype_enabled = "freetype" in env.module_list
+msdfgen_enabled = "msdfgen" in env.module_list
 
 if env["builtin_harfbuzz"]:
     env_harfbuzz = env_modules.Clone()

+ 2 - 2
modules/text_server_fb/SCsub

@@ -3,8 +3,8 @@
 Import("env")
 Import("env_modules")
 
-freetype_enabled = env.module_check_dependencies("text_server_fb", ["freetype"], True)
-msdfgen_enabled = env.module_check_dependencies("text_server_fb", ["msdfgen"], True)
+freetype_enabled = "freetype" in env.module_list
+msdfgen_enabled = "msdfgen" in env.module_list
 
 env_text_server_fb = env_modules.Clone()
 

+ 2 - 1
modules/theora/config.py

@@ -1,7 +1,8 @@
 def can_build(env, platform):
     if env["arch"].startswith("rv"):
         return False
-    return env.module_check_dependencies("theora", ["ogg", "vorbis"])
+    env.module_add_dependencies("theora", ["ogg", "vorbis"])
+    return True
 
 
 def configure(env):

+ 2 - 1
modules/vorbis/config.py

@@ -1,5 +1,6 @@
 def can_build(env, platform):
-    return env.module_check_dependencies("vorbis", ["ogg"])
+    env.module_add_dependencies("vorbis", ["ogg"])
+    return True
 
 
 def configure(env):