From patchwork Fri Nov 13 10:15:36 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Nyekjaer X-Patchwork-Id: 103982 Received: from mail-43170.protonmail.ch (mail-43170.protonmail.ch [185.70.43.170]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.7931.1794564951269539076 for ; Fri, 13 Nov 2026 02:15:52 -0800 Authentication-Results: mx.groups.io; dkim=fail reason="dkim: body hash did not verify" header.i=@geanix.com header.s=protonmail header.b=7ZxdYhSR; spf=pass (domain: geanix.com, ip: 185.70.43.170, mailfrom: sean@geanix.com) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=geanix.com; s=protonmail; t=1794564947; x=1794824147; bh=1j7/8LUrrqCgzEek4VqgbgTIFAxFyzthkHlf8B/NsmA=; h=From:To:Cc:Subject:Date:Message-ID:From:To:Cc:Date:Subject: Reply-To:Feedback-ID:Message-ID:BIMI-Selector; b=7ZxdYhSRfmdphGc6QdJXZTrIq433yvaFGVl7/vs95q1CrRPcLu3rXFQJKTakaWoTN nfzG6Wignj7TzOjrZ6OEpUjxWx4+XuWuh2Ftb4qr6ba6ki1R+WUe17Tlgm8QCO/pdd WC2S6vj3fU6WnlEV0jgwwcG5nP+goaXjIa7hvB42RoA1uqAbf+Zz/eNJDuSCRrysgL SQQP+B5Lw6q+vpSG8dY1L7MHgcwXM0X4g7U8CAkyjmw7cE8r0gLIp19hv2m7DyE+q0 Kz1o1bH1vbfxsEepRnXzWaznSV9MaJezb89VpVEDRDGDxypFWs/KZ7lBMyhgf1qEfp QdvGnmRvBCtTQ== X-Pm-Submission-Id: 4jQtSL1Yjnz1DF5P From: Sean Nyekjaer To: openembedded-core@lists.openembedded.org Cc: Sean Nyekjaer Subject: [PATCH 1/2] license_image: don't apply INCOMPATIBLE_LICENSE to SDK host tools Date: Fri, 13 Nov 2026 11:15:36 +0100 Message-ID: <20261113101537.3586467-1-sean@geanix.com> X-Mailer: git-send-email 2.56.0 MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Fri, 13 Nov 2026 10:15:56 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/250157 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 --- 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(-) diff --git a/meta/classes-recipe/license_image.bbclass b/meta/classes-recipe/license_image.bbclass index 7d00b1ae53..728db8ae3a 100644 --- a/meta/classes-recipe/license_image.bbclass +++ b/meta/classes-recipe/license_image.bbclass @@ -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 diff --git a/meta/lib/oe/license.py b/meta/lib/oe/license.py index e2a2bcc47d..035311d469 100644 --- a/meta/lib/oe/license.py +++ b/meta/lib/oe/license.py @@ -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) From patchwork Fri Nov 13 10:15:37 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Nyekjaer X-Patchwork-Id: 103981 Received: from mail-106112.protonmail.ch (mail-106112.protonmail.ch [79.135.106.112]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.7932.1794564951767781098 for ; Fri, 13 Nov 2026 02:15:52 -0800 Authentication-Results: mx.groups.io; dkim=fail reason="dkim: body hash did not verify" header.i=@geanix.com header.s=protonmail header.b=Mdxaxvh4; spf=pass (domain: geanix.com, ip: 79.135.106.112, mailfrom: sean@geanix.com) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=geanix.com; s=protonmail; t=1794564949; x=1794824149; bh=zAibuKcnPaytrHHm+y2CI+5zxhPFS6f3vz0LoZXz6ug=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References:From:To: Cc:Date:Subject:Reply-To:Feedback-ID:Message-ID:BIMI-Selector; b=Mdxaxvh4axarD3w0rTRdy+gR893jzZ5r+ye8nURiO4GbyLBF+4pcNuUPvjaqEZHL/ PXVKDMYAV+x6nWIup8+uYHnPcpFTb7CyPoNMdv4I+vBVDoBQs7Q0rhHe4MeAmAaX5e 41Nlr9emmO5HZ8CGPA6eduNeIeoZop/KzxVuPxkNqidjHk0kvWIRDKhCB2raj709d5 HfJKIoV9gRE9AxPjzgo/XzXIoa0kv5puJgs30kMu0K8FcifWuk+wdH9c4kmx4rV2XU frv2lBDnGuwQ0zG2PzXJWsrW1gzh2HMWQfMctbr5hgDXLrbn9dgcfDjfSaO2m8e6rq 4lf0GNKx0ZZHQ== X-Pm-Submission-Id: 4jQtSM144Zz1DFF6 From: Sean Nyekjaer To: openembedded-core@lists.openembedded.org Cc: Sean Nyekjaer Subject: [PATCH 2/2] oeqa/selftest/incompatible_lic: test INCOMPATIBLE_LICENSE in populate_sdk Date: Fri, 13 Nov 2026 11:15:37 +0100 Message-ID: <20261113101537.3586467-2-sean@geanix.com> X-Mailer: git-send-email 2.56.0 In-Reply-To: <20261113101537.3586467-1-sean@geanix.com> References: <20261113101537.3586467-1-sean@geanix.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Fri, 13 Nov 2026 10:15:56 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/250156 Check that do_populate_sdk ignores the image's INCOMPATIBLE_LICENSE for SDK host tools (nativesdk-bash) and still applies it to packages in the SDK target sysroot (which). bash can't be used for the target check, as target-sdk-provides-dummy RPROVIDES bash, so it is never installed into the SDK target sysroot. Autoconf-exception-macro is added to the exceptions, as the SDK's complementary packages include xz-src. AI-Generated: Claude Opus 5.5 (Claude Code) Signed-off-by: Sean Nyekjaer --- It seems weird to add the AI-Generated tag here. It took quite a lot of effort to get the tests to fail before 1/2 and pass after 1/2. .../oeqa/selftest/cases/incompatible_lic.py | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/meta/lib/oeqa/selftest/cases/incompatible_lic.py b/meta/lib/oeqa/selftest/cases/incompatible_lic.py index 406f92e37b..e05e2ee31c 100644 --- a/meta/lib/oeqa/selftest/cases/incompatible_lic.py +++ b/meta/lib/oeqa/selftest/cases/incompatible_lic.py @@ -155,6 +155,34 @@ NO_GENERIC_LICENSE[SomeLicense] = "COPYING" """)) bitbake('core-image-minimal') +class IncompatibleLicensePerImageSDKTests(OESelftestTestCase): + def default_config(self): + return """ +INCOMPATIBLE_LICENSE:pn-core-image-minimal = "GPL-3.0* LGPL-3.0*" +INCOMPATIBLE_LICENSE_EXCEPTIONS:pn-core-image-minimal = "GCC-exception-3.1 Autoconf-exception-macro" +ERROR_QA:remove:pn-core-image-minimal = "license-exception" + +require conf/distro/include/no-gplv3.inc +""" + + # Verify that host tools in the SDK (nativesdk, cross-canadian) are not + # checked against the image's INCOMPATIBLE_LICENSE, the same as at parse + # time + def test_sdk_host_gpl3(self): + self.write_config(self.default_config() + '\nTOOLCHAIN_HOST_TASK:append:pn-core-image-minimal = " nativesdk-bash"') + + bitbake('core-image-minimal -c populate_sdk') + + # Verify that target packages in the SDK sysroot are still checked + # against the image's INCOMPATIBLE_LICENSE + def test_sdk_target_gpl3(self): + self.write_config(self.default_config() + '\nTOOLCHAIN_TARGET_TASK:append:pn-core-image-minimal = " which"') + error_msg = "ERROR: core-image-minimal-1.0-r0 do_populate_sdk: Some packages cannot be installed into the image because they have incompatible licenses:\n\twhich (GPL-3.0-or-later)" + + result = bitbake('core-image-minimal -c populate_sdk', ignore_status=True) + if error_msg not in result.output: + raise AssertionError(result.output) + class NoGPL3InImagesTests(OESelftestTestCase): def test_core_image_minimal(self): self.write_config("""