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