Update to new recipe system (S++ 2.0).
This commit is contained in:
100
SConscript
100
SConscript
@@ -1,6 +1,6 @@
|
||||
|
||||
import copy
|
||||
import enum
|
||||
import json
|
||||
import os
|
||||
import psutil
|
||||
import sys
|
||||
@@ -24,6 +24,7 @@ class _Dependency:
|
||||
version_spec: _VersionSpec
|
||||
recipe = None
|
||||
depdeps: list = []
|
||||
cook_result: dict = {}
|
||||
|
||||
class _Target:
|
||||
builder = None
|
||||
@@ -46,13 +47,18 @@ def _find_recipe(env: Environment, recipe_name: str):
|
||||
raise Exception(f'Could not find recipe {recipe_name}.')
|
||||
spec = importlib.util.spec_from_file_location(recipe_name, source_file)
|
||||
recipe = importlib.util.module_from_spec(spec)
|
||||
recipe.env = env
|
||||
spec.loader.exec_module(recipe)
|
||||
env['SPP_RECIPES'][recipe_name] = recipe
|
||||
return recipe
|
||||
|
||||
def _cook(env: Environment, recipe_name: str, *args, **kwargs):
|
||||
recipe = _find_recipe(env, recipe_name)
|
||||
return recipe.cook(env, *args, **kwargs)
|
||||
def _cook(env: Environment, recipe_name: str):
|
||||
dependency = env['SPP_DEPENDENCIES'].get(recipe_name)
|
||||
if not dependency:
|
||||
raise Exception(f'Cannot cook {recipe_name} as it was not listed as a dependency.')
|
||||
if not dependency.cook_result:
|
||||
dependency.cook_result = dependency.recipe.cook(env, dependency.version)
|
||||
return dependency.cook_result
|
||||
|
||||
def _module(env: Environment, file: str):
|
||||
return SConscript(file, exports = 'env', variant_dir = env['VARIANT_DIR'], src_dir = '.')
|
||||
@@ -83,7 +89,14 @@ def _inject_dependency(dependency, kwargs: dict, add_sources: bool = True) -> No
|
||||
for inner_dependency in dependency['DEPENDENCIES']:
|
||||
_inject_dependency(inner_dependency, kwargs, False)
|
||||
elif isinstance(dependency, _Dependency):
|
||||
pass
|
||||
if not dependency.cook_result:
|
||||
dependency.cook_result = dependency.recipe.cook(env, dependency.version)
|
||||
_inject_list(kwargs, dependency.cook_result, 'CPPPATH')
|
||||
_inject_list(kwargs, dependency.cook_result, 'CPPDEFINES')
|
||||
_inject_list(kwargs, dependency.cook_result, 'LIBPATH')
|
||||
_inject_list(kwargs, dependency.cook_result, 'LIBS')
|
||||
for depdep in dependency.depdeps:
|
||||
_inject_dependency(depdep, kwargs)
|
||||
|
||||
def _rglob(env: Environment, root_path: str, pattern: str, **kwargs):
|
||||
result_nodes = []
|
||||
@@ -95,6 +108,14 @@ def _rglob(env: Environment, root_path: str, pattern: str, **kwargs):
|
||||
result_nodes.extend(env.Glob(f'{path}/{pattern}', **kwargs))
|
||||
return sorted(result_nodes)
|
||||
|
||||
def _deps_from_json(env: Environment, deps: dict) -> dict:
|
||||
for _, dep in deps.items():
|
||||
if 'min' in dep and isinstance(dep['min'], list):
|
||||
dep['min'] = tuple(dep['min'])
|
||||
if 'max' in dep and isinstance(dep['max'], list):
|
||||
dep['max'] = tuple(dep['max'])
|
||||
return deps
|
||||
|
||||
def _make_interface(env: Environment, dependencies: list = []):
|
||||
kwargs = {}
|
||||
for dependency in dependencies:
|
||||
@@ -104,7 +125,7 @@ def _make_interface(env: Environment, dependencies: list = []):
|
||||
'CPPDEFINES': kwargs.get('CPPDEFINES', [])
|
||||
}
|
||||
|
||||
def _lib_filename(name: str, type: str = 'static') -> str:
|
||||
def _lib_filename(env: Environment, name: str, type: str = 'static') -> str:
|
||||
# TODO: windows
|
||||
ext = {
|
||||
'static': 'a',
|
||||
@@ -112,12 +133,14 @@ def _lib_filename(name: str, type: str = 'static') -> str:
|
||||
}[type]
|
||||
return f'lib{name}.{ext}'
|
||||
|
||||
def _find_lib(env: Environment, name: str, paths: 'list[str]', type : str = 'static'):
|
||||
def _find_lib(env: Environment, name: str, paths: 'list[str]', type : str = 'static', allow_fail: bool = False):
|
||||
for path in paths:
|
||||
lib_path = os.path.join(path, _lib_filename(name, type))
|
||||
lib_path = os.path.join(path, _lib_filename(env, name, type))
|
||||
if os.path.exists(lib_path):
|
||||
return lib_path
|
||||
return None
|
||||
if allow_fail:
|
||||
return None
|
||||
raise Exception(f'Could not find library with name {name} in paths: "{",".join(paths)}".')
|
||||
|
||||
def _error(env: Environment, message: str):
|
||||
print(message, file=sys.stderr)
|
||||
@@ -177,12 +200,12 @@ def _add_dependency(env: Environment, name: str, version_spec: _VersionSpec) ->
|
||||
def _sort_versions(versions: list) -> None:
|
||||
import functools
|
||||
def _compare(left, right):
|
||||
if left[0] != right[0]:
|
||||
return right[0] - left[0]
|
||||
elif left[1] != right[1]:
|
||||
return right[1] - left[1]
|
||||
if left < right:
|
||||
return 1
|
||||
elif left == right:
|
||||
return 0
|
||||
else:
|
||||
return right[2] - left[2]
|
||||
return -1
|
||||
versions.sort(key=functools.cmp_to_key(_compare))
|
||||
|
||||
def _version_matches(version, version_spec: _VersionSpec) -> bool:
|
||||
@@ -225,12 +248,6 @@ def _wrap_builder(builder, is_lib: bool = False):
|
||||
kwargs['LIBPATH'] = copy.copy(env['LIBPATH'])
|
||||
if 'LIBS' not in kwargs and 'LIBS' in env:
|
||||
kwargs['LIBS'] = copy.copy(env['LIBS'])
|
||||
if 'LIBS' in kwargs:
|
||||
libs_copy = list(kwargs['LIBS'])
|
||||
for lib in libs_copy:
|
||||
if isinstance(lib, str) and os.path.isabs(lib):
|
||||
kwargs['LIBS'].remove(lib)
|
||||
kwargs['source'].append(lib)
|
||||
if 'source' in kwargs:
|
||||
source = kwargs['source']
|
||||
if not isinstance(source, list):
|
||||
@@ -249,6 +266,8 @@ def _wrap_builder(builder, is_lib: bool = False):
|
||||
target.kwargs = kwargs
|
||||
target.dependencies = target_dependencies
|
||||
env.Append(SPP_TARGETS = [target])
|
||||
if not target.dependencies:
|
||||
_build_target(target)
|
||||
return target
|
||||
return _wrapped
|
||||
|
||||
@@ -273,16 +292,47 @@ def _wrap_depends(depends):
|
||||
depends(dependant, dependency)
|
||||
return _wrapped
|
||||
|
||||
def _build_target(target: _Target):
|
||||
for dependency in target.dependencies:
|
||||
_inject_dependency(dependency, target.kwargs)
|
||||
if 'LIBS' in target.kwargs:
|
||||
libs_copy = list(target.kwargs['LIBS'])
|
||||
for lib in libs_copy:
|
||||
if isinstance(lib, str) and os.path.isabs(lib):
|
||||
target.kwargs['LIBS'].remove(lib)
|
||||
target.kwargs['source'].append(lib)
|
||||
elif isinstance(lib, _Target):
|
||||
if not lib.target:
|
||||
_build_target(lib)
|
||||
target.kwargs['LIBS'].remove(lib)
|
||||
target.kwargs['LIBS'].append(lib.target)
|
||||
target.target = target.builder(*target.args, **target.kwargs)
|
||||
|
||||
def _version_to_string(version) -> str:
|
||||
return '.'.join([str(v) for v in version])
|
||||
|
||||
def _finalize(env: Environment):
|
||||
version_requirements = {dep.name: {
|
||||
'min': dep.version_spec.minimum_version and _version_to_string(dep.version_spec.minimum_version),
|
||||
'max': dep.version_spec.maximum_version and _version_to_string(dep.version_spec.maximum_version),
|
||||
} for dep in env['SPP_DEPENDENCIES'].values()}
|
||||
env['_SPP_DEPENDENCIES_OKAY'] = False
|
||||
while not env['_SPP_DEPENDENCIES_OKAY']:
|
||||
env['_SPP_DEPENDENCIES_OKAY'] = True
|
||||
for dependency in list(env['SPP_DEPENDENCIES'].values()):
|
||||
_find_version(env, dependency)
|
||||
if not dependency.version:
|
||||
_find_version(env, dependency)
|
||||
with open('cache/versions.json', 'w') as f:
|
||||
json.dump({
|
||||
'requirements': version_requirements,
|
||||
'selected': {
|
||||
dep.name: _version_to_string(dep.version) for dep in env['SPP_DEPENDENCIES'].values()
|
||||
}
|
||||
}, f)
|
||||
|
||||
|
||||
for target in env['SPP_TARGETS']:
|
||||
for dependency in target.dependencies:
|
||||
_inject_dependency(dependency, target.kwargs)
|
||||
target.target = target.builder(*target.args, **target.kwargs)
|
||||
_build_target(target)
|
||||
for target in env['SPP_DEFAULT_TARGETS']:
|
||||
env.Default(target.target)
|
||||
|
||||
@@ -581,7 +631,9 @@ elif env['COMPILER_FAMILY'] == 'clang':
|
||||
env.AddMethod(_cook, 'Cook')
|
||||
env.AddMethod(_parse_lib_conf, 'ParseLibConf')
|
||||
env.AddMethod(_rglob, 'RGlob')
|
||||
env.AddMethod(_deps_from_json, 'DepsFromJson')
|
||||
env.AddMethod(_make_interface, 'MakeInterface')
|
||||
env.AddMethod(_lib_filename, 'LibFilename')
|
||||
env.AddMethod(_find_lib, 'FindLib')
|
||||
env.AddMethod(_error, 'Error')
|
||||
env.AddMethod(_wrap_builder(env.Library, is_lib = True), 'Library')
|
||||
|
||||
Reference in New Issue
Block a user