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. |