diff options
| author | Joshua Watt <JPEWhacker@gmail.com> | 2021-09-01 08:44:50 -0500 |
|---|---|---|
| committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2021-09-03 09:53:28 +0100 |
| commit | 902480107dd0db7b77ada4654d2e0f061a04765d (patch) | |
| tree | 8078d3cb307999d69d1eba7360d1455b06d303fa /meta | |
| parent | 0d5c2d9f352bb6e81d6e4f2592a074195c26f578 (diff) | |
| download | poky-902480107dd0db7b77ada4654d2e0f061a04765d.tar.gz | |
classes/create-spdx: Fix up license reporting
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
(From OE-Core rev: 28d9d035c0ff8fcaf28bc96a976a43a602a47e94)
Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta')
| -rw-r--r-- | meta/classes/create-spdx.bbclass | 55 | ||||
| -rw-r--r-- | 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" | |||
| 23 | SPDX_UUID_NAMESPACE ??= "sbom.openembedded.org" | 23 | SPDX_UUID_NAMESPACE ??= "sbom.openembedded.org" |
| 24 | SPDX_NAMESPACE_PREFIX ??= "http://spdx.org/spdxdoc" | 24 | SPDX_NAMESPACE_PREFIX ??= "http://spdx.org/spdxdoc" |
| 25 | 25 | ||
| 26 | SPDX_LICENSES ??= "${COREBASE}/meta/files/spdx-licenses.json" | ||
| 27 | |||
| 26 | do_image_complete[depends] = "virtual/kernel:do_create_spdx" | 28 | do_image_complete[depends] = "virtual/kernel:do_create_spdx" |
| 27 | 29 | ||
| 28 | def get_doc_namespace(d, doc): | 30 | def get_doc_namespace(d, doc): |
| @@ -36,21 +38,54 @@ def is_work_shared(d): | |||
| 36 | return bb.data.inherits_class('kernel', d) or pn.startswith('gcc-source') | 38 | return bb.data.inherits_class('kernel', d) or pn.startswith('gcc-source') |
| 37 | 39 | ||
| 38 | 40 | ||
| 39 | def convert_license_to_spdx(lic, d): | 41 | python() { |
| 42 | import json | ||
| 43 | if d.getVar("SPDX_LICENSE_DATA"): | ||
| 44 | return | ||
| 45 | |||
| 46 | with open(d.getVar("SPDX_LICENSES"), "r") as f: | ||
| 47 | d.setVar("SPDX_LICENSE_DATA", json.load(f)) | ||
| 48 | } | ||
| 49 | |||
| 50 | def convert_license_to_spdx(lic, document, d): | ||
| 51 | import oe.spdx | ||
| 52 | |||
| 53 | license_data = d.getVar("SPDX_LICENSE_DATA") | ||
| 40 | def convert(l): | 54 | def convert(l): |
| 55 | if l == "(" or l == ")": | ||
| 56 | return l | ||
| 57 | |||
| 41 | if l == "&": | 58 | if l == "&": |
| 42 | return "AND" | 59 | return "AND" |
| 43 | 60 | ||
| 44 | if l == "|": | 61 | if l == "|": |
| 45 | return "OR" | 62 | return "OR" |
| 46 | 63 | ||
| 47 | spdx = d.getVarFlag('SPDXLICENSEMAP', l) | 64 | spdx_license = d.getVarFlag("SPDXLICENSEMAP", l) or l |
| 48 | if spdx is not None: | 65 | for lic_data in license_data["licenses"]: |
| 49 | return spdx | 66 | if lic_data["licenseId"] == spdx_license: |
| 67 | return spdx_license | ||
| 68 | |||
| 69 | spdx_license = "LicenseRef-" + l | ||
| 70 | for spdx_lic in document.hasExtractedLicensingInfos: | ||
| 71 | if spdx_lic.licenseId == spdx_license: | ||
| 72 | return spdx_license | ||
| 73 | |||
| 74 | bb.warn("No SPDX License found for %s. Creating a place holder" % l) | ||
| 75 | |||
| 76 | spdx_lic = oe.spdx.SPDXExtractedLicensingInfo() | ||
| 77 | spdx_lic.name = l | ||
| 78 | spdx_lic.licenseId = spdx_license | ||
| 79 | # TODO: Extract the actual license text from the common license files | ||
| 80 | spdx_lic.extractedText = "This software is licensed under the %s license" % l | ||
| 81 | |||
| 82 | document.hasExtractedLicensingInfos.append(spdx_lic) | ||
| 83 | |||
| 84 | return spdx_license | ||
| 50 | 85 | ||
| 51 | return l | 86 | lic_split = lic.replace("(", " ( ").replace(")", " ) ").split() |
| 52 | 87 | ||
| 53 | return ' '.join(convert(l) for l in lic.split()) | 88 | return ' '.join(convert(l) for l in lic_split) |
| 54 | 89 | ||
| 55 | 90 | ||
| 56 | def process_sources(d): | 91 | def process_sources(d): |
| @@ -334,6 +369,7 @@ python do_create_spdx() { | |||
| 334 | doc.documentNamespace = get_doc_namespace(d, doc) | 369 | doc.documentNamespace = get_doc_namespace(d, doc) |
| 335 | doc.creationInfo.created = creation_time | 370 | doc.creationInfo.created = creation_time |
| 336 | doc.creationInfo.comment = "This document was created by analyzing recipe files during the build." | 371 | doc.creationInfo.comment = "This document was created by analyzing recipe files during the build." |
| 372 | doc.creationInfo.licenseListVersion = d.getVar("SPDX_LICENSE_DATA")["licenseListVersion"] | ||
| 337 | doc.creationInfo.creators.append("Tool: OpenEmbedded Core create-spdx.bbclass") | 373 | doc.creationInfo.creators.append("Tool: OpenEmbedded Core create-spdx.bbclass") |
| 338 | doc.creationInfo.creators.append("Organization: OpenEmbedded ()") | 374 | doc.creationInfo.creators.append("Organization: OpenEmbedded ()") |
| 339 | doc.creationInfo.creators.append("Person: N/A ()") | 375 | doc.creationInfo.creators.append("Person: N/A ()") |
| @@ -353,7 +389,7 @@ python do_create_spdx() { | |||
| 353 | 389 | ||
| 354 | license = d.getVar("LICENSE") | 390 | license = d.getVar("LICENSE") |
| 355 | if license: | 391 | if license: |
| 356 | recipe.licenseDeclared = convert_license_to_spdx(license, d) | 392 | recipe.licenseDeclared = convert_license_to_spdx(license, doc, d) |
| 357 | 393 | ||
| 358 | summary = d.getVar("SUMMARY") | 394 | summary = d.getVar("SUMMARY") |
| 359 | if summary: | 395 | if summary: |
| @@ -422,6 +458,7 @@ python do_create_spdx() { | |||
| 422 | package_doc.documentNamespace = get_doc_namespace(d, package_doc) | 458 | package_doc.documentNamespace = get_doc_namespace(d, package_doc) |
| 423 | package_doc.creationInfo.created = creation_time | 459 | package_doc.creationInfo.created = creation_time |
| 424 | package_doc.creationInfo.comment = "This document was created by analyzing packages created during the build." | 460 | package_doc.creationInfo.comment = "This document was created by analyzing packages created during the build." |
| 461 | package_doc.creationInfo.licenseListVersion = d.getVar("SPDX_LICENSE_DATA")["licenseListVersion"] | ||
| 425 | package_doc.creationInfo.creators.append("Tool: OpenEmbedded Core create-spdx.bbclass") | 462 | package_doc.creationInfo.creators.append("Tool: OpenEmbedded Core create-spdx.bbclass") |
| 426 | package_doc.creationInfo.creators.append("Organization: OpenEmbedded ()") | 463 | package_doc.creationInfo.creators.append("Organization: OpenEmbedded ()") |
| 427 | package_doc.creationInfo.creators.append("Person: N/A ()") | 464 | package_doc.creationInfo.creators.append("Person: N/A ()") |
| @@ -441,7 +478,7 @@ python do_create_spdx() { | |||
| 441 | spdx_package.SPDXID = oe.sbom.get_package_spdxid(pkg_name) | 478 | spdx_package.SPDXID = oe.sbom.get_package_spdxid(pkg_name) |
| 442 | spdx_package.name = pkg_name | 479 | spdx_package.name = pkg_name |
| 443 | spdx_package.versionInfo = d.getVar("PV") | 480 | spdx_package.versionInfo = d.getVar("PV") |
| 444 | spdx_package.licenseDeclared = convert_license_to_spdx(package_license, d) | 481 | spdx_package.licenseDeclared = convert_license_to_spdx(package_license, package_doc, d) |
| 445 | 482 | ||
| 446 | package_doc.packages.append(spdx_package) | 483 | package_doc.packages.append(spdx_package) |
| 447 | 484 | ||
| @@ -561,6 +598,7 @@ python do_create_runtime_spdx() { | |||
| 561 | runtime_doc.documentNamespace = get_doc_namespace(localdata, runtime_doc) | 598 | runtime_doc.documentNamespace = get_doc_namespace(localdata, runtime_doc) |
| 562 | runtime_doc.creationInfo.created = creation_time | 599 | runtime_doc.creationInfo.created = creation_time |
| 563 | runtime_doc.creationInfo.comment = "This document was created by analyzing package runtime dependencies." | 600 | runtime_doc.creationInfo.comment = "This document was created by analyzing package runtime dependencies." |
| 601 | runtime_doc.creationInfo.licenseListVersion = d.getVar("SPDX_LICENSE_DATA")["licenseListVersion"] | ||
| 564 | runtime_doc.creationInfo.creators.append("Tool: OpenEmbedded Core create-spdx.bbclass") | 602 | runtime_doc.creationInfo.creators.append("Tool: OpenEmbedded Core create-spdx.bbclass") |
| 565 | runtime_doc.creationInfo.creators.append("Organization: OpenEmbedded ()") | 603 | runtime_doc.creationInfo.creators.append("Organization: OpenEmbedded ()") |
| 566 | runtime_doc.creationInfo.creators.append("Person: N/A ()") | 604 | runtime_doc.creationInfo.creators.append("Person: N/A ()") |
| @@ -720,6 +758,7 @@ python image_combine_spdx() { | |||
| 720 | doc.documentNamespace = get_doc_namespace(d, doc) | 758 | doc.documentNamespace = get_doc_namespace(d, doc) |
| 721 | doc.creationInfo.created = creation_time | 759 | doc.creationInfo.created = creation_time |
| 722 | doc.creationInfo.comment = "This document was created by analyzing the source of the Yocto recipe during the build." | 760 | doc.creationInfo.comment = "This document was created by analyzing the source of the Yocto recipe during the build." |
| 761 | doc.creationInfo.licenseListVersion = d.getVar("SPDX_LICENSE_DATA")["licenseListVersion"] | ||
| 723 | doc.creationInfo.creators.append("Tool: OpenEmbedded Core create-spdx.bbclass") | 762 | doc.creationInfo.creators.append("Tool: OpenEmbedded Core create-spdx.bbclass") |
| 724 | doc.creationInfo.creators.append("Organization: OpenEmbedded ()") | 763 | doc.creationInfo.creators.append("Organization: OpenEmbedded ()") |
| 725 | doc.creationInfo.creators.append("Person: N/A ()") | 764 | 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): | |||
| 189 | checksum = _Object(SPDXChecksum) | 189 | checksum = _Object(SPDXChecksum) |
| 190 | 190 | ||
| 191 | 191 | ||
| 192 | class SPDXExtractedLicensingInfo(SPDXObject): | ||
| 193 | name = _String() | ||
| 194 | comment = _String() | ||
| 195 | licenseId = _String() | ||
| 196 | extractedText = _String() | ||
| 197 | |||
| 198 | |||
| 192 | class SPDXDocument(SPDXObject): | 199 | class SPDXDocument(SPDXObject): |
| 193 | spdxVersion = _String(default="SPDX-" + SPDX_VERSION) | 200 | spdxVersion = _String(default="SPDX-" + SPDX_VERSION) |
| 194 | dataLicense = _String(default="CC0-1.0") | 201 | dataLicense = _String(default="CC0-1.0") |
| @@ -200,6 +207,7 @@ class SPDXDocument(SPDXObject): | |||
| 200 | files = _ObjectList(SPDXFile) | 207 | files = _ObjectList(SPDXFile) |
| 201 | relationships = _ObjectList(SPDXRelationship) | 208 | relationships = _ObjectList(SPDXRelationship) |
| 202 | externalDocumentRefs = _ObjectList(SPDXExternalDocumentRef) | 209 | externalDocumentRefs = _ObjectList(SPDXExternalDocumentRef) |
| 210 | hasExtractedLicensingInfos = _ObjectList(SPDXExtractedLicensingInfo) | ||
| 203 | 211 | ||
| 204 | def __init__(self, **d): | 212 | def __init__(self, **d): |
| 205 | super().__init__(**d) | 213 | super().__init__(**d) |
