From 039062218957bdae6473b482adc8800fd9be7ed3 Mon Sep 17 00:00:00 2001 From: Sam Thursfield Date: Fri, 9 Jun 2017 18:57:01 +0100 Subject: Add --host-arch and --target-arch, and 'host-arches' conditional This command adds initial cross-compilation support to BuildStream. It has been tested against a converted version of the Baserock compiler bootstrap and used to cross build sysroots for armv8l64 and ppc64l from an x86_64 host. For example, to build a sysroot for ARM v8 64-bit you can do this: bst build --target-arch=armv8b64 gnu-toolchain/stage2.bst This would cause the adapted Baserock definitions to produce a stage1 simple cross compiler that runs on the native architecture and produces armv8b64 binaries, and then cross build a stage2 sysroot that executes on armv8b64. Currently the --host-arch option does nothing of use. It will one day enable host-incompatible builds using a QEMU-powered cross sandbox. The `--arch=` option is now shorthand for `--host-arch= --target-arch=`. Elements have 2 new variables available, %{bst-host-arch} and %{bst-target-arch}. The 'arches' conditional now follows %{bst-target-arch}, while the new 'host-arches' conditional follows %{bst-host-arch}. All of --arch, --host-arch and --target-arch default to the output of `uname -a`. There's no magic here that would make all BuildStream elements suddenly able to cross compile. It is up to an individual element to support this by honouring %{bst-target-arch} in whatever way makes sense. --- buildstream/_frontend/main.py | 91 +++++++++++++++------- buildstream/_frontend/widget.py | 3 +- buildstream/_loader.py | 32 +++++--- buildstream/_pipeline.py | 3 +- buildstream/context.py | 15 ++-- buildstream/project.py | 22 ++++-- doc/source/format.rst | 3 + tests/context/context.py | 2 +- tests/loader/arches.py | 76 +++++++++++++++--- .../arches/elements/host-arch-conditional.bst | 20 +++++ tests/loader/basics.py | 10 +-- tests/loader/dependencies.py | 18 ++--- tests/loader/variants.py | 32 ++++---- tests/sources/fixture.py | 2 +- 14 files changed, 232 insertions(+), 97 deletions(-) create mode 100644 tests/loader/arches/elements/host-arch-conditional.bst diff --git a/buildstream/_frontend/main.py b/buildstream/_frontend/main.py index 0224ce50e..fa8ea12a6 100644 --- a/buildstream/_frontend/main.py +++ b/buildstream/_frontend/main.py @@ -98,15 +98,20 @@ def cli(context, **kwargs): @click.option('--track', default=False, is_flag=True, help="Track new source references before building (implies --all)") @click.option('--arch', '-a', default=host_machine, - help="The target architecture (default: %s)" % host_machine) + help="Architecture of the machine running the build (default: %s)" % host_machine) +@click.option('--host-arch', + help="Run as a native build for the given architecture (defaults to --arch)") +@click.option('--target-arch', + help="Produce elements that execute on this architecture (defaults to --arch)") @click.option('--variant', help='A variant of the specified target') @click.argument('target') @click.pass_obj -def build(app, target, arch, variant, all, track): +def build(app, target, arch, host_arch, target_arch, variant, all, track): """Build elements in a pipeline""" - app.initialize(target, arch, variant, rewritable=track, inconsistent=track) + app.initialize(target, host_arch or arch, target_arch or arch, variant, + rewritable=track, inconsistent=track) app.print_heading() try: app.pipeline.build(app.scheduler, all, track) @@ -128,12 +133,16 @@ def build(app, target, arch, variant, all, track): @click.option('--track', default=False, is_flag=True, help="Track new source references before fetching") @click.option('--arch', '-a', default=host_machine, - help="The target architecture (default: %s)" % host_machine) + help="Architecture of the machine running the build (default: %s)" % host_machine) +@click.option('--host-arch', + help="Run as a native build for the given architecture (defaults to --arch)") +@click.option('--target-arch', + help="Produce elements that execute on this architecture (defaults to --arch)") @click.option('--variant', help='A variant of the specified target') @click.argument('target') @click.pass_obj -def fetch(app, target, arch, variant, deps, track, except_): +def fetch(app, target, arch, host_arch, target_arch, variant, deps, track, except_): """Fetch sources required to build the pipeline By default this will only try to fetch sources which are @@ -148,7 +157,8 @@ def fetch(app, target, arch, variant, deps, track, except_): plan: Only dependencies required for the build plan all: All dependencies """ - app.initialize(target, arch, variant, rewritable=track, inconsistent=track) + app.initialize(target, host_arch or arch, target_arch or arch, variant, + rewritable=track, inconsistent=track) try: dependencies = app.pipeline.deps_elements(deps, except_) app.print_heading(deps=dependencies) @@ -169,12 +179,16 @@ def fetch(app, target, arch, variant, deps, track, except_): type=click.Choice(['none', 'all']), help='The dependencies to track (default: none)') @click.option('--arch', '-a', default=host_machine, - help="The target architecture (default: %s)" % host_machine) + help="Architecture of the machine running the build (default: %s)" % host_machine) +@click.option('--host-arch', + help="Run as a native build for the given architecture (defaults to --arch)") +@click.option('--target-arch', + help="Produce elements that execute on this architecture (defaults to --arch)") @click.option('--variant', help='A variant of the specified target') @click.argument('target') @click.pass_obj -def track(app, target, arch, variant, deps, except_): +def track(app, target, arch, host_arch, target_arch, variant, deps, except_): """Consults the specified tracking branches for new versions available to build and updates the project with any newly available references. @@ -187,7 +201,8 @@ def track(app, target, arch, variant, deps, except_): none: No dependencies, just the element itself all: All dependencies """ - app.initialize(target, arch, variant, rewritable=True, inconsistent=True) + app.initialize(target, host_arch or arch, target_arch or arch, variant, + rewritable=True, inconsistent=True) try: dependencies = app.pipeline.deps_elements(deps, except_) app.print_heading(deps=dependencies) @@ -214,12 +229,16 @@ def track(app, target, arch, variant, deps, except_): type=click.STRING, help='Format string for each element') @click.option('--arch', '-a', default=host_machine, - help="The target architecture (default: %s)" % host_machine) + help="Architecture of the machine running the build (default: %s)" % host_machine) +@click.option('--host-arch', + help="Run as a native build for the given architecture (defaults to --arch)") +@click.option('--target-arch', + help="Produce elements that execute on this architecture (defaults to --arch)") @click.option('--variant', help='A variant of the specified target') @click.argument('target') @click.pass_obj -def show(app, target, arch, variant, deps, except_, order, format): +def show(app, target, arch, host_arch, target_arch, variant, deps, except_, order, format): """Show elements in the pipeline By default this will show all of the dependencies of the @@ -264,7 +283,7 @@ def show(app, target, arch, variant, deps, except_, order, format): bst show target.bst --format \\ $'---------- %{name} ----------\\n%{vars}' """ - app.initialize(target, arch, variant) + app.initialize(target, host_arch or arch, target_arch or arch, variant) try: dependencies = app.pipeline.deps_elements(deps, except_) except PipelineError as e: @@ -289,12 +308,16 @@ def show(app, target, arch, variant, deps, except_, order, format): type=click.Choice(['build', 'run']), help='Specify element scope to stage') @click.option('--arch', '-a', default=host_machine, - help="The target architecture (default: %s)" % host_machine) + help="Architecture of the machine running the build (default: %s)" % host_machine) +@click.option('--host-arch', + help="Run as a native build for the given architecture (defaults to --arch)") +@click.option('--target-arch', + help="Produce elements that execute on this architecture (defaults to --arch)") @click.option('--variant', help='A variant of the specified target') @click.argument('target') @click.pass_obj -def shell(app, target, arch, variant, builddir, scope): +def shell(app, target, arch, host_arch, target_arch, variant, builddir, scope): """Shell into an element's sandbox environment This can be used either to debug building or to launch @@ -313,7 +336,7 @@ def shell(app, target, arch, variant, builddir, scope): elif scope == "build": scope = Scope.BUILD - app.initialize(target, arch, variant) + app.initialize(target, host_arch or arch, target_arch or arch, variant) # Assert we have everything we need built. missing_deps = [] @@ -346,16 +369,20 @@ def shell(app, target, arch, variant, builddir, scope): @click.option('--force', '-f', default=False, is_flag=True, help="Overwrite files existing in checkout directory") @click.option('--arch', '-a', default=host_machine, - help="The target architecture (default: %s)" % host_machine) + help="Architecture of the machine running the build (default: %s)" % host_machine) +@click.option('--host-arch', + help="Run as a native build for the given architecture (defaults to --arch)") +@click.option('--target-arch', + help="Produce elements that execute on this architecture (defaults to --arch)") @click.option('--variant', help='A variant of the specified target') @click.argument('target') @click.argument('directory') @click.pass_obj -def checkout(app, target, arch, variant, directory, force): +def checkout(app, target, arch, host_arch, target_arch, variant, directory, force): """Checkout a built artifact to the specified directory """ - app.initialize(target, arch, variant) + app.initialize(target, host_arch or arch, target_arch or arch, variant) try: app.pipeline.checkout(directory, force) click.echo("") @@ -380,7 +407,11 @@ def checkout(app, target, arch, variant, directory, force): @click.option('--track', default=False, is_flag=True, help="Track new source references before building") @click.option('--arch', '-a', default=host_machine, - help="The target architecture (default: %s)" % host_machine) + help="Architecture of the machine running the build (default: %s)" % host_machine) +@click.option('--host-arch', + help="Run as a native build for the given architecture (defaults to --arch)") +@click.option('--target-arch', + help="Produce elements that execute on this architecture (defaults to --arch)") @click.option('--variant', help='A variant of the specified target') @click.option('--force', '-f', default=False, is_flag=True, @@ -389,7 +420,7 @@ def checkout(app, target, arch, variant, directory, force): help="The directory to write the tarball to") @click.argument('target') @click.pass_obj -def source_bundle(app, target, arch, variant, force, directory, +def source_bundle(app, target, arch, host_arch, target_arch, variant, force, directory, track, deps, compression, except_): """Produce a build bundle to be manually executed @@ -400,7 +431,8 @@ def source_bundle(app, target, arch, variant, force, directory, run: Runtime dependencies, including the element itself build: Build time dependencies, excluding the element itself """ - app.initialize(target, arch, variant, rewritable=track, inconsistent=track) + app.initialize(target, host_arch or arch, target_arch or arch, variant, + rewritable=track, inconsistent=track) try: dependencies = app.pipeline.deps_elements(deps, except_) app.print_heading(dependencies) @@ -425,7 +457,8 @@ class App(): self.logger = None self.status = None self.target = None - self.arch = None + self.host_arch = None + self.target_arch = None self.variant = None # Main asset handles @@ -473,18 +506,20 @@ class App(): # # Initialize the main pipeline # - def initialize(self, target, arch, variant, rewritable=False, inconsistent=False): + def initialize(self, target, host_arch, target_arch, variant, + rewritable=False, inconsistent=False): self.target = target - self.arch = arch + self.host_arch = host_arch + self.target_arch = target_arch self.variant = variant - profile_start(Topics.LOAD_PIPELINE, target.replace(os.sep, '-') + '-' + arch) + profile_start(Topics.LOAD_PIPELINE, target.replace(os.sep, '-') + '-' + host_arch + '-' + target_arch) directory = self.main_options['directory'] config = self.main_options['config'] try: - self.context = Context(arch) + self.context = Context(host_arch, target_arch) self.context.load(config) except _BstError as e: click.echo("Error loading user configuration: %s" % str(e)) @@ -534,7 +569,7 @@ class App(): self.context._set_message_handler(self.message_handler) try: - self.project = Project(directory, arch) + self.project = Project(directory, host_arch, target_arch) except _BstError as e: click.echo("Error loading project: %s" % str(e)) sys.exit(1) @@ -559,7 +594,7 @@ class App(): self.logger.size_request(self.pipeline) self.messaging_enabled = True - profile_end(Topics.LOAD_PIPELINE, target.replace(os.sep, '-') + '-' + arch) + profile_end(Topics.LOAD_PIPELINE, target.replace(os.sep, '-') + '-' + host_arch + '-' + target_arch) # # Render the status area, conditional on some internal state diff --git a/buildstream/_frontend/widget.py b/buildstream/_frontend/widget.py index a9f574d32..760a40b6a 100644 --- a/buildstream/_frontend/widget.py +++ b/buildstream/_frontend/widget.py @@ -426,7 +426,8 @@ class LogLine(Widget): values["Session Start"] = starttime.strftime('%A, %d-%m-%Y at %H:%M:%S') values["Project"] = "{} ({})".format(project.name, project.directory) values["Target"] = pipeline.target.name - values["Machine Architecture"] = context.arch + values["Host Architecture"] = context.host_arch + values["Target Architecture"] = context.target_arch values["Variant"] = variant text += self.format_values(values) diff --git a/buildstream/_loader.py b/buildstream/_loader.py index f8196ed8e..fd2eef655 100644 --- a/buildstream/_loader.py +++ b/buildstream/_loader.py @@ -45,6 +45,7 @@ class Symbol(): VARIANT = "variant" VARIANTS = "variants" ARCHES = "arches" + HOST_ARCHES = "host-arches" SOURCES = "sources" CONFIG = "config" VARIABLES = "variables" @@ -117,9 +118,11 @@ class VariantError(Exception): # the arches dict from the data node afterwards, this is shared # with project.py # -def resolve_arch(data, active_arch): +def resolve_arch(data, host_arch, target_arch=None): + + def resolve_single_arch_conditional(symbol, active_arch): + arches = _yaml.node_get(data, Mapping, symbol, default_value={}) - arches = _yaml.node_get(data, Mapping, Symbol.ARCHES, default_value={}) arch = {} if arches: arch = _yaml.node_get(arches, Mapping, active_arch, default_value={}) @@ -133,12 +136,16 @@ def resolve_arch(data, active_arch): provenance = _yaml.node_get_provenance(arch, key=active_arch) raise LoadError(LoadErrorReason.ILLEGAL_COMPOSITE, "%s: Arch %s specifies type '%s' for path '%s', expected '%s'" % - (str(provenance), active_arch, + (str(provenance), + active_arch, e.actual_type.__name__, e.path, e.expected_type.__name__)) from e - del data[Symbol.ARCHES] + del data[symbol] + + resolve_single_arch_conditional(Symbol.HOST_ARCHES, active_arch=host_arch) + resolve_single_arch_conditional(Symbol.ARCHES, active_arch=target_arch or host_arch) # A transient object breaking down what is loaded @@ -147,11 +154,12 @@ def resolve_arch(data, active_arch): # class LoadElement(): - def __init__(self, data, filename, basedir, arch, elements): + def __init__(self, data, filename, basedir, host_arch, target_arch, elements): self.filename = filename self.data = data - self.arch = arch + self.host_arch = host_arch + self.target_arch = target_arch self.name = filename self.elements = elements @@ -159,7 +167,7 @@ class LoadElement(): self.basedir = basedir # Process arch conditionals - resolve_arch(self.data, self.arch) + resolve_arch(self.data, self.host_arch, self.target_arch) # Dependency objects after resolving variants self.variant_name = None @@ -178,7 +186,7 @@ class LoadElement(): variant = Variant(self.name, variant_node) # Process arch conditionals on individual variants - resolve_arch(variant.data, self.arch) + resolve_arch(variant.data, self.host_arch, self.target_arch) self.variants.append(variant) if len(self.variants) == 1: @@ -356,7 +364,7 @@ def extract_depends_from_node(owner, data): # class Loader(): - def __init__(self, basedir, filename, variant, arch): + def __init__(self, basedir, filename, variant, host_arch, target_arch): # Ensure we have an absolute path for the base directory # @@ -381,8 +389,8 @@ class Loader(): # Optional variant self.target_variant = variant - # Build architecture - self.arch = arch + self.host_arch = host_arch + self.target_arch = target_arch self.loaded_files = {} # Table of files we've already loaded self.meta_elements = {} # Dict of resolved meta elements by name @@ -465,7 +473,7 @@ class Loader(): # Load the element and track it in our elements table data = _yaml.load(fullpath, shortname=filename, copy_tree=rewritable) - element = LoadElement(data, filename, self.basedir, self.arch, self.elements) + element = LoadElement(data, filename, self.basedir, self.host_arch, self.target_arch, self.elements) self.elements[filename] = element diff --git a/buildstream/_pipeline.py b/buildstream/_pipeline.py index f931a0e83..c1eb3a863 100644 --- a/buildstream/_pipeline.py +++ b/buildstream/_pipeline.py @@ -140,7 +140,8 @@ class Pipeline(): self.element_factory = ElementFactory(pluginbase, project._plugin_element_paths) self.source_factory = SourceFactory(pluginbase, project._plugin_source_paths) - loader = Loader(self.project.element_path, target, target_variant, context.arch) + loader = Loader(self.project.element_path, target, target_variant, + context.host_arch, context.target_arch) meta_element = loader.load(rewritable, load_ticker) if load_ticker: load_ticker(None) diff --git a/buildstream/context.py b/buildstream/context.py index 33aae86ae..0ad894d96 100644 --- a/buildstream/context.py +++ b/buildstream/context.py @@ -45,15 +45,19 @@ class Context(): """Context of how BuildStream was invoked Args: - arch (string): The target architecture to build for + host_arch (string): The desired architecture on which to run the build + target_arch (string): The machine on which the results of the build should execute """ - def __init__(self, arch): + def __init__(self, host_arch, target_arch=None): self.config_origin = None """Filename indicating which configuration file was used, or None for the defaults""" - self.arch = arch - """The target architecture to build for""" + self.host_arch = host_arch + """The desired architecture on which to run the build""" + + self.target_arch = target_arch or host_arch + """The machine on which the results of the build should execute""" self.sourcedir = None """The directory where various sources are stored""" @@ -205,7 +209,8 @@ class Context(): # Anything that alters the build goes into the unique key self._cache_key = utils._generate_key({ - 'arch': self.arch + 'host-arch': self.host_arch, + 'target-arch': self.target_arch }) return self._cache_key diff --git a/buildstream/project.py b/buildstream/project.py index 6af6657f5..6ec270857 100644 --- a/buildstream/project.py +++ b/buildstream/project.py @@ -44,12 +44,16 @@ class Project(): Args: directory (str): The project directory - arch (str): Symbolic machine architecture name + host_arch (str): Symbolic host machine architecture name + target_arch (str): Symbolic target machine architecture name Raises: :class:`.LoadError` """ - def __init__(self, directory, arch): + def __init__(self, directory, host_arch, target_arch=None): + + host_arch = host_arch + target_arch = target_arch or host_arch self.name = None """str: The project name""" @@ -69,7 +73,7 @@ class Project(): self._cache_key = None profile_start(Topics.LOAD_PROJECT, self.directory.replace(os.sep, '-')) - self._load(arch) + self._load(host_arch, target_arch) profile_end(Topics.LOAD_PROJECT, self.directory.replace(os.sep, '-')) def translate_url(self, url): @@ -101,7 +105,7 @@ class Project(): # # Raises: LoadError if there was a problem with the project.conf # - def _load(self, arch): + def _load(self, host_arch, target_arch): # Load builtin default projectfile = os.path.join(self.directory, "project.conf") @@ -111,14 +115,20 @@ class Project(): # be processed here before compositing any overrides variables = _yaml.node_get(config, Mapping, 'variables') variables['max-jobs'] = multiprocessing.cpu_count() - variables['bst-arch'] = arch + + variables['bst-host-arch'] = host_arch + variables['bst-target-arch'] = target_arch + + # This is kept around for compatibility with existing definitions, + # but we should probably remove it due to being ambiguous. + variables['bst-arch'] = host_arch # Load project local config and override the builtin project_conf = _yaml.load(projectfile) _yaml.composite(config, project_conf, typesafe=True) # Resolve arches keyword, project may have arch conditionals - _loader.resolve_arch(config, arch) + _loader.resolve_arch(config, host_arch, target_arch) # The project name self.name = _yaml.node_get(config, str, 'name') diff --git a/doc/source/format.rst b/doc/source/format.rst index f77f3a368..ebe8e2636 100644 --- a/doc/source/format.rst +++ b/doc/source/format.rst @@ -453,6 +453,9 @@ The ``arches`` attribute, if provided, overrides the element for a given archite name. It is not considered an error if the element does not provide an architecture clause for the specific architecture BuildStream was launched to build for. +There is also a ``host-arches`` attribute, which operates in the same manner but +follows the *host* architecture rather than the *target* architecture. + In the above example we demonstrate that a given ``config`` attribute can be overridden by an architecture conditional, this can however be done for any segment of the element such as ``depends``, ``sources`` and ``public`` as well. It is however illegal diff --git a/tests/context/context.py b/tests/context/context.py index c09643b75..65f6f51fd 100644 --- a/tests/context/context.py +++ b/tests/context/context.py @@ -30,7 +30,7 @@ def context_fixture(): def test_context_create(context_fixture): context = context_fixture['context'] assert(isinstance(context, Context)) - assert(context.arch == 'x86_64') + assert(context.host_arch == 'x86_64') ####################################### diff --git a/tests/loader/arches.py b/tests/loader/arches.py index 99602d181..bc69d5b8f 100644 --- a/tests/loader/arches.py +++ b/tests/loader/arches.py @@ -19,7 +19,7 @@ def test_simple_conditional_nomatch(datafiles): basedir = os.path.join(datafiles.dirname, datafiles.basename) loader = Loader( - basedir, 'elements/simple-conditional.bst', None, 'arm') + basedir, 'elements/simple-conditional.bst', None, 'arm', None) element = loader.load() assert(isinstance(element, MetaElement)) @@ -34,7 +34,7 @@ def test_simple_conditional_x86_64(datafiles): basedir = os.path.join(datafiles.dirname, datafiles.basename) loader = Loader( - basedir, 'elements/simple-conditional.bst', None, 'x86_64') + basedir, 'elements/simple-conditional.bst', None, 'x86_64', None) element = loader.load() assert(isinstance(element, MetaElement)) @@ -49,7 +49,7 @@ def test_simple_conditional_x86_32(datafiles): basedir = os.path.join(datafiles.dirname, datafiles.basename) loader = Loader( - basedir, 'elements/simple-conditional.bst', None, 'x86_32') + basedir, 'elements/simple-conditional.bst', None, 'x86_32', None) element = loader.load() assert(isinstance(element, MetaElement)) @@ -59,6 +59,58 @@ def test_simple_conditional_x86_32(datafiles): assert(number == 7) +############################################################## +# Test Arch and Host-Arch Conditionals # +############################################################## + + +@pytest.mark.datafiles(DATA_DIR) +def test_host_arch_conditional_armv8(datafiles): + + basedir = os.path.join(datafiles.dirname, datafiles.basename) + loader = Loader( + basedir, 'elements/host-arch-conditional.bst', None, 'armv8', None) + + element = loader.load() + assert(isinstance(element, MetaElement)) + number = element.config.get('number') + + # armv8 host-arch overrides the number to 88 + assert(number == 88) + + +@pytest.mark.datafiles(DATA_DIR) +def test_host_arch_conditional_ignores_target_arch(datafiles): + + basedir = os.path.join(datafiles.dirname, datafiles.basename) + loader = Loader( + basedir, 'elements/host-arch-conditional.bst', None, 'armv8', 'x86_32') + + element = loader.load() + assert(isinstance(element, MetaElement)) + number = element.config.get('number') + + # The setting a target-arch has no effect on host-arches: the number is + # still 88 + assert(number == 88) + + +@pytest.mark.datafiles(DATA_DIR) +def test_host_arch_conditional_overridden(datafiles): + + basedir = os.path.join(datafiles.dirname, datafiles.basename) + loader = Loader( + basedir, 'elements/host-arch-conditional.bst', None, 'armv8', 'x86_64') + + element = loader.load() + assert(isinstance(element, MetaElement)) + number = element.config.get('number') + + # The 'arches' conditional follows the target architecture, and overrides + # anything specified in 'host-arches'. + assert(number == 6) + + ############################################################## # Test Arch Conditionals inside Variants # ############################################################## @@ -67,7 +119,7 @@ def test_variant_arch_default(datafiles): basedir = os.path.join(datafiles.dirname, datafiles.basename) loader = Loader( - basedir, 'elements/variant-arch-conditional.bst', None, 'arm') + basedir, 'elements/variant-arch-conditional.bst', None, 'arm', None) element = loader.load() assert(isinstance(element, MetaElement)) @@ -82,7 +134,7 @@ def test_variant_arch_default_x86_64(datafiles): basedir = os.path.join(datafiles.dirname, datafiles.basename) loader = Loader( - basedir, 'elements/variant-arch-conditional.bst', None, 'x86_64') + basedir, 'elements/variant-arch-conditional.bst', None, 'x86_64', None) element = loader.load() assert(isinstance(element, MetaElement)) @@ -96,7 +148,7 @@ def test_variant_arch_default_x86_32(datafiles): basedir = os.path.join(datafiles.dirname, datafiles.basename) loader = Loader( - basedir, 'elements/variant-arch-conditional.bst', None, 'x86_32') + basedir, 'elements/variant-arch-conditional.bst', None, 'x86_32', None) element = loader.load() assert(isinstance(element, MetaElement)) @@ -110,7 +162,7 @@ def test_variant_arch_pink_pony(datafiles): basedir = os.path.join(datafiles.dirname, datafiles.basename) loader = Loader( - basedir, 'elements/variant-arch-conditional.bst', 'pink', 'arm') + basedir, 'elements/variant-arch-conditional.bst', 'pink', 'arm', None) element = loader.load() assert(isinstance(element, MetaElement)) @@ -125,7 +177,7 @@ def test_variant_arch_pink_pony_x86_64(datafiles): basedir = os.path.join(datafiles.dirname, datafiles.basename) loader = Loader( - basedir, 'elements/variant-arch-conditional.bst', 'pink', 'x86_64') + basedir, 'elements/variant-arch-conditional.bst', 'pink', 'x86_64', None) element = loader.load() assert(isinstance(element, MetaElement)) @@ -139,7 +191,7 @@ def test_variant_arch_pink_pony_x86_32(datafiles): basedir = os.path.join(datafiles.dirname, datafiles.basename) loader = Loader( - basedir, 'elements/variant-arch-conditional.bst', 'pink', 'x86_32') + basedir, 'elements/variant-arch-conditional.bst', 'pink', 'x86_32', None) element = loader.load() assert(isinstance(element, MetaElement)) @@ -153,7 +205,7 @@ def test_variant_arch_blue_pony(datafiles): basedir = os.path.join(datafiles.dirname, datafiles.basename) loader = Loader( - basedir, 'elements/variant-arch-conditional.bst', 'blue', 'arm') + basedir, 'elements/variant-arch-conditional.bst', 'blue', 'arm', None) element = loader.load() assert(isinstance(element, MetaElement)) @@ -168,7 +220,7 @@ def test_variant_arch_blue_pony_x86_64(datafiles): basedir = os.path.join(datafiles.dirname, datafiles.basename) loader = Loader( - basedir, 'elements/variant-arch-conditional.bst', 'blue', 'x86_64') + basedir, 'elements/variant-arch-conditional.bst', 'blue', 'x86_64', None) element = loader.load() assert(isinstance(element, MetaElement)) @@ -182,7 +234,7 @@ def test_variant_arch_blue_pony_x86_32(datafiles): basedir = os.path.join(datafiles.dirname, datafiles.basename) loader = Loader( - basedir, 'elements/variant-arch-conditional.bst', 'blue', 'x86_32') + basedir, 'elements/variant-arch-conditional.bst', 'blue', 'x86_32', None) element = loader.load() assert(isinstance(element, MetaElement)) diff --git a/tests/loader/arches/elements/host-arch-conditional.bst b/tests/loader/arches/elements/host-arch-conditional.bst new file mode 100644 index 000000000..4c9272feb --- /dev/null +++ b/tests/loader/arches/elements/host-arch-conditional.bst @@ -0,0 +1,20 @@ +kind: pony +description: | + An element with host-arches and arches conditionals. + + The 'arches' conditional follows --target-arch if specified, while the + 'host-arches' conditional does not. The 'arches' conditional overrides + 'host-arches' if both for some reason try to override the same thing. +config: + number: 5 +arches: + x86_64: + config: + number: 6 +host-arches: + x86_64: + config: + number: 66 + armv8: + config: + number: 88 diff --git a/tests/loader/basics.py b/tests/loader/basics.py index f706d06ec..d7f85b0fe 100644 --- a/tests/loader/basics.py +++ b/tests/loader/basics.py @@ -18,7 +18,7 @@ DATA_DIR = os.path.join( def test_one_file(datafiles): basedir = os.path.join(datafiles.dirname, datafiles.basename) - loader = Loader(basedir, 'elements/onefile.bst', None, None) + loader = Loader(basedir, 'elements/onefile.bst', None, None, None) element = loader.load() @@ -30,7 +30,7 @@ def test_one_file(datafiles): def test_missing_file(datafiles): basedir = os.path.join(datafiles.dirname, datafiles.basename) - loader = Loader(basedir, 'elements/missing.bst', None, None) + loader = Loader(basedir, 'elements/missing.bst', None, None, None) with pytest.raises(LoadError) as exc: element = loader.load() @@ -42,7 +42,7 @@ def test_missing_file(datafiles): def test_invalid_reference(datafiles): basedir = os.path.join(datafiles.dirname, datafiles.basename) - loader = Loader(basedir, 'elements/badreference.bst', None, None) + loader = Loader(basedir, 'elements/badreference.bst', None, None, None) with pytest.raises(LoadError) as exc: element = loader.load() @@ -54,7 +54,7 @@ def test_invalid_reference(datafiles): def test_invalid_yaml(datafiles): basedir = os.path.join(datafiles.dirname, datafiles.basename) - loader = Loader(basedir, 'elements/badfile.bst', None, None) + loader = Loader(basedir, 'elements/badfile.bst', None, None, None) with pytest.raises(LoadError) as exc: element = loader.load() @@ -69,6 +69,6 @@ def test_fail_fullpath_target(datafiles): fullpath = os.path.join(basedir, 'elements', 'onefile.bst') with pytest.raises(LoadError) as exc: - loader = Loader(basedir, fullpath, None, None) + loader = Loader(basedir, fullpath, None, None, None) assert (exc.value.reason == LoadErrorReason.INVALID_DATA) diff --git a/tests/loader/dependencies.py b/tests/loader/dependencies.py index 8a88bcaf8..a701d4723 100644 --- a/tests/loader/dependencies.py +++ b/tests/loader/dependencies.py @@ -18,7 +18,7 @@ DATA_DIR = os.path.join( def test_two_files(datafiles): basedir = os.path.join(datafiles.dirname, datafiles.basename) - loader = Loader(basedir, 'elements/target.bst', None, None) + loader = Loader(basedir, 'elements/target.bst', None, None, None) element = loader.load() assert(isinstance(element, MetaElement)) @@ -34,7 +34,7 @@ def test_two_files(datafiles): def test_shared_dependency(datafiles): basedir = os.path.join(datafiles.dirname, datafiles.basename) - loader = Loader(basedir, 'elements/shareddeptarget.bst', None, None) + loader = Loader(basedir, 'elements/shareddeptarget.bst', None, None, None) element = loader.load() # Toplevel is 'pony' with 2 dependencies @@ -77,7 +77,7 @@ def test_shared_dependency(datafiles): def test_dependency_dict(datafiles): basedir = os.path.join(datafiles.dirname, datafiles.basename) - loader = Loader(basedir, 'elements/target-depdict.bst', None, None) + loader = Loader(basedir, 'elements/target-depdict.bst', None, None, None) element = loader.load() assert(isinstance(element, MetaElement)) @@ -92,7 +92,7 @@ def test_dependency_dict(datafiles): @pytest.mark.datafiles(DATA_DIR) def test_invalid_dependency_declaration(datafiles): basedir = os.path.join(datafiles.dirname, datafiles.basename) - loader = Loader(basedir, 'elements/invaliddep.bst', None, None) + loader = Loader(basedir, 'elements/invaliddep.bst', None, None, None) with pytest.raises(LoadError) as exc: element = loader.load() @@ -103,7 +103,7 @@ def test_invalid_dependency_declaration(datafiles): @pytest.mark.datafiles(DATA_DIR) def test_circular_dependency(datafiles): basedir = os.path.join(datafiles.dirname, datafiles.basename) - loader = Loader(basedir, 'elements/circulartarget.bst', None, None) + loader = Loader(basedir, 'elements/circulartarget.bst', None, None, None) with pytest.raises(LoadError) as exc: element = loader.load() @@ -114,7 +114,7 @@ def test_circular_dependency(datafiles): @pytest.mark.datafiles(DATA_DIR) def test_invalid_dependency_type(datafiles): basedir = os.path.join(datafiles.dirname, datafiles.basename) - loader = Loader(basedir, 'elements/invaliddeptype.bst', None, None) + loader = Loader(basedir, 'elements/invaliddeptype.bst', None, None, None) with pytest.raises(LoadError) as exc: element = loader.load() @@ -125,7 +125,7 @@ def test_invalid_dependency_type(datafiles): @pytest.mark.datafiles(DATA_DIR) def test_build_dependency(datafiles): basedir = os.path.join(datafiles.dirname, datafiles.basename) - loader = Loader(basedir, 'elements/builddep.bst', None, None) + loader = Loader(basedir, 'elements/builddep.bst', None, None, None) element = loader.load() assert(isinstance(element, MetaElement)) @@ -141,7 +141,7 @@ def test_build_dependency(datafiles): @pytest.mark.datafiles(DATA_DIR) def test_runtime_dependency(datafiles): basedir = os.path.join(datafiles.dirname, datafiles.basename) - loader = Loader(basedir, 'elements/runtimedep.bst', None, None) + loader = Loader(basedir, 'elements/runtimedep.bst', None, None, None) element = loader.load() assert(isinstance(element, MetaElement)) @@ -157,7 +157,7 @@ def test_runtime_dependency(datafiles): @pytest.mark.datafiles(DATA_DIR) def test_build_runtime_dependency(datafiles): basedir = os.path.join(datafiles.dirname, datafiles.basename) - loader = Loader(basedir, 'elements/target.bst', None, None) + loader = Loader(basedir, 'elements/target.bst', None, None, None) element = loader.load() assert(isinstance(element, MetaElement)) diff --git a/tests/loader/variants.py b/tests/loader/variants.py index 0e20faf93..865ffa268 100644 --- a/tests/loader/variants.py +++ b/tests/loader/variants.py @@ -18,7 +18,7 @@ DATA_DIR = os.path.join( def test_variant_not_list(datafiles): basedir = os.path.join(datafiles.dirname, datafiles.basename) - loader = Loader(basedir, 'elements/variants-not-list.bst', None, None) + loader = Loader(basedir, 'elements/variants-not-list.bst', None, None, None) with pytest.raises(LoadError) as exc: element = loader.load() @@ -30,7 +30,7 @@ def test_variant_not_list(datafiles): def test_variant_unnamed(datafiles): basedir = os.path.join(datafiles.dirname, datafiles.basename) - loader = Loader(basedir, 'elements/unnamed-variant.bst', None, None) + loader = Loader(basedir, 'elements/unnamed-variant.bst', None, None, None) with pytest.raises(LoadError) as exc: element = loader.load() @@ -42,7 +42,7 @@ def test_variant_unnamed(datafiles): def test_variant_bad_name(datafiles): basedir = os.path.join(datafiles.dirname, datafiles.basename) - loader = Loader(basedir, 'elements/variant-bad-name.bst', None, None) + loader = Loader(basedir, 'elements/variant-bad-name.bst', None, None, None) with pytest.raises(LoadError) as exc: element = loader.load() @@ -54,7 +54,7 @@ def test_variant_bad_name(datafiles): def test_variant_only_one(datafiles): basedir = os.path.join(datafiles.dirname, datafiles.basename) - loader = Loader(basedir, 'elements/only-one-variant.bst', None, None) + loader = Loader(basedir, 'elements/only-one-variant.bst', None, None, None) with pytest.raises(LoadError) as exc: element = loader.load() @@ -67,7 +67,7 @@ def test_variant_illegal_composite(datafiles): basedir = os.path.join(datafiles.dirname, datafiles.basename) loader = Loader( - basedir, 'elements/variant-illegal-composite.bst', None, None) + basedir, 'elements/variant-illegal-composite.bst', None, None, None) with pytest.raises(LoadError) as exc: element = loader.load() @@ -83,7 +83,7 @@ def test_variant_simple_composite_default(datafiles): basedir = os.path.join(datafiles.dirname, datafiles.basename) loader = Loader( - basedir, 'elements/simple-variant-compositing.bst', None, None) + basedir, 'elements/simple-variant-compositing.bst', None, None, None) element = loader.load() @@ -100,7 +100,7 @@ def test_variant_simple_composite_pink_pony(datafiles): basedir = os.path.join(datafiles.dirname, datafiles.basename) loader = Loader( - basedir, 'elements/simple-variant-compositing.bst', 'pink', None) + basedir, 'elements/simple-variant-compositing.bst', 'pink', None, None) element = loader.load() @@ -117,7 +117,7 @@ def test_variant_simple_composite_blue_pony(datafiles): basedir = os.path.join(datafiles.dirname, datafiles.basename) loader = Loader( - basedir, 'elements/simple-variant-compositing.bst', 'blue', None) + basedir, 'elements/simple-variant-compositing.bst', 'blue', None, None) element = loader.load() @@ -155,7 +155,7 @@ def test_variant_simple_dependency_default(datafiles): basedir = os.path.join(datafiles.dirname, datafiles.basename) loader = Loader( - basedir, 'elements/simple-dependency-variants.bst', None, None) + basedir, 'elements/simple-dependency-variants.bst', None, None, None) element = loader.load() assert(isinstance(element, MetaElement)) @@ -170,7 +170,7 @@ def test_variant_simple_dependency_pink_pony(datafiles): basedir = os.path.join(datafiles.dirname, datafiles.basename) loader = Loader( - basedir, 'elements/simple-dependency-variants.bst', 'pink', None) + basedir, 'elements/simple-dependency-variants.bst', 'pink', None, None) element = loader.load() assert(isinstance(element, MetaElement)) @@ -185,7 +185,7 @@ def test_variant_simple_dependency_blue_pony(datafiles): basedir = os.path.join(datafiles.dirname, datafiles.basename) loader = Loader( - basedir, 'elements/simple-dependency-variants.bst', 'blue', None) + basedir, 'elements/simple-dependency-variants.bst', 'blue', None, None) element = loader.load() assert(isinstance(element, MetaElement)) @@ -200,7 +200,7 @@ def test_variant_indirect_dependency_default(datafiles): basedir = os.path.join(datafiles.dirname, datafiles.basename) loader = Loader( - basedir, 'elements/indirect-dependency-variants.bst', None, None) + basedir, 'elements/indirect-dependency-variants.bst', None, None, None) element = loader.load() assert(isinstance(element, MetaElement)) @@ -219,7 +219,7 @@ def test_variant_indirect_dependency_blue_pony(datafiles): basedir = os.path.join(datafiles.dirname, datafiles.basename) loader = Loader( - basedir, 'elements/indirect-dependency-variants.bst', 'blue', None) + basedir, 'elements/indirect-dependency-variants.bst', 'blue', None, None) element = loader.load() assert(isinstance(element, MetaElement)) @@ -238,7 +238,7 @@ def test_variant_indirect_dependency_pink_pony(datafiles): basedir = os.path.join(datafiles.dirname, datafiles.basename) loader = Loader( - basedir, 'elements/indirect-dependency-variants.bst', 'pink', None) + basedir, 'elements/indirect-dependency-variants.bst', 'pink', None, None) element = loader.load() assert(isinstance(element, MetaElement)) @@ -256,7 +256,7 @@ def test_variant_indirect_dependency_pink_pony(datafiles): def test_engine_resolve_agreement(datafiles): basedir = os.path.join(datafiles.dirname, datafiles.basename) - loader = Loader(basedir, 'elements/tricky.bst', None, None) + loader = Loader(basedir, 'elements/tricky.bst', None, None, None) element = loader.load() assert(isinstance(element, MetaElement)) @@ -271,7 +271,7 @@ def test_engine_resolve_agreement(datafiles): def test_engine_disagreement(datafiles): basedir = os.path.join(datafiles.dirname, datafiles.basename) - loader = Loader(basedir, 'elements/disagreement.bst', None, None) + loader = Loader(basedir, 'elements/disagreement.bst', None, None, None) with pytest.raises(LoadError) as exc: element = loader.load() diff --git a/tests/sources/fixture.py b/tests/sources/fixture.py index a9ba94e1d..c7b3a8fe6 100644 --- a/tests/sources/fixture.py +++ b/tests/sources/fixture.py @@ -39,7 +39,7 @@ class Setup(): if not os.path.exists(self.context.builddir): os.mkdir(self.context.builddir) - loader = Loader(directory, target, None, None) + loader = Loader(directory, target, None, None, None) element = loader.load() assert(len(element.sources) == 1) self.meta_source = element.sources[0] -- cgit v1.2.1