1*4882a593Smuzhiyun# 2*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0-only 3*4882a593Smuzhiyun# 4*4882a593Smuzhiyun 5*4882a593Smuzhiyunfrom abc import ABCMeta, abstractmethod 6*4882a593Smuzhiyunimport os 7*4882a593Smuzhiyunimport re 8*4882a593Smuzhiyunimport bb 9*4882a593Smuzhiyun 10*4882a593Smuzhiyunclass Manifest(object, metaclass=ABCMeta): 11*4882a593Smuzhiyun """ 12*4882a593Smuzhiyun This is an abstract class. Do not instantiate this directly. 13*4882a593Smuzhiyun """ 14*4882a593Smuzhiyun 15*4882a593Smuzhiyun PKG_TYPE_MUST_INSTALL = "mip" 16*4882a593Smuzhiyun PKG_TYPE_MULTILIB = "mlp" 17*4882a593Smuzhiyun PKG_TYPE_LANGUAGE = "lgp" 18*4882a593Smuzhiyun PKG_TYPE_ATTEMPT_ONLY = "aop" 19*4882a593Smuzhiyun 20*4882a593Smuzhiyun MANIFEST_TYPE_IMAGE = "image" 21*4882a593Smuzhiyun MANIFEST_TYPE_SDK_HOST = "sdk_host" 22*4882a593Smuzhiyun MANIFEST_TYPE_SDK_TARGET = "sdk_target" 23*4882a593Smuzhiyun 24*4882a593Smuzhiyun var_maps = { 25*4882a593Smuzhiyun MANIFEST_TYPE_IMAGE: { 26*4882a593Smuzhiyun "PACKAGE_INSTALL": PKG_TYPE_MUST_INSTALL, 27*4882a593Smuzhiyun "PACKAGE_INSTALL_ATTEMPTONLY": PKG_TYPE_ATTEMPT_ONLY, 28*4882a593Smuzhiyun "LINGUAS_INSTALL": PKG_TYPE_LANGUAGE 29*4882a593Smuzhiyun }, 30*4882a593Smuzhiyun MANIFEST_TYPE_SDK_HOST: { 31*4882a593Smuzhiyun "TOOLCHAIN_HOST_TASK": PKG_TYPE_MUST_INSTALL, 32*4882a593Smuzhiyun "TOOLCHAIN_HOST_TASK_ATTEMPTONLY": PKG_TYPE_ATTEMPT_ONLY 33*4882a593Smuzhiyun }, 34*4882a593Smuzhiyun MANIFEST_TYPE_SDK_TARGET: { 35*4882a593Smuzhiyun "TOOLCHAIN_TARGET_TASK": PKG_TYPE_MUST_INSTALL, 36*4882a593Smuzhiyun "TOOLCHAIN_TARGET_TASK_ATTEMPTONLY": PKG_TYPE_ATTEMPT_ONLY 37*4882a593Smuzhiyun } 38*4882a593Smuzhiyun } 39*4882a593Smuzhiyun 40*4882a593Smuzhiyun INSTALL_ORDER = [ 41*4882a593Smuzhiyun PKG_TYPE_LANGUAGE, 42*4882a593Smuzhiyun PKG_TYPE_MUST_INSTALL, 43*4882a593Smuzhiyun PKG_TYPE_ATTEMPT_ONLY, 44*4882a593Smuzhiyun PKG_TYPE_MULTILIB 45*4882a593Smuzhiyun ] 46*4882a593Smuzhiyun 47*4882a593Smuzhiyun initial_manifest_file_header = \ 48*4882a593Smuzhiyun "# This file was generated automatically and contains the packages\n" \ 49*4882a593Smuzhiyun "# passed on to the package manager in order to create the rootfs.\n\n" \ 50*4882a593Smuzhiyun "# Format:\n" \ 51*4882a593Smuzhiyun "# <package_type>,<package_name>\n" \ 52*4882a593Smuzhiyun "# where:\n" \ 53*4882a593Smuzhiyun "# <package_type> can be:\n" \ 54*4882a593Smuzhiyun "# 'mip' = must install package\n" \ 55*4882a593Smuzhiyun "# 'aop' = attempt only package\n" \ 56*4882a593Smuzhiyun "# 'mlp' = multilib package\n" \ 57*4882a593Smuzhiyun "# 'lgp' = language package\n\n" 58*4882a593Smuzhiyun 59*4882a593Smuzhiyun def __init__(self, d, manifest_dir=None, manifest_type=MANIFEST_TYPE_IMAGE): 60*4882a593Smuzhiyun self.d = d 61*4882a593Smuzhiyun self.manifest_type = manifest_type 62*4882a593Smuzhiyun 63*4882a593Smuzhiyun if manifest_dir is None: 64*4882a593Smuzhiyun if manifest_type != self.MANIFEST_TYPE_IMAGE: 65*4882a593Smuzhiyun self.manifest_dir = self.d.getVar('SDK_DIR') 66*4882a593Smuzhiyun else: 67*4882a593Smuzhiyun self.manifest_dir = self.d.getVar('WORKDIR') 68*4882a593Smuzhiyun else: 69*4882a593Smuzhiyun self.manifest_dir = manifest_dir 70*4882a593Smuzhiyun 71*4882a593Smuzhiyun bb.utils.mkdirhier(self.manifest_dir) 72*4882a593Smuzhiyun 73*4882a593Smuzhiyun self.initial_manifest = os.path.join(self.manifest_dir, "%s_initial_manifest" % manifest_type) 74*4882a593Smuzhiyun self.final_manifest = os.path.join(self.manifest_dir, "%s_final_manifest" % manifest_type) 75*4882a593Smuzhiyun self.full_manifest = os.path.join(self.manifest_dir, "%s_full_manifest" % manifest_type) 76*4882a593Smuzhiyun 77*4882a593Smuzhiyun # packages in the following vars will be split in 'must install' and 78*4882a593Smuzhiyun # 'multilib' 79*4882a593Smuzhiyun self.vars_to_split = ["PACKAGE_INSTALL", 80*4882a593Smuzhiyun "TOOLCHAIN_HOST_TASK", 81*4882a593Smuzhiyun "TOOLCHAIN_TARGET_TASK"] 82*4882a593Smuzhiyun 83*4882a593Smuzhiyun """ 84*4882a593Smuzhiyun This creates a standard initial manifest for core-image-(minimal|sato|sato-sdk). 85*4882a593Smuzhiyun This will be used for testing until the class is implemented properly! 86*4882a593Smuzhiyun """ 87*4882a593Smuzhiyun def _create_dummy_initial(self): 88*4882a593Smuzhiyun image_rootfs = self.d.getVar('IMAGE_ROOTFS') 89*4882a593Smuzhiyun pkg_list = dict() 90*4882a593Smuzhiyun if image_rootfs.find("core-image-sato-sdk") > 0: 91*4882a593Smuzhiyun pkg_list[self.PKG_TYPE_MUST_INSTALL] = \ 92*4882a593Smuzhiyun "packagegroup-core-x11-sato-games packagegroup-base-extended " \ 93*4882a593Smuzhiyun "packagegroup-core-x11-sato packagegroup-core-x11-base " \ 94*4882a593Smuzhiyun "packagegroup-core-sdk packagegroup-core-tools-debug " \ 95*4882a593Smuzhiyun "packagegroup-core-boot packagegroup-core-tools-testapps " \ 96*4882a593Smuzhiyun "packagegroup-core-eclipse-debug packagegroup-core-qt-demoapps " \ 97*4882a593Smuzhiyun "apt packagegroup-core-tools-profile psplash " \ 98*4882a593Smuzhiyun "packagegroup-core-standalone-sdk-target " \ 99*4882a593Smuzhiyun "packagegroup-core-ssh-openssh dpkg kernel-dev" 100*4882a593Smuzhiyun pkg_list[self.PKG_TYPE_LANGUAGE] = \ 101*4882a593Smuzhiyun "locale-base-en-us locale-base-en-gb" 102*4882a593Smuzhiyun elif image_rootfs.find("core-image-sato") > 0: 103*4882a593Smuzhiyun pkg_list[self.PKG_TYPE_MUST_INSTALL] = \ 104*4882a593Smuzhiyun "packagegroup-core-ssh-dropbear packagegroup-core-x11-sato-games " \ 105*4882a593Smuzhiyun "packagegroup-core-x11-base psplash apt dpkg packagegroup-base-extended " \ 106*4882a593Smuzhiyun "packagegroup-core-x11-sato packagegroup-core-boot" 107*4882a593Smuzhiyun pkg_list['lgp'] = \ 108*4882a593Smuzhiyun "locale-base-en-us locale-base-en-gb" 109*4882a593Smuzhiyun elif image_rootfs.find("core-image-minimal") > 0: 110*4882a593Smuzhiyun pkg_list[self.PKG_TYPE_MUST_INSTALL] = "packagegroup-core-boot" 111*4882a593Smuzhiyun 112*4882a593Smuzhiyun with open(self.initial_manifest, "w+") as manifest: 113*4882a593Smuzhiyun manifest.write(self.initial_manifest_file_header) 114*4882a593Smuzhiyun 115*4882a593Smuzhiyun for pkg_type in pkg_list: 116*4882a593Smuzhiyun for pkg in pkg_list[pkg_type].split(): 117*4882a593Smuzhiyun manifest.write("%s,%s\n" % (pkg_type, pkg)) 118*4882a593Smuzhiyun 119*4882a593Smuzhiyun """ 120*4882a593Smuzhiyun This will create the initial manifest which will be used by Rootfs class to 121*4882a593Smuzhiyun generate the rootfs 122*4882a593Smuzhiyun """ 123*4882a593Smuzhiyun @abstractmethod 124*4882a593Smuzhiyun def create_initial(self): 125*4882a593Smuzhiyun pass 126*4882a593Smuzhiyun 127*4882a593Smuzhiyun """ 128*4882a593Smuzhiyun This creates the manifest after everything has been installed. 129*4882a593Smuzhiyun """ 130*4882a593Smuzhiyun @abstractmethod 131*4882a593Smuzhiyun def create_final(self): 132*4882a593Smuzhiyun pass 133*4882a593Smuzhiyun 134*4882a593Smuzhiyun """ 135*4882a593Smuzhiyun This creates the manifest after the package in initial manifest has been 136*4882a593Smuzhiyun dummy installed. It lists all *to be installed* packages. There is no real 137*4882a593Smuzhiyun installation, just a test. 138*4882a593Smuzhiyun """ 139*4882a593Smuzhiyun @abstractmethod 140*4882a593Smuzhiyun def create_full(self, pm): 141*4882a593Smuzhiyun pass 142*4882a593Smuzhiyun 143*4882a593Smuzhiyun """ 144*4882a593Smuzhiyun The following function parses an initial manifest and returns a dictionary 145*4882a593Smuzhiyun object with the must install, attempt only, multilib and language packages. 146*4882a593Smuzhiyun """ 147*4882a593Smuzhiyun def parse_initial_manifest(self): 148*4882a593Smuzhiyun pkgs = dict() 149*4882a593Smuzhiyun 150*4882a593Smuzhiyun with open(self.initial_manifest) as manifest: 151*4882a593Smuzhiyun for line in manifest.read().split('\n'): 152*4882a593Smuzhiyun comment = re.match("^#.*", line) 153*4882a593Smuzhiyun pattern = "^(%s|%s|%s|%s),(.*)$" % \ 154*4882a593Smuzhiyun (self.PKG_TYPE_MUST_INSTALL, 155*4882a593Smuzhiyun self.PKG_TYPE_ATTEMPT_ONLY, 156*4882a593Smuzhiyun self.PKG_TYPE_MULTILIB, 157*4882a593Smuzhiyun self.PKG_TYPE_LANGUAGE) 158*4882a593Smuzhiyun pkg = re.match(pattern, line) 159*4882a593Smuzhiyun 160*4882a593Smuzhiyun if comment is not None: 161*4882a593Smuzhiyun continue 162*4882a593Smuzhiyun 163*4882a593Smuzhiyun if pkg is not None: 164*4882a593Smuzhiyun pkg_type = pkg.group(1) 165*4882a593Smuzhiyun pkg_name = pkg.group(2) 166*4882a593Smuzhiyun 167*4882a593Smuzhiyun if not pkg_type in pkgs: 168*4882a593Smuzhiyun pkgs[pkg_type] = [pkg_name] 169*4882a593Smuzhiyun else: 170*4882a593Smuzhiyun pkgs[pkg_type].append(pkg_name) 171*4882a593Smuzhiyun 172*4882a593Smuzhiyun return pkgs 173*4882a593Smuzhiyun 174*4882a593Smuzhiyun ''' 175*4882a593Smuzhiyun This following function parses a full manifest and return a list 176*4882a593Smuzhiyun object with packages. 177*4882a593Smuzhiyun ''' 178*4882a593Smuzhiyun def parse_full_manifest(self): 179*4882a593Smuzhiyun installed_pkgs = list() 180*4882a593Smuzhiyun if not os.path.exists(self.full_manifest): 181*4882a593Smuzhiyun bb.note('full manifest not exist') 182*4882a593Smuzhiyun return installed_pkgs 183*4882a593Smuzhiyun 184*4882a593Smuzhiyun with open(self.full_manifest, 'r') as manifest: 185*4882a593Smuzhiyun for pkg in manifest.read().split('\n'): 186*4882a593Smuzhiyun installed_pkgs.append(pkg.strip()) 187*4882a593Smuzhiyun 188*4882a593Smuzhiyun return installed_pkgs 189*4882a593Smuzhiyun 190*4882a593Smuzhiyun 191*4882a593Smuzhiyun 192*4882a593Smuzhiyundef create_manifest(d, final_manifest=False, manifest_dir=None, 193*4882a593Smuzhiyun manifest_type=Manifest.MANIFEST_TYPE_IMAGE): 194*4882a593Smuzhiyun import importlib 195*4882a593Smuzhiyun manifest = importlib.import_module('oe.package_manager.' + d.getVar('IMAGE_PKGTYPE') + '.manifest').PkgManifest(d, manifest_dir, manifest_type) 196*4882a593Smuzhiyun 197*4882a593Smuzhiyun if final_manifest: 198*4882a593Smuzhiyun manifest.create_final() 199*4882a593Smuzhiyun else: 200*4882a593Smuzhiyun manifest.create_initial() 201*4882a593Smuzhiyun 202*4882a593Smuzhiyun 203*4882a593Smuzhiyunif __name__ == "__main__": 204*4882a593Smuzhiyun pass 205