@@ -128,16 +128,23 @@ def write_license_files(d, license_manifest, pkg_dic, rootfs):
pkg_allow_licenses = oe.license.filter_pkg_license_list(pkg, allow_licenses)
+ # Host tools in the SDK (nativesdk, cross-canadian) are not
+ # subject to INCOMPATIBLE_LICENSE, same as at parse time.
+ if oe.license.incompatible_license_check_needed(d, pkg_dic[pkg]["PN"]):
+ pkg_bad_licenses = bad_licenses
+ else:
+ pkg_bad_licenses = []
+
if node:
- if incompatible_licenses := oe.license.license_allowed(node, bad_licenses, pkg_allow_licenses):
+ if incompatible_licenses := oe.license.license_allowed(node, pkg_bad_licenses, pkg_allow_licenses):
incompatible_packages.append("%s (%s)" % (pkg, ' '.join(n.to_string() for n in incompatible_licenses)))
- elif incompatible_licenses := oe.license.license_allowed(node, bad_licenses, []):
+ elif incompatible_licenses := oe.license.license_allowed(node, pkg_bad_licenses, []):
oe.qa.handle_error('license-exception', "Including %s with incompatible license(s) %s into the image, because it has been allowed by exception list." %
(pkg, ' '.join(n.to_string() for n in incompatible_licenses)), d)
(pkg_dic[pkg]["LICENSE"], pkg_dic[pkg]["LICENSES"]) = \
oe.license.manifest_licenses(d, pkg_dic[pkg]["LICENSE"],
- bad_licenses, pkg_allow_licenses)
+ pkg_bad_licenses, pkg_allow_licenses)
if not "IMAGE_MANIFEST" in pkg_dic[pkg]:
# Rootfs manifest
@@ -561,23 +561,28 @@ def filter_pkg_license_list(pkg, lst):
return pkg_lst
+def incompatible_license_check_needed(d, pn):
+ """
+ Return False for recipes that INCOMPATIBLE_LICENSE does not apply to:
+ native, nativesdk, cross and cross-canadian recipes, and gcc-source.
+ """
+ if pn.startswith("nativesdk-") or pn.startswith("gcc-source-"):
+ return False
+ for t in ["-native", "-cross-${TARGET_ARCH}", "-cross-initial-${TARGET_ARCH}",
+ "-crosssdk-${SDK_SYS}", "-crosssdk-initial-${SDK_SYS}",
+ "-cross-canadian-${TRANSLATED_TARGET_ARCH}"]:
+ if pn.endswith(d.expand(t)):
+ return False
+ return True
+
def skip_incompatible_package_licenses(d, pkgs):
if not pkgs:
return {}
pn = d.getVar("PN")
- check_license = False if pn.startswith("nativesdk-") else True
- for t in ["-native", "-cross-${TARGET_ARCH}", "-cross-initial-${TARGET_ARCH}",
- "-crosssdk-${SDK_SYS}", "-crosssdk-initial-${SDK_SYS}",
- "-cross-canadian-${TRANSLATED_TARGET_ARCH}"]:
- if pn.endswith(d.expand(t)):
- check_license = False
- if pn.startswith("gcc-source-"):
- check_license = False
-
bad_licenses = (d.getVar('INCOMPATIBLE_LICENSE') or "").split()
- if not check_license or not bad_licenses:
+ if not incompatible_license_check_needed(d, pn) or not bad_licenses:
return {}
bad_licenses = expand_wildcard_licenses(d, bad_licenses)
Since the SDK host and target sysroots are passed through write_license_files(), do_populate_sdk checks every nativesdk and cross-canadian package against the image's INCOMPATIBLE_LICENSE and fails, e.g. with INCOMPATIBLE_LICENSE = "GPL-3.0*": Some packages cannot be installed into the image because they have incompatible licenses: nativesdk-autoconf (GPL-3.0-or-later) At parse time skip_incompatible_package_licenses() exempts these recipes, so they are built and packaged, and only the SDK manifest step rejects them. Move that exemption into incompatible_license_check_needed() and use it in write_license_files() too, so host tools in the SDK are treated the same way. Target packages in the image and in the SDK target sysroot are still checked. Fixes: f757ae4dadab ("license_image: extend to SDK coverage") AI-Generated: Claude Opus 5.5 (Claude Code) Signed-off-by: Sean Nyekjaer <sean@geanix.com> --- Patches for the discussion here: https://lists.openembedded.org/g/openembedded-core/topic/122226717 I would like for this to go into the wrynose branch, but it doesn't apply as is. meta/classes-recipe/license_image.bbclass | 13 +++++++++--- meta/lib/oe/license.py | 25 ++++++++++++++--------- 2 files changed, 25 insertions(+), 13 deletions(-)