diff options
author | Richard Purdie <richard.purdie@linuxfoundation.org> | 2018-07-23 15:34:31 +0000 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2018-07-25 16:48:27 +0100 |
commit | a6a865ba933ca7f8a2f93ac4aeaa918ef42d36b1 (patch) | |
tree | 2fc1acc178b51458d2e56c5f7bd164b29aabf63a /meta/classes/license.bbclass | |
parent | 2dda838683bea563624f0588ae14fc778955fe3c (diff) | |
download | poky-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.bbclass | 284 |
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 | |||
16 | do_populate_lic[dirs] = "${LICSSTATEDIR}/${PN}" | 16 | do_populate_lic[dirs] = "${LICSSTATEDIR}/${PN}" |
17 | do_populate_lic[cleandirs] = "${LICSSTATEDIR}" | 17 | do_populate_lic[cleandirs] = "${LICSSTATEDIR}" |
18 | 18 | ||
19 | python 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 | |||
32 | python write_deploy_manifest() { | ||
33 | license_deployed_manifest(d) | ||
34 | } | ||
35 | |||
36 | python 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 | |||
60 | def 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 | |||
173 | def 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 | |||
203 | def 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 | ||
248 | get_deployed_dependencies[vardepsexclude] = "BB_TASKDEPDATA" | ||
249 | |||
250 | def 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 | ||
280 | get_boot_dependencies[vardepsexclude] = "BB_TASKDEPDATA" | ||
281 | |||
282 | def 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 | |||
297 | python do_populate_lic() { | 19 | python 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" | |||
675 | do_populate_lic[sstate-inputdirs] = "${LICSSTATEDIR}" | 397 | do_populate_lic[sstate-inputdirs] = "${LICSSTATEDIR}" |
676 | do_populate_lic[sstate-outputdirs] = "${LICENSE_DIRECTORY}/" | 398 | do_populate_lic[sstate-outputdirs] = "${LICENSE_DIRECTORY}/" |
677 | 399 | ||
678 | ROOTFS_POSTPROCESS_COMMAND_prepend = "write_package_manifest; license_create_manifest; " | 400 | IMAGE_CLASSES_append = " license_image" |
679 | do_rootfs[recrdeptask] += "do_populate_lic" | ||
680 | |||
681 | IMAGE_POSTPROCESS_COMMAND_prepend = "write_deploy_manifest; " | ||
682 | do_image[recrdeptask] += "do_populate_lic" | ||
683 | 401 | ||
684 | python do_populate_lic_setscene () { | 402 | python do_populate_lic_setscene () { |
685 | sstate_setscene(d) | 403 | sstate_setscene(d) |