| Message ID | 20260303234247.8034-1-martin.jansa@gmail.com |
|---|---|
| State | Under Review |
| Headers | show |
| Series | license_image.bbclass: report all packages with incompatible license | expand |
> -----Original Message----- > From: openembedded-core@lists.openembedded.org <openembedded-core@lists.openembedded.org> On Behalf Of Martin Jansa via lists.openembedded.org > Sent: den 4 mars 2026 00:43 > To: openembedded-core@lists.openembedded.org > Cc: Martin Jansa <martin.jansa@gmail.com> > Subject: [OE-core] [PATCH] license_image.bbclass: report all packages with incompatible license > > From: Martin Jansa <martin.jansa@gmail.com> > > When multiple packages cannot be installed it shows only first one it > finds, because of bb.fatal use. It might require many iterations to find > all packages to avoid. > > e.g. with ptest enabled and GPL-3.0-or-later, GPL-3.0-only set as > incompatible licenses you might get list like this for relatively small > image: > > Some packages cannot be installed into the image because they have incompatible licenses: bzip2-ptest (GPL-3.0-or-later), coreutils (GPL-3.0-or-later), coreutils-stdbuf (GPL-3.0-or-later), diffutils (GPL-3.0-or-later), findutils (GPL-3.0-or-later), gawk (GPL-3.0-or-later), gnutls-openssl (GPL-3.0-or-later), gnutls-ptest (GPL-3.0-or-later), grep (GPL-3.0-only), make (GPL-3.0-only), mpfr (LGPL-3.0-or-later), python3-dbusmock (GPL-3.0-only), readline (GPL-3.0-or-later), sed (GPL-3.0-or-later) > > Signed-off-by: Martin Jansa <martin.jansa@gmail.com> > --- > meta/classes-recipe/license_image.bbclass | 6 +++++- > 1 file changed, 5 insertions(+), 1 deletion(-) > > diff --git a/meta/classes-recipe/license_image.bbclass b/meta/classes-recipe/license_image.bbclass > index 8332905da5..252754727b 100644 > --- a/meta/classes-recipe/license_image.bbclass > +++ b/meta/classes-recipe/license_image.bbclass > @@ -116,6 +116,7 @@ def write_license_files(d, license_manifest, pkg_dic, > rootfs): > bad_licenses = oe.license.expand_wildcard_licenses(d, bad_licenses) > pkgarchs = d.getVar("SSTATE_ARCHS").split() > pkgarchs.reverse() > + incompatible_packages = [] > > exceptions = (d.getVar("INCOMPATIBLE_LICENSE_EXCEPTIONS") or "").split() > with open(license_manifest, "w") as license_file: > @@ -123,7 +124,7 @@ def write_license_files(d, license_manifest, pkg_dic, rootfs): > remaining_bad_licenses = oe.license.apply_pkg_license_exception(pkg, bad_licenses, exceptions) > incompatible_licenses = oe.license.incompatible_pkg_license(d, remaining_bad_licenses, pkg_dic[pkg]["LICENSE"]) > if incompatible_licenses: > - bb.fatal("Package %s cannot be installed into the image because it has incompatible license(s): %s" %(pkg, ' '.join(incompatible_licenses))) > + incompatible_packages.append("%s (%s)" % (pkg, ' '.join(incompatible_licenses))) > else: > incompatible_licenses = oe.license.incompatible_pkg_license(d, bad_licenses, pkg_dic[pkg]["LICENSE"]) > if incompatible_licenses: > @@ -171,6 +172,9 @@ def write_license_files(d, license_manifest, pkg_dic, rootfs): > "The license listed %s was not in the "\ > "licenses collected for recipe %s" > % (lic, pkg_dic[pkg]["PN"]), d) > + if incompatible_packages: > + bb.fatal("Some packages cannot be installed into the image because they have incompatible licenses: %s" % (', '.join(incompatible_packages))) May I suggest to use "\n\t" as separator instead. Especially if you expect a lot of packages to be shown, having them all on one line becomes messy very quickly. E.g.: bb.fatal("Some packages cannot be installed into the image because they have incompatible licenses:\n\t%s" % ("\n\t".join(incompatible_packages))) > + > oe.qa.exit_if_errors(d) > > # Two options here: //Peter
diff --git a/meta/classes-recipe/license_image.bbclass b/meta/classes-recipe/license_image.bbclass index 8332905da5..252754727b 100644 --- a/meta/classes-recipe/license_image.bbclass +++ b/meta/classes-recipe/license_image.bbclass @@ -116,6 +116,7 @@ def write_license_files(d, license_manifest, pkg_dic, rootfs): bad_licenses = oe.license.expand_wildcard_licenses(d, bad_licenses) pkgarchs = d.getVar("SSTATE_ARCHS").split() pkgarchs.reverse() + incompatible_packages = [] exceptions = (d.getVar("INCOMPATIBLE_LICENSE_EXCEPTIONS") or "").split() with open(license_manifest, "w") as license_file: @@ -123,7 +124,7 @@ def write_license_files(d, license_manifest, pkg_dic, rootfs): remaining_bad_licenses = oe.license.apply_pkg_license_exception(pkg, bad_licenses, exceptions) incompatible_licenses = oe.license.incompatible_pkg_license(d, remaining_bad_licenses, pkg_dic[pkg]["LICENSE"]) if incompatible_licenses: - bb.fatal("Package %s cannot be installed into the image because it has incompatible license(s): %s" %(pkg, ' '.join(incompatible_licenses))) + incompatible_packages.append("%s (%s)" % (pkg, ' '.join(incompatible_licenses))) else: incompatible_licenses = oe.license.incompatible_pkg_license(d, bad_licenses, pkg_dic[pkg]["LICENSE"]) if incompatible_licenses: @@ -171,6 +172,9 @@ def write_license_files(d, license_manifest, pkg_dic, rootfs): "The license listed %s was not in the "\ "licenses collected for recipe %s" % (lic, pkg_dic[pkg]["PN"]), d) + if incompatible_packages: + bb.fatal("Some packages cannot be installed into the image because they have incompatible licenses: %s" % (', '.join(incompatible_packages))) + oe.qa.exit_if_errors(d) # Two options here: