diff options
| -rw-r--r-- | meta/lib/oeqa/selftest/cases/reproducible.py | 66 |
1 files changed, 35 insertions, 31 deletions
diff --git a/meta/lib/oeqa/selftest/cases/reproducible.py b/meta/lib/oeqa/selftest/cases/reproducible.py index db538a4f89..b7484f3e10 100644 --- a/meta/lib/oeqa/selftest/cases/reproducible.py +++ b/meta/lib/oeqa/selftest/cases/reproducible.py | |||
| @@ -80,6 +80,13 @@ class ReproducibleTests(OESelftestTestCase): | |||
| 80 | package_classes = ['deb', 'ipk'] | 80 | package_classes = ['deb', 'ipk'] |
| 81 | images = ['core-image-minimal', 'core-image-sato', 'core-image-full-cmdline'] | 81 | images = ['core-image-minimal', 'core-image-sato', 'core-image-full-cmdline'] |
| 82 | save_results = False | 82 | save_results = False |
| 83 | # This variable controls if one of the test builds is allowed to pull from | ||
| 84 | # an sstate cache/mirror. The other build is always done clean as a point of | ||
| 85 | # comparison. | ||
| 86 | # If you know that your sstate archives are reproducible, enabling this | ||
| 87 | # will test that and also make the test run faster. If your sstate is not | ||
| 88 | # reproducible, disable this in your derived test class | ||
| 89 | build_from_sstate = True | ||
| 83 | 90 | ||
| 84 | def setUpLocal(self): | 91 | def setUpLocal(self): |
| 85 | super().setUpLocal() | 92 | super().setUpLocal() |
| @@ -127,7 +134,7 @@ class ReproducibleTests(OESelftestTestCase): | |||
| 127 | bb.utils.mkdirhier(os.path.dirname(dest)) | 134 | bb.utils.mkdirhier(os.path.dirname(dest)) |
| 128 | shutil.copyfile(source, dest) | 135 | shutil.copyfile(source, dest) |
| 129 | 136 | ||
| 130 | def test_reproducible_builds(self): | 137 | def do_test_build(self, name, use_sstate): |
| 131 | capture_vars = ['DEPLOY_DIR_' + c.upper() for c in self.package_classes] | 138 | capture_vars = ['DEPLOY_DIR_' + c.upper() for c in self.package_classes] |
| 132 | 139 | ||
| 133 | if self.save_results: | 140 | if self.save_results: |
| @@ -135,41 +142,38 @@ class ReproducibleTests(OESelftestTestCase): | |||
| 135 | os.chmod(save_dir, stat.S_IRWXU | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH) | 142 | os.chmod(save_dir, stat.S_IRWXU | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH) |
| 136 | self.logger.info('Non-reproducible packages will be copied to %s', save_dir) | 143 | self.logger.info('Non-reproducible packages will be copied to %s', save_dir) |
| 137 | 144 | ||
| 138 | # Build native utilities | 145 | tmpdir = os.path.join(self.topdir, name, 'tmp') |
| 139 | self.write_config('') | 146 | if os.path.exists(tmpdir): |
| 140 | bitbake("diffutils-native -c addto_recipe_sysroot") | 147 | bb.utils.remove(tmpdir, recurse=True) |
| 141 | diffutils_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "diffutils-native") | ||
| 142 | 148 | ||
| 143 | # Reproducible builds should not pull from sstate or mirrors, but | 149 | config = textwrap.dedent('''\ |
| 144 | # sharing DL_DIR is fine | ||
| 145 | common_config = textwrap.dedent('''\ | ||
| 146 | INHERIT += "reproducible_build" | 150 | INHERIT += "reproducible_build" |
| 147 | PACKAGE_CLASSES = "%s" | 151 | PACKAGE_CLASSES = "{package_classes}" |
| 148 | SSTATE_DIR = "${TMPDIR}/sstate" | 152 | TMPDIR = "{tmpdir}" |
| 149 | ''') % (' '.join('package_%s' % c for c in self.package_classes)) | 153 | ''').format(package_classes=' '.join('package_%s' % c for c in self.package_classes), |
| 150 | 154 | tmpdir=tmpdir) | |
| 151 | # Perform a build. | 155 | |
| 152 | reproducibleA_tmp = os.path.join(self.topdir, 'reproducibleA', 'tmp') | 156 | if not use_sstate: |
| 153 | if os.path.exists(reproducibleA_tmp): | 157 | # This config fragment will disable using shared and the sstate |
| 154 | bb.utils.remove(reproducibleA_tmp, recurse=True) | 158 | # mirror, forcing a complete build from scratch |
| 155 | 159 | config += textwrap.dedent('''\ | |
| 156 | self.write_config((textwrap.dedent('''\ | 160 | SSTATE_DIR = "${TMPDIR}/sstate" |
| 157 | TMPDIR = "%s" | 161 | SSTATE_MIRROR = "" |
| 158 | ''') % reproducibleA_tmp) + common_config) | 162 | ''') |
| 159 | vars_A = get_bb_vars(capture_vars) | 163 | |
| 164 | self.write_config(config) | ||
| 165 | d = get_bb_vars(capture_vars) | ||
| 160 | bitbake(' '.join(self.images)) | 166 | bitbake(' '.join(self.images)) |
| 167 | return d | ||
| 161 | 168 | ||
| 162 | # Perform another build. | 169 | def test_reproducible_builds(self): |
| 163 | reproducibleB_tmp = os.path.join(self.topdir, 'reproducibleB', 'tmp') | 170 | # Build native utilities |
| 164 | if os.path.exists(reproducibleB_tmp): | 171 | self.write_config('') |
| 165 | bb.utils.remove(reproducibleB_tmp, recurse=True) | 172 | bitbake("diffutils-native -c addto_recipe_sysroot") |
| 173 | diffutils_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "diffutils-native") | ||
| 166 | 174 | ||
| 167 | self.write_config((textwrap.dedent('''\ | 175 | vars_A = self.do_test_build('reproducibleA', self.build_from_sstate) |
| 168 | SSTATE_MIRROR = "" | 176 | vars_B = self.do_test_build('reproducibleB', False) |
| 169 | TMPDIR = "%s" | ||
| 170 | ''') % reproducibleB_tmp) + common_config) | ||
| 171 | vars_B = get_bb_vars(capture_vars) | ||
| 172 | bitbake(' '.join(self.images)) | ||
| 173 | 177 | ||
| 174 | # NOTE: The temp directories from the reproducible build are purposely | 178 | # NOTE: The temp directories from the reproducible build are purposely |
| 175 | # kept after the build so it can be diffed for debugging. | 179 | # kept after the build so it can be diffed for debugging. |
