copy_buildsystem.py 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. # This class should provide easy access to the different aspects of the
  2. # buildsystem such as layers, bitbake location, etc.
  3. import stat
  4. import shutil
  5. def _smart_copy(src, dest):
  6. # smart_copy will choose the correct function depending on whether the
  7. # source is a file or a directory.
  8. mode = os.stat(src).st_mode
  9. if stat.S_ISDIR(mode):
  10. shutil.copytree(src, dest, symlinks=True)
  11. else:
  12. shutil.copyfile(src, dest)
  13. shutil.copymode(src, dest)
  14. class BuildSystem(object):
  15. def __init__(self, context, d):
  16. self.d = d
  17. self.context = context
  18. self.layerdirs = d.getVar('BBLAYERS', True).split()
  19. self.layers_exclude = (d.getVar('SDK_LAYERS_EXCLUDE', True) or "").split()
  20. def copy_bitbake_and_layers(self, destdir, workspace_name=None):
  21. # Copy in all metadata layers + bitbake (as repositories)
  22. layers_copied = []
  23. bb.utils.mkdirhier(destdir)
  24. layers = list(self.layerdirs)
  25. corebase = self.d.getVar('COREBASE', True)
  26. layers.append(corebase)
  27. # Exclude layers
  28. for layer_exclude in self.layers_exclude:
  29. if layer_exclude in layers:
  30. layers.remove(layer_exclude)
  31. workspace_newname = workspace_name
  32. if workspace_newname:
  33. layernames = [os.path.basename(layer) for layer in layers]
  34. extranum = 0
  35. while workspace_newname in layernames:
  36. extranum += 1
  37. workspace_newname = '%s-%d' % (workspace_name, extranum)
  38. corebase_files = self.d.getVar('COREBASE_FILES', True).split()
  39. corebase_files = [corebase + '/' +x for x in corebase_files]
  40. # Make sure bitbake goes in
  41. bitbake_dir = bb.__file__.rsplit('/', 3)[0]
  42. corebase_files.append(bitbake_dir)
  43. for layer in layers:
  44. layerconf = os.path.join(layer, 'conf', 'layer.conf')
  45. layernewname = os.path.basename(layer)
  46. workspace = False
  47. if os.path.exists(layerconf):
  48. with open(layerconf, 'r') as f:
  49. if f.readline().startswith("# ### workspace layer auto-generated by devtool ###"):
  50. if workspace_newname:
  51. layernewname = workspace_newname
  52. workspace = True
  53. else:
  54. bb.plain("NOTE: Excluding local workspace layer %s from %s" % (layer, self.context))
  55. continue
  56. # If the layer was already under corebase, leave it there
  57. # since layers such as meta have issues when moved.
  58. layerdestpath = destdir
  59. if corebase == os.path.dirname(layer):
  60. layerdestpath += '/' + os.path.basename(corebase)
  61. layerdestpath += '/' + layernewname
  62. layer_relative = os.path.relpath(layerdestpath,
  63. destdir)
  64. layers_copied.append(layer_relative)
  65. # Treat corebase as special since it typically will contain
  66. # build directories or other custom items.
  67. if corebase == layer:
  68. bb.utils.mkdirhier(layerdestpath)
  69. for f in corebase_files:
  70. f_basename = os.path.basename(f)
  71. destname = os.path.join(layerdestpath, f_basename)
  72. _smart_copy(f, destname)
  73. else:
  74. if os.path.exists(layerdestpath):
  75. bb.note("Skipping layer %s, already handled" % layer)
  76. else:
  77. _smart_copy(layer, layerdestpath)
  78. if workspace:
  79. # Make some adjustments original workspace layer
  80. # Drop sources (recipe tasks will be locked, so we don't need them)
  81. srcdir = os.path.join(layerdestpath, 'sources')
  82. if os.path.isdir(srcdir):
  83. shutil.rmtree(srcdir)
  84. # Drop all bbappends except the one for the image the SDK is being built for
  85. # (because of externalsrc, the workspace bbappends will interfere with the
  86. # locked signatures if present, and we don't need them anyway)
  87. image_bbappend = os.path.splitext(os.path.basename(self.d.getVar('FILE', True)))[0] + '.bbappend'
  88. appenddir = os.path.join(layerdestpath, 'appends')
  89. if os.path.isdir(appenddir):
  90. for fn in os.listdir(appenddir):
  91. if fn == image_bbappend:
  92. continue
  93. else:
  94. os.remove(os.path.join(appenddir, fn))
  95. # Drop README
  96. readme = os.path.join(layerdestpath, 'README')
  97. if os.path.exists(readme):
  98. os.remove(readme)
  99. # Filter out comments in layer.conf and change layer name
  100. layerconf = os.path.join(layerdestpath, 'conf', 'layer.conf')
  101. with open(layerconf, 'r') as f:
  102. origlines = f.readlines()
  103. with open(layerconf, 'w') as f:
  104. for line in origlines:
  105. if line.startswith('#'):
  106. continue
  107. line = line.replace('workspacelayer', workspace_newname)
  108. f.write(line)
  109. return layers_copied
  110. def generate_locked_sigs(sigfile, d):
  111. bb.utils.mkdirhier(os.path.dirname(sigfile))
  112. depd = d.getVar('BB_TASKDEPDATA', False)
  113. tasks = ['%s.%s' % (v[2], v[1]) for v in depd.itervalues()]
  114. bb.parse.siggen.dump_lockedsigs(sigfile, tasks)
  115. def prune_lockedsigs(excluded_tasks, excluded_targets, lockedsigs, pruned_output):
  116. with open(lockedsigs, 'r') as infile:
  117. bb.utils.mkdirhier(os.path.dirname(pruned_output))
  118. with open(pruned_output, 'w') as f:
  119. invalue = False
  120. for line in infile:
  121. if invalue:
  122. if line.endswith('\\\n'):
  123. splitval = line.strip().split(':')
  124. if not splitval[1] in excluded_tasks and not splitval[0] in excluded_targets:
  125. f.write(line)
  126. else:
  127. f.write(line)
  128. invalue = False
  129. elif line.startswith('SIGGEN_LOCKEDSIGS'):
  130. invalue = True
  131. f.write(line)
  132. def merge_lockedsigs(copy_tasks, lockedsigs_main, lockedsigs_extra, merged_output, copy_output):
  133. merged = {}
  134. arch_order = []
  135. with open(lockedsigs_main, 'r') as f:
  136. invalue = None
  137. for line in f:
  138. if invalue:
  139. if line.endswith('\\\n'):
  140. merged[invalue].append(line)
  141. else:
  142. invalue = None
  143. elif line.startswith('SIGGEN_LOCKEDSIGS_t-'):
  144. invalue = line[18:].split('=', 1)[0].rstrip()
  145. merged[invalue] = []
  146. arch_order.append(invalue)
  147. with open(lockedsigs_extra, 'r') as f:
  148. invalue = None
  149. tocopy = {}
  150. for line in f:
  151. if invalue:
  152. if line.endswith('\\\n'):
  153. if not line in merged[invalue]:
  154. target, task = line.strip().split(':')[:2]
  155. if not copy_tasks or task in copy_tasks:
  156. tocopy[invalue].append(line)
  157. merged[invalue].append(line)
  158. else:
  159. invalue = None
  160. elif line.startswith('SIGGEN_LOCKEDSIGS_t-'):
  161. invalue = line[18:].split('=', 1)[0].rstrip()
  162. if not invalue in merged:
  163. merged[invalue] = []
  164. arch_order.append(invalue)
  165. tocopy[invalue] = []
  166. def write_sigs_file(fn, types, sigs):
  167. fulltypes = []
  168. bb.utils.mkdirhier(os.path.dirname(fn))
  169. with open(fn, 'w') as f:
  170. for typename in types:
  171. lines = sigs[typename]
  172. if lines:
  173. f.write('SIGGEN_LOCKEDSIGS_%s = "\\\n' % typename)
  174. for line in lines:
  175. f.write(line)
  176. f.write(' "\n')
  177. fulltypes.append(typename)
  178. f.write('SIGGEN_LOCKEDSIGS_TYPES = "%s"\n' % ' '.join(fulltypes))
  179. write_sigs_file(copy_output, tocopy.keys(), tocopy)
  180. if merged_output:
  181. write_sigs_file(merged_output, arch_order, merged)
  182. def create_locked_sstate_cache(lockedsigs, input_sstate_cache, output_sstate_cache, d, fixedlsbstring=""):
  183. bb.note('Generating sstate-cache...')
  184. nativelsbstring = d.getVar('NATIVELSBSTRING', True)
  185. bb.process.run("gen-lockedsig-cache %s %s %s %s" % (lockedsigs, input_sstate_cache, output_sstate_cache, nativelsbstring))
  186. if fixedlsbstring:
  187. nativedir = output_sstate_cache + '/' + nativelsbstring
  188. if os.path.isdir(nativedir):
  189. destdir = os.path.join(output_sstate_cache, fixedlsbstring)
  190. bb.utils.mkdirhier(destdir)
  191. dirlist = os.listdir(nativedir)
  192. for i in dirlist:
  193. src = os.path.join(nativedir, i)
  194. dest = os.path.join(destdir, i)
  195. os.rename(src, dest)