All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Joshua Watt" <JPEWhacker@gmail.com>
To: openembedded-core@lists.openembedded.org
Cc: ross.burton@arm.com, saul.wold@windriver.com,
	Joshua Watt <JPEWhacker@gmail.com>
Subject: [OE-core][PATCH 11/31] classes/create-spdx: Fix up license reporting
Date: Wed,  1 Sep 2021 08:44:50 -0500	[thread overview]
Message-ID: <20210901134510.29561-12-JPEWhacker@gmail.com> (raw)
In-Reply-To: <20210901134510.29561-1-JPEWhacker@gmail.com>

Licenses reported in the SPDX documents should be either:
 A) A valid SPDX identifier cross referenced from the SPDX license
    database
 B) A "LicenseRef" to a license described in the SPDX document

The licensing code will now add a placeholder extracted license with
corresponding "LicenseRef" for any licenses that are not matched to the
SPDX database

Parenthesis in the license expression are now handled correctly

Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
---
 meta/classes/create-spdx.bbclass | 55 +++++++++++++++++++++++++++-----
 meta/lib/oe/spdx.py              |  8 +++++
 2 files changed, 55 insertions(+), 8 deletions(-)

diff --git a/meta/classes/create-spdx.bbclass b/meta/classes/create-spdx.bbclass
index 72c1385feb..2e13b19b5b 100644
--- a/meta/classes/create-spdx.bbclass
+++ b/meta/classes/create-spdx.bbclass
@@ -23,6 +23,8 @@ SPDX_ARCHIVE_PACKAGED ??= "0"
 SPDX_UUID_NAMESPACE ??= "sbom.openembedded.org"
 SPDX_NAMESPACE_PREFIX ??= "http://spdx.org/spdxdoc"
 
+SPDX_LICENSES ??= "${COREBASE}/meta/files/spdx-licenses.json"
+
 do_image_complete[depends] = "virtual/kernel:do_create_spdx"
 
 def get_doc_namespace(d, doc):
@@ -36,21 +38,54 @@ def is_work_shared(d):
     return bb.data.inherits_class('kernel', d) or pn.startswith('gcc-source')
 
 
-def convert_license_to_spdx(lic, d):
+python() {
+    import json
+    if d.getVar("SPDX_LICENSE_DATA"):
+        return
+
+    with open(d.getVar("SPDX_LICENSES"), "r") as f:
+        d.setVar("SPDX_LICENSE_DATA", json.load(f))
+}
+
+def convert_license_to_spdx(lic, document, d):
+    import oe.spdx
+
+    license_data = d.getVar("SPDX_LICENSE_DATA")
     def convert(l):
+        if l == "(" or l == ")":
+            return l
+
         if l == "&":
             return "AND"
 
         if l == "|":
             return "OR"
 
-        spdx = d.getVarFlag('SPDXLICENSEMAP', l)
-        if spdx is not None:
-            return spdx
+        spdx_license = d.getVarFlag("SPDXLICENSEMAP", l) or l
+        for lic_data in license_data["licenses"]:
+            if lic_data["licenseId"] == spdx_license:
+                return spdx_license
+
+        spdx_license = "LicenseRef-" + l
+        for spdx_lic in document.hasExtractedLicensingInfos:
+            if spdx_lic.licenseId == spdx_license:
+                return spdx_license
+
+        bb.warn("No SPDX License found for %s. Creating a place holder" % l)
+
+        spdx_lic = oe.spdx.SPDXExtractedLicensingInfo()
+        spdx_lic.name = l
+        spdx_lic.licenseId = spdx_license
+        # TODO: Extract the actual license text from the common license files
+        spdx_lic.extractedText = "This software is licensed under the %s license" % l
+
+        document.hasExtractedLicensingInfos.append(spdx_lic)
+
+        return spdx_license
 
-        return l
+    lic_split = lic.replace("(", " ( ").replace(")", " ) ").split()
 
-    return ' '.join(convert(l) for l in lic.split())
+    return ' '.join(convert(l) for l in lic_split)
 
 
 def process_sources(d):
@@ -334,6 +369,7 @@ python do_create_spdx() {
     doc.documentNamespace = get_doc_namespace(d, doc)
     doc.creationInfo.created = creation_time
     doc.creationInfo.comment = "This document was created by analyzing recipe files during the build."
+    doc.creationInfo.licenseListVersion = d.getVar("SPDX_LICENSE_DATA")["licenseListVersion"]
     doc.creationInfo.creators.append("Tool: OpenEmbedded Core create-spdx.bbclass")
     doc.creationInfo.creators.append("Organization: OpenEmbedded ()")
     doc.creationInfo.creators.append("Person: N/A ()")
@@ -353,7 +389,7 @@ python do_create_spdx() {
 
     license = d.getVar("LICENSE")
     if license:
-        recipe.licenseDeclared = convert_license_to_spdx(license, d)
+        recipe.licenseDeclared = convert_license_to_spdx(license, doc, d)
 
     summary = d.getVar("SUMMARY")
     if summary:
@@ -422,6 +458,7 @@ python do_create_spdx() {
         package_doc.documentNamespace = get_doc_namespace(d, package_doc)
         package_doc.creationInfo.created = creation_time
         package_doc.creationInfo.comment = "This document was created by analyzing packages created during the build."
+        package_doc.creationInfo.licenseListVersion = d.getVar("SPDX_LICENSE_DATA")["licenseListVersion"]
         package_doc.creationInfo.creators.append("Tool: OpenEmbedded Core create-spdx.bbclass")
         package_doc.creationInfo.creators.append("Organization: OpenEmbedded ()")
         package_doc.creationInfo.creators.append("Person: N/A ()")
@@ -441,7 +478,7 @@ python do_create_spdx() {
         spdx_package.SPDXID = oe.sbom.get_package_spdxid(pkg_name)
         spdx_package.name = pkg_name
         spdx_package.versionInfo = d.getVar("PV")
-        spdx_package.licenseDeclared = convert_license_to_spdx(package_license, d)
+        spdx_package.licenseDeclared = convert_license_to_spdx(package_license, package_doc, d)
 
         package_doc.packages.append(spdx_package)
 
@@ -561,6 +598,7 @@ python do_create_runtime_spdx() {
         runtime_doc.documentNamespace = get_doc_namespace(localdata, runtime_doc)
         runtime_doc.creationInfo.created = creation_time
         runtime_doc.creationInfo.comment = "This document was created by analyzing package runtime dependencies."
+        runtime_doc.creationInfo.licenseListVersion = d.getVar("SPDX_LICENSE_DATA")["licenseListVersion"]
         runtime_doc.creationInfo.creators.append("Tool: OpenEmbedded Core create-spdx.bbclass")
         runtime_doc.creationInfo.creators.append("Organization: OpenEmbedded ()")
         runtime_doc.creationInfo.creators.append("Person: N/A ()")
@@ -720,6 +758,7 @@ python image_combine_spdx() {
     doc.documentNamespace = get_doc_namespace(d, doc)
     doc.creationInfo.created = creation_time
     doc.creationInfo.comment = "This document was created by analyzing the source of the Yocto recipe during the build."
+    doc.creationInfo.licenseListVersion = d.getVar("SPDX_LICENSE_DATA")["licenseListVersion"]
     doc.creationInfo.creators.append("Tool: OpenEmbedded Core create-spdx.bbclass")
     doc.creationInfo.creators.append("Organization: OpenEmbedded ()")
     doc.creationInfo.creators.append("Person: N/A ()")
diff --git a/meta/lib/oe/spdx.py b/meta/lib/oe/spdx.py
index 3f569c6862..9814fbfd66 100644
--- a/meta/lib/oe/spdx.py
+++ b/meta/lib/oe/spdx.py
@@ -189,6 +189,13 @@ class SPDXExternalDocumentRef(SPDXObject):
     checksum = _Object(SPDXChecksum)
 
 
+class SPDXExtractedLicensingInfo(SPDXObject):
+    name = _String()
+    comment = _String()
+    licenseId = _String()
+    extractedText = _String()
+
+
 class SPDXDocument(SPDXObject):
     spdxVersion = _String(default="SPDX-" + SPDX_VERSION)
     dataLicense = _String(default="CC0-1.0")
@@ -200,6 +207,7 @@ class SPDXDocument(SPDXObject):
     files = _ObjectList(SPDXFile)
     relationships = _ObjectList(SPDXRelationship)
     externalDocumentRefs = _ObjectList(SPDXExternalDocumentRef)
+    hasExtractedLicensingInfos = _ObjectList(SPDXExtractedLicensingInfo)
 
     def __init__(self, **d):
         super().__init__(**d)
-- 
2.32.0


  parent reply	other threads:[~2021-09-01 13:45 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-09-01 13:44 [OE-core][PATCH 00/31] Add initial SBoM support Joshua Watt
2021-09-01 13:44 ` [OE-core][PATCH 01/31] classes/package: Add extended packaged data Joshua Watt
2021-09-01 13:44 ` [OE-core][PATCH 02/31] classes/create-spdx: Add class Joshua Watt
2021-09-01 13:44 ` [OE-core][PATCH 03/31] classes/create-spdx: Change creator Joshua Watt
2021-09-01 13:44 ` [OE-core][PATCH 04/31] classes/create-spdx: Add SHA1 to index file Joshua Watt
2021-09-01 13:44 ` [OE-core][PATCH 05/31] classes/create-spdx: Add index to DEPLOYDIR Joshua Watt
2021-09-01 13:44 ` [OE-core][PATCH 06/31] classes/create-spdx: Add runtime dependency mapping Joshua Watt
2021-09-01 13:44 ` [OE-core][PATCH 07/31] classes/create-spdx: Add NOASSERTION for unknown debug sources Joshua Watt
2021-09-01 13:44 ` [OE-core][PATCH 08/31] classes/create-spdx: Fix another creator Joshua Watt
2021-09-01 13:44 ` [OE-core][PATCH 09/31] classes/create-spdx: extend DocumentRef to include name Joshua Watt
2021-09-01 13:44 ` [OE-core][PATCH 10/31] Add SPDX licenses Joshua Watt
2021-09-01 13:44 ` Joshua Watt [this message]
2021-09-01 13:44 ` [OE-core][PATCH 12/31] classes/create-spdx: Speed up hash calculations Joshua Watt
2021-09-01 13:44 ` [OE-core][PATCH 13/31] classes/create-spdx: Fix file:// in downloadLocation Joshua Watt
2021-09-01 13:44 ` [OE-core][PATCH 14/31] classes/create-spdx: Add special exception for Public Domain license Joshua Watt
2021-09-01 13:44 ` [OE-core][PATCH 15/31] classes/create-spdx: Collect all task dependencies Joshua Watt
2021-09-01 13:44 ` [OE-core][PATCH 16/31] classes/create-spdx: Skip package processing for native recipes Joshua Watt
2021-09-01 13:44 ` [OE-core][PATCH 17/31] classes/create-spdx: Comment out placeholder license warning Joshua Watt
2021-09-01 13:44 ` [OE-core][PATCH 18/31] conf/licenses: Add FreeType SPDX mapping Joshua Watt
2021-09-01 13:44 ` [OE-core][PATCH 19/31] tzdata: Remove BSD License specifier Joshua Watt
2021-09-01 23:00   ` Denys Dmytriyenko
2021-09-02  6:52     ` Richard Purdie
2021-09-01 13:44 ` [OE-core][PATCH 20/31] glib-2.0: Use specific BSD license variant Joshua Watt
2021-09-01 13:45 ` [OE-core][PATCH 21/31] e2fsprogs: " Joshua Watt
2021-09-01 13:45 ` [OE-core][PATCH 22/31] shadow: " Joshua Watt
2021-09-01 13:45 ` [OE-core][PATCH 23/31] sudo: " Joshua Watt
2021-09-01 13:45 ` [OE-core][PATCH 24/31] libcap: " Joshua Watt
2021-09-01 13:45 ` [OE-core][PATCH 25/31] libpam: " Joshua Watt
2021-09-01 13:45 ` [OE-core][PATCH 26/31] libxfont2: " Joshua Watt
2021-09-01 13:45 ` [OE-core][PATCH 27/31] libjitterentropy: " Joshua Watt
2021-09-01 13:45 ` [OE-core][PATCH 28/31] libx11: " Joshua Watt
2021-09-01 13:45 ` [OE-core][PATCH 29/31] font-util: " Joshua Watt
2021-09-01 13:45 ` [OE-core][PATCH 30/31] flac: " Joshua Watt
2021-09-01 13:45 ` [OE-core][PATCH 31/31] swig: " Joshua Watt

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210901134510.29561-12-JPEWhacker@gmail.com \
    --to=jpewhacker@gmail.com \
    --cc=openembedded-core@lists.openembedded.org \
    --cc=ross.burton@arm.com \
    --cc=saul.wold@windriver.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.