[Notes] [Git][BuildStream/buildstream][chandan/bst-checkout-build] 4 commits: element.py: Fix cache check in non-strict mode



Title: GitLab

Chandan Singh pushed to branch chandan/bst-checkout-build at BuildStream / buildstream

Commits:

8 changed files:

Changes:

  • buildstream/_frontend/cli.py
    ... ... @@ -630,7 +630,7 @@ def shell(app, element, sysroot, mount, isolate, build_, command):
    630 630
     @click.option('--force', '-f', default=False, is_flag=True,
    
    631 631
                   help="Allow files to be overwritten")
    
    632 632
     @click.option('--deps', '-d', default='run',
    
    633
    -              type=click.Choice(['run', 'none']),
    
    633
    +              type=click.Choice(['run', 'build', 'none']),
    
    634 634
                   help='The dependencies to checkout (default: run)')
    
    635 635
     @click.option('--integrate/--no-integrate', default=True, is_flag=True,
    
    636 636
                   help="Whether to run integration commands")
    

  • buildstream/element.py
    ... ... @@ -423,7 +423,7 @@ class Element(Plugin):
    423 423
                                                     visited=visited, recursed=True)
    
    424 424
     
    
    425 425
             # Yeild self only at the end, after anything needed has been traversed
    
    426
    -        if should_yield and (recurse or recursed) and (scope == Scope.ALL or scope == Scope.RUN):
    
    426
    +        if should_yield and (recurse or recursed) and scope != Scope.BUILD:
    
    427 427
                 yield self
    
    428 428
     
    
    429 429
         def search(self, scope, name):
    
    ... ... @@ -671,37 +671,37 @@ class Element(Plugin):
    671 671
             if self.__can_build_incrementally() and workspace.last_successful:
    
    672 672
                 old_dep_keys = self.__get_artifact_metadata_dependencies(workspace.last_successful)
    
    673 673
     
    
    674
    -        for dep in self.dependencies(scope):
    
    674
    +        for element in self.dependencies(scope):
    
    675 675
                 # If we are workspaced, and we therefore perform an
    
    676 676
                 # incremental build, we must ensure that we update the mtimes
    
    677 677
                 # of any files created by our dependencies since the last
    
    678 678
                 # successful build.
    
    679 679
                 to_update = None
    
    680 680
                 if workspace and old_dep_keys:
    
    681
    -                dep.__assert_cached()
    
    681
    +                element.__assert_cached()
    
    682 682
     
    
    683
    -                if dep.name in old_dep_keys:
    
    684
    -                    key_new = dep._get_cache_key()
    
    685
    -                    key_old = old_dep_keys[dep.name]
    
    683
    +                if element.name in old_dep_keys:
    
    684
    +                    key_new = element._get_cache_key()
    
    685
    +                    key_old = old_dep_keys[element.name]
    
    686 686
     
    
    687 687
                         # We only need to worry about modified and added
    
    688 688
                         # files, since removed files will be picked up by
    
    689 689
                         # build systems anyway.
    
    690
    -                    to_update, _, added = self.__artifacts.diff(dep, key_old, key_new, subdir='files')
    
    691
    -                    workspace.add_running_files(dep.name, to_update + added)
    
    692
    -                    to_update.extend(workspace.running_files[dep.name])
    
    690
    +                    to_update, _, added = self.__artifacts.diff(element, key_old, key_new, subdir='files')
    
    691
    +                    workspace.add_running_files(element.name, to_update + added)
    
    692
    +                    to_update.extend(workspace.running_files[element.name])
    
    693 693
     
    
    694 694
                         # In case we are running `bst shell`, this happens in the
    
    695 695
                         # main process and we need to update the workspace config
    
    696 696
                         if utils._is_main_process():
    
    697 697
                             self._get_context().get_workspaces().save_config()
    
    698 698
     
    
    699
    -            result = dep.stage_artifact(sandbox,
    
    700
    -                                        path=path,
    
    701
    -                                        include=include,
    
    702
    -                                        exclude=exclude,
    
    703
    -                                        orphans=orphans,
    
    704
    -                                        update_mtimes=to_update)
    
    699
    +            result = element.stage_artifact(sandbox,
    
    700
    +                                            path=path,
    
    701
    +                                            include=include,
    
    702
    +                                            exclude=exclude,
    
    703
    +                                            orphans=orphans,
    
    704
    +                                            update_mtimes=to_update)
    
    705 705
                 if result.overwritten:
    
    706 706
                     for overwrite in result.overwritten:
    
    707 707
                         # Completely new overwrite
    
    ... ... @@ -710,13 +710,13 @@ class Element(Plugin):
    710 710
                             # written the element before
    
    711 711
                             for elm, contents in files_written.items():
    
    712 712
                                 if overwrite in contents:
    
    713
    -                                overlaps[overwrite] = [elm, dep.name]
    
    713
    +                                overlaps[overwrite] = [elm, element.name]
    
    714 714
                         else:
    
    715
    -                        overlaps[overwrite].append(dep.name)
    
    716
    -            files_written[dep.name] = result.files_written
    
    715
    +                        overlaps[overwrite].append(element.name)
    
    716
    +            files_written[element.name] = result.files_written
    
    717 717
     
    
    718 718
                 if result.ignored:
    
    719
    -                ignored[dep.name] = result.ignored
    
    719
    +                ignored[element.name] = result.ignored
    
    720 720
     
    
    721 721
             if overlaps:
    
    722 722
                 overlap_warning = False
    
    ... ... @@ -1318,17 +1318,24 @@ class Element(Plugin):
    1318 1318
                     if scope == Scope.BUILD:
    
    1319 1319
                         self.stage(sandbox)
    
    1320 1320
                     elif scope == Scope.RUN:
    
    1321
    +
    
    1322
    +                    if deps == 'build':
    
    1323
    +                        dependency_scope = Scope.BUILD
    
    1324
    +                    elif deps == 'run':
    
    1325
    +                        dependency_scope = Scope.RUN
    
    1326
    +                    else:
    
    1327
    +                        dependency_scope = Scope.NONE
    
    1328
    +
    
    1321 1329
                         # Stage deps in the sandbox root
    
    1322
    -                    if deps == 'run':
    
    1323
    -                        with self.timed_activity("Staging dependencies", silent_nested=True):
    
    1324
    -                            self.stage_dependency_artifacts(sandbox, scope)
    
    1330
    +                    with self.timed_activity("Staging dependencies", silent_nested=True):
    
    1331
    +                        self.stage_dependency_artifacts(sandbox, dependency_scope)
    
    1325 1332
     
    
    1326
    -                        # Run any integration commands provided by the dependencies
    
    1327
    -                        # once they are all staged and ready
    
    1328
    -                        if integrate:
    
    1329
    -                            with self.timed_activity("Integrating sandbox"):
    
    1330
    -                                for dep in self.dependencies(scope):
    
    1331
    -                                    dep.integrate(sandbox)
    
    1333
    +                    # Run any integration commands provided by the dependencies
    
    1334
    +                    # once they are all staged and ready
    
    1335
    +                    if integrate:
    
    1336
    +                        with self.timed_activity("Integrating sandbox"):
    
    1337
    +                            for dep in self.dependencies(dependency_scope):
    
    1338
    +                                dep.integrate(sandbox)
    
    1332 1339
     
    
    1333 1340
                 yield sandbox
    
    1334 1341
     
    
    ... ... @@ -2084,7 +2091,7 @@ class Element(Plugin):
    2084 2091
         #
    
    2085 2092
         # Raises an error if the artifact is not cached.
    
    2086 2093
         #
    
    2087
    -    def __assert_cached(self, keystrength=_KeyStrength.STRONG):
    
    2094
    +    def __assert_cached(self, keystrength=None):
    
    2088 2095
             assert self.__is_cached(keystrength=keystrength), "{}: Missing artifact {}".format(
    
    2089 2096
                 self, self._get_brief_display_key())
    
    2090 2097
     
    

  • buildstream/element_enums.py
    ... ... @@ -59,3 +59,7 @@ class Scope(Enum):
    59 59
         """All elements required for running the element. Including the element
    
    60 60
         itself.
    
    61 61
         """
    
    62
    +
    
    63
    +    NONE = 4
    
    64
    +    """Just the element itself, no dependencies.
    
    65
    +    """

  • tests/frontend/buildcheckout.py
    ... ... @@ -61,13 +61,14 @@ def test_build_checkout(datafiles, cli, strict, hardlinks):
    61 61
     
    
    62 62
     
    
    63 63
     @pytest.mark.datafiles(DATA_DIR)
    
    64
    -@pytest.mark.parametrize("deps", [("run"), ("none")])
    
    64
    +@pytest.mark.parametrize("deps", [("run"), ("none"), ("build")])
    
    65 65
     def test_build_checkout_deps(datafiles, cli, deps):
    
    66 66
         project = os.path.join(datafiles.dirname, datafiles.basename)
    
    67 67
         checkout = os.path.join(cli.directory, 'checkout')
    
    68
    +    element_name = 'checkout-deps.bst'
    
    68 69
     
    
    69 70
         # First build it
    
    70
    -    result = cli.run(project=project, args=['build', 'target.bst'])
    
    71
    +    result = cli.run(project=project, args=['build', element_name])
    
    71 72
         result.assert_success()
    
    72 73
     
    
    73 74
         # Assert that after a successful build, the builddir is empty
    
    ... ... @@ -76,20 +77,25 @@ def test_build_checkout_deps(datafiles, cli, deps):
    76 77
         assert not os.listdir(builddir)
    
    77 78
     
    
    78 79
         # Now check it out
    
    79
    -    result = cli.run(project=project, args=['checkout', 'target.bst', '--deps', deps, checkout])
    
    80
    +    result = cli.run(project=project, args=['checkout', element_name, '--deps', deps, checkout])
    
    80 81
         result.assert_success()
    
    81 82
     
    
    82
    -    # Check that the executable hello file is found in the checkout
    
    83
    -    filename = os.path.join(checkout, 'usr', 'bin', 'hello')
    
    83
    +    # Verify output of this element
    
    84
    +    filename = os.path.join(checkout, 'etc', 'buildstream', 'config')
    
    85
    +    if deps == "build":
    
    86
    +        assert not os.path.exists(filename)
    
    87
    +    else:
    
    88
    +        assert os.path.exists(filename)
    
    84 89
     
    
    85
    -    if deps == "run":
    
    90
    +    # Verify output of this element's build dependencies
    
    91
    +    filename = os.path.join(checkout, 'usr', 'include', 'pony.h')
    
    92
    +    if deps == "build":
    
    86 93
             assert os.path.exists(filename)
    
    87 94
         else:
    
    88 95
             assert not os.path.exists(filename)
    
    89 96
     
    
    90
    -    # Check that the executable hello file is found in the checkout
    
    91
    -    filename = os.path.join(checkout, 'usr', 'include', 'pony.h')
    
    92
    -
    
    97
    +    # Verify output of this element's runtime dependencies
    
    98
    +    filename = os.path.join(checkout, 'usr', 'bin', 'hello')
    
    93 99
         if deps == "run":
    
    94 100
             assert os.path.exists(filename)
    
    95 101
         else:
    

  • tests/frontend/project/elements/checkout-deps.bst
    1
    +kind: import
    
    2
    +description: It is important for this element to have both build and runtime dependencies
    
    3
    +sources:
    
    4
    +- kind: local
    
    5
    +  path: files/etc-files
    
    6
    +depends:
    
    7
    +- filename: import-dev.bst
    
    8
    +  type: build
    
    9
    +- filename: import-bin.bst
    
    10
    +  type: runtime

  • tests/frontend/project/elements/rebuild-target.bst
    1
    +kind: compose
    
    2
    +
    
    3
    +build-depends:
    
    4
    +- target.bst

  • tests/frontend/project/files/etc-files/etc/buildstream/config
    1
    +config

  • tests/frontend/rebuild.py
    1
    +import os
    
    2
    +import pytest
    
    3
    +from tests.testutils import cli
    
    4
    +
    
    5
    +# Project directory
    
    6
    +DATA_DIR = os.path.join(
    
    7
    +    os.path.dirname(os.path.realpath(__file__)),
    
    8
    +    "project",
    
    9
    +)
    
    10
    +
    
    11
    +
    
    12
    +def strict_args(args, strict):
    
    13
    +    if strict != "strict":
    
    14
    +        return ['--no-strict'] + args
    
    15
    +    return args
    
    16
    +
    
    17
    +
    
    18
    +@pytest.mark.datafiles(DATA_DIR)
    
    19
    +@pytest.mark.parametrize("strict", ["strict", "non-strict"])
    
    20
    +def test_rebuild(datafiles, cli, strict):
    
    21
    +    project = os.path.join(datafiles.dirname, datafiles.basename)
    
    22
    +    checkout = os.path.join(cli.directory, 'checkout')
    
    23
    +
    
    24
    +    # First build intermediate target.bst
    
    25
    +    result = cli.run(project=project, args=strict_args(['build', 'target.bst'], strict))
    
    26
    +    result.assert_success()
    
    27
    +
    
    28
    +    # Modify base import
    
    29
    +    with open(os.path.join(project, 'files', 'dev-files', 'usr', 'include', 'new.h'), "w") as f:
    
    30
    +        f.write("#define NEW")
    
    31
    +
    
    32
    +    # Rebuild base import and build top-level rebuild-target.bst
    
    33
    +    # In non-strict mode, this does not rebuild intermediate target.bst,
    
    34
    +    # which means that a weakly cached target.bst will be staged as dependency.
    
    35
    +    result = cli.run(project=project, args=strict_args(['build', 'rebuild-target.bst'], strict))
    
    36
    +    result.assert_success()



  • [Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]