PageRenderTime 43ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/meta/lib/oe/manifest.py

https://gitlab.com/actawithamana/poky
Python | 344 lines | 239 code | 70 blank | 35 comment | 58 complexity | 2d1f5c43898db67b5e4f30e839d4d029 MD5 | raw file
  1. from abc import ABCMeta, abstractmethod
  2. import os
  3. import re
  4. import bb
  5. class Manifest(object, metaclass=ABCMeta):
  6. """
  7. This is an abstract class. Do not instantiate this directly.
  8. """
  9. PKG_TYPE_MUST_INSTALL = "mip"
  10. PKG_TYPE_MULTILIB = "mlp"
  11. PKG_TYPE_LANGUAGE = "lgp"
  12. PKG_TYPE_ATTEMPT_ONLY = "aop"
  13. MANIFEST_TYPE_IMAGE = "image"
  14. MANIFEST_TYPE_SDK_HOST = "sdk_host"
  15. MANIFEST_TYPE_SDK_TARGET = "sdk_target"
  16. var_maps = {
  17. MANIFEST_TYPE_IMAGE: {
  18. "PACKAGE_INSTALL": PKG_TYPE_MUST_INSTALL,
  19. "PACKAGE_INSTALL_ATTEMPTONLY": PKG_TYPE_ATTEMPT_ONLY,
  20. "LINGUAS_INSTALL": PKG_TYPE_LANGUAGE
  21. },
  22. MANIFEST_TYPE_SDK_HOST: {
  23. "TOOLCHAIN_HOST_TASK": PKG_TYPE_MUST_INSTALL,
  24. "TOOLCHAIN_HOST_TASK_ATTEMPTONLY": PKG_TYPE_ATTEMPT_ONLY
  25. },
  26. MANIFEST_TYPE_SDK_TARGET: {
  27. "TOOLCHAIN_TARGET_TASK": PKG_TYPE_MUST_INSTALL,
  28. "TOOLCHAIN_TARGET_TASK_ATTEMPTONLY": PKG_TYPE_ATTEMPT_ONLY
  29. }
  30. }
  31. INSTALL_ORDER = [
  32. PKG_TYPE_LANGUAGE,
  33. PKG_TYPE_MUST_INSTALL,
  34. PKG_TYPE_ATTEMPT_ONLY,
  35. PKG_TYPE_MULTILIB
  36. ]
  37. initial_manifest_file_header = \
  38. "# This file was generated automatically and contains the packages\n" \
  39. "# passed on to the package manager in order to create the rootfs.\n\n" \
  40. "# Format:\n" \
  41. "# <package_type>,<package_name>\n" \
  42. "# where:\n" \
  43. "# <package_type> can be:\n" \
  44. "# 'mip' = must install package\n" \
  45. "# 'aop' = attempt only package\n" \
  46. "# 'mlp' = multilib package\n" \
  47. "# 'lgp' = language package\n\n"
  48. def __init__(self, d, manifest_dir=None, manifest_type=MANIFEST_TYPE_IMAGE):
  49. self.d = d
  50. self.manifest_type = manifest_type
  51. if manifest_dir is None:
  52. if manifest_type != self.MANIFEST_TYPE_IMAGE:
  53. self.manifest_dir = self.d.getVar('SDK_DIR', True)
  54. else:
  55. self.manifest_dir = self.d.getVar('WORKDIR', True)
  56. else:
  57. self.manifest_dir = manifest_dir
  58. bb.utils.mkdirhier(self.manifest_dir)
  59. self.initial_manifest = os.path.join(self.manifest_dir, "%s_initial_manifest" % manifest_type)
  60. self.final_manifest = os.path.join(self.manifest_dir, "%s_final_manifest" % manifest_type)
  61. self.full_manifest = os.path.join(self.manifest_dir, "%s_full_manifest" % manifest_type)
  62. # packages in the following vars will be split in 'must install' and
  63. # 'multilib'
  64. self.vars_to_split = ["PACKAGE_INSTALL",
  65. "TOOLCHAIN_HOST_TASK",
  66. "TOOLCHAIN_TARGET_TASK"]
  67. """
  68. This creates a standard initial manifest for core-image-(minimal|sato|sato-sdk).
  69. This will be used for testing until the class is implemented properly!
  70. """
  71. def _create_dummy_initial(self):
  72. image_rootfs = self.d.getVar('IMAGE_ROOTFS', True)
  73. pkg_list = dict()
  74. if image_rootfs.find("core-image-sato-sdk") > 0:
  75. pkg_list[self.PKG_TYPE_MUST_INSTALL] = \
  76. "packagegroup-core-x11-sato-games packagegroup-base-extended " \
  77. "packagegroup-core-x11-sato packagegroup-core-x11-base " \
  78. "packagegroup-core-sdk packagegroup-core-tools-debug " \
  79. "packagegroup-core-boot packagegroup-core-tools-testapps " \
  80. "packagegroup-core-eclipse-debug packagegroup-core-qt-demoapps " \
  81. "apt packagegroup-core-tools-profile psplash " \
  82. "packagegroup-core-standalone-sdk-target " \
  83. "packagegroup-core-ssh-openssh dpkg kernel-dev"
  84. pkg_list[self.PKG_TYPE_LANGUAGE] = \
  85. "locale-base-en-us locale-base-en-gb"
  86. elif image_rootfs.find("core-image-sato") > 0:
  87. pkg_list[self.PKG_TYPE_MUST_INSTALL] = \
  88. "packagegroup-core-ssh-dropbear packagegroup-core-x11-sato-games " \
  89. "packagegroup-core-x11-base psplash apt dpkg packagegroup-base-extended " \
  90. "packagegroup-core-x11-sato packagegroup-core-boot"
  91. pkg_list['lgp'] = \
  92. "locale-base-en-us locale-base-en-gb"
  93. elif image_rootfs.find("core-image-minimal") > 0:
  94. pkg_list[self.PKG_TYPE_MUST_INSTALL] = "run-postinsts packagegroup-core-boot"
  95. with open(self.initial_manifest, "w+") as manifest:
  96. manifest.write(self.initial_manifest_file_header)
  97. for pkg_type in pkg_list:
  98. for pkg in pkg_list[pkg_type].split():
  99. manifest.write("%s,%s\n" % (pkg_type, pkg))
  100. """
  101. This will create the initial manifest which will be used by Rootfs class to
  102. generate the rootfs
  103. """
  104. @abstractmethod
  105. def create_initial(self):
  106. pass
  107. """
  108. This creates the manifest after everything has been installed.
  109. """
  110. @abstractmethod
  111. def create_final(self):
  112. pass
  113. """
  114. This creates the manifest after the package in initial manifest has been
  115. dummy installed. It lists all *to be installed* packages. There is no real
  116. installation, just a test.
  117. """
  118. @abstractmethod
  119. def create_full(self, pm):
  120. pass
  121. """
  122. The following function parses an initial manifest and returns a dictionary
  123. object with the must install, attempt only, multilib and language packages.
  124. """
  125. def parse_initial_manifest(self):
  126. pkgs = dict()
  127. with open(self.initial_manifest) as manifest:
  128. for line in manifest.read().split('\n'):
  129. comment = re.match("^#.*", line)
  130. pattern = "^(%s|%s|%s|%s),(.*)$" % \
  131. (self.PKG_TYPE_MUST_INSTALL,
  132. self.PKG_TYPE_ATTEMPT_ONLY,
  133. self.PKG_TYPE_MULTILIB,
  134. self.PKG_TYPE_LANGUAGE)
  135. pkg = re.match(pattern, line)
  136. if comment is not None:
  137. continue
  138. if pkg is not None:
  139. pkg_type = pkg.group(1)
  140. pkg_name = pkg.group(2)
  141. if not pkg_type in pkgs:
  142. pkgs[pkg_type] = [pkg_name]
  143. else:
  144. pkgs[pkg_type].append(pkg_name)
  145. return pkgs
  146. '''
  147. This following function parses a full manifest and return a list
  148. object with packages.
  149. '''
  150. def parse_full_manifest(self):
  151. installed_pkgs = list()
  152. if not os.path.exists(self.full_manifest):
  153. bb.note('full manifest not exist')
  154. return installed_pkgs
  155. with open(self.full_manifest, 'r') as manifest:
  156. for pkg in manifest.read().split('\n'):
  157. installed_pkgs.append(pkg.strip())
  158. return installed_pkgs
  159. class RpmManifest(Manifest):
  160. """
  161. Returns a dictionary object with mip and mlp packages.
  162. """
  163. def _split_multilib(self, pkg_list):
  164. pkgs = dict()
  165. for pkg in pkg_list.split():
  166. pkg_type = self.PKG_TYPE_MUST_INSTALL
  167. ml_variants = self.d.getVar('MULTILIB_VARIANTS', True).split()
  168. for ml_variant in ml_variants:
  169. if pkg.startswith(ml_variant + '-'):
  170. pkg_type = self.PKG_TYPE_MULTILIB
  171. if not pkg_type in pkgs:
  172. pkgs[pkg_type] = pkg
  173. else:
  174. pkgs[pkg_type] += " " + pkg
  175. return pkgs
  176. def create_initial(self):
  177. pkgs = dict()
  178. with open(self.initial_manifest, "w+") as manifest:
  179. manifest.write(self.initial_manifest_file_header)
  180. for var in self.var_maps[self.manifest_type]:
  181. if var in self.vars_to_split:
  182. split_pkgs = self._split_multilib(self.d.getVar(var, True))
  183. if split_pkgs is not None:
  184. pkgs = dict(list(pkgs.items()) + list(split_pkgs.items()))
  185. else:
  186. pkg_list = self.d.getVar(var, True)
  187. if pkg_list is not None:
  188. pkgs[self.var_maps[self.manifest_type][var]] = self.d.getVar(var, True)
  189. for pkg_type in pkgs:
  190. for pkg in pkgs[pkg_type].split():
  191. manifest.write("%s,%s\n" % (pkg_type, pkg))
  192. def create_final(self):
  193. pass
  194. def create_full(self, pm):
  195. pass
  196. class OpkgManifest(Manifest):
  197. """
  198. Returns a dictionary object with mip and mlp packages.
  199. """
  200. def _split_multilib(self, pkg_list):
  201. pkgs = dict()
  202. for pkg in pkg_list.split():
  203. pkg_type = self.PKG_TYPE_MUST_INSTALL
  204. ml_variants = self.d.getVar('MULTILIB_VARIANTS', True).split()
  205. for ml_variant in ml_variants:
  206. if pkg.startswith(ml_variant + '-'):
  207. pkg_type = self.PKG_TYPE_MULTILIB
  208. if not pkg_type in pkgs:
  209. pkgs[pkg_type] = pkg
  210. else:
  211. pkgs[pkg_type] += " " + pkg
  212. return pkgs
  213. def create_initial(self):
  214. pkgs = dict()
  215. with open(self.initial_manifest, "w+") as manifest:
  216. manifest.write(self.initial_manifest_file_header)
  217. for var in self.var_maps[self.manifest_type]:
  218. if var in self.vars_to_split:
  219. split_pkgs = self._split_multilib(self.d.getVar(var, True))
  220. if split_pkgs is not None:
  221. pkgs = dict(list(pkgs.items()) + list(split_pkgs.items()))
  222. else:
  223. pkg_list = self.d.getVar(var, True)
  224. if pkg_list is not None:
  225. pkgs[self.var_maps[self.manifest_type][var]] = self.d.getVar(var, True)
  226. for pkg_type in pkgs:
  227. for pkg in pkgs[pkg_type].split():
  228. manifest.write("%s,%s\n" % (pkg_type, pkg))
  229. def create_final(self):
  230. pass
  231. def create_full(self, pm):
  232. if not os.path.exists(self.initial_manifest):
  233. self.create_initial()
  234. initial_manifest = self.parse_initial_manifest()
  235. pkgs_to_install = list()
  236. for pkg_type in initial_manifest:
  237. pkgs_to_install += initial_manifest[pkg_type]
  238. if len(pkgs_to_install) == 0:
  239. return
  240. output = pm.dummy_install(pkgs_to_install)
  241. with open(self.full_manifest, 'w+') as manifest:
  242. pkg_re = re.compile('^Installing ([^ ]+) [^ ].*')
  243. for line in set(output.split('\n')):
  244. m = pkg_re.match(line)
  245. if m:
  246. manifest.write(m.group(1) + '\n')
  247. return
  248. class DpkgManifest(Manifest):
  249. def create_initial(self):
  250. with open(self.initial_manifest, "w+") as manifest:
  251. manifest.write(self.initial_manifest_file_header)
  252. for var in self.var_maps[self.manifest_type]:
  253. pkg_list = self.d.getVar(var, True)
  254. if pkg_list is None:
  255. continue
  256. for pkg in pkg_list.split():
  257. manifest.write("%s,%s\n" %
  258. (self.var_maps[self.manifest_type][var], pkg))
  259. def create_final(self):
  260. pass
  261. def create_full(self, pm):
  262. pass
  263. def create_manifest(d, final_manifest=False, manifest_dir=None,
  264. manifest_type=Manifest.MANIFEST_TYPE_IMAGE):
  265. manifest_map = {'rpm': RpmManifest,
  266. 'ipk': OpkgManifest,
  267. 'deb': DpkgManifest}
  268. manifest = manifest_map[d.getVar('IMAGE_PKGTYPE', True)](d, manifest_dir, manifest_type)
  269. if final_manifest:
  270. manifest.create_final()
  271. else:
  272. manifest.create_initial()
  273. if __name__ == "__main__":
  274. pass