summaryrefslogtreecommitdiffstats
path: root/meta/lib/oe/license.py
diff options
context:
space:
mode:
Diffstat (limited to 'meta/lib/oe/license.py')
-rw-r--r--meta/lib/oe/license.py203
1 files changed, 203 insertions, 0 deletions
diff --git a/meta/lib/oe/license.py b/meta/lib/oe/license.py
index d9c8d94da4..6f882c3812 100644
--- a/meta/lib/oe/license.py
+++ b/meta/lib/oe/license.py
@@ -7,6 +7,7 @@
7 7
8import ast 8import ast
9import re 9import re
10import oe.qa
10from fnmatch import fnmatchcase as fnmatch 11from fnmatch import fnmatchcase as fnmatch
11 12
12def license_ok(license, dont_want_licenses): 13def license_ok(license, dont_want_licenses):
@@ -259,3 +260,205 @@ def apply_pkg_license_exception(pkg, bad_licenses, exceptions):
259 """Return remaining bad licenses after removing any package exceptions""" 260 """Return remaining bad licenses after removing any package exceptions"""
260 261
261 return [lic for lic in bad_licenses if pkg + ':' + lic not in exceptions] 262 return [lic for lic in bad_licenses if pkg + ':' + lic not in exceptions]
263
264def return_spdx(d, license):
265 """
266 This function returns the spdx mapping of a license if it exists.
267 """
268 return d.getVarFlag('SPDXLICENSEMAP', license)
269
270def canonical_license(d, license):
271 """
272 Return the canonical (SPDX) form of the license if available (so GPLv3
273 becomes GPL-3.0-only) or the passed license if there is no canonical form.
274 """
275 return d.getVarFlag('SPDXLICENSEMAP', license) or license
276
277def expand_wildcard_licenses(d, wildcard_licenses):
278 """
279 There are some common wildcard values users may want to use. Support them
280 here.
281 """
282 licenses = set(wildcard_licenses)
283 mapping = {
284 "AGPL-3.0*" : ["AGPL-3.0-only", "AGPL-3.0-or-later"],
285 "GPL-3.0*" : ["GPL-3.0-only", "GPL-3.0-or-later"],
286 "LGPL-3.0*" : ["LGPL-3.0-only", "LGPL-3.0-or-later"],
287 }
288 for k in mapping:
289 if k in wildcard_licenses:
290 licenses.remove(k)
291 for item in mapping[k]:
292 licenses.add(item)
293
294 for l in licenses:
295 if l in obsolete_license_list():
296 bb.fatal("Error, %s is an obsolete license, please use an SPDX reference in INCOMPATIBLE_LICENSE" % l)
297 if "*" in l:
298 bb.fatal("Error, %s is an invalid license wildcard entry" % l)
299
300 return list(licenses)
301
302def incompatible_license_contains(license, truevalue, falsevalue, d):
303 license = canonical_license(d, license)
304 bad_licenses = (d.getVar('INCOMPATIBLE_LICENSE') or "").split()
305 bad_licenses = expand_wildcard_licenses(d, bad_licenses)
306 return truevalue if license in bad_licenses else falsevalue
307
308def incompatible_pkg_license(d, dont_want_licenses, license):
309 # Handles an "or" or two license sets provided by
310 # flattened_licenses(), pick one that works if possible.
311 def choose_lic_set(a, b):
312 return a if all(license_ok(canonical_license(d, lic),
313 dont_want_licenses) for lic in a) else b
314
315 try:
316 licenses = flattened_licenses(license, choose_lic_set)
317 except LicenseError as exc:
318 bb.fatal('%s: %s' % (d.getVar('P'), exc))
319
320 incompatible_lic = []
321 for l in licenses:
322 license = canonical_license(d, l)
323 if not license_ok(license, dont_want_licenses):
324 incompatible_lic.append(license)
325
326 return sorted(incompatible_lic)
327
328def incompatible_license(d, dont_want_licenses, package=None):
329 """
330 This function checks if a recipe has only incompatible licenses. It also
331 take into consideration 'or' operand. dont_want_licenses should be passed
332 as canonical (SPDX) names.
333 """
334 license = d.getVar("LICENSE:%s" % package) if package else None
335 if not license:
336 license = d.getVar('LICENSE')
337
338 return incompatible_pkg_license(d, dont_want_licenses, license)
339
340def check_license_flags(d):
341 """
342 This function checks if a recipe has any LICENSE_FLAGS that
343 aren't acceptable.
344
345 If it does, it returns the all LICENSE_FLAGS missing from the list
346 of acceptable license flags, or all of the LICENSE_FLAGS if there
347 is no list of acceptable flags.
348
349 If everything is is acceptable, it returns None.
350 """
351
352 def license_flag_matches(flag, acceptlist, pn):
353 """
354 Return True if flag matches something in acceptlist, None if not.
355
356 Before we test a flag against the acceptlist, we append _${PN}
357 to it. We then try to match that string against the
358 acceptlist. This covers the normal case, where we expect
359 LICENSE_FLAGS to be a simple string like 'commercial', which
360 the user typically matches exactly in the acceptlist by
361 explicitly appending the package name e.g 'commercial_foo'.
362 If we fail the match however, we then split the flag across
363 '_' and append each fragment and test until we either match or
364 run out of fragments.
365 """
366 flag_pn = ("%s_%s" % (flag, pn))
367 for candidate in acceptlist:
368 if flag_pn == candidate:
369 return True
370
371 flag_cur = ""
372 flagments = flag_pn.split("_")
373 flagments.pop() # we've already tested the full string
374 for flagment in flagments:
375 if flag_cur:
376 flag_cur += "_"
377 flag_cur += flagment
378 for candidate in acceptlist:
379 if flag_cur == candidate:
380 return True
381 return False
382
383 def all_license_flags_match(license_flags, acceptlist):
384 """ Return all unmatched flags, None if all flags match """
385 pn = d.getVar('PN')
386 split_acceptlist = acceptlist.split()
387 flags = []
388 for flag in license_flags.split():
389 if not license_flag_matches(flag, split_acceptlist, pn):
390 flags.append(flag)
391 return flags if flags else None
392
393 license_flags = d.getVar('LICENSE_FLAGS')
394 if license_flags:
395 acceptlist = d.getVar('LICENSE_FLAGS_ACCEPTED')
396 if not acceptlist:
397 return license_flags.split()
398 unmatched_flags = all_license_flags_match(license_flags, acceptlist)
399 if unmatched_flags:
400 return unmatched_flags
401 return None
402
403def check_license_format(d):
404 """
405 This function checks if LICENSE is well defined,
406 Validate operators in LICENSES.
407 No spaces are allowed between LICENSES.
408 """
409 pn = d.getVar('PN')
410 licenses = d.getVar('LICENSE')
411
412 elements = list(filter(lambda x: x.strip(), license_operator.split(licenses)))
413 for pos, element in enumerate(elements):
414 if license_pattern.match(element):
415 if pos > 0 and license_pattern.match(elements[pos - 1]):
416 oe.qa.handle_error('license-format',
417 '%s: LICENSE value "%s" has an invalid format - license names ' \
418 'must be separated by the following characters to indicate ' \
419 'the license selection: %s' %
420 (pn, licenses, license_operator_chars), d)
421 elif not license_operator.match(element):
422 oe.qa.handle_error('license-format',
423 '%s: LICENSE value "%s" has an invalid separator "%s" that is not ' \
424 'in the valid list of separators (%s)' %
425 (pn, licenses, element, license_operator_chars), d)
426
427def skip_incompatible_package_licenses(d, pkgs):
428 if not pkgs:
429 return {}
430
431 pn = d.getVar("PN")
432
433 check_license = False if pn.startswith("nativesdk-") else True
434 for t in ["-native", "-cross-${TARGET_ARCH}", "-cross-initial-${TARGET_ARCH}",
435 "-crosssdk-${SDK_SYS}", "-crosssdk-initial-${SDK_SYS}",
436 "-cross-canadian-${TRANSLATED_TARGET_ARCH}"]:
437 if pn.endswith(d.expand(t)):
438 check_license = False
439 if pn.startswith("gcc-source-"):
440 check_license = False
441
442 bad_licenses = (d.getVar('INCOMPATIBLE_LICENSE') or "").split()
443 if not check_license or not bad_licenses:
444 return {}
445
446 bad_licenses = expand_wildcard_licenses(d, bad_licenses)
447
448 exceptions = (d.getVar("INCOMPATIBLE_LICENSE_EXCEPTIONS") or "").split()
449
450 for lic_exception in exceptions:
451 if ":" in lic_exception:
452 lic_exception = lic_exception.split(":")[1]
453 if lic_exception in obsolete_license_list():
454 bb.fatal("Obsolete license %s used in INCOMPATIBLE_LICENSE_EXCEPTIONS" % lic_exception)
455
456 skipped_pkgs = {}
457 for pkg in pkgs:
458 remaining_bad_licenses = apply_pkg_license_exception(pkg, bad_licenses, exceptions)
459
460 incompatible_lic = incompatible_license(d, remaining_bad_licenses, pkg)
461 if incompatible_lic:
462 skipped_pkgs[pkg] = incompatible_lic
463
464 return skipped_pkgs