blob: 43944e6ee6cf037510323d5f145fa4e2bd09f838 [file] [log] [blame]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001# Populates LICENSE_DIRECTORY as set in distro config with the license files as set by
2# LIC_FILES_CHKSUM.
3# TODO:
4# - There is a real issue revolving around license naming standards.
5
6LICENSE_DIRECTORY ??= "${DEPLOY_DIR}/licenses"
7LICSSTATEDIR = "${WORKDIR}/license-destdir/"
8
9# Create extra package with license texts and add it to RRECOMMENDS_${PN}
10LICENSE_CREATE_PACKAGE[type] = "boolean"
11LICENSE_CREATE_PACKAGE ??= "0"
12LICENSE_PACKAGE_SUFFIX ??= "-lic"
13LICENSE_FILES_DIRECTORY ??= "${datadir}/licenses/"
14
15addtask populate_lic after do_patch before do_build
16do_populate_lic[dirs] = "${LICSSTATEDIR}/${PN}"
17do_populate_lic[cleandirs] = "${LICSSTATEDIR}"
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
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050024 from oe.utils import format_pkg_list
25
26 pkgs = image_list_installed_packages(d)
27 output = format_pkg_list(pkgs)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050028 open(os.path.join(license_image_dir, 'package.manifest'),
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050029 'w+').write(output)
30}
31
32python write_deploy_manifest() {
33 license_deployed_manifest(d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050034}
35
36python license_create_manifest() {
Patrick Williamsc124f4f2015-09-15 14:41:29 -050037 import oe.packagedata
38 from oe.rootfs import image_list_installed_packages
39
Patrick Williamsc124f4f2015-09-15 14:41:29 -050040 build_images_from_feeds = d.getVar('BUILD_IMAGES_FROM_FEEDS', True)
41 if build_images_from_feeds == "1":
42 return 0
43
44 pkg_dic = {}
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050045 for pkg in sorted(image_list_installed_packages(d)):
Patrick Williamsc124f4f2015-09-15 14:41:29 -050046 pkg_info = os.path.join(d.getVar('PKGDATA_DIR', True),
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
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050055 rootfs_license_manifest = os.path.join(d.getVar('LICENSE_DIRECTORY', True),
Patrick Williamsc124f4f2015-09-15 14:41:29 -050056 d.getVar('IMAGE_NAME', True), 'license.manifest')
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050057 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", True) or "").split()
64 bad_licenses = map(lambda l: canonical_license(d, l), bad_licenses)
65 bad_licenses = expand_wildcard_licenses(d, bad_licenses)
66
Patrick Williamsc124f4f2015-09-15 14:41:29 -050067 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', True), exc))
76 else:
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050077 pkg_dic[pkg]["LICENSES"] = re.sub('[|&()*]', ' ', pkg_dic[pkg]["LICENSE"])
Patrick Williamsc124f4f2015-09-15 14:41:29 -050078 pkg_dic[pkg]["LICENSES"] = re.sub(' *', ' ', pkg_dic[pkg]["LICENSES"])
79 pkg_dic[pkg]["LICENSES"] = pkg_dic[pkg]["LICENSES"].split()
80
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050081 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"])
Patrick Williamsc124f4f2015-09-15 14:41:29 -050087
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050088 # 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"])
Patrick Williamsc124f4f2015-09-15 14:41:29 -050099
100 for lic in pkg_dic[pkg]["LICENSES"]:
101 lic_file = os.path.join(d.getVar('LICENSE_DIRECTORY', True),
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', True)
118 copy_lic_dirs = d.getVar('COPY_LIC_DIRS', True)
119 if copy_lic_manifest == "1":
120 rootfs_license_dir = os.path.join(d.getVar('IMAGE_ROOTFS', 'True'),
121 'usr', 'share', 'common-licenses')
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500122 bb.utils.mkdirhier(rootfs_license_dir)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500123 rootfs_license_manifest = os.path.join(rootfs_license_dir,
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500124 os.path.split(license_manifest)[1])
125 if not os.path.exists(rootfs_license_manifest):
126 os.link(license_manifest, rootfs_license_manifest)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500127
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)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500131 bb.utils.mkdirhier(pkg_rootfs_license_dir)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500132 pkg_license_dir = os.path.join(d.getVar('LICENSE_DIRECTORY', True),
133 pkg_dic[pkg]["PN"])
134 licenses = os.listdir(pkg_license_dir)
135 for lic in licenses:
136 rootfs_license = os.path.join(rootfs_license_dir, lic)
137 pkg_license = os.path.join(pkg_license_dir, lic)
138 pkg_rootfs_license = os.path.join(pkg_rootfs_license_dir, lic)
139
140 if re.match("^generic_.*$", lic):
141 generic_lic = re.search("^generic_(.*)$", lic).group(1)
142 if oe.license.license_ok(canonical_license(d,
143 generic_lic), bad_licenses) == False:
144 continue
145
146 if not os.path.exists(rootfs_license):
147 os.link(pkg_license, rootfs_license)
148
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500149 if not os.path.exists(pkg_rootfs_license):
150 os.symlink(os.path.join('..', lic), pkg_rootfs_license)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500151 else:
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500152 if (oe.license.license_ok(canonical_license(d,
153 lic), bad_licenses) == False or
154 os.path.exists(pkg_rootfs_license)):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500155 continue
156
157 os.link(pkg_license, pkg_rootfs_license)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500158
159
160def license_deployed_manifest(d):
161 """
162 Write the license manifest for the deployed recipes.
163 The deployed recipes usually includes the bootloader
164 and extra files to boot the target.
165 """
166
167 dep_dic = {}
168 man_dic = {}
169 lic_dir = d.getVar("LICENSE_DIRECTORY", True)
170
171 dep_dic = get_deployed_dependencies(d)
172 for dep in dep_dic.keys():
173 man_dic[dep] = {}
174 # It is necessary to mark this will be used for image manifest
175 man_dic[dep]["IMAGE_MANIFEST"] = True
176 man_dic[dep]["PN"] = dep
177 man_dic[dep]["FILES"] = \
178 " ".join(get_deployed_files(dep_dic[dep]))
179 with open(os.path.join(lic_dir, dep, "recipeinfo"), "r") as f:
180 for line in f.readlines():
181 key,val = line.split(": ", 1)
182 man_dic[dep][key] = val[:-1]
183
184 image_license_manifest = os.path.join(d.getVar('LICENSE_DIRECTORY', True),
185 d.getVar('IMAGE_NAME', True), 'image_license.manifest')
186 write_license_files(d, image_license_manifest, man_dic)
187
188def get_deployed_dependencies(d):
189 """
190 Get all the deployed dependencies of an image
191 """
192
193 deploy = {}
194 # Get all the dependencies for the current task (rootfs).
195 # Also get EXTRA_IMAGEDEPENDS because the bootloader is
196 # usually in this var and not listed in rootfs.
197 # At last, get the dependencies from boot classes because
198 # it might contain the bootloader.
199 taskdata = d.getVar("BB_TASKDEPDATA", False)
200 depends = list(set([dep[0] for dep
201 in taskdata.itervalues()
202 if not dep[0].endswith("-native")]))
203 extra_depends = d.getVar("EXTRA_IMAGEDEPENDS", True)
204 boot_depends = get_boot_dependencies(d)
205 depends.extend(extra_depends.split())
206 depends.extend(boot_depends)
207 depends = list(set(depends))
208
209 # To verify what was deployed it checks the rootfs dependencies against
210 # the SSTATE_MANIFESTS for "deploy" task.
211 # The manifest file name contains the arch. Because we are not running
212 # in the recipe context it is necessary to check every arch used.
213 sstate_manifest_dir = d.getVar("SSTATE_MANIFESTS", True)
214 sstate_archs = d.getVar("SSTATE_ARCHS", True)
215 extra_archs = d.getVar("PACKAGE_EXTRA_ARCHS", True)
216 archs = list(set(("%s %s" % (sstate_archs, extra_archs)).split()))
217 for dep in depends:
218 # Some recipes have an arch on their own, so we try that first.
219 special_arch = d.getVar("PACKAGE_ARCH_pn-%s" % dep, True)
220 if special_arch:
221 sstate_manifest_file = os.path.join(sstate_manifest_dir,
222 "manifest-%s-%s.deploy" % (special_arch, dep))
223 if os.path.exists(sstate_manifest_file):
224 deploy[dep] = sstate_manifest_file
225 continue
226
227 for arch in archs:
228 sstate_manifest_file = os.path.join(sstate_manifest_dir,
229 "manifest-%s-%s.deploy" % (arch, dep))
230 if os.path.exists(sstate_manifest_file):
231 deploy[dep] = sstate_manifest_file
232 break
233
234 return deploy
235get_deployed_dependencies[vardepsexclude] = "BB_TASKDEPDATA"
236
237def get_boot_dependencies(d):
238 """
239 Return the dependencies from boot tasks
240 """
241
242 depends = []
243 boot_depends_string = ""
244 taskdepdata = d.getVar("BB_TASKDEPDATA", False)
245 # Only bootimg and bootdirectdisk include the depends flag
246 boot_tasks = ["do_bootimg", "do_bootdirectdisk",]
247
248 for task in boot_tasks:
249 boot_depends_string = "%s %s" % (boot_depends_string,
250 d.getVarFlag(task, "depends", True) or "")
251 boot_depends = [dep.split(":")[0] for dep
252 in boot_depends_string.split()
253 if not dep.split(":")[0].endswith("-native")]
254 for dep in boot_depends:
255 info_file = os.path.join(d.getVar("LICENSE_DIRECTORY", True),
256 dep, "recipeinfo")
257 # If the recipe and dependency name is the same
258 if os.path.exists(info_file):
259 depends.append(dep)
260 # We need to search for the provider of the dependency
261 else:
262 for taskdep in taskdepdata.itervalues():
263 # The fifth field contains what the task provides
264 if dep in taskdep[4]:
265 info_file = os.path.join(
266 d.getVar("LICENSE_DIRECTORY", True),
267 taskdep[0], "recipeinfo")
268 if os.path.exists(info_file):
269 depends.append(taskdep[0])
270 break
271 return depends
272get_boot_dependencies[vardepsexclude] = "BB_TASKDEPDATA"
273
274def get_deployed_files(man_file):
275 """
276 Get the files deployed from the sstate manifest
277 """
278
279 dep_files = []
280 excluded_files = ["README_-_DO_NOT_DELETE_FILES_IN_THIS_DIRECTORY.txt"]
281 with open(man_file, "r") as manifest:
282 all_files = manifest.read()
283 for f in all_files.splitlines():
284 if ((not (os.path.islink(f) or os.path.isdir(f))) and
285 not os.path.basename(f) in excluded_files):
286 dep_files.append(os.path.basename(f))
287 return dep_files
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500288
289python do_populate_lic() {
290 """
291 Populate LICENSE_DIRECTORY with licenses.
292 """
293 lic_files_paths = find_license_files(d)
294
295 # The base directory we wrangle licenses to
296 destdir = os.path.join(d.getVar('LICSSTATEDIR', True), d.getVar('PN', True))
297 copy_license_files(lic_files_paths, destdir)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500298 info = get_recipe_info(d)
299 with open(os.path.join(destdir, "recipeinfo"), "w") as f:
300 for key in sorted(info.keys()):
301 f.write("%s: %s\n" % (key, info[key]))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500302}
303
304# it would be better to copy them in do_install_append, but find_license_filesa is python
305python perform_packagecopy_prepend () {
306 enabled = oe.data.typed_value('LICENSE_CREATE_PACKAGE', d)
307 if d.getVar('CLASSOVERRIDE', True) == 'class-target' and enabled:
308 lic_files_paths = find_license_files(d)
309
310 # LICENSE_FILES_DIRECTORY starts with '/' so os.path.join cannot be used to join D and LICENSE_FILES_DIRECTORY
311 destdir = d.getVar('D', True) + os.path.join(d.getVar('LICENSE_FILES_DIRECTORY', True), d.getVar('PN', True))
312 copy_license_files(lic_files_paths, destdir)
313 add_package_and_files(d)
314}
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500315perform_packagecopy[vardeps] += "LICENSE_CREATE_PACKAGE"
316
317def get_recipe_info(d):
318 info = {}
319 info["PV"] = d.getVar("PV", True)
320 info["PR"] = d.getVar("PR", True)
321 info["LICENSE"] = d.getVar("LICENSE", True)
322 return info
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500323
324def add_package_and_files(d):
325 packages = d.getVar('PACKAGES', True)
326 files = d.getVar('LICENSE_FILES_DIRECTORY', True)
327 pn = d.getVar('PN', True)
328 pn_lic = "%s%s" % (pn, d.getVar('LICENSE_PACKAGE_SUFFIX', False))
329 if pn_lic in packages:
330 bb.warn("%s package already existed in %s." % (pn_lic, pn))
331 else:
332 # first in PACKAGES to be sure that nothing else gets LICENSE_FILES_DIRECTORY
333 d.setVar('PACKAGES', "%s %s" % (pn_lic, packages))
334 d.setVar('FILES_' + pn_lic, files)
335 rrecommends_pn = d.getVar('RRECOMMENDS_' + pn, True)
336 if rrecommends_pn:
337 d.setVar('RRECOMMENDS_' + pn, "%s %s" % (pn_lic, rrecommends_pn))
338 else:
339 d.setVar('RRECOMMENDS_' + pn, "%s" % (pn_lic))
340
341def copy_license_files(lic_files_paths, destdir):
342 import shutil
343
344 bb.utils.mkdirhier(destdir)
345 for (basename, path) in lic_files_paths:
346 try:
347 src = path
348 dst = os.path.join(destdir, basename)
349 if os.path.exists(dst):
350 os.remove(dst)
351 if os.access(src, os.W_OK) and (os.stat(src).st_dev == os.stat(destdir).st_dev):
352 os.link(src, dst)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500353 try:
354 os.chown(dst,0,0)
355 except OSError as err:
356 import errno
357 if err.errno in (errno.EPERM, errno.EINVAL):
358 # Suppress "Operation not permitted" error, as
359 # sometimes this function is not executed under pseudo.
360 # Also ignore "Invalid argument" errors that happen in
361 # some (unprivileged) container environments (no root).
362 pass
363 else:
364 raise
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500365 else:
366 shutil.copyfile(src, dst)
367 except Exception as e:
368 bb.warn("Could not copy license file %s to %s: %s" % (src, dst, e))
369
370def find_license_files(d):
371 """
372 Creates list of files used in LIC_FILES_CHKSUM and generic LICENSE files.
373 """
374 import shutil
375 import oe.license
376
377 pn = d.getVar('PN', True)
378 for package in d.getVar('PACKAGES', True):
379 if d.getVar('LICENSE_' + package, True):
380 license_types = license_types + ' & ' + \
381 d.getVar('LICENSE_' + package, True)
382
383 #If we get here with no license types, then that means we have a recipe
384 #level license. If so, we grab only those.
385 try:
386 license_types
387 except NameError:
388 # All the license types at the recipe level
389 license_types = d.getVar('LICENSE', True)
390
391 # All the license files for the package
392 lic_files = d.getVar('LIC_FILES_CHKSUM', True)
393 pn = d.getVar('PN', True)
394 # The license files are located in S/LIC_FILE_CHECKSUM.
395 srcdir = d.getVar('S', True)
396 # Directory we store the generic licenses as set in the distro configuration
397 generic_directory = d.getVar('COMMON_LICENSE_DIR', True)
398 # List of basename, path tuples
399 lic_files_paths = []
400 license_source_dirs = []
401 license_source_dirs.append(generic_directory)
402 try:
403 additional_lic_dirs = d.getVar('LICENSE_PATH', True).split()
404 for lic_dir in additional_lic_dirs:
405 license_source_dirs.append(lic_dir)
406 except:
407 pass
408
409 class FindVisitor(oe.license.LicenseVisitor):
410 def visit_Str(self, node):
411 #
412 # Until I figure out what to do with
413 # the two modifiers I support (or greater = +
414 # and "with exceptions" being *
415 # we'll just strip out the modifier and put
416 # the base license.
417 find_license(node.s.replace("+", "").replace("*", ""))
418 self.generic_visit(node)
419
420 def find_license(license_type):
421 try:
422 bb.utils.mkdirhier(gen_lic_dest)
423 except:
424 pass
425 spdx_generic = None
426 license_source = None
427 # If the generic does not exist we need to check to see if there is an SPDX mapping to it,
428 # unless NO_GENERIC_LICENSE is set.
429
430 for lic_dir in license_source_dirs:
431 if not os.path.isfile(os.path.join(lic_dir, license_type)):
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500432 if d.getVarFlag('SPDXLICENSEMAP', license_type, True) != None:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500433 # Great, there is an SPDXLICENSEMAP. We can copy!
434 bb.debug(1, "We need to use a SPDXLICENSEMAP for %s" % (license_type))
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500435 spdx_generic = d.getVarFlag('SPDXLICENSEMAP', license_type, True)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500436 license_source = lic_dir
437 break
438 elif os.path.isfile(os.path.join(lic_dir, license_type)):
439 spdx_generic = license_type
440 license_source = lic_dir
441 break
442
443 if spdx_generic and license_source:
444 # we really should copy to generic_ + spdx_generic, however, that ends up messing the manifest
445 # audit up. This should be fixed in emit_pkgdata (or, we actually got and fix all the recipes)
446
447 lic_files_paths.append(("generic_" + license_type, os.path.join(license_source, spdx_generic)))
448
449 # The user may attempt to use NO_GENERIC_LICENSE for a generic license which doesn't make sense
450 # and should not be allowed, warn the user in this case.
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500451 if d.getVarFlag('NO_GENERIC_LICENSE', license_type, True):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500452 bb.warn("%s: %s is a generic license, please don't use NO_GENERIC_LICENSE for it." % (pn, license_type))
453
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500454 elif d.getVarFlag('NO_GENERIC_LICENSE', license_type, True):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500455 # if NO_GENERIC_LICENSE is set, we copy the license files from the fetched source
456 # of the package rather than the license_source_dirs.
457 for (basename, path) in lic_files_paths:
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500458 if d.getVarFlag('NO_GENERIC_LICENSE', license_type, True) == basename:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500459 lic_files_paths.append(("generic_" + license_type, path))
460 break
461 else:
462 # Add explicity avoid of CLOSED license because this isn't generic
463 if license_type != 'CLOSED':
464 # And here is where we warn people that their licenses are lousy
465 bb.warn("%s: No generic license file exists for: %s in any provider" % (pn, license_type))
466 pass
467
468 if not generic_directory:
469 raise bb.build.FuncFailed("COMMON_LICENSE_DIR is unset. Please set this in your distro config")
470
471 if not lic_files:
472 # No recipe should have an invalid license file. This is checked else
473 # where, but let's be pedantic
474 bb.note(pn + ": Recipe file does not have license file information.")
475 return lic_files_paths
476
477 for url in lic_files.split():
478 try:
479 (type, host, path, user, pswd, parm) = bb.fetch.decodeurl(url)
480 except bb.fetch.MalformedUrl:
481 raise bb.build.FuncFailed("%s: LIC_FILES_CHKSUM contains an invalid URL: %s" % (d.getVar('PF', True), url))
482 # We want the license filename and path
483 srclicfile = os.path.join(srcdir, path)
484 lic_files_paths.append((os.path.basename(path), srclicfile))
485
486 v = FindVisitor()
487 try:
488 v.visit_string(license_types)
489 except oe.license.InvalidLicense as exc:
490 bb.fatal('%s: %s' % (d.getVar('PF', True), exc))
491 except SyntaxError:
492 bb.warn("%s: Failed to parse it's LICENSE field." % (d.getVar('PF', True)))
493
494 return lic_files_paths
495
496def return_spdx(d, license):
497 """
498 This function returns the spdx mapping of a license if it exists.
499 """
500 return d.getVarFlag('SPDXLICENSEMAP', license, True)
501
502def canonical_license(d, license):
503 """
504 Return the canonical (SPDX) form of the license if available (so GPLv3
505 becomes GPL-3.0), for the license named 'X+', return canonical form of
506 'X' if availabel and the tailing '+' (so GPLv3+ becomes GPL-3.0+),
507 or the passed license if there is no canonical form.
508 """
509 lic = d.getVarFlag('SPDXLICENSEMAP', license, True) or ""
510 if not lic and license.endswith('+'):
511 lic = d.getVarFlag('SPDXLICENSEMAP', license.rstrip('+'), True)
512 if lic:
513 lic += '+'
514 return lic or license
515
516def expand_wildcard_licenses(d, wildcard_licenses):
517 """
518 Return actual spdx format license names if wildcard used. We expand
519 wildcards from SPDXLICENSEMAP flags and SRC_DISTRIBUTE_LICENSES values.
520 """
521 import fnmatch
522 licenses = []
523 spdxmapkeys = d.getVarFlags('SPDXLICENSEMAP').keys()
524 for wld_lic in wildcard_licenses:
525 spdxflags = fnmatch.filter(spdxmapkeys, wld_lic)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500526 licenses += [d.getVarFlag('SPDXLICENSEMAP', flag, True) for flag in spdxflags]
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500527
528 spdx_lics = (d.getVar('SRC_DISTRIBUTE_LICENSES', False) or '').split()
529 for wld_lic in wildcard_licenses:
530 licenses += fnmatch.filter(spdx_lics, wld_lic)
531
532 licenses = list(set(licenses))
533 return licenses
534
535def incompatible_license_contains(license, truevalue, falsevalue, d):
536 license = canonical_license(d, license)
537 bad_licenses = (d.getVar('INCOMPATIBLE_LICENSE', True) or "").split()
538 bad_licenses = expand_wildcard_licenses(d, bad_licenses)
539 return truevalue if license in bad_licenses else falsevalue
540
541def incompatible_license(d, dont_want_licenses, package=None):
542 """
543 This function checks if a recipe has only incompatible licenses. It also
544 take into consideration 'or' operand. dont_want_licenses should be passed
545 as canonical (SPDX) names.
546 """
547 import oe.license
548 license = d.getVar("LICENSE_%s" % package, True) if package else None
549 if not license:
550 license = d.getVar('LICENSE', True)
551
552 # Handles an "or" or two license sets provided by
553 # flattened_licenses(), pick one that works if possible.
554 def choose_lic_set(a, b):
555 return a if all(oe.license.license_ok(canonical_license(d, lic),
556 dont_want_licenses) for lic in a) else b
557
558 try:
559 licenses = oe.license.flattened_licenses(license, choose_lic_set)
560 except oe.license.LicenseError as exc:
561 bb.fatal('%s: %s' % (d.getVar('P', True), exc))
562 return any(not oe.license.license_ok(canonical_license(d, l), \
563 dont_want_licenses) for l in licenses)
564
565def check_license_flags(d):
566 """
567 This function checks if a recipe has any LICENSE_FLAGS that
568 aren't whitelisted.
569
570 If it does, it returns the first LICENSE_FLAGS item missing from the
571 whitelist, or all of the LICENSE_FLAGS if there is no whitelist.
572
573 If everything is is properly whitelisted, it returns None.
574 """
575
576 def license_flag_matches(flag, whitelist, pn):
577 """
578 Return True if flag matches something in whitelist, None if not.
579
580 Before we test a flag against the whitelist, we append _${PN}
581 to it. We then try to match that string against the
582 whitelist. This covers the normal case, where we expect
583 LICENSE_FLAGS to be a simple string like 'commercial', which
584 the user typically matches exactly in the whitelist by
585 explicitly appending the package name e.g 'commercial_foo'.
586 If we fail the match however, we then split the flag across
587 '_' and append each fragment and test until we either match or
588 run out of fragments.
589 """
590 flag_pn = ("%s_%s" % (flag, pn))
591 for candidate in whitelist:
592 if flag_pn == candidate:
593 return True
594
595 flag_cur = ""
596 flagments = flag_pn.split("_")
597 flagments.pop() # we've already tested the full string
598 for flagment in flagments:
599 if flag_cur:
600 flag_cur += "_"
601 flag_cur += flagment
602 for candidate in whitelist:
603 if flag_cur == candidate:
604 return True
605 return False
606
607 def all_license_flags_match(license_flags, whitelist):
608 """ Return first unmatched flag, None if all flags match """
609 pn = d.getVar('PN', True)
610 split_whitelist = whitelist.split()
611 for flag in license_flags.split():
612 if not license_flag_matches(flag, split_whitelist, pn):
613 return flag
614 return None
615
616 license_flags = d.getVar('LICENSE_FLAGS', True)
617 if license_flags:
618 whitelist = d.getVar('LICENSE_FLAGS_WHITELIST', True)
619 if not whitelist:
620 return license_flags
621 unmatched_flag = all_license_flags_match(license_flags, whitelist)
622 if unmatched_flag:
623 return unmatched_flag
624 return None
625
626def check_license_format(d):
627 """
628 This function checks if LICENSE is well defined,
629 Validate operators in LICENSES.
630 No spaces are allowed between LICENSES.
631 """
632 pn = d.getVar('PN', True)
633 licenses = d.getVar('LICENSE', True)
634 from oe.license import license_operator, license_operator_chars, license_pattern
635
636 elements = filter(lambda x: x.strip(), license_operator.split(licenses))
637 for pos, element in enumerate(elements):
638 if license_pattern.match(element):
639 if pos > 0 and license_pattern.match(elements[pos - 1]):
640 bb.warn('%s: LICENSE value "%s" has an invalid format - license names ' \
641 'must be separated by the following characters to indicate ' \
642 'the license selection: %s' %
643 (pn, licenses, license_operator_chars))
644 elif not license_operator.match(element):
645 bb.warn('%s: LICENSE value "%s" has an invalid separator "%s" that is not ' \
646 'in the valid list of separators (%s)' %
647 (pn, licenses, element, license_operator_chars))
648
649SSTATETASKS += "do_populate_lic"
650do_populate_lic[sstate-inputdirs] = "${LICSSTATEDIR}"
651do_populate_lic[sstate-outputdirs] = "${LICENSE_DIRECTORY}/"
652
653ROOTFS_POSTPROCESS_COMMAND_prepend = "write_package_manifest; license_create_manifest; "
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500654do_rootfs[recrdeptask] += "do_populate_lic"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500655
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500656IMAGE_POSTPROCESS_COMMAND_prepend = "write_deploy_manifest; "
657do_image[recrdeptask] += "do_populate_lic"
658
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500659do_populate_lic_setscene[dirs] = "${LICSSTATEDIR}/${PN}"
660do_populate_lic_setscene[cleandirs] = "${LICSSTATEDIR}"
661python do_populate_lic_setscene () {
662 sstate_setscene(d)
663}
664addtask do_populate_lic_setscene