INCOMPATIBLE_LICENSE: support for spdx and pkg licenses

This adds a few things to the incompatible license functionality

1. INCOMPATIBLE_LICENSE was unable to distinguish any variation
within LICENSE (e.g. GPLv3 v. GPLv3.0). This now utilizes the
SPDXLICENSEMAP of the license indicated as INCOMPATIBLE_LICENSE

2. Given a recipe where the main LICENSE was incompatible but
a package of the recipe was compatible, the entire recipe would
be excluded. This allows us some finer grained control over what
exactly gets excluded.

(From OE-Core rev: a8d7246f7b13ef2636c325263c8bfa22552d7a57)

Signed-off-by: Elizabeth Flanagan <elizabeth.flanagan@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
This commit is contained in:
Elizabeth Flanagan 2012-03-23 16:51:42 -07:00 committed by Richard Purdie
parent a3da6c381f
commit bdf2d94c35
3 changed files with 70 additions and 28 deletions

View File

@ -389,17 +389,43 @@ python () {
dont_want_license = d.getVar('INCOMPATIBLE_LICENSE', True) dont_want_license = d.getVar('INCOMPATIBLE_LICENSE', True)
if dont_want_license and not pn.endswith("-native") and not pn.endswith("-cross") and not pn.endswith("-cross-initial") and not pn.endswith("-cross-intermediate") and not pn.endswith("-crosssdk-intermediate") and not pn.endswith("-crosssdk") and not pn.endswith("-crosssdk-initial"):
hosttools_whitelist = (d.getVar('HOSTTOOLS_WHITELIST_%s' % dont_want_license, True) or "").split()
lgplv2_whitelist = (d.getVar('LGPLv2_WHITELIST_%s' % dont_want_license, True) or "").split()
dont_want_whitelist = (d.getVar('WHITELIST_%s' % dont_want_license, True) or "").split()
if pn not in hosttools_whitelist and pn not in lgplv2_whitelist and pn not in dont_want_whitelist:
if dont_want_license and not pn.endswith("-native") and not pn.endswith("-cross") and not pn.endswith("-cross-initial") and not pn.endswith("-cross-intermediate") and not pn.endswith("-crosssdk-intermediate") and not pn.endswith("-crosssdk") and not pn.endswith("-crosssdk-initial") and not pn.endswith("-nativesdk"):
# Internally, we'll use the license mapping. This way INCOMPATIBLE_LICENSE = "GPLv2" and
# INCOMPATIBLE_LICENSE = "GPLv2.0" will pick up all variations of GPL-2.0
spdx_license = return_spdx(d, dont_want_license)
hosttools_whitelist = (d.getVar('HOSTTOOLS_WHITELIST_%s' % dont_want_license, True) or d.getVar('HOSTTOOLS_WHITELIST_%s' % spdx_license, True) or "").split()
lgplv2_whitelist = (d.getVar('LGPLv2_WHITELIST_%s' % dont_want_license, True) or d.getVar('HOSTTOOLS_WHITELIST_%s' % spdx_license, True) or "").split()
dont_want_whitelist = (d.getVar('WHITELIST_%s' % dont_want_license, True) or d.getVar('HOSTTOOLS_WHITELIST_%s' % spdx_license, True) or "").split()
if pn not in hosttools_whitelist and pn not in lgplv2_whitelist and pn not in dont_want_whitelist:
this_license = d.getVar('LICENSE', True) this_license = d.getVar('LICENSE', True)
if incompatible_license(d,dont_want_license): # At this point we know the recipe contains an INCOMPATIBLE_LICENSE, however it may contain packages that do not.
bb.note("SKIPPING %s because it's %s" % (pn, this_license)) packages = d.getVar('PACKAGES', True).split()
dont_skip_recipe = False
skipped_packages = {}
unskipped_packages = []
for pkg in packages:
if incompatible_license(d, dont_want_license, pkg):
skipped_packages[pkg] = this_license
dont_skip_recipe = True
else:
unskipped_packages.append(pkg)
if not unskipped_packages:
# if we hit here and have excluded all packages, then we can just exclude the recipe
dont_skip_recipe = False
elif skipped_packages and unskipped_packages:
for pkg, license in skipped_packages.iteritems():
bb.note("SKIPPING the package " + pkg + " at do_rootfs because it's " + this_license)
d.setVar('LICENSE_EXCLUSION-' + pkg, 1)
for index, pkg in enumerate(unskipped_packages):
bb.note("INCLUDING the package " + pkg)
if dont_skip_recipe is False and incompatible_license(d, dont_want_license):
bb.note("SKIPPING recipe %s because it's %s" % (pn, this_license))
raise bb.parse.SkipPackage("incompatible with license %s" % this_license) raise bb.parse.SkipPackage("incompatible with license %s" % this_license)
srcuri = d.getVar('SRC_URI', True) srcuri = d.getVar('SRC_URI', True)
# Svn packages should DEPEND on subversion-native # Svn packages should DEPEND on subversion-native
if "svn://" in srcuri: if "svn://" in srcuri:

View File

@ -81,7 +81,7 @@ license_create_manifest() {
INSTALLED_PKGS=`cat ${LICENSE_DIRECTORY}/${IMAGE_NAME}/package.manifest` INSTALLED_PKGS=`cat ${LICENSE_DIRECTORY}/${IMAGE_NAME}/package.manifest`
# list of installed packages is broken for deb # list of installed packages is broken for deb
for pkg in ${INSTALLED_PKGS}; do for pkg in ${INSTALLED_PKGS}; do
# not the best way to do this but licenses are not arch-dependent iirc # not the best way to do this but licenses are not arch dependant iirc
files=`find ${TMPDIR}/pkgdata/*/runtime -name ${pkg}| head -1` files=`find ${TMPDIR}/pkgdata/*/runtime -name ${pkg}| head -1`
for filename in $files; do for filename in $files; do
pkged_pn="$(sed -n 's/^PN: //p' ${filename})" pkged_pn="$(sed -n 's/^PN: //p' ${filename})"
@ -135,7 +135,6 @@ license_create_manifest() {
} }
python do_populate_lic() { python do_populate_lic() {
""" """
Populate LICENSE_DIRECTORY with licenses. Populate LICENSE_DIRECTORY with licenses.
@ -254,27 +253,40 @@ python do_populate_lic() {
} }
def incompatible_license(d,dont_want_license): def return_spdx(d, license):
""" """
This function checks if a package has only incompatible licenses. It also take into consideration 'or' This function returns the spdx mapping of a license.
"""
if d.getVarFlag('SPDXLICENSEMAP', license) != None:
return license
else:
return d.getVarFlag('SPDXLICENSEMAP', license_type)
def incompatible_license(d, dont_want_license, package=""):
"""
This function checks if a recipe has only incompatible licenses. It also take into consideration 'or'
operand. operand.
""" """
import re import re
import oe.license import oe.license
from fnmatch import fnmatchcase as fnmatch from fnmatch import fnmatchcase as fnmatch
pn = d.getVar('PN', True)
dont_want_licenses = [] dont_want_licenses = []
dont_want_licenses.append(d.getVar('INCOMPATIBLE_LICENSE', True)) dont_want_licenses.append(d.getVar('INCOMPATIBLE_LICENSE', True))
if d.getVarFlag('SPDXLICENSEMAP', dont_want_license): recipe_license = d.getVar('LICENSE', True)
dont_want_licenses.append(d.getVarFlag('SPDXLICENSEMAP', dont_want_license)) if package != "":
if d.getVar('LICENSE_' + pn + '-' + package, True):
license = d.getVar('LICENSE_' + pn + '-' + package, True)
else:
license = recipe_license
else:
license = recipe_license
spdx_license = return_spdx(d, dont_want_license)
dont_want_licenses.append(spdx_license)
def include_license(license): def include_license(license):
if any(fnmatch(license, pattern) for pattern in dont_want_licenses): if any(fnmatch(license, pattern) for pattern in dont_want_licenses):
return False return False
else:
spdx_license = d.getVarFlag('SPDXLICENSEMAP', license)
if spdx_license and any(fnmatch(spdx_license, pattern) for pattern in dont_want_licenses):
return False
else: else:
return True return True
@ -290,16 +302,15 @@ def incompatible_license(d,dont_want_license):
is not a 'X+' license. is not a 'X+' license.
""" """
if not re.search(r'[+]',dont_want_license): if not re.search(r'[+]',dont_want_license):
licenses=oe.license.flattened_licenses(re.sub(r'[+]', '', d.getVar('LICENSE', True)), choose_licenses) licenses=oe.license.flattened_licenses(re.sub(r'[+]', '', license), choose_licenses)
else: else:
licenses=oe.license.flattened_licenses(d.getVar('LICENSE', True), choose_licenses) licenses=oe.license.flattened_licenses(license, choose_licenses)
for onelicense in licenses: for onelicense in licenses:
if not include_license(onelicense): if not include_license(onelicense):
return True return True
return False return False
def check_license_flags(d): def check_license_flags(d):
""" """
This function checks if a recipe has any LICENSE_FLAGs that This function checks if a recipe has any LICENSE_FLAGs that

View File

@ -887,15 +887,20 @@ python populate_packages () {
bb.mkdirhier(outdir) bb.mkdirhier(outdir)
os.chdir(dvar) os.chdir(dvar)
# Sanity check PACKAGES for duplicates - should be moved to # Sanity check PACKAGES for duplicates and for LICENSE_EXCLUSION
# sanity.bbclass once we have the infrastucture # Sanity should be moved to sanity.bbclass once we have the infrastucture
package_list = [] package_list = []
for pkg in packages.split():
if pkg in package_list:
bb.error("%s is listed in PACKAGES multiple times, this leads to packaging errors." % pkg)
else:
package_list.append(pkg)
for pkg in packages.split():
if d.getVar('LICENSE_EXCLUSION-' + pkg, True):
bb.warn("%s has an incompatible license. Excluding from packaging." % pkg)
packages.remove(pkg)
else:
if pkg in package_list:
bb.error("%s is listed in PACKAGES multiple times, this leads to packaging errors." % pkg)
else:
package_list.append(pkg)
d.setVar('PACKAGES', ' '.join(package_list))
pkgdest = d.getVar('PKGDEST', True) pkgdest = d.getVar('PKGDEST', True)
os.system('rm -rf %s' % pkgdest) os.system('rm -rf %s' % pkgdest)