summaryrefslogtreecommitdiff
path: root/methods.py
diff options
context:
space:
mode:
Diffstat (limited to 'methods.py')
-rw-r--r--methods.py110
1 files changed, 89 insertions, 21 deletions
diff --git a/methods.py b/methods.py
index 15eb82ae74..6f1e7a7279 100644
--- a/methods.py
+++ b/methods.py
@@ -6,9 +6,11 @@ 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 SCons import Node
+from SCons.Script import Action
+from SCons.Script import ARGUMENTS
from SCons.Script import Glob
+from SCons.Variables.BoolVariable import _text2bool
from platform_methods import run_in_subprocess
@@ -145,34 +147,97 @@ def parse_cg_file(fname, uniforms, sizes, conditionals):
fs.close()
-def detect_modules(at_path):
- module_list = OrderedDict() # name : path
+def get_cmdline_bool(option, default):
+ """We use `ARGUMENTS.get()` to check if options were manually overridden on the command line,
+ and SCons' _text2bool helper to convert them to booleans, otherwise they're handled as strings.
+ """
+ cmdline_val = ARGUMENTS.get(option)
+ if cmdline_val is not None:
+ return _text2bool(cmdline_val)
+ else:
+ return default
+
+
+def detect_modules(search_path, recursive=False):
+ """Detects and collects a list of C++ modules at specified path
+
+ `search_path` - a directory path containing modules. The path may point to
+ a single module, which may have other nested modules. A module must have
+ "register_types.h", "SCsub", "config.py" files created to be detected.
- modules_glob = os.path.join(at_path, "*")
- files = glob.glob(modules_glob)
- files.sort() # so register_module_types does not change that often, and also plugins are registered in alphabetic order
+ `recursive` - if `True`, then all subdirectories are searched for modules as
+ specified by the `search_path`, otherwise collects all modules under the
+ `search_path` directory. If the `search_path` is a module, it is collected
+ in all cases.
- for x in files:
- if not is_module(x):
- continue
- name = os.path.basename(x)
- path = x.replace("\\", "/") # win32
- module_list[name] = path
+ Returns an `OrderedDict` with module names as keys, and directory paths as
+ values. If a path is relative, then it is a built-in module. If a path is
+ absolute, then it is a custom module collected outside of the engine source.
+ """
+ modules = OrderedDict()
+
+ def add_module(path):
+ module_name = os.path.basename(path)
+ module_path = path.replace("\\", "/") # win32
+ modules[module_name] = module_path
+
+ def is_engine(path):
+ # Prevent recursively detecting modules in self and other
+ # Godot sources when using `custom_modules` build option.
+ version_path = os.path.join(path, "version.py")
+ if os.path.exists(version_path):
+ with open(version_path) as f:
+ if 'short_name = "godot"' in f.read():
+ return True
+ return False
- return module_list
+ def get_files(path):
+ files = glob.glob(os.path.join(path, "*"))
+ # Sort so that `register_module_types` does not change that often,
+ # and plugins are registered in alphabetic order as well.
+ files.sort()
+ return files
+
+ if not recursive:
+ if is_module(search_path):
+ add_module(search_path)
+ for path in get_files(search_path):
+ if is_engine(path):
+ continue
+ if is_module(path):
+ add_module(path)
+ else:
+ to_search = [search_path]
+ while to_search:
+ path = to_search.pop()
+ if is_module(path):
+ add_module(path)
+ for child in get_files(path):
+ if not os.path.isdir(child):
+ continue
+ if is_engine(child):
+ continue
+ to_search.insert(0, child)
+ return modules
def is_module(path):
- return os.path.isdir(path) and os.path.exists(os.path.join(path, "SCsub"))
+ if not os.path.isdir(path):
+ return False
+ must_exist = ["register_types.h", "SCsub", "config.py"]
+ for f in must_exist:
+ if not os.path.exists(os.path.join(path, f)):
+ return False
+ return True
-def write_modules(module_list):
+def write_modules(modules):
includes_cpp = ""
preregister_cpp = ""
register_cpp = ""
unregister_cpp = ""
- for name, path in module_list.items():
+ for name, path in modules.items():
try:
with open(os.path.join(path, "register_types.h")):
includes_cpp += '#include "' + path + '/register_types.h"\n'
@@ -230,8 +295,6 @@ def convert_custom_modules_path(path):
raise ValueError(err_msg % "point to an existing directory.")
if path == os.path.realpath("modules"):
raise ValueError(err_msg % "be a directory other than built-in `modules` directory.")
- if is_module(path):
- raise ValueError(err_msg % "point to a directory with modules, not a single module.")
return path
@@ -271,7 +334,7 @@ def use_windows_spawn_fix(self, platform=None):
# On Windows, due to the limited command line length, when creating a static library
# from a very high number of objects SCons will invoke "ar" once per object file;
# that makes object files with same names to be overwritten so the last wins and
- # the library looses symbols defined by overwritten objects.
+ # the library loses symbols defined by overwritten objects.
# By enabling quick append instead of the default mode (replacing), libraries will
# got built correctly regardless the invocation strategy.
# Furthermore, since SCons will rebuild the library from scratch when an object file
@@ -415,7 +478,7 @@ def detect_visual_c_compiler_version(tools_env):
# and not scons setup environment (env)... so make sure you call the right environment on it or it will fail to detect
# the proper vc version that will be called
- # There is no flag to give to visual c compilers to set the architecture, ie scons bits argument (32,64,ARM etc)
+ # There is no flag to give to visual c compilers to set the architecture, i.e. scons bits argument (32,64,ARM etc)
# There are many different cl.exe files that are run, and each one compiles & links to a different architecture
# As far as I know, the only way to figure out what compiler will be run when Scons calls cl.exe via Program()
# is to check the PATH variable and figure out which one will be called first. Code below does that and returns:
@@ -570,7 +633,7 @@ def generate_vs_project(env, num_jobs):
'call "' + batch_file + '" !plat!',
]
- # windows allows us to have spaces in paths, so we need
+ # Windows allows us to have spaces in paths, so we need
# to double quote off the directory. However, the path ends
# in a backslash, so we need to remove this, lest it escape the
# last double quote off, confusing MSBuild
@@ -583,6 +646,9 @@ def generate_vs_project(env, num_jobs):
"-j%s" % num_jobs,
]
+ if env["tests"]:
+ common_build_postfix.append("tests=yes")
+
if env["custom_modules"]:
common_build_postfix.append("custom_modules=%s" % env["custom_modules"])
@@ -595,6 +661,8 @@ def generate_vs_project(env, num_jobs):
add_to_vs_project(env, env.modules_sources)
add_to_vs_project(env, env.scene_sources)
add_to_vs_project(env, env.servers_sources)
+ if env["tests"]:
+ add_to_vs_project(env, env.tests_sources)
add_to_vs_project(env, env.editor_sources)
for header in glob_recursive("**/*.h"):