Brad Bishop | c342db3 | 2019-05-15 21:57:59 -0400 | [diff] [blame] | 1 | # |
Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame] | 2 | # Copyright OpenEmbedded Contributors |
| 3 | # |
Brad Bishop | c342db3 | 2019-05-15 21:57:59 -0400 | [diff] [blame] | 4 | # SPDX-License-Identifier: GPL-2.0-only |
| 5 | # |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 6 | # This class should provide easy access to the different aspects of the |
| 7 | # buildsystem such as layers, bitbake location, etc. |
Brad Bishop | 1a4b7ee | 2018-12-16 17:11:34 -0800 | [diff] [blame] | 8 | # |
| 9 | # SDK_LAYERS_EXCLUDE: Layers which will be excluded from SDK layers. |
| 10 | # SDK_LAYERS_EXCLUDE_PATTERN: The simiar to SDK_LAYERS_EXCLUDE, this supports |
| 11 | # python regular expression, use space as separator, |
| 12 | # e.g.: ".*-downloads closed-.*" |
| 13 | # |
| 14 | |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 15 | import stat |
| 16 | import shutil |
| 17 | |
| 18 | def _smart_copy(src, dest): |
Brad Bishop | 37a0e4d | 2017-12-04 01:01:44 -0500 | [diff] [blame] | 19 | import subprocess |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 20 | # smart_copy will choose the correct function depending on whether the |
| 21 | # source is a file or a directory. |
| 22 | mode = os.stat(src).st_mode |
| 23 | if stat.S_ISDIR(mode): |
Brad Bishop | 37a0e4d | 2017-12-04 01:01:44 -0500 | [diff] [blame] | 24 | bb.utils.mkdirhier(dest) |
Andrew Geissler | 95ac1b8 | 2021-03-31 14:34:31 -0500 | [diff] [blame] | 25 | cmd = "tar --exclude='.git' --exclude='__pycache__' --xattrs --xattrs-include='*' -chf - -C %s -p . \ |
Brad Bishop | 37a0e4d | 2017-12-04 01:01:44 -0500 | [diff] [blame] | 26 | | tar --xattrs --xattrs-include='*' -xf - -C %s" % (src, dest) |
| 27 | subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT) |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 28 | else: |
| 29 | shutil.copyfile(src, dest) |
| 30 | shutil.copymode(src, dest) |
| 31 | |
| 32 | class BuildSystem(object): |
Patrick Williams | f1e5d69 | 2016-03-30 15:21:19 -0500 | [diff] [blame] | 33 | def __init__(self, context, d): |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 34 | self.d = d |
Patrick Williams | f1e5d69 | 2016-03-30 15:21:19 -0500 | [diff] [blame] | 35 | self.context = context |
Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 36 | self.layerdirs = [os.path.abspath(pth) for pth in d.getVar('BBLAYERS').split()] |
| 37 | self.layers_exclude = (d.getVar('SDK_LAYERS_EXCLUDE') or "").split() |
Brad Bishop | 1a4b7ee | 2018-12-16 17:11:34 -0800 | [diff] [blame] | 38 | self.layers_exclude_pattern = d.getVar('SDK_LAYERS_EXCLUDE_PATTERN') |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 39 | |
Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 40 | def copy_bitbake_and_layers(self, destdir, workspace_name=None): |
Brad Bishop | 1a4b7ee | 2018-12-16 17:11:34 -0800 | [diff] [blame] | 41 | import re |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 42 | # Copy in all metadata layers + bitbake (as repositories) |
Brad Bishop | 1a4b7ee | 2018-12-16 17:11:34 -0800 | [diff] [blame] | 43 | copied_corebase = None |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 44 | layers_copied = [] |
| 45 | bb.utils.mkdirhier(destdir) |
| 46 | layers = list(self.layerdirs) |
| 47 | |
Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 48 | corebase = os.path.abspath(self.d.getVar('COREBASE')) |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 49 | layers.append(corebase) |
Brad Bishop | d7bf8c1 | 2018-02-25 22:55:05 -0500 | [diff] [blame] | 50 | # The bitbake build system uses the meta-skeleton layer as a layout |
| 51 | # for common recipies, e.g: the recipetool script to create kernel recipies |
| 52 | # Add the meta-skeleton layer to be included as part of the eSDK installation |
| 53 | layers.append(os.path.join(corebase, 'meta-skeleton')) |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 54 | |
Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 55 | # Exclude layers |
| 56 | for layer_exclude in self.layers_exclude: |
| 57 | if layer_exclude in layers: |
Brad Bishop | 1a4b7ee | 2018-12-16 17:11:34 -0800 | [diff] [blame] | 58 | bb.note('Excluded %s from sdk layers since it is in SDK_LAYERS_EXCLUDE' % layer_exclude) |
Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 59 | layers.remove(layer_exclude) |
| 60 | |
Brad Bishop | 1a4b7ee | 2018-12-16 17:11:34 -0800 | [diff] [blame] | 61 | if self.layers_exclude_pattern: |
| 62 | layers_cp = layers[:] |
| 63 | for pattern in self.layers_exclude_pattern.split(): |
| 64 | for layer in layers_cp: |
| 65 | if re.match(pattern, layer): |
| 66 | bb.note('Excluded %s from sdk layers since matched SDK_LAYERS_EXCLUDE_PATTERN' % layer) |
| 67 | layers.remove(layer) |
| 68 | |
Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 69 | workspace_newname = workspace_name |
| 70 | if workspace_newname: |
| 71 | layernames = [os.path.basename(layer) for layer in layers] |
| 72 | extranum = 0 |
| 73 | while workspace_newname in layernames: |
| 74 | extranum += 1 |
| 75 | workspace_newname = '%s-%d' % (workspace_name, extranum) |
| 76 | |
Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 77 | corebase_files = self.d.getVar('COREBASE_FILES').split() |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 78 | corebase_files = [corebase + '/' +x for x in corebase_files] |
| 79 | # Make sure bitbake goes in |
| 80 | bitbake_dir = bb.__file__.rsplit('/', 3)[0] |
| 81 | corebase_files.append(bitbake_dir) |
| 82 | |
| 83 | for layer in layers: |
| 84 | layerconf = os.path.join(layer, 'conf', 'layer.conf') |
Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 85 | layernewname = os.path.basename(layer) |
| 86 | workspace = False |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 87 | if os.path.exists(layerconf): |
| 88 | with open(layerconf, 'r') as f: |
| 89 | if f.readline().startswith("# ### workspace layer auto-generated by devtool ###"): |
Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 90 | if workspace_newname: |
| 91 | layernewname = workspace_newname |
| 92 | workspace = True |
| 93 | else: |
| 94 | bb.plain("NOTE: Excluding local workspace layer %s from %s" % (layer, self.context)) |
| 95 | continue |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 96 | |
| 97 | # If the layer was already under corebase, leave it there |
| 98 | # since layers such as meta have issues when moved. |
| 99 | layerdestpath = destdir |
| 100 | if corebase == os.path.dirname(layer): |
| 101 | layerdestpath += '/' + os.path.basename(corebase) |
Andrew Geissler | 9aee500 | 2022-03-30 16:27:02 +0000 | [diff] [blame] | 102 | # If the layer is located somewhere under the same parent directory |
| 103 | # as corebase we keep the layer structure. |
| 104 | elif os.path.commonpath([layer, corebase]) == os.path.dirname(corebase): |
| 105 | layer_relative = os.path.relpath(layer, os.path.dirname(corebase)) |
Brad Bishop | d7bf8c1 | 2018-02-25 22:55:05 -0500 | [diff] [blame] | 106 | if os.path.dirname(layer_relative) != layernewname: |
| 107 | layerdestpath += '/' + os.path.dirname(layer_relative) |
| 108 | |
Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 109 | layerdestpath += '/' + layernewname |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 110 | |
| 111 | layer_relative = os.path.relpath(layerdestpath, |
| 112 | destdir) |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 113 | # Treat corebase as special since it typically will contain |
| 114 | # build directories or other custom items. |
| 115 | if corebase == layer: |
Brad Bishop | 1a4b7ee | 2018-12-16 17:11:34 -0800 | [diff] [blame] | 116 | copied_corebase = layer_relative |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 117 | bb.utils.mkdirhier(layerdestpath) |
| 118 | for f in corebase_files: |
| 119 | f_basename = os.path.basename(f) |
| 120 | destname = os.path.join(layerdestpath, f_basename) |
| 121 | _smart_copy(f, destname) |
| 122 | else: |
Brad Bishop | 1a4b7ee | 2018-12-16 17:11:34 -0800 | [diff] [blame] | 123 | layers_copied.append(layer_relative) |
| 124 | |
Brad Bishop | 316dfdd | 2018-06-25 12:45:53 -0400 | [diff] [blame] | 125 | if os.path.exists(os.path.join(layerdestpath, 'conf/layer.conf')): |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 126 | bb.note("Skipping layer %s, already handled" % layer) |
| 127 | else: |
| 128 | _smart_copy(layer, layerdestpath) |
| 129 | |
Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 130 | if workspace: |
| 131 | # Make some adjustments original workspace layer |
| 132 | # Drop sources (recipe tasks will be locked, so we don't need them) |
| 133 | srcdir = os.path.join(layerdestpath, 'sources') |
| 134 | if os.path.isdir(srcdir): |
| 135 | shutil.rmtree(srcdir) |
| 136 | # Drop all bbappends except the one for the image the SDK is being built for |
| 137 | # (because of externalsrc, the workspace bbappends will interfere with the |
| 138 | # locked signatures if present, and we don't need them anyway) |
Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 139 | image_bbappend = os.path.splitext(os.path.basename(self.d.getVar('FILE')))[0] + '.bbappend' |
Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 140 | appenddir = os.path.join(layerdestpath, 'appends') |
| 141 | if os.path.isdir(appenddir): |
| 142 | for fn in os.listdir(appenddir): |
| 143 | if fn == image_bbappend: |
| 144 | continue |
| 145 | else: |
| 146 | os.remove(os.path.join(appenddir, fn)) |
| 147 | # Drop README |
| 148 | readme = os.path.join(layerdestpath, 'README') |
| 149 | if os.path.exists(readme): |
| 150 | os.remove(readme) |
| 151 | # Filter out comments in layer.conf and change layer name |
| 152 | layerconf = os.path.join(layerdestpath, 'conf', 'layer.conf') |
| 153 | with open(layerconf, 'r') as f: |
| 154 | origlines = f.readlines() |
| 155 | with open(layerconf, 'w') as f: |
| 156 | for line in origlines: |
| 157 | if line.startswith('#'): |
| 158 | continue |
| 159 | line = line.replace('workspacelayer', workspace_newname) |
| 160 | f.write(line) |
| 161 | |
Brad Bishop | d7bf8c1 | 2018-02-25 22:55:05 -0500 | [diff] [blame] | 162 | # meta-skeleton layer is added as part of the build system |
| 163 | # but not as a layer included in the build, therefore it is |
| 164 | # not reported to the function caller. |
| 165 | for layer in layers_copied: |
| 166 | if layer.endswith('/meta-skeleton'): |
| 167 | layers_copied.remove(layer) |
| 168 | break |
| 169 | |
Brad Bishop | 1a4b7ee | 2018-12-16 17:11:34 -0800 | [diff] [blame] | 170 | return copied_corebase, layers_copied |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 171 | |
| 172 | def generate_locked_sigs(sigfile, d): |
| 173 | bb.utils.mkdirhier(os.path.dirname(sigfile)) |
Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 174 | depd = d.getVar('BB_TASKDEPDATA', False) |
Brad Bishop | 08902b0 | 2019-08-20 09:16:51 -0400 | [diff] [blame] | 175 | tasks = ['%s:%s' % (v[2], v[1]) for v in depd.values()] |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 176 | bb.parse.siggen.dump_lockedsigs(sigfile, tasks) |
| 177 | |
Brad Bishop | a34c030 | 2019-09-23 22:34:48 -0400 | [diff] [blame] | 178 | def prune_lockedsigs(excluded_tasks, excluded_targets, lockedsigs, onlynative, pruned_output): |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 179 | with open(lockedsigs, 'r') as infile: |
| 180 | bb.utils.mkdirhier(os.path.dirname(pruned_output)) |
| 181 | with open(pruned_output, 'w') as f: |
| 182 | invalue = False |
| 183 | for line in infile: |
| 184 | if invalue: |
| 185 | if line.endswith('\\\n'): |
| 186 | splitval = line.strip().split(':') |
Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 187 | if not splitval[1] in excluded_tasks and not splitval[0] in excluded_targets: |
Brad Bishop | a34c030 | 2019-09-23 22:34:48 -0400 | [diff] [blame] | 188 | if onlynative: |
| 189 | if 'nativesdk' in splitval[0]: |
| 190 | f.write(line) |
| 191 | else: |
| 192 | f.write(line) |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 193 | else: |
| 194 | f.write(line) |
| 195 | invalue = False |
| 196 | elif line.startswith('SIGGEN_LOCKEDSIGS'): |
| 197 | invalue = True |
| 198 | f.write(line) |
| 199 | |
Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 200 | def merge_lockedsigs(copy_tasks, lockedsigs_main, lockedsigs_extra, merged_output, copy_output=None): |
Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 201 | merged = {} |
| 202 | arch_order = [] |
| 203 | with open(lockedsigs_main, 'r') as f: |
| 204 | invalue = None |
| 205 | for line in f: |
| 206 | if invalue: |
| 207 | if line.endswith('\\\n'): |
| 208 | merged[invalue].append(line) |
| 209 | else: |
| 210 | invalue = None |
| 211 | elif line.startswith('SIGGEN_LOCKEDSIGS_t-'): |
| 212 | invalue = line[18:].split('=', 1)[0].rstrip() |
| 213 | merged[invalue] = [] |
| 214 | arch_order.append(invalue) |
| 215 | |
| 216 | with open(lockedsigs_extra, 'r') as f: |
| 217 | invalue = None |
| 218 | tocopy = {} |
| 219 | for line in f: |
| 220 | if invalue: |
| 221 | if line.endswith('\\\n'): |
| 222 | if not line in merged[invalue]: |
| 223 | target, task = line.strip().split(':')[:2] |
| 224 | if not copy_tasks or task in copy_tasks: |
| 225 | tocopy[invalue].append(line) |
| 226 | merged[invalue].append(line) |
| 227 | else: |
| 228 | invalue = None |
| 229 | elif line.startswith('SIGGEN_LOCKEDSIGS_t-'): |
| 230 | invalue = line[18:].split('=', 1)[0].rstrip() |
| 231 | if not invalue in merged: |
| 232 | merged[invalue] = [] |
| 233 | arch_order.append(invalue) |
| 234 | tocopy[invalue] = [] |
| 235 | |
| 236 | def write_sigs_file(fn, types, sigs): |
| 237 | fulltypes = [] |
| 238 | bb.utils.mkdirhier(os.path.dirname(fn)) |
| 239 | with open(fn, 'w') as f: |
| 240 | for typename in types: |
| 241 | lines = sigs[typename] |
| 242 | if lines: |
| 243 | f.write('SIGGEN_LOCKEDSIGS_%s = "\\\n' % typename) |
| 244 | for line in lines: |
| 245 | f.write(line) |
| 246 | f.write(' "\n') |
| 247 | fulltypes.append(typename) |
| 248 | f.write('SIGGEN_LOCKEDSIGS_TYPES = "%s"\n' % ' '.join(fulltypes)) |
| 249 | |
Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 250 | if copy_output: |
| 251 | write_sigs_file(copy_output, list(tocopy.keys()), tocopy) |
Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 252 | if merged_output: |
| 253 | write_sigs_file(merged_output, arch_order, merged) |
| 254 | |
Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 255 | def create_locked_sstate_cache(lockedsigs, input_sstate_cache, output_sstate_cache, d, fixedlsbstring="", filterfile=None): |
| 256 | import shutil |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 257 | bb.note('Generating sstate-cache...') |
| 258 | |
Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 259 | nativelsbstring = d.getVar('NATIVELSBSTRING') |
Andrew Geissler | 95ac1b8 | 2021-03-31 14:34:31 -0500 | [diff] [blame] | 260 | bb.process.run("PYTHONDONTWRITEBYTECODE=1 gen-lockedsig-cache %s %s %s %s %s" % (lockedsigs, input_sstate_cache, output_sstate_cache, nativelsbstring, filterfile or '')) |
Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 261 | if fixedlsbstring and nativelsbstring != fixedlsbstring: |
Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 262 | nativedir = output_sstate_cache + '/' + nativelsbstring |
| 263 | if os.path.isdir(nativedir): |
| 264 | destdir = os.path.join(output_sstate_cache, fixedlsbstring) |
Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 265 | for root, _, files in os.walk(nativedir): |
| 266 | for fn in files: |
| 267 | src = os.path.join(root, fn) |
| 268 | dest = os.path.join(destdir, os.path.relpath(src, nativedir)) |
| 269 | if os.path.exists(dest): |
| 270 | # Already exists, and it'll be the same file, so just delete it |
| 271 | os.unlink(src) |
| 272 | else: |
| 273 | bb.utils.mkdirhier(os.path.dirname(dest)) |
| 274 | shutil.move(src, dest) |
Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 275 | |
Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 276 | def check_sstate_task_list(d, targets, filteroutfile, cmdprefix='', cwd=None, logfile=None): |
| 277 | import subprocess |
| 278 | |
| 279 | bb.note('Generating sstate task list...') |
| 280 | |
| 281 | if not cwd: |
| 282 | cwd = os.getcwd() |
| 283 | if logfile: |
| 284 | logparam = '-l %s' % logfile |
| 285 | else: |
| 286 | logparam = '' |
Andrew Geissler | 95ac1b8 | 2021-03-31 14:34:31 -0500 | [diff] [blame] | 287 | cmd = "%sPYTHONDONTWRITEBYTECODE=1 BB_SETSCENE_ENFORCE=1 PSEUDO_DISABLED=1 oe-check-sstate %s -s -o %s %s" % (cmdprefix, targets, filteroutfile, logparam) |
Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 288 | env = dict(d.getVar('BB_ORIGENV', False)) |
| 289 | env.pop('BUILDDIR', '') |
Brad Bishop | d7bf8c1 | 2018-02-25 22:55:05 -0500 | [diff] [blame] | 290 | env.pop('BBPATH', '') |
Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 291 | pathitems = env['PATH'].split(':') |
| 292 | env['PATH'] = ':'.join([item for item in pathitems if not item.endswith('/bitbake/bin')]) |
| 293 | bb.process.run(cmd, stderr=subprocess.STDOUT, env=env, cwd=cwd, executable='/bin/bash') |