in builder/core/project.py [0:0]
def produce_config(build_spec, project, overrides=None, variant_config=None, **additional_variables):
""" Traverse the configurations to produce one for the given spec """
host_os = current_os()
defaults = {
'hosts': HOSTS,
'targets': TARGETS,
'compilers': COMPILERS,
'architectures': ARCHS,
}
# Build the list of config options to poll
configs = UniqueList()
# Processes a config object (could come from a file), searching for keys hosts, targets, and compilers
def process_config(config, depth=0):
def process_element(map, element_name, instance):
if not map or not isinstance(map, dict):
return
element = map.get(element_name)
# Some keys will just contain lists or scalars (e.g. hosts)
if not element or not isinstance(element, dict):
return
new_config = element.get(instance)
if not new_config:
return
configs.append(new_config)
# recursively process config as long as sub-sections are found
process_config(new_config, depth+1)
return new_config
# Pull out any top level defaults
if depth == 0:
defaults = {}
for key, value in config.items():
if key not in ('hosts', 'targets', 'compilers', 'architectures', 'variants'):
defaults[key] = value
if len(defaults) > 0:
configs.append(defaults)
# pull out arch + any aliases
archs = _arch_aliases(build_spec)
for arch in archs:
process_element(config, 'architectures', arch)
# Get defaults from os (linux) then override with host (al2, manylinux, etc)
if host_os != build_spec.host:
process_element(config, 'hosts', host_os)
process_element(config, 'hosts', build_spec.host)
# pull out spec target to override
process_element(config, 'targets', build_spec.target)
# pull out spec compiler and version info
compiler = process_element(config, 'compilers', build_spec.compiler)
# Allow most specific resolves to come last
process_element(compiler, 'versions', build_spec.compiler_version)
# Process defaults first
process_config(defaults)
# process platform
# target, arch -> platform
target_platform = '{}-{}'.format(build_spec.target, build_spec.arch)
configs.append(PLATFORMS[target_platform])
# then override with config file
project_config = project.config
process_config(project_config)
# then add variant
if variant_config:
process_config(variant_config)
new_version = {
'spec': build_spec,
}
# Iterate all keys and apply them
for key, default in KEYS.items():
new_version[key] = default
for config in configs:
override_key = '!' + key
apply_key = '+' + key
if override_key in config: # Force Override
new_version[key] = config[override_key]
elif apply_key in config: # Force Apply
_apply_value(new_version, key, config[apply_key])
elif key in config:
# Project configs override defaults unless force applied
if key in project_config and config[key] == project_config[key]:
new_version[key] = config[key]
else: # By default, merge all values (except strings)
_apply_value(new_version, key, config[key])
new_version = _coalesce_pkg_options(build_spec, new_version)
def apply_overrides(config, overrides):
if not overrides:
return
for key, val in overrides.items():
if key.startswith('!'):
# re-init and replace current value, obeying type coercion rules
key = key[1:]
if key in config:
config[key] = config[key].__class__()
_apply_value(config, key, val)
else:
_apply_value(config, key, val)
apply_overrides(new_version, overrides)
# Default variables
replacements = {
'host': build_spec.host,
'compiler': build_spec.compiler,
'version': build_spec.compiler_version,
'target': build_spec.target,
'arch': build_spec.arch,
'cwd': os.getcwd(),
**additional_variables,
}
# Pull variables from the configs
for config in configs:
if 'variables' in config:
variables = config['variables']
assert type(variables) == dict
replacements.update(variables)
# Post process
new_version = replace_variables(new_version, replacements)
new_version['variables'] = replacements
# resolve build variants for the top level config
if not variant_config:
variants = project_config.get('variants', {})
resolved_variants = {}
for name, variant_config in variants.items():
variant = produce_config(build_spec, project, None, variant_config, **additional_variables)
resolved_variants[name] = variant
new_version['variants'] = resolved_variants
new_version['__processed'] = True
return new_version