blob: afaff6859850231f2f60e347170affe793acb52e [file] [log] [blame]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001# This class should provide easy access to the different aspects of the
2# buildsystem such as layers, bitbake location, etc.
3import stat
4import shutil
5
6def _smart_copy(src, dest):
7 # smart_copy will choose the correct function depending on whether the
8 # source is a file or a directory.
9 mode = os.stat(src).st_mode
10 if stat.S_ISDIR(mode):
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050011 shutil.copytree(src, dest, symlinks=True, ignore=shutil.ignore_patterns('.git'))
Patrick Williamsc124f4f2015-09-15 14:41:29 -050012 else:
13 shutil.copyfile(src, dest)
14 shutil.copymode(src, dest)
15
16class BuildSystem(object):
Patrick Williamsf1e5d692016-03-30 15:21:19 -050017 def __init__(self, context, d):
Patrick Williamsc124f4f2015-09-15 14:41:29 -050018 self.d = d
Patrick Williamsf1e5d692016-03-30 15:21:19 -050019 self.context = context
Patrick Williamsc0f7c042017-02-23 20:41:17 -060020 self.layerdirs = [os.path.abspath(pth) for pth in d.getVar('BBLAYERS', True).split()]
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050021 self.layers_exclude = (d.getVar('SDK_LAYERS_EXCLUDE', True) or "").split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -050022
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050023 def copy_bitbake_and_layers(self, destdir, workspace_name=None):
Patrick Williamsc124f4f2015-09-15 14:41:29 -050024 # Copy in all metadata layers + bitbake (as repositories)
25 layers_copied = []
26 bb.utils.mkdirhier(destdir)
27 layers = list(self.layerdirs)
28
Patrick Williamsc0f7c042017-02-23 20:41:17 -060029 corebase = os.path.abspath(self.d.getVar('COREBASE', True))
Patrick Williamsc124f4f2015-09-15 14:41:29 -050030 layers.append(corebase)
31
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050032 # Exclude layers
33 for layer_exclude in self.layers_exclude:
34 if layer_exclude in layers:
35 layers.remove(layer_exclude)
36
37 workspace_newname = workspace_name
38 if workspace_newname:
39 layernames = [os.path.basename(layer) for layer in layers]
40 extranum = 0
41 while workspace_newname in layernames:
42 extranum += 1
43 workspace_newname = '%s-%d' % (workspace_name, extranum)
44
Patrick Williamsc124f4f2015-09-15 14:41:29 -050045 corebase_files = self.d.getVar('COREBASE_FILES', True).split()
46 corebase_files = [corebase + '/' +x for x in corebase_files]
47 # Make sure bitbake goes in
48 bitbake_dir = bb.__file__.rsplit('/', 3)[0]
49 corebase_files.append(bitbake_dir)
50
51 for layer in layers:
52 layerconf = os.path.join(layer, 'conf', 'layer.conf')
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050053 layernewname = os.path.basename(layer)
54 workspace = False
Patrick Williamsc124f4f2015-09-15 14:41:29 -050055 if os.path.exists(layerconf):
56 with open(layerconf, 'r') as f:
57 if f.readline().startswith("# ### workspace layer auto-generated by devtool ###"):
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050058 if workspace_newname:
59 layernewname = workspace_newname
60 workspace = True
61 else:
62 bb.plain("NOTE: Excluding local workspace layer %s from %s" % (layer, self.context))
63 continue
Patrick Williamsc124f4f2015-09-15 14:41:29 -050064
65 # If the layer was already under corebase, leave it there
66 # since layers such as meta have issues when moved.
67 layerdestpath = destdir
68 if corebase == os.path.dirname(layer):
69 layerdestpath += '/' + os.path.basename(corebase)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050070 layerdestpath += '/' + layernewname
Patrick Williamsc124f4f2015-09-15 14:41:29 -050071
72 layer_relative = os.path.relpath(layerdestpath,
73 destdir)
74 layers_copied.append(layer_relative)
75
76 # Treat corebase as special since it typically will contain
77 # build directories or other custom items.
78 if corebase == layer:
79 bb.utils.mkdirhier(layerdestpath)
80 for f in corebase_files:
81 f_basename = os.path.basename(f)
82 destname = os.path.join(layerdestpath, f_basename)
83 _smart_copy(f, destname)
84 else:
85 if os.path.exists(layerdestpath):
86 bb.note("Skipping layer %s, already handled" % layer)
87 else:
88 _smart_copy(layer, layerdestpath)
89
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050090 if workspace:
91 # Make some adjustments original workspace layer
92 # Drop sources (recipe tasks will be locked, so we don't need them)
93 srcdir = os.path.join(layerdestpath, 'sources')
94 if os.path.isdir(srcdir):
95 shutil.rmtree(srcdir)
96 # Drop all bbappends except the one for the image the SDK is being built for
97 # (because of externalsrc, the workspace bbappends will interfere with the
98 # locked signatures if present, and we don't need them anyway)
99 image_bbappend = os.path.splitext(os.path.basename(self.d.getVar('FILE', True)))[0] + '.bbappend'
100 appenddir = os.path.join(layerdestpath, 'appends')
101 if os.path.isdir(appenddir):
102 for fn in os.listdir(appenddir):
103 if fn == image_bbappend:
104 continue
105 else:
106 os.remove(os.path.join(appenddir, fn))
107 # Drop README
108 readme = os.path.join(layerdestpath, 'README')
109 if os.path.exists(readme):
110 os.remove(readme)
111 # Filter out comments in layer.conf and change layer name
112 layerconf = os.path.join(layerdestpath, 'conf', 'layer.conf')
113 with open(layerconf, 'r') as f:
114 origlines = f.readlines()
115 with open(layerconf, 'w') as f:
116 for line in origlines:
117 if line.startswith('#'):
118 continue
119 line = line.replace('workspacelayer', workspace_newname)
120 f.write(line)
121
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500122 return layers_copied
123
124def generate_locked_sigs(sigfile, d):
125 bb.utils.mkdirhier(os.path.dirname(sigfile))
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500126 depd = d.getVar('BB_TASKDEPDATA', False)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600127 tasks = ['%s.%s' % (v[2], v[1]) for v in depd.values()]
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500128 bb.parse.siggen.dump_lockedsigs(sigfile, tasks)
129
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500130def prune_lockedsigs(excluded_tasks, excluded_targets, lockedsigs, pruned_output):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500131 with open(lockedsigs, 'r') as infile:
132 bb.utils.mkdirhier(os.path.dirname(pruned_output))
133 with open(pruned_output, 'w') as f:
134 invalue = False
135 for line in infile:
136 if invalue:
137 if line.endswith('\\\n'):
138 splitval = line.strip().split(':')
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500139 if not splitval[1] in excluded_tasks and not splitval[0] in excluded_targets:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500140 f.write(line)
141 else:
142 f.write(line)
143 invalue = False
144 elif line.startswith('SIGGEN_LOCKEDSIGS'):
145 invalue = True
146 f.write(line)
147
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600148def merge_lockedsigs(copy_tasks, lockedsigs_main, lockedsigs_extra, merged_output, copy_output=None):
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500149 merged = {}
150 arch_order = []
151 with open(lockedsigs_main, 'r') as f:
152 invalue = None
153 for line in f:
154 if invalue:
155 if line.endswith('\\\n'):
156 merged[invalue].append(line)
157 else:
158 invalue = None
159 elif line.startswith('SIGGEN_LOCKEDSIGS_t-'):
160 invalue = line[18:].split('=', 1)[0].rstrip()
161 merged[invalue] = []
162 arch_order.append(invalue)
163
164 with open(lockedsigs_extra, 'r') as f:
165 invalue = None
166 tocopy = {}
167 for line in f:
168 if invalue:
169 if line.endswith('\\\n'):
170 if not line in merged[invalue]:
171 target, task = line.strip().split(':')[:2]
172 if not copy_tasks or task in copy_tasks:
173 tocopy[invalue].append(line)
174 merged[invalue].append(line)
175 else:
176 invalue = None
177 elif line.startswith('SIGGEN_LOCKEDSIGS_t-'):
178 invalue = line[18:].split('=', 1)[0].rstrip()
179 if not invalue in merged:
180 merged[invalue] = []
181 arch_order.append(invalue)
182 tocopy[invalue] = []
183
184 def write_sigs_file(fn, types, sigs):
185 fulltypes = []
186 bb.utils.mkdirhier(os.path.dirname(fn))
187 with open(fn, 'w') as f:
188 for typename in types:
189 lines = sigs[typename]
190 if lines:
191 f.write('SIGGEN_LOCKEDSIGS_%s = "\\\n' % typename)
192 for line in lines:
193 f.write(line)
194 f.write(' "\n')
195 fulltypes.append(typename)
196 f.write('SIGGEN_LOCKEDSIGS_TYPES = "%s"\n' % ' '.join(fulltypes))
197
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600198 if copy_output:
199 write_sigs_file(copy_output, list(tocopy.keys()), tocopy)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500200 if merged_output:
201 write_sigs_file(merged_output, arch_order, merged)
202
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600203def create_locked_sstate_cache(lockedsigs, input_sstate_cache, output_sstate_cache, d, fixedlsbstring="", filterfile=None):
204 import shutil
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500205 bb.note('Generating sstate-cache...')
206
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500207 nativelsbstring = d.getVar('NATIVELSBSTRING', True)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600208 bb.process.run("gen-lockedsig-cache %s %s %s %s %s" % (lockedsigs, input_sstate_cache, output_sstate_cache, nativelsbstring, filterfile or ''))
209 if fixedlsbstring and nativelsbstring != fixedlsbstring:
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500210 nativedir = output_sstate_cache + '/' + nativelsbstring
211 if os.path.isdir(nativedir):
212 destdir = os.path.join(output_sstate_cache, fixedlsbstring)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600213 for root, _, files in os.walk(nativedir):
214 for fn in files:
215 src = os.path.join(root, fn)
216 dest = os.path.join(destdir, os.path.relpath(src, nativedir))
217 if os.path.exists(dest):
218 # Already exists, and it'll be the same file, so just delete it
219 os.unlink(src)
220 else:
221 bb.utils.mkdirhier(os.path.dirname(dest))
222 shutil.move(src, dest)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500223
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600224def check_sstate_task_list(d, targets, filteroutfile, cmdprefix='', cwd=None, logfile=None):
225 import subprocess
226
227 bb.note('Generating sstate task list...')
228
229 if not cwd:
230 cwd = os.getcwd()
231 if logfile:
232 logparam = '-l %s' % logfile
233 else:
234 logparam = ''
235 cmd = "%sBB_SETSCENE_ENFORCE=1 PSEUDO_DISABLED=1 oe-check-sstate %s -s -o %s %s" % (cmdprefix, targets, filteroutfile, logparam)
236 env = dict(d.getVar('BB_ORIGENV', False))
237 env.pop('BUILDDIR', '')
238 pathitems = env['PATH'].split(':')
239 env['PATH'] = ':'.join([item for item in pathitems if not item.endswith('/bitbake/bin')])
240 bb.process.run(cmd, stderr=subprocess.STDOUT, env=env, cwd=cwd, executable='/bin/bash')