diff options
author | Elizabeth Flanagan <elizabeth.flanagan@intel.com> | 2012-03-23 16:51:42 -0700 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2012-03-25 12:23:38 +0100 |
commit | bdf2d94c35b7e5ed1723f987696a6c865bff212c (patch) | |
tree | 6a39dfeac0ff192a45143842e4b70e96a57aee1c | |
parent | a3da6c381f792535e68a67f7cb78eb82b5a09842 (diff) | |
download | poky-bdf2d94c35b7e5ed1723f987696a6c865bff212c.tar.gz |
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>
-rw-r--r-- | meta/classes/base.bbclass | 40 | ||||
-rw-r--r-- | meta/classes/license.bbclass | 39 | ||||
-rw-r--r-- | meta/classes/package.bbclass | 17 |
3 files changed, 69 insertions, 27 deletions
diff --git a/meta/classes/base.bbclass b/meta/classes/base.bbclass index c8ed5447e4..ef9267a126 100644 --- a/meta/classes/base.bbclass +++ b/meta/classes/base.bbclass | |||
@@ -389,17 +389,43 @@ python () { | |||
389 | 389 | ||
390 | 390 | ||
391 | dont_want_license = d.getVar('INCOMPATIBLE_LICENSE', True) | 391 | dont_want_license = d.getVar('INCOMPATIBLE_LICENSE', True) |
392 | 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"): | ||
393 | hosttools_whitelist = (d.getVar('HOSTTOOLS_WHITELIST_%s' % dont_want_license, True) or "").split() | ||
394 | lgplv2_whitelist = (d.getVar('LGPLv2_WHITELIST_%s' % dont_want_license, True) or "").split() | ||
395 | dont_want_whitelist = (d.getVar('WHITELIST_%s' % dont_want_license, True) or "").split() | ||
396 | if pn not in hosttools_whitelist and pn not in lgplv2_whitelist and pn not in dont_want_whitelist: | ||
397 | 392 | ||
393 | 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"): | ||
394 | # Internally, we'll use the license mapping. This way INCOMPATIBLE_LICENSE = "GPLv2" and | ||
395 | # INCOMPATIBLE_LICENSE = "GPLv2.0" will pick up all variations of GPL-2.0 | ||
396 | spdx_license = return_spdx(d, dont_want_license) | ||
397 | hosttools_whitelist = (d.getVar('HOSTTOOLS_WHITELIST_%s' % dont_want_license, True) or d.getVar('HOSTTOOLS_WHITELIST_%s' % spdx_license, True) or "").split() | ||
398 | lgplv2_whitelist = (d.getVar('LGPLv2_WHITELIST_%s' % dont_want_license, True) or d.getVar('HOSTTOOLS_WHITELIST_%s' % spdx_license, True) or "").split() | ||
399 | dont_want_whitelist = (d.getVar('WHITELIST_%s' % dont_want_license, True) or d.getVar('HOSTTOOLS_WHITELIST_%s' % spdx_license, True) or "").split() | ||
400 | if pn not in hosttools_whitelist and pn not in lgplv2_whitelist and pn not in dont_want_whitelist: | ||
398 | this_license = d.getVar('LICENSE', True) | 401 | this_license = d.getVar('LICENSE', True) |
399 | if incompatible_license(d,dont_want_license): | 402 | # At this point we know the recipe contains an INCOMPATIBLE_LICENSE, however it may contain packages that do not. |
400 | bb.note("SKIPPING %s because it's %s" % (pn, this_license)) | 403 | packages = d.getVar('PACKAGES', True).split() |
404 | dont_skip_recipe = False | ||
405 | skipped_packages = {} | ||
406 | unskipped_packages = [] | ||
407 | for pkg in packages: | ||
408 | if incompatible_license(d, dont_want_license, pkg): | ||
409 | skipped_packages[pkg] = this_license | ||
410 | dont_skip_recipe = True | ||
411 | else: | ||
412 | unskipped_packages.append(pkg) | ||
413 | if not unskipped_packages: | ||
414 | # if we hit here and have excluded all packages, then we can just exclude the recipe | ||
415 | dont_skip_recipe = False | ||
416 | elif skipped_packages and unskipped_packages: | ||
417 | for pkg, license in skipped_packages.iteritems(): | ||
418 | bb.note("SKIPPING the package " + pkg + " at do_rootfs because it's " + this_license) | ||
419 | d.setVar('LICENSE_EXCLUSION-' + pkg, 1) | ||
420 | for index, pkg in enumerate(unskipped_packages): | ||
421 | bb.note("INCLUDING the package " + pkg) | ||
422 | |||
423 | if dont_skip_recipe is False and incompatible_license(d, dont_want_license): | ||
424 | bb.note("SKIPPING recipe %s because it's %s" % (pn, this_license)) | ||
401 | raise bb.parse.SkipPackage("incompatible with license %s" % this_license) | 425 | raise bb.parse.SkipPackage("incompatible with license %s" % this_license) |
402 | 426 | ||
427 | |||
428 | |||
403 | srcuri = d.getVar('SRC_URI', True) | 429 | srcuri = d.getVar('SRC_URI', True) |
404 | # Svn packages should DEPEND on subversion-native | 430 | # Svn packages should DEPEND on subversion-native |
405 | if "svn://" in srcuri: | 431 | if "svn://" in srcuri: |
diff --git a/meta/classes/license.bbclass b/meta/classes/license.bbclass index 4b392ceea0..eab630e47b 100644 --- a/meta/classes/license.bbclass +++ b/meta/classes/license.bbclass | |||
@@ -81,7 +81,7 @@ license_create_manifest() { | |||
81 | INSTALLED_PKGS=`cat ${LICENSE_DIRECTORY}/${IMAGE_NAME}/package.manifest` | 81 | INSTALLED_PKGS=`cat ${LICENSE_DIRECTORY}/${IMAGE_NAME}/package.manifest` |
82 | # list of installed packages is broken for deb | 82 | # list of installed packages is broken for deb |
83 | for pkg in ${INSTALLED_PKGS}; do | 83 | for pkg in ${INSTALLED_PKGS}; do |
84 | # not the best way to do this but licenses are not arch-dependent iirc | 84 | # not the best way to do this but licenses are not arch dependant iirc |
85 | files=`find ${TMPDIR}/pkgdata/*/runtime -name ${pkg}| head -1` | 85 | files=`find ${TMPDIR}/pkgdata/*/runtime -name ${pkg}| head -1` |
86 | for filename in $files; do | 86 | for filename in $files; do |
87 | pkged_pn="$(sed -n 's/^PN: //p' ${filename})" | 87 | pkged_pn="$(sed -n 's/^PN: //p' ${filename})" |
@@ -135,7 +135,6 @@ license_create_manifest() { | |||
135 | 135 | ||
136 | } | 136 | } |
137 | 137 | ||
138 | |||
139 | python do_populate_lic() { | 138 | python do_populate_lic() { |
140 | """ | 139 | """ |
141 | Populate LICENSE_DIRECTORY with licenses. | 140 | Populate LICENSE_DIRECTORY with licenses. |
@@ -254,27 +253,40 @@ python do_populate_lic() { | |||
254 | 253 | ||
255 | } | 254 | } |
256 | 255 | ||
257 | def incompatible_license(d,dont_want_license): | 256 | def return_spdx(d, license): |
257 | """ | ||
258 | This function returns the spdx mapping of a license. | ||
258 | """ | 259 | """ |
259 | This function checks if a package has only incompatible licenses. It also take into consideration 'or' | 260 | if d.getVarFlag('SPDXLICENSEMAP', license) != None: |
261 | return license | ||
262 | else: | ||
263 | return d.getVarFlag('SPDXLICENSEMAP', license_type) | ||
264 | |||
265 | def incompatible_license(d, dont_want_license, package=""): | ||
266 | """ | ||
267 | This function checks if a recipe has only incompatible licenses. It also take into consideration 'or' | ||
260 | operand. | 268 | operand. |
261 | """ | 269 | """ |
262 | import re | 270 | import re |
263 | import oe.license | 271 | import oe.license |
264 | from fnmatch import fnmatchcase as fnmatch | 272 | from fnmatch import fnmatchcase as fnmatch |
265 | 273 | pn = d.getVar('PN', True) | |
266 | dont_want_licenses = [] | 274 | dont_want_licenses = [] |
267 | dont_want_licenses.append(d.getVar('INCOMPATIBLE_LICENSE', True)) | 275 | dont_want_licenses.append(d.getVar('INCOMPATIBLE_LICENSE', True)) |
268 | if d.getVarFlag('SPDXLICENSEMAP', dont_want_license): | 276 | recipe_license = d.getVar('LICENSE', True) |
269 | dont_want_licenses.append(d.getVarFlag('SPDXLICENSEMAP', dont_want_license)) | 277 | if package != "": |
278 | if d.getVar('LICENSE_' + pn + '-' + package, True): | ||
279 | license = d.getVar('LICENSE_' + pn + '-' + package, True) | ||
280 | else: | ||
281 | license = recipe_license | ||
282 | else: | ||
283 | license = recipe_license | ||
284 | spdx_license = return_spdx(d, dont_want_license) | ||
285 | dont_want_licenses.append(spdx_license) | ||
270 | 286 | ||
271 | def include_license(license): | 287 | def include_license(license): |
272 | if any(fnmatch(license, pattern) for pattern in dont_want_licenses): | 288 | if any(fnmatch(license, pattern) for pattern in dont_want_licenses): |
273 | return False | 289 | return False |
274 | else: | ||
275 | spdx_license = d.getVarFlag('SPDXLICENSEMAP', license) | ||
276 | if spdx_license and any(fnmatch(spdx_license, pattern) for pattern in dont_want_licenses): | ||
277 | return False | ||
278 | else: | 290 | else: |
279 | return True | 291 | return True |
280 | 292 | ||
@@ -290,16 +302,15 @@ def incompatible_license(d,dont_want_license): | |||
290 | is not a 'X+' license. | 302 | is not a 'X+' license. |
291 | """ | 303 | """ |
292 | if not re.search(r'[+]',dont_want_license): | 304 | if not re.search(r'[+]',dont_want_license): |
293 | licenses=oe.license.flattened_licenses(re.sub(r'[+]', '', d.getVar('LICENSE', True)), choose_licenses) | 305 | licenses=oe.license.flattened_licenses(re.sub(r'[+]', '', license), choose_licenses) |
294 | else: | 306 | else: |
295 | licenses=oe.license.flattened_licenses(d.getVar('LICENSE', True), choose_licenses) | 307 | licenses=oe.license.flattened_licenses(license, choose_licenses) |
296 | 308 | ||
297 | for onelicense in licenses: | 309 | for onelicense in licenses: |
298 | if not include_license(onelicense): | 310 | if not include_license(onelicense): |
299 | return True | 311 | return True |
300 | return False | 312 | return False |
301 | 313 | ||
302 | |||
303 | def check_license_flags(d): | 314 | def check_license_flags(d): |
304 | """ | 315 | """ |
305 | This function checks if a recipe has any LICENSE_FLAGs that | 316 | This function checks if a recipe has any LICENSE_FLAGs that |
diff --git a/meta/classes/package.bbclass b/meta/classes/package.bbclass index bdc4d37af6..20af8b7914 100644 --- a/meta/classes/package.bbclass +++ b/meta/classes/package.bbclass | |||
@@ -887,15 +887,20 @@ python populate_packages () { | |||
887 | bb.mkdirhier(outdir) | 887 | bb.mkdirhier(outdir) |
888 | os.chdir(dvar) | 888 | os.chdir(dvar) |
889 | 889 | ||
890 | # Sanity check PACKAGES for duplicates - should be moved to | 890 | # Sanity check PACKAGES for duplicates and for LICENSE_EXCLUSION |
891 | # sanity.bbclass once we have the infrastucture | 891 | # Sanity should be moved to sanity.bbclass once we have the infrastucture |
892 | package_list = [] | 892 | package_list = [] |
893 | |||
893 | for pkg in packages.split(): | 894 | for pkg in packages.split(): |
894 | if pkg in package_list: | 895 | if d.getVar('LICENSE_EXCLUSION-' + pkg, True): |
895 | bb.error("%s is listed in PACKAGES multiple times, this leads to packaging errors." % pkg) | 896 | bb.warn("%s has an incompatible license. Excluding from packaging." % pkg) |
897 | packages.remove(pkg) | ||
896 | else: | 898 | else: |
897 | package_list.append(pkg) | 899 | if pkg in package_list: |
898 | 900 | bb.error("%s is listed in PACKAGES multiple times, this leads to packaging errors." % pkg) | |
901 | else: | ||
902 | package_list.append(pkg) | ||
903 | d.setVar('PACKAGES', ' '.join(package_list)) | ||
899 | pkgdest = d.getVar('PKGDEST', True) | 904 | pkgdest = d.getVar('PKGDEST', True) |
900 | os.system('rm -rf %s' % pkgdest) | 905 | os.system('rm -rf %s' % pkgdest) |
901 | 906 | ||