summaryrefslogtreecommitdiffstats
path: root/meta/classes/license.bbclass
diff options
context:
space:
mode:
authorRichard Purdie <richard.purdie@linuxfoundation.org>2018-07-23 15:34:31 +0000
committerRichard Purdie <richard.purdie@linuxfoundation.org>2018-07-25 16:48:27 +0100
commita6a865ba933ca7f8a2f93ac4aeaa918ef42d36b1 (patch)
tree2fc1acc178b51458d2e56c5f7bd164b29aabf63a /meta/classes/license.bbclass
parent2dda838683bea563624f0588ae14fc778955fe3c (diff)
downloadpoky-a6a865ba933ca7f8a2f93ac4aeaa918ef42d36b1.tar.gz
license: Split image license functions to a separate class
This means the image code is only included in image recipes through the IMAGE_CLASSES variable. This sets things up to allow us to fix image deploy dependency problems. (From OE-Core rev: fd44b8b4b2484f2d35c7a0e749e7dc316d601989) Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/classes/license.bbclass')
-rw-r--r--meta/classes/license.bbclass284
1 files changed, 1 insertions, 283 deletions
diff --git a/meta/classes/license.bbclass b/meta/classes/license.bbclass
index 141af5de4d..2ac15a1bc8 100644
--- a/meta/classes/license.bbclass
+++ b/meta/classes/license.bbclass
@@ -16,284 +16,6 @@ addtask populate_lic after do_patch before do_build
16do_populate_lic[dirs] = "${LICSSTATEDIR}/${PN}" 16do_populate_lic[dirs] = "${LICSSTATEDIR}/${PN}"
17do_populate_lic[cleandirs] = "${LICSSTATEDIR}" 17do_populate_lic[cleandirs] = "${LICSSTATEDIR}"
18 18
19python write_package_manifest() {
20 # Get list of installed packages
21 license_image_dir = d.expand('${LICENSE_DIRECTORY}/${IMAGE_NAME}')
22 bb.utils.mkdirhier(license_image_dir)
23 from oe.rootfs import image_list_installed_packages
24 from oe.utils import format_pkg_list
25
26 pkgs = image_list_installed_packages(d)
27 output = format_pkg_list(pkgs)
28 open(os.path.join(license_image_dir, 'package.manifest'),
29 'w+').write(output)
30}
31
32python write_deploy_manifest() {
33 license_deployed_manifest(d)
34}
35
36python license_create_manifest() {
37 import oe.packagedata
38 from oe.rootfs import image_list_installed_packages
39
40 build_images_from_feeds = d.getVar('BUILD_IMAGES_FROM_FEEDS')
41 if build_images_from_feeds == "1":
42 return 0
43
44 pkg_dic = {}
45 for pkg in sorted(image_list_installed_packages(d)):
46 pkg_info = os.path.join(d.getVar('PKGDATA_DIR'),
47 'runtime-reverse', pkg)
48 pkg_name = os.path.basename(os.readlink(pkg_info))
49
50 pkg_dic[pkg_name] = oe.packagedata.read_pkgdatafile(pkg_info)
51 if not "LICENSE" in pkg_dic[pkg_name].keys():
52 pkg_lic_name = "LICENSE_" + pkg_name
53 pkg_dic[pkg_name]["LICENSE"] = pkg_dic[pkg_name][pkg_lic_name]
54
55 rootfs_license_manifest = os.path.join(d.getVar('LICENSE_DIRECTORY'),
56 d.getVar('IMAGE_NAME'), 'license.manifest')
57 write_license_files(d, rootfs_license_manifest, pkg_dic)
58}
59
60def write_license_files(d, license_manifest, pkg_dic):
61 import re
62
63 bad_licenses = (d.getVar("INCOMPATIBLE_LICENSE") or "").split()
64 bad_licenses = map(lambda l: canonical_license(d, l), bad_licenses)
65 bad_licenses = expand_wildcard_licenses(d, bad_licenses)
66
67 with open(license_manifest, "w") as license_file:
68 for pkg in sorted(pkg_dic):
69 if bad_licenses:
70 try:
71 (pkg_dic[pkg]["LICENSE"], pkg_dic[pkg]["LICENSES"]) = \
72 oe.license.manifest_licenses(pkg_dic[pkg]["LICENSE"],
73 bad_licenses, canonical_license, d)
74 except oe.license.LicenseError as exc:
75 bb.fatal('%s: %s' % (d.getVar('P'), exc))
76 else:
77 pkg_dic[pkg]["LICENSES"] = re.sub('[|&()*]', ' ', pkg_dic[pkg]["LICENSE"])
78 pkg_dic[pkg]["LICENSES"] = re.sub(' *', ' ', pkg_dic[pkg]["LICENSES"])
79 pkg_dic[pkg]["LICENSES"] = pkg_dic[pkg]["LICENSES"].split()
80
81 if not "IMAGE_MANIFEST" in pkg_dic[pkg]:
82 # Rootfs manifest
83 license_file.write("PACKAGE NAME: %s\n" % pkg)
84 license_file.write("PACKAGE VERSION: %s\n" % pkg_dic[pkg]["PV"])
85 license_file.write("RECIPE NAME: %s\n" % pkg_dic[pkg]["PN"])
86 license_file.write("LICENSE: %s\n\n" % pkg_dic[pkg]["LICENSE"])
87
88 # If the package doesn't contain any file, that is, its size is 0, the license
89 # isn't relevant as far as the final image is concerned. So doing license check
90 # doesn't make much sense, skip it.
91 if pkg_dic[pkg]["PKGSIZE_%s" % pkg] == "0":
92 continue
93 else:
94 # Image manifest
95 license_file.write("RECIPE NAME: %s\n" % pkg_dic[pkg]["PN"])
96 license_file.write("VERSION: %s\n" % pkg_dic[pkg]["PV"])
97 license_file.write("LICENSE: %s\n" % pkg_dic[pkg]["LICENSE"])
98 license_file.write("FILES: %s\n\n" % pkg_dic[pkg]["FILES"])
99
100 for lic in pkg_dic[pkg]["LICENSES"]:
101 lic_file = os.path.join(d.getVar('LICENSE_DIRECTORY'),
102 pkg_dic[pkg]["PN"], "generic_%s" %
103 re.sub('\+', '', lic))
104 # add explicity avoid of CLOSED license because isn't generic
105 if lic == "CLOSED":
106 continue
107
108 if not os.path.exists(lic_file):
109 bb.warn("The license listed %s was not in the "\
110 "licenses collected for recipe %s"
111 % (lic, pkg_dic[pkg]["PN"]))
112
113 # Two options here:
114 # - Just copy the manifest
115 # - Copy the manifest and the license directories
116 # With both options set we see a .5 M increase in core-image-minimal
117 copy_lic_manifest = d.getVar('COPY_LIC_MANIFEST')
118 copy_lic_dirs = d.getVar('COPY_LIC_DIRS')
119 if copy_lic_manifest == "1":
120 rootfs_license_dir = os.path.join(d.getVar('IMAGE_ROOTFS'),
121 'usr', 'share', 'common-licenses')
122 bb.utils.mkdirhier(rootfs_license_dir)
123 rootfs_license_manifest = os.path.join(rootfs_license_dir,
124 os.path.split(license_manifest)[1])
125 if not os.path.exists(rootfs_license_manifest):
126 os.link(license_manifest, rootfs_license_manifest)
127
128 if copy_lic_dirs == "1":
129 for pkg in sorted(pkg_dic):
130 pkg_rootfs_license_dir = os.path.join(rootfs_license_dir, pkg)
131 bb.utils.mkdirhier(pkg_rootfs_license_dir)
132 pkg_license_dir = os.path.join(d.getVar('LICENSE_DIRECTORY'),
133 pkg_dic[pkg]["PN"])
134
135 pkg_manifest_licenses = [canonical_license(d, lic) \
136 for lic in pkg_dic[pkg]["LICENSES"]]
137
138 licenses = os.listdir(pkg_license_dir)
139 for lic in licenses:
140 rootfs_license = os.path.join(rootfs_license_dir, lic)
141 pkg_license = os.path.join(pkg_license_dir, lic)
142 pkg_rootfs_license = os.path.join(pkg_rootfs_license_dir, lic)
143
144 if re.match("^generic_.*$", lic):
145 generic_lic = canonical_license(d,
146 re.search("^generic_(.*)$", lic).group(1))
147
148 # Do not copy generic license into package if isn't
149 # declared into LICENSES of the package.
150 if not re.sub('\+$', '', generic_lic) in \
151 [re.sub('\+', '', lic) for lic in \
152 pkg_manifest_licenses]:
153 continue
154
155 if oe.license.license_ok(generic_lic,
156 bad_licenses) == False:
157 continue
158
159 if not os.path.exists(rootfs_license):
160 os.link(pkg_license, rootfs_license)
161
162 if not os.path.exists(pkg_rootfs_license):
163 os.symlink(os.path.join('..', lic), pkg_rootfs_license)
164 else:
165 if (oe.license.license_ok(canonical_license(d,
166 lic), bad_licenses) == False or
167 os.path.exists(pkg_rootfs_license)):
168 continue
169
170 os.link(pkg_license, pkg_rootfs_license)
171
172
173def license_deployed_manifest(d):
174 """
175 Write the license manifest for the deployed recipes.
176 The deployed recipes usually includes the bootloader
177 and extra files to boot the target.
178 """
179
180 dep_dic = {}
181 man_dic = {}
182 lic_dir = d.getVar("LICENSE_DIRECTORY")
183
184 dep_dic = get_deployed_dependencies(d)
185 for dep in dep_dic.keys():
186 man_dic[dep] = {}
187 # It is necessary to mark this will be used for image manifest
188 man_dic[dep]["IMAGE_MANIFEST"] = True
189 man_dic[dep]["PN"] = dep
190 man_dic[dep]["FILES"] = \
191 " ".join(get_deployed_files(dep_dic[dep]))
192 with open(os.path.join(lic_dir, dep, "recipeinfo"), "r") as f:
193 for line in f.readlines():
194 key,val = line.split(": ", 1)
195 man_dic[dep][key] = val[:-1]
196
197 lic_manifest_dir = os.path.join(d.getVar('LICENSE_DIRECTORY'),
198 d.getVar('IMAGE_NAME'))
199 bb.utils.mkdirhier(lic_manifest_dir)
200 image_license_manifest = os.path.join(lic_manifest_dir, 'image_license.manifest')
201 write_license_files(d, image_license_manifest, man_dic)
202
203def get_deployed_dependencies(d):
204 """
205 Get all the deployed dependencies of an image
206 """
207
208 deploy = {}
209 # Get all the dependencies for the current task (rootfs).
210 # Also get EXTRA_IMAGEDEPENDS because the bootloader is
211 # usually in this var and not listed in rootfs.
212 # At last, get the dependencies from boot classes because
213 # it might contain the bootloader.
214 taskdata = d.getVar("BB_TASKDEPDATA", False)
215 depends = list(set([dep[0] for dep
216 in list(taskdata.values())
217 if not dep[0].endswith("-native")]))
218 extra_depends = d.getVar("EXTRA_IMAGEDEPENDS")
219 boot_depends = get_boot_dependencies(d)
220 depends.extend(extra_depends.split())
221 depends.extend(boot_depends)
222 depends = list(set(depends))
223
224 # To verify what was deployed it checks the rootfs dependencies against
225 # the SSTATE_MANIFESTS for "deploy" task.
226 # The manifest file name contains the arch. Because we are not running
227 # in the recipe context it is necessary to check every arch used.
228 sstate_manifest_dir = d.getVar("SSTATE_MANIFESTS")
229 archs = list(set(d.getVar("SSTATE_ARCHS").split()))
230 for dep in depends:
231 # Some recipes have an arch on their own, so we try that first.
232 special_arch = d.getVar("PACKAGE_ARCH_pn-%s" % dep)
233 if special_arch:
234 sstate_manifest_file = os.path.join(sstate_manifest_dir,
235 "manifest-%s-%s.deploy" % (special_arch, dep))
236 if os.path.exists(sstate_manifest_file):
237 deploy[dep] = sstate_manifest_file
238 continue
239
240 for arch in archs:
241 sstate_manifest_file = os.path.join(sstate_manifest_dir,
242 "manifest-%s-%s.deploy" % (arch, dep))
243 if os.path.exists(sstate_manifest_file):
244 deploy[dep] = sstate_manifest_file
245 break
246
247 return deploy
248get_deployed_dependencies[vardepsexclude] = "BB_TASKDEPDATA"
249
250def get_boot_dependencies(d):
251 """
252 Return the dependencies from boot tasks
253 """
254
255 depends = []
256 taskdepdata = d.getVar("BB_TASKDEPDATA", False)
257 # Only bootimg includes the depends flag
258 boot_depends_string = d.getVarFlag("do_bootimg", "depends") or ""
259 boot_depends = [dep.split(":")[0] for dep
260 in boot_depends_string.split()
261 if not dep.split(":")[0].endswith("-native")]
262 for dep in boot_depends:
263 info_file = os.path.join(d.getVar("LICENSE_DIRECTORY"),
264 dep, "recipeinfo")
265 # If the recipe and dependency name is the same
266 if os.path.exists(info_file):
267 depends.append(dep)
268 # We need to search for the provider of the dependency
269 else:
270 for taskdep in taskdepdata.values():
271 # The fifth field contains what the task provides
272 if dep in taskdep[4]:
273 info_file = os.path.join(
274 d.getVar("LICENSE_DIRECTORY"),
275 taskdep[0], "recipeinfo")
276 if os.path.exists(info_file):
277 depends.append(taskdep[0])
278 break
279 return depends
280get_boot_dependencies[vardepsexclude] = "BB_TASKDEPDATA"
281
282def get_deployed_files(man_file):
283 """
284 Get the files deployed from the sstate manifest
285 """
286
287 dep_files = []
288 excluded_files = []
289 with open(man_file, "r") as manifest:
290 all_files = manifest.read()
291 for f in all_files.splitlines():
292 if ((not (os.path.islink(f) or os.path.isdir(f))) and
293 not os.path.basename(f) in excluded_files):
294 dep_files.append(os.path.basename(f))
295 return dep_files
296
297python do_populate_lic() { 19python do_populate_lic() {
298 """ 20 """
299 Populate LICENSE_DIRECTORY with licenses. 21 Populate LICENSE_DIRECTORY with licenses.
@@ -675,11 +397,7 @@ SSTATETASKS += "do_populate_lic"
675do_populate_lic[sstate-inputdirs] = "${LICSSTATEDIR}" 397do_populate_lic[sstate-inputdirs] = "${LICSSTATEDIR}"
676do_populate_lic[sstate-outputdirs] = "${LICENSE_DIRECTORY}/" 398do_populate_lic[sstate-outputdirs] = "${LICENSE_DIRECTORY}/"
677 399
678ROOTFS_POSTPROCESS_COMMAND_prepend = "write_package_manifest; license_create_manifest; " 400IMAGE_CLASSES_append = " license_image"
679do_rootfs[recrdeptask] += "do_populate_lic"
680
681IMAGE_POSTPROCESS_COMMAND_prepend = "write_deploy_manifest; "
682do_image[recrdeptask] += "do_populate_lic"
683 401
684python do_populate_lic_setscene () { 402python do_populate_lic_setscene () {
685 sstate_setscene(d) 403 sstate_setscene(d)