Some more work on the new dependency resolution system.
This commit is contained in:
		
							parent
							
								
									17ee9777ed
								
							
						
					
					
						commit
						6f83b68788
					
				
							
								
								
									
										200
									
								
								SConscript
									
									
									
									
									
								
							
							
						
						
									
										200
									
								
								SConscript
									
									
									
									
									
								
							@ -1,26 +1,40 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import copy
 | 
					import copy
 | 
				
			||||||
 | 
					import enum
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
import psutil
 | 
					import psutil
 | 
				
			||||||
import sys
 | 
					import sys
 | 
				
			||||||
import time
 | 
					import time
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import SCons.Script
 | 
					
 | 
				
			||||||
import SCons.Warnings
 | 
					class _VersionSpec:
 | 
				
			||||||
 | 
					    minimum_version = None
 | 
				
			||||||
 | 
					    maximum_version = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __init__(self, minimum_version = None, maximum_version = None):
 | 
				
			||||||
 | 
					        self.minimum_version = minimum_version
 | 
				
			||||||
 | 
					        self.maximum_version = maximum_version
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __str__(self):
 | 
				
			||||||
 | 
					        return f'Min: {self.minimum_version}, Max: {self.maximum_version}'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class _Dependency:
 | 
					class _Dependency:
 | 
				
			||||||
    name: str = ''
 | 
					    name: str = ''
 | 
				
			||||||
    version: str = ''
 | 
					    version = None
 | 
				
			||||||
 | 
					    version_spec: _VersionSpec
 | 
				
			||||||
 | 
					    recipe = None
 | 
				
			||||||
 | 
					    depdeps: list = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class _Target:
 | 
					class _Target:
 | 
				
			||||||
    builder = None
 | 
					    builder = None
 | 
				
			||||||
    target = None
 | 
					 | 
				
			||||||
    source = None
 | 
					 | 
				
			||||||
    args: list = []
 | 
					    args: list = []
 | 
				
			||||||
    kwargs: dict = {}
 | 
					    kwargs: dict = {}
 | 
				
			||||||
    dependencies: list = []
 | 
					    dependencies: list = []
 | 
				
			||||||
 | 
					    target = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _cook(env: Environment, recipe_name: str, *args, **kwargs):
 | 
					def _find_recipe(env: Environment, recipe_name: str):
 | 
				
			||||||
 | 
					    if recipe_name in env['SPP_RECIPES']:
 | 
				
			||||||
 | 
					        return env['SPP_RECIPES'][recipe_name]
 | 
				
			||||||
    import importlib.util
 | 
					    import importlib.util
 | 
				
			||||||
    source_file = None
 | 
					    source_file = None
 | 
				
			||||||
    for folder in env['RECIPES_FOLDERS']:
 | 
					    for folder in env['RECIPES_FOLDERS']:
 | 
				
			||||||
@ -33,6 +47,11 @@ def _cook(env: Environment, recipe_name: str, *args, **kwargs):
 | 
				
			|||||||
    spec = importlib.util.spec_from_file_location(recipe_name, source_file)
 | 
					    spec = importlib.util.spec_from_file_location(recipe_name, source_file)
 | 
				
			||||||
    recipe = importlib.util.module_from_spec(spec)
 | 
					    recipe = importlib.util.module_from_spec(spec)
 | 
				
			||||||
    spec.loader.exec_module(recipe)
 | 
					    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)
 | 
					    return recipe.cook(env, *args, **kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _module(env: Environment, file: str):
 | 
					def _module(env: Environment, file: str):
 | 
				
			||||||
@ -63,6 +82,8 @@ def _inject_dependency(dependency, kwargs: dict, add_sources: bool = True) -> No
 | 
				
			|||||||
        if 'DEPENDENCIES' in dependency:
 | 
					        if 'DEPENDENCIES' in dependency:
 | 
				
			||||||
            for inner_dependency in dependency['DEPENDENCIES']:
 | 
					            for inner_dependency in dependency['DEPENDENCIES']:
 | 
				
			||||||
                _inject_dependency(inner_dependency, kwargs, False)
 | 
					                _inject_dependency(inner_dependency, kwargs, False)
 | 
				
			||||||
 | 
					    elif isinstance(dependency, _Dependency):
 | 
				
			||||||
 | 
					        pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _rglob(env: Environment, root_path: str, pattern: str, **kwargs):
 | 
					def _rglob(env: Environment, root_path: str, pattern: str, **kwargs):
 | 
				
			||||||
    result_nodes = []
 | 
					    result_nodes = []
 | 
				
			||||||
@ -102,23 +123,99 @@ def _error(env: Environment, message: str):
 | 
				
			|||||||
    print(message, file=sys.stderr)
 | 
					    print(message, file=sys.stderr)
 | 
				
			||||||
    env.Exit(1)
 | 
					    env.Exit(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _build_action(target, source, env):
 | 
					def _find_common_depenency_version(name: str, versionA: _VersionSpec, versionB: _VersionSpec) -> _VersionSpec:
 | 
				
			||||||
    the_target = env['_target']
 | 
					    result_version = _VersionSpec()
 | 
				
			||||||
    the_target.builder.method(env=env, *the_target.args, **the_target.kwargs)
 | 
					    if versionA.minimum_version is not None:
 | 
				
			||||||
 | 
					        if versionB.minimum_version is not None:
 | 
				
			||||||
 | 
					            result_version.minimum_version = max(versionA.minimum_version, versionB.minimum_version)
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            result_version.minimum_version = versionA.minimum_version
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        result_version.minimum_version = versionB.minimum_version
 | 
				
			||||||
 | 
					
 | 
				
			||||||
_Builder = Builder(action=Action(_build_action, None))
 | 
					    if versionA.maximum_version is not None:
 | 
				
			||||||
 | 
					        if versionB.maximum_version is not None:
 | 
				
			||||||
 | 
					            result_version.maximum_version = min(versionA.maximum_version, versionB.maximum_version)
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            result_version.maximum_version = versionA.maximum_version
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        result_version.maximum_version = versionB.maximum_version
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _add_dependency(name: str, version: str) -> _Dependency:
 | 
					    if result_version.minimum_version is not None and result_version.maximum_version is not None \
 | 
				
			||||||
 | 
					        and (result_version.minimum_version > result_version.maximum_version):
 | 
				
			||||||
 | 
					        return None
 | 
				
			||||||
 | 
					    return result_version
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def _parse_version_spec(version_spec: dict) -> _VersionSpec:
 | 
				
			||||||
 | 
					    return _VersionSpec(version_spec.get('min'), version_spec.get('max'))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def _can_add_dependency(env: Environment, name: str, version_spec: _VersionSpec) -> bool:
 | 
				
			||||||
 | 
					    if name not in env['SPP_DEPENDENCIES']:
 | 
				
			||||||
 | 
					        return True
 | 
				
			||||||
 | 
					    dependency = env['SPP_DEPENDENCIES'][name]
 | 
				
			||||||
 | 
					    common_version_spec = _find_common_depenency_version(name, dependency.version_spec, version_spec)
 | 
				
			||||||
 | 
					    return common_version_spec is not None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def _add_dependency(env: Environment, name: str, version_spec: _VersionSpec) -> _Dependency:
 | 
				
			||||||
 | 
					    if name in env['SPP_DEPENDENCIES']:
 | 
				
			||||||
 | 
					        dependency = env['SPP_DEPENDENCIES'][name]
 | 
				
			||||||
 | 
					        common_version_spec = _find_common_depenency_version(name, dependency.version_spec, version_spec)
 | 
				
			||||||
 | 
					        if common_version_spec is None:
 | 
				
			||||||
 | 
					            raise Exception(f'Incompatible versions detected for {name}: {dependency.version_spec} and {version_spec}')
 | 
				
			||||||
 | 
					        if dependency.version_spec != common_version_spec:
 | 
				
			||||||
 | 
					            env['_SPP_DEPENDENCIES_OKAY'] = False
 | 
				
			||||||
 | 
					            dependency.version_spec = common_version_spec
 | 
				
			||||||
 | 
					        return dependency
 | 
				
			||||||
    dependency = _Dependency()
 | 
					    dependency = _Dependency()
 | 
				
			||||||
    dependency.name = name
 | 
					    dependency.name = name
 | 
				
			||||||
    dependency.version = version
 | 
					    dependency.version_spec = version_spec
 | 
				
			||||||
 | 
					    dependency.recipe = _find_recipe(env, name)
 | 
				
			||||||
 | 
					    env['SPP_DEPENDENCIES'][name] = dependency
 | 
				
			||||||
 | 
					    env['_SPP_DEPENDENCIES_OKAY'] = False
 | 
				
			||||||
    return dependency
 | 
					    return dependency
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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]
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            return right[2] - left[2]
 | 
				
			||||||
 | 
					    versions.sort(key=functools.cmp_to_key(_compare))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def _version_matches(version, version_spec: _VersionSpec) -> bool:
 | 
				
			||||||
 | 
					    if version_spec.minimum_version is not None and version < version_spec.minimum_version:
 | 
				
			||||||
 | 
					        return False
 | 
				
			||||||
 | 
					    if version_spec.maximum_version is not None and version > version_spec.maximum_version:
 | 
				
			||||||
 | 
					        return False
 | 
				
			||||||
 | 
					    return True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def _find_version(env: Environment, dependency: _Dependency):
 | 
				
			||||||
 | 
					    versions = dependency.recipe.versions(env, update=False)
 | 
				
			||||||
 | 
					    _sort_versions(versions)
 | 
				
			||||||
 | 
					    for version in versions:
 | 
				
			||||||
 | 
					        if _version_matches(version, dependency.version_spec):
 | 
				
			||||||
 | 
					            canadd = True
 | 
				
			||||||
 | 
					            for depname, depspec in dependency.recipe.dependencies(env, version).items():
 | 
				
			||||||
 | 
					                if not _can_add_dependency(env, depname, _parse_version_spec(depspec)):
 | 
				
			||||||
 | 
					                    canadd = False
 | 
				
			||||||
 | 
					                    break
 | 
				
			||||||
 | 
					            if canadd:
 | 
				
			||||||
 | 
					                depdeps = []
 | 
				
			||||||
 | 
					                for depname, depspec in dependency.recipe.dependencies(env, version).items():
 | 
				
			||||||
 | 
					                    depdeps.append(_add_dependency(env, depname, _parse_version_spec(depspec)))
 | 
				
			||||||
 | 
					                dependency.version = version
 | 
				
			||||||
 | 
					                dependency.depdeps = depdeps
 | 
				
			||||||
 | 
					                return
 | 
				
			||||||
 | 
					    raise Exception(f'Could not find a suitable version for dependency {dependency.name}.')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _wrap_builder(builder, is_lib: bool = False):
 | 
					def _wrap_builder(builder, is_lib: bool = False):
 | 
				
			||||||
    def _wrapped(env, dependencies = {}, *args, **kwargs):
 | 
					    def _wrapped(env, dependencies = {}, *args, **kwargs):
 | 
				
			||||||
        target_dependencies = []
 | 
					        target_dependencies = []
 | 
				
			||||||
        for name, version in dependencies.items():
 | 
					        for name, version_spec in dependencies.items():
 | 
				
			||||||
            target_dependencies.append(_add_dependency(name, version))
 | 
					            target_dependencies.append(_add_dependency(env, name, _parse_version_spec(version_spec)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if 'CPPPATH' not in kwargs:
 | 
					        if 'CPPPATH' not in kwargs:
 | 
				
			||||||
            kwargs['CPPPATH'] = copy.copy(env['CPPPATH'])
 | 
					            kwargs['CPPPATH'] = copy.copy(env['CPPPATH'])
 | 
				
			||||||
@ -134,22 +231,32 @@ def _wrap_builder(builder, is_lib: bool = False):
 | 
				
			|||||||
                if isinstance(lib, str) and os.path.isabs(lib):
 | 
					                if isinstance(lib, str) and os.path.isabs(lib):
 | 
				
			||||||
                    kwargs['LIBS'].remove(lib)
 | 
					                    kwargs['LIBS'].remove(lib)
 | 
				
			||||||
                    kwargs['source'].append(lib)
 | 
					                    kwargs['source'].append(lib)
 | 
				
			||||||
 | 
					        if 'source' in kwargs:
 | 
				
			||||||
 | 
					            source = kwargs['source']
 | 
				
			||||||
 | 
					            if not isinstance(source, list):
 | 
				
			||||||
 | 
					                source = [source]
 | 
				
			||||||
 | 
					            new_source = []
 | 
				
			||||||
 | 
					            for src in source:
 | 
				
			||||||
 | 
					                if isinstance(src, str):
 | 
				
			||||||
 | 
					                    new_source.append(env.Entry(src))
 | 
				
			||||||
 | 
					                else:
 | 
				
			||||||
 | 
					                    new_source.append(src)
 | 
				
			||||||
 | 
					            kwargs['source'] = new_source
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        target = _Target()
 | 
					        target = _Target()
 | 
				
			||||||
        target.target = kwargs.get('target', None)
 | 
					 | 
				
			||||||
        target.source = kwargs.get('source', None)
 | 
					 | 
				
			||||||
        target.builder = builder
 | 
					        target.builder = builder
 | 
				
			||||||
        target.args = args
 | 
					        target.args = args
 | 
				
			||||||
        target.kwargs = kwargs
 | 
					        target.kwargs = kwargs
 | 
				
			||||||
        target.dependencies = target_dependencies
 | 
					        target.dependencies = target_dependencies
 | 
				
			||||||
        # return _Builder(target=kwargs.get('target', None), source=kwargs.get('source', None), env=env, _target=target)
 | 
					        env.Append(SPP_TARGETS = [target])
 | 
				
			||||||
        return builder(*args, **kwargs)
 | 
					        return target
 | 
				
			||||||
    return _wrapped
 | 
					    return _wrapped
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _wrap_default(default):
 | 
					def _wrap_default(default):
 | 
				
			||||||
    print(default)
 | 
					 | 
				
			||||||
    def _wrapped(env, arg):
 | 
					    def _wrapped(env, arg):
 | 
				
			||||||
        if isinstance(arg, dict) and '_target' in arg:
 | 
					        if isinstance(arg, _Target):
 | 
				
			||||||
 | 
					            env.Append(SPP_DEFAULT_TARGETS = [arg])
 | 
				
			||||||
 | 
					        elif isinstance(arg, dict) and '_target' in arg:
 | 
				
			||||||
            default(arg['_target'])
 | 
					            default(arg['_target'])
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            default(arg)
 | 
					            default(arg)
 | 
				
			||||||
@ -157,13 +264,28 @@ def _wrap_default(default):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
def _wrap_depends(depends):
 | 
					def _wrap_depends(depends):
 | 
				
			||||||
    def _wrapped(env, dependant, dependency):
 | 
					    def _wrapped(env, dependant, dependency):
 | 
				
			||||||
        if isinstance(dependant, dict) and '_target' in dependant:
 | 
					        if isinstance(dependant, _Target) or isinstance(dependency, _Target):
 | 
				
			||||||
 | 
					            env.Append(SPP_TARGET_DEPENDENCIES = [(dependant, dependency)])
 | 
				
			||||||
 | 
					        elif isinstance(dependant, dict) and '_target' in dependant:
 | 
				
			||||||
            dependant = dependant['_target']
 | 
					            dependant = dependant['_target']
 | 
				
			||||||
        if isinstance(dependency, dict) and '_target' in dependency:
 | 
					        elif isinstance(dependency, dict) and '_target' in dependency:
 | 
				
			||||||
            dependency = dependency['_target']
 | 
					            dependency = dependency['_target']
 | 
				
			||||||
        depends(dependant, dependency)
 | 
					        depends(dependant, dependency)
 | 
				
			||||||
    return _wrapped
 | 
					    return _wrapped
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def _finalize(env: Environment):
 | 
				
			||||||
 | 
					    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)
 | 
				
			||||||
 | 
					    for target in env['SPP_TARGETS']:
 | 
				
			||||||
 | 
					        for dependency in target.dependencies:
 | 
				
			||||||
 | 
					            _inject_dependency(dependency, target.kwargs)
 | 
				
			||||||
 | 
					        target.target = target.builder(*target.args, **target.kwargs)
 | 
				
			||||||
 | 
					    for target in env['SPP_DEFAULT_TARGETS']:
 | 
				
			||||||
 | 
					        env.Default(target.target)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _get_fallback_cache_dir() -> str:
 | 
					def _get_fallback_cache_dir() -> str:
 | 
				
			||||||
    return Dir('#cache').abspath
 | 
					    return Dir('#cache').abspath
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -338,6 +460,13 @@ env.Append(CPPPATH = [])
 | 
				
			|||||||
env.Append(CPPDEFINES = [])
 | 
					env.Append(CPPDEFINES = [])
 | 
				
			||||||
env.Append(LINKFLAGS = [])
 | 
					env.Append(LINKFLAGS = [])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# init SPP environment variables
 | 
				
			||||||
 | 
					env['SPP_TARGETS'] = []
 | 
				
			||||||
 | 
					env['SPP_DEFAULT_TARGETS'] = []
 | 
				
			||||||
 | 
					env['SPP_TARGET_DEPENDENCIES'] = []
 | 
				
			||||||
 | 
					env['SPP_DEPENDENCIES'] = {}
 | 
				
			||||||
 | 
					env['SPP_RECIPES'] = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# create the cache dir
 | 
					# create the cache dir
 | 
				
			||||||
os.makedirs(env['CACHE_DIR'], exist_ok=True)
 | 
					os.makedirs(env['CACHE_DIR'], exist_ok=True)
 | 
				
			||||||
cache_gitignore = f'{env["CACHE_DIR"]}/.gitignore'
 | 
					cache_gitignore = f'{env["CACHE_DIR"]}/.gitignore'
 | 
				
			||||||
@ -467,6 +596,7 @@ env.AddMethod(_wrap_builder(env.UnityLibrary, is_lib = True), 'UnityLibrary')
 | 
				
			|||||||
env.AddMethod(_wrap_builder(env.UnityStaticLibrary, is_lib = True), 'UnityStaticLibrary')
 | 
					env.AddMethod(_wrap_builder(env.UnityStaticLibrary, is_lib = True), 'UnityStaticLibrary')
 | 
				
			||||||
env.AddMethod(_wrap_builder(env.UnitySharedLibrary, is_lib = True), 'UnitySharedLibrary')
 | 
					env.AddMethod(_wrap_builder(env.UnitySharedLibrary, is_lib = True), 'UnitySharedLibrary')
 | 
				
			||||||
env.AddMethod(_module, 'Module')
 | 
					env.AddMethod(_module, 'Module')
 | 
				
			||||||
 | 
					env.AddMethod(_finalize, 'Finalize')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if hasattr(env, 'Gch'):
 | 
					if hasattr(env, 'Gch'):
 | 
				
			||||||
    env.AddMethod(_wrap_builder(env.Gch), 'Gch')
 | 
					    env.AddMethod(_wrap_builder(env.Gch), 'Gch')
 | 
				
			||||||
@ -479,30 +609,4 @@ if dump_env:
 | 
				
			|||||||
    print(env.Dump())
 | 
					    print(env.Dump())
 | 
				
			||||||
    print('==== End Environment Dump =====')
 | 
					    print('==== End Environment Dump =====')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
_old_fn = SCons.Warnings.process_warn_strings
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import SCons.Util
 | 
					 | 
				
			||||||
class _FrameWrapper(SCons.Util.Proxy):
 | 
					 | 
				
			||||||
    def __init__(self, subject):
 | 
					 | 
				
			||||||
        super().__init__(subject)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def __getattr__(self, name):
 | 
					 | 
				
			||||||
        if name == 'retval':
 | 
					 | 
				
			||||||
            print('YAY')
 | 
					 | 
				
			||||||
        return super().__getattr__(name)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
SCons.Script.call_stack[0] = _FrameWrapper(SCons.Script.call_stack[0])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
print(SCons.Script.call_stack)
 | 
					 | 
				
			||||||
def _wrapped(*args, **kwargs):
 | 
					 | 
				
			||||||
    for target in SCons.Script.BUILD_TARGETS:
 | 
					 | 
				
			||||||
        if hasattr(target, 'abspath'):
 | 
					 | 
				
			||||||
            print('Target: ', target.abspath)
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            print('Target: ', target)
 | 
					 | 
				
			||||||
    _old_fn(*args, **kwargs)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
SCons.Warnings.process_warn_strings = _wrapped
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Return('env')
 | 
					Return('env')
 | 
				
			||||||
 | 
				
			|||||||
@ -7,7 +7,7 @@ from SCons.Script import *
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Import('env')
 | 
					Import('env')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _gitbranch(env: Environment, repo_name: str, remote_url: str, git_ref: str = "main") -> dict:
 | 
					def _clone(env: Environment, repo_name: str, remote_url: str):
 | 
				
			||||||
    repo_dir = os.path.join(env['CLONE_DIR'], 'git', repo_name, '_bare')
 | 
					    repo_dir = os.path.join(env['CLONE_DIR'], 'git', repo_name, '_bare')
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
        repo = Repo(repo_dir)
 | 
					        repo = Repo(repo_dir)
 | 
				
			||||||
@ -16,6 +16,10 @@ def _gitbranch(env: Environment, repo_name: str, remote_url: str, git_ref: str =
 | 
				
			|||||||
        print(f'Initializing git repository at {repo_dir}.')
 | 
					        print(f'Initializing git repository at {repo_dir}.')
 | 
				
			||||||
        repo = Repo.init(repo_dir, bare=True)
 | 
					        repo = Repo.init(repo_dir, bare=True)
 | 
				
			||||||
        origin = repo.create_remote('origin', remote_url)
 | 
					        origin = repo.create_remote('origin', remote_url)
 | 
				
			||||||
 | 
					    return repo, origin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def _gitbranch(env: Environment, repo_name: str, remote_url: str, git_ref: str = 'main') -> dict:
 | 
				
			||||||
 | 
					    repo, origin = _clone(env, repo_name, remote_url)
 | 
				
			||||||
    worktree_dir = os.path.join(env['CLONE_DIR'], 'git', repo_name, hashlib.shake_128(git_ref.encode('utf-8')).hexdigest(6)) # TODO: commit hash would be better, right? -> not if it's a branch!
 | 
					    worktree_dir = os.path.join(env['CLONE_DIR'], 'git', repo_name, hashlib.shake_128(git_ref.encode('utf-8')).hexdigest(6)) # TODO: commit hash would be better, right? -> not if it's a branch!
 | 
				
			||||||
    if not os.path.exists(worktree_dir):
 | 
					    if not os.path.exists(worktree_dir):
 | 
				
			||||||
        print(f'Checking out into {worktree_dir}.')
 | 
					        print(f'Checking out into {worktree_dir}.')
 | 
				
			||||||
@ -34,6 +38,12 @@ def _gitbranch(env: Environment, repo_name: str, remote_url: str, git_ref: str =
 | 
				
			|||||||
        'checkout_root': worktree_dir
 | 
					        'checkout_root': worktree_dir
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def _gittags(env: Environment, repo_name: str, remote_url: str, force_fetch: bool = False) -> 'list[str]':
 | 
				
			||||||
 | 
					    repo, origin = _clone(env, repo_name, remote_url)
 | 
				
			||||||
 | 
					    if force_fetch or env['UPDATE_REPOSITORIES']:
 | 
				
			||||||
 | 
					        origin.fetch(tags=True)
 | 
				
			||||||
 | 
					    return [t.name for t in repo.tags]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
env.AddMethod(_gitbranch, 'GitBranch')
 | 
					env.AddMethod(_gitbranch, 'GitBranch')
 | 
				
			||||||
 | 
					env.AddMethod(_gittags, 'GitTags')
 | 
				
			||||||
Return('env')
 | 
					Return('env')
 | 
				
			||||||
@ -1,6 +1,28 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					import re
 | 
				
			||||||
from SCons.Script import *
 | 
					from SCons.Script import *
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					_REPO_NAME = 'libpng'
 | 
				
			||||||
 | 
					_REPO_URL = 'https://git.code.sf.net/p/libpng/code.git'
 | 
				
			||||||
 | 
					_TAG_PATTERN = re.compile(r'^v([0-9])+\.([0-9])+\.([0-9])$')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def available(env: Environment) -> bool:
 | 
				
			||||||
 | 
					    return hasattr(env, 'GitBranch') and hasattr(env, 'GitTags')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def versions(env: Environment, update: bool = False) -> 'list[str]':
 | 
				
			||||||
 | 
					    tags = env.GitTags(repo_name = _REPO_NAME, remote_url = _REPO_URL, force_fetch=update)
 | 
				
			||||||
 | 
					    result = []
 | 
				
			||||||
 | 
					    for tag in tags:
 | 
				
			||||||
 | 
					        match = _TAG_PATTERN.match(tag)
 | 
				
			||||||
 | 
					        if match:
 | 
				
			||||||
 | 
					            result.append((int(match.groups()[0]), int(match.groups()[1]), int(match.groups()[2])))
 | 
				
			||||||
 | 
					    return result
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def dependencies(env: Environment, version) -> 'list[dict]':
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					        'zlib': {}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def cook(env: Environment, git_ref = 'master') -> dict:
 | 
					def cook(env: Environment, git_ref = 'master') -> dict:
 | 
				
			||||||
    lib_z = env.Cook('zlib')
 | 
					    lib_z = env.Cook('zlib')
 | 
				
			||||||
    repo = env.GitBranch(repo_name = 'libpng', remote_url = 'https://git.code.sf.net/p/libpng/code.git', git_ref = git_ref)
 | 
					    repo = env.GitBranch(repo_name = 'libpng', remote_url = 'https://git.code.sf.net/p/libpng/code.git', git_ref = git_ref)
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user