blob: f0fbb763f1d4d3ee7c7c93b96081accdc2774deb [file] [log] [blame]
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001python write_package_manifest() {
2 # Get list of installed packages
3 license_image_dir = d.expand('${LICENSE_DIRECTORY}/${IMAGE_NAME}')
4 bb.utils.mkdirhier(license_image_dir)
5 from oe.rootfs import image_list_installed_packages
6 from oe.utils import format_pkg_list
7
8 pkgs = image_list_installed_packages(d)
9 output = format_pkg_list(pkgs)
10 open(os.path.join(license_image_dir, 'package.manifest'),
11 'w+').write(output)
12}
13
14python license_create_manifest() {
15 import oe.packagedata
16 from oe.rootfs import image_list_installed_packages
17
18 build_images_from_feeds = d.getVar('BUILD_IMAGES_FROM_FEEDS')
19 if build_images_from_feeds == "1":
20 return 0
21
22 pkg_dic = {}
23 for pkg in sorted(image_list_installed_packages(d)):
24 pkg_info = os.path.join(d.getVar('PKGDATA_DIR'),
25 'runtime-reverse', pkg)
26 pkg_name = os.path.basename(os.readlink(pkg_info))
27
28 pkg_dic[pkg_name] = oe.packagedata.read_pkgdatafile(pkg_info)
29 if not "LICENSE" in pkg_dic[pkg_name].keys():
30 pkg_lic_name = "LICENSE_" + pkg_name
31 pkg_dic[pkg_name]["LICENSE"] = pkg_dic[pkg_name][pkg_lic_name]
32
33 rootfs_license_manifest = os.path.join(d.getVar('LICENSE_DIRECTORY'),
34 d.getVar('IMAGE_NAME'), 'license.manifest')
35 write_license_files(d, rootfs_license_manifest, pkg_dic)
36}
37
38def write_license_files(d, license_manifest, pkg_dic):
39 import re
40
41 bad_licenses = (d.getVar("INCOMPATIBLE_LICENSE") or "").split()
42 bad_licenses = map(lambda l: canonical_license(d, l), bad_licenses)
43 bad_licenses = expand_wildcard_licenses(d, bad_licenses)
44
45 with open(license_manifest, "w") as license_file:
46 for pkg in sorted(pkg_dic):
47 if bad_licenses:
48 try:
49 (pkg_dic[pkg]["LICENSE"], pkg_dic[pkg]["LICENSES"]) = \
50 oe.license.manifest_licenses(pkg_dic[pkg]["LICENSE"],
51 bad_licenses, canonical_license, d)
52 except oe.license.LicenseError as exc:
53 bb.fatal('%s: %s' % (d.getVar('P'), exc))
54 else:
55 pkg_dic[pkg]["LICENSES"] = re.sub('[|&()*]', ' ', pkg_dic[pkg]["LICENSE"])
56 pkg_dic[pkg]["LICENSES"] = re.sub(' *', ' ', pkg_dic[pkg]["LICENSES"])
57 pkg_dic[pkg]["LICENSES"] = pkg_dic[pkg]["LICENSES"].split()
58
59 if not "IMAGE_MANIFEST" in pkg_dic[pkg]:
60 # Rootfs manifest
61 license_file.write("PACKAGE NAME: %s\n" % pkg)
62 license_file.write("PACKAGE VERSION: %s\n" % pkg_dic[pkg]["PV"])
63 license_file.write("RECIPE NAME: %s\n" % pkg_dic[pkg]["PN"])
64 license_file.write("LICENSE: %s\n\n" % pkg_dic[pkg]["LICENSE"])
65
66 # If the package doesn't contain any file, that is, its size is 0, the license
67 # isn't relevant as far as the final image is concerned. So doing license check
68 # doesn't make much sense, skip it.
69 if pkg_dic[pkg]["PKGSIZE_%s" % pkg] == "0":
70 continue
71 else:
72 # Image manifest
73 license_file.write("RECIPE NAME: %s\n" % pkg_dic[pkg]["PN"])
74 license_file.write("VERSION: %s\n" % pkg_dic[pkg]["PV"])
75 license_file.write("LICENSE: %s\n" % pkg_dic[pkg]["LICENSE"])
76 license_file.write("FILES: %s\n\n" % pkg_dic[pkg]["FILES"])
77
78 for lic in pkg_dic[pkg]["LICENSES"]:
79 lic_file = os.path.join(d.getVar('LICENSE_DIRECTORY'),
80 pkg_dic[pkg]["PN"], "generic_%s" %
81 re.sub('\+', '', lic))
82 # add explicity avoid of CLOSED license because isn't generic
83 if lic == "CLOSED":
84 continue
85
86 if not os.path.exists(lic_file):
87 bb.warn("The license listed %s was not in the "\
88 "licenses collected for recipe %s"
89 % (lic, pkg_dic[pkg]["PN"]))
90
91 # Two options here:
92 # - Just copy the manifest
93 # - Copy the manifest and the license directories
94 # With both options set we see a .5 M increase in core-image-minimal
95 copy_lic_manifest = d.getVar('COPY_LIC_MANIFEST')
96 copy_lic_dirs = d.getVar('COPY_LIC_DIRS')
97 if copy_lic_manifest == "1":
98 rootfs_license_dir = os.path.join(d.getVar('IMAGE_ROOTFS'),
99 'usr', 'share', 'common-licenses')
100 bb.utils.mkdirhier(rootfs_license_dir)
101 rootfs_license_manifest = os.path.join(rootfs_license_dir,
102 os.path.split(license_manifest)[1])
103 if not os.path.exists(rootfs_license_manifest):
104 os.link(license_manifest, rootfs_license_manifest)
105
106 if copy_lic_dirs == "1":
107 for pkg in sorted(pkg_dic):
108 pkg_rootfs_license_dir = os.path.join(rootfs_license_dir, pkg)
109 bb.utils.mkdirhier(pkg_rootfs_license_dir)
110 pkg_license_dir = os.path.join(d.getVar('LICENSE_DIRECTORY'),
111 pkg_dic[pkg]["PN"])
112
113 pkg_manifest_licenses = [canonical_license(d, lic) \
114 for lic in pkg_dic[pkg]["LICENSES"]]
115
116 licenses = os.listdir(pkg_license_dir)
117 for lic in licenses:
118 rootfs_license = os.path.join(rootfs_license_dir, lic)
119 pkg_license = os.path.join(pkg_license_dir, lic)
120 pkg_rootfs_license = os.path.join(pkg_rootfs_license_dir, lic)
121
122 if re.match("^generic_.*$", lic):
123 generic_lic = canonical_license(d,
124 re.search("^generic_(.*)$", lic).group(1))
125
126 # Do not copy generic license into package if isn't
127 # declared into LICENSES of the package.
128 if not re.sub('\+$', '', generic_lic) in \
129 [re.sub('\+', '', lic) for lic in \
130 pkg_manifest_licenses]:
131 continue
132
133 if oe.license.license_ok(generic_lic,
134 bad_licenses) == False:
135 continue
136
137 if not os.path.exists(rootfs_license):
138 os.link(pkg_license, rootfs_license)
139
140 if not os.path.exists(pkg_rootfs_license):
141 os.symlink(os.path.join('..', lic), pkg_rootfs_license)
142 else:
143 if (oe.license.license_ok(canonical_license(d,
144 lic), bad_licenses) == False or
145 os.path.exists(pkg_rootfs_license)):
146 continue
147
148 os.link(pkg_license, pkg_rootfs_license)
149
150
151def license_deployed_manifest(d):
152 """
153 Write the license manifest for the deployed recipes.
154 The deployed recipes usually includes the bootloader
155 and extra files to boot the target.
156 """
157
158 dep_dic = {}
159 man_dic = {}
160 lic_dir = d.getVar("LICENSE_DIRECTORY")
161
162 dep_dic = get_deployed_dependencies(d)
163 for dep in dep_dic.keys():
164 man_dic[dep] = {}
165 # It is necessary to mark this will be used for image manifest
166 man_dic[dep]["IMAGE_MANIFEST"] = True
167 man_dic[dep]["PN"] = dep
168 man_dic[dep]["FILES"] = \
169 " ".join(get_deployed_files(dep_dic[dep]))
170 with open(os.path.join(lic_dir, dep, "recipeinfo"), "r") as f:
171 for line in f.readlines():
172 key,val = line.split(": ", 1)
173 man_dic[dep][key] = val[:-1]
174
175 lic_manifest_dir = os.path.join(d.getVar('LICENSE_DIRECTORY'),
176 d.getVar('IMAGE_NAME'))
177 bb.utils.mkdirhier(lic_manifest_dir)
178 image_license_manifest = os.path.join(lic_manifest_dir, 'image_license.manifest')
179 write_license_files(d, image_license_manifest, man_dic)
180
181def get_deployed_dependencies(d):
182 """
183 Get all the deployed dependencies of an image
184 """
185
186 deploy = {}
187 # Get all the dependencies for the current task (rootfs).
188 # Also get EXTRA_IMAGEDEPENDS because the bootloader is
189 # usually in this var and not listed in rootfs.
190 # At last, get the dependencies from boot classes because
191 # it might contain the bootloader.
192 taskdata = d.getVar("BB_TASKDEPDATA", False)
193 depends = list(set([dep[0] for dep
194 in list(taskdata.values())
195 if not dep[0].endswith("-native")]))
196
197 # To verify what was deployed it checks the rootfs dependencies against
198 # the SSTATE_MANIFESTS for "deploy" task.
199 # The manifest file name contains the arch. Because we are not running
200 # in the recipe context it is necessary to check every arch used.
201 sstate_manifest_dir = d.getVar("SSTATE_MANIFESTS")
202 archs = list(set(d.getVar("SSTATE_ARCHS").split()))
203 for dep in depends:
204 for arch in archs:
205 sstate_manifest_file = os.path.join(sstate_manifest_dir,
206 "manifest-%s-%s.deploy" % (arch, dep))
207 if os.path.exists(sstate_manifest_file):
208 deploy[dep] = sstate_manifest_file
209 break
210
211 return deploy
212get_deployed_dependencies[vardepsexclude] = "BB_TASKDEPDATA"
213
214def get_deployed_files(man_file):
215 """
216 Get the files deployed from the sstate manifest
217 """
218
219 dep_files = []
220 excluded_files = []
221 with open(man_file, "r") as manifest:
222 all_files = manifest.read()
223 for f in all_files.splitlines():
224 if ((not (os.path.islink(f) or os.path.isdir(f))) and
225 not os.path.basename(f) in excluded_files):
226 dep_files.append(os.path.basename(f))
227 return dep_files
228
229ROOTFS_POSTPROCESS_COMMAND_prepend = "write_package_manifest; license_create_manifest; "
230do_rootfs[recrdeptask] += "do_populate_lic"
231
232python do_populate_lic_deploy() {
233 license_deployed_manifest(d)
234}
235
236addtask populate_lic_deploy before do_build after do_image_complete
237do_populate_lic_deploy[recrdeptask] += "do_populate_lic do_deploy"
238