diff options
author | Richard Purdie <richard.purdie@linuxfoundation.org> | 2024-08-02 10:26:28 +0100 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2024-08-07 15:47:15 +0100 |
commit | a211f058cc3a5673d8e686b9e6e8fcf1e7cd972b (patch) | |
tree | a4f9de9e79332521a477df5fc56e8cbc15a1a6b7 | |
parent | 7355465f9ead0c4969adbfc167d7f29d0ca1fc11 (diff) | |
download | poky-a211f058cc3a5673d8e686b9e6e8fcf1e7cd972b.tar.gz |
sdpx: Avoid loading of SPDX_LICENSE_DATA into global config
Loading a load of json files into a memory structure and stashing in a bitbake
variable is relatively anti-social making bitbake -e output hard to read for
example as well as other potential performance issues.
Defer loading of that data until it is actually needed/used in a funciton
where it is now passed as a parameter.
(From OE-Core rev: 6f21cc9598178288784ff451ab3c40b174c0ef3e)
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r-- | meta/classes/create-spdx-2.2.bbclass | 25 | ||||
-rw-r--r-- | meta/classes/spdx-common.bbclass | 6 | ||||
-rw-r--r-- | meta/lib/oe/sbom30.py | 8 | ||||
-rw-r--r-- | meta/lib/oe/spdx30_tasks.py | 17 | ||||
-rw-r--r-- | meta/lib/oe/spdx_common.py | 5 |
5 files changed, 32 insertions, 29 deletions
diff --git a/meta/classes/create-spdx-2.2.bbclass b/meta/classes/create-spdx-2.2.bbclass index 509d3b58b6..795ba1a882 100644 --- a/meta/classes/create-spdx-2.2.bbclass +++ b/meta/classes/create-spdx-2.2.bbclass | |||
@@ -44,11 +44,10 @@ def get_json_indent(d): | |||
44 | return None | 44 | return None |
45 | 45 | ||
46 | 46 | ||
47 | def convert_license_to_spdx(lic, document, d, existing={}): | 47 | def convert_license_to_spdx(lic, license_data, document, d, existing={}): |
48 | from pathlib import Path | 48 | from pathlib import Path |
49 | import oe.spdx | 49 | import oe.spdx |
50 | 50 | ||
51 | license_data = d.getVar("SPDX_LICENSE_DATA") | ||
52 | extracted = {} | 51 | extracted = {} |
53 | 52 | ||
54 | def add_extracted_license(ident, name): | 53 | def add_extracted_license(ident, name): |
@@ -385,10 +384,10 @@ def add_download_packages(d, doc, recipe): | |||
385 | # but this should be sufficient for now | 384 | # but this should be sufficient for now |
386 | doc.add_relationship(package, "BUILD_DEPENDENCY_OF", recipe) | 385 | doc.add_relationship(package, "BUILD_DEPENDENCY_OF", recipe) |
387 | 386 | ||
388 | def get_license_list_version(d): | 387 | def get_license_list_version(license_data, d): |
389 | # Newer versions of the SPDX license list are SemVer ("MAJOR.MINOR.MICRO"), | 388 | # Newer versions of the SPDX license list are SemVer ("MAJOR.MINOR.MICRO"), |
390 | # but SPDX 2 only uses "MAJOR.MINOR". | 389 | # but SPDX 2 only uses "MAJOR.MINOR". |
391 | return ".".join(d.getVar("SPDX_LICENSE_DATA")["licenseListVersion"].split(".")[:2]) | 390 | return ".".join(license_data["licenseListVersion"].split(".")[:2]) |
392 | 391 | ||
393 | 392 | ||
394 | python do_create_spdx() { | 393 | python do_create_spdx() { |
@@ -401,6 +400,8 @@ python do_create_spdx() { | |||
401 | from contextlib import contextmanager | 400 | from contextlib import contextmanager |
402 | import oe.cve_check | 401 | import oe.cve_check |
403 | 402 | ||
403 | license_data = oe.spdx_common.load_spdx_license_data(d) | ||
404 | |||
404 | @contextmanager | 405 | @contextmanager |
405 | def optional_tarfile(name, guard, mode="w"): | 406 | def optional_tarfile(name, guard, mode="w"): |
406 | import tarfile | 407 | import tarfile |
@@ -432,7 +433,7 @@ python do_create_spdx() { | |||
432 | doc.documentNamespace = get_namespace(d, doc.name) | 433 | doc.documentNamespace = get_namespace(d, doc.name) |
433 | doc.creationInfo.created = creation_time | 434 | doc.creationInfo.created = creation_time |
434 | doc.creationInfo.comment = "This document was created by analyzing recipe files during the build." | 435 | doc.creationInfo.comment = "This document was created by analyzing recipe files during the build." |
435 | doc.creationInfo.licenseListVersion = get_license_list_version(d) | 436 | doc.creationInfo.licenseListVersion = get_license_list_version(license_data, d) |
436 | doc.creationInfo.creators.append("Tool: OpenEmbedded Core create-spdx.bbclass") | 437 | doc.creationInfo.creators.append("Tool: OpenEmbedded Core create-spdx.bbclass") |
437 | doc.creationInfo.creators.append("Organization: %s" % d.getVar("SPDX_ORG")) | 438 | doc.creationInfo.creators.append("Organization: %s" % d.getVar("SPDX_ORG")) |
438 | doc.creationInfo.creators.append("Person: N/A ()") | 439 | doc.creationInfo.creators.append("Person: N/A ()") |
@@ -451,7 +452,7 @@ python do_create_spdx() { | |||
451 | 452 | ||
452 | license = d.getVar("LICENSE") | 453 | license = d.getVar("LICENSE") |
453 | if license: | 454 | if license: |
454 | recipe.licenseDeclared = convert_license_to_spdx(license, doc, d) | 455 | recipe.licenseDeclared = convert_license_to_spdx(license, license_data, doc, d) |
455 | 456 | ||
456 | summary = d.getVar("SUMMARY") | 457 | summary = d.getVar("SUMMARY") |
457 | if summary: | 458 | if summary: |
@@ -536,7 +537,7 @@ python do_create_spdx() { | |||
536 | package_doc.documentNamespace = get_namespace(d, package_doc.name) | 537 | package_doc.documentNamespace = get_namespace(d, package_doc.name) |
537 | package_doc.creationInfo.created = creation_time | 538 | package_doc.creationInfo.created = creation_time |
538 | package_doc.creationInfo.comment = "This document was created by analyzing packages created during the build." | 539 | package_doc.creationInfo.comment = "This document was created by analyzing packages created during the build." |
539 | package_doc.creationInfo.licenseListVersion = get_license_list_version(d) | 540 | package_doc.creationInfo.licenseListVersion = get_license_list_version(license_data, d) |
540 | package_doc.creationInfo.creators.append("Tool: OpenEmbedded Core create-spdx.bbclass") | 541 | package_doc.creationInfo.creators.append("Tool: OpenEmbedded Core create-spdx.bbclass") |
541 | package_doc.creationInfo.creators.append("Organization: %s" % d.getVar("SPDX_ORG")) | 542 | package_doc.creationInfo.creators.append("Organization: %s" % d.getVar("SPDX_ORG")) |
542 | package_doc.creationInfo.creators.append("Person: N/A ()") | 543 | package_doc.creationInfo.creators.append("Person: N/A ()") |
@@ -549,7 +550,7 @@ python do_create_spdx() { | |||
549 | spdx_package.SPDXID = oe.sbom.get_package_spdxid(pkg_name) | 550 | spdx_package.SPDXID = oe.sbom.get_package_spdxid(pkg_name) |
550 | spdx_package.name = pkg_name | 551 | spdx_package.name = pkg_name |
551 | spdx_package.versionInfo = d.getVar("PV") | 552 | spdx_package.versionInfo = d.getVar("PV") |
552 | spdx_package.licenseDeclared = convert_license_to_spdx(package_license, package_doc, d, found_licenses) | 553 | spdx_package.licenseDeclared = convert_license_to_spdx(package_license, license_data, package_doc, d, found_licenses) |
553 | spdx_package.supplier = d.getVar("SPDX_SUPPLIER") | 554 | spdx_package.supplier = d.getVar("SPDX_SUPPLIER") |
554 | 555 | ||
555 | package_doc.packages.append(spdx_package) | 556 | package_doc.packages.append(spdx_package) |
@@ -608,6 +609,8 @@ python do_create_runtime_spdx() { | |||
608 | 609 | ||
609 | creation_time = datetime.now(tz=timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ") | 610 | creation_time = datetime.now(tz=timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ") |
610 | 611 | ||
612 | license_data = oe.spdx_common.load_spdx_license_data(d) | ||
613 | |||
611 | providers = oe.spdx_common.collect_package_providers(d) | 614 | providers = oe.spdx_common.collect_package_providers(d) |
612 | pkg_arch = d.getVar("SSTATE_PKGARCH") | 615 | pkg_arch = d.getVar("SSTATE_PKGARCH") |
613 | package_archs = d.getVar("SPDX_MULTILIB_SSTATE_ARCHS").split() | 616 | package_archs = d.getVar("SPDX_MULTILIB_SSTATE_ARCHS").split() |
@@ -644,7 +647,7 @@ python do_create_runtime_spdx() { | |||
644 | runtime_doc.documentNamespace = get_namespace(localdata, runtime_doc.name) | 647 | runtime_doc.documentNamespace = get_namespace(localdata, runtime_doc.name) |
645 | runtime_doc.creationInfo.created = creation_time | 648 | runtime_doc.creationInfo.created = creation_time |
646 | runtime_doc.creationInfo.comment = "This document was created by analyzing package runtime dependencies." | 649 | runtime_doc.creationInfo.comment = "This document was created by analyzing package runtime dependencies." |
647 | runtime_doc.creationInfo.licenseListVersion = get_license_list_version(d) | 650 | runtime_doc.creationInfo.licenseListVersion = get_license_list_version(license_data, d) |
648 | runtime_doc.creationInfo.creators.append("Tool: OpenEmbedded Core create-spdx.bbclass") | 651 | runtime_doc.creationInfo.creators.append("Tool: OpenEmbedded Core create-spdx.bbclass") |
649 | runtime_doc.creationInfo.creators.append("Organization: %s" % d.getVar("SPDX_ORG")) | 652 | runtime_doc.creationInfo.creators.append("Organization: %s" % d.getVar("SPDX_ORG")) |
650 | runtime_doc.creationInfo.creators.append("Person: N/A ()") | 653 | runtime_doc.creationInfo.creators.append("Person: N/A ()") |
@@ -797,6 +800,8 @@ def combine_spdx(d, rootfs_name, rootfs_deploydir, rootfs_spdxid, packages, spdx | |||
797 | import tarfile | 800 | import tarfile |
798 | import bb.compress.zstd | 801 | import bb.compress.zstd |
799 | 802 | ||
803 | license_data = oe.spdx_common.load_spdx_license_data(d) | ||
804 | |||
800 | providers = oe.spdx_common.collect_package_providers(d) | 805 | providers = oe.spdx_common.collect_package_providers(d) |
801 | package_archs = d.getVar("SPDX_MULTILIB_SSTATE_ARCHS").split() | 806 | package_archs = d.getVar("SPDX_MULTILIB_SSTATE_ARCHS").split() |
802 | package_archs.reverse() | 807 | package_archs.reverse() |
@@ -810,7 +815,7 @@ def combine_spdx(d, rootfs_name, rootfs_deploydir, rootfs_spdxid, packages, spdx | |||
810 | doc.documentNamespace = get_namespace(d, doc.name) | 815 | doc.documentNamespace = get_namespace(d, doc.name) |
811 | doc.creationInfo.created = creation_time | 816 | doc.creationInfo.created = creation_time |
812 | doc.creationInfo.comment = "This document was created by analyzing the source of the Yocto recipe during the build." | 817 | doc.creationInfo.comment = "This document was created by analyzing the source of the Yocto recipe during the build." |
813 | doc.creationInfo.licenseListVersion = get_license_list_version(d) | 818 | doc.creationInfo.licenseListVersion = get_license_list_version(license_data, d) |
814 | doc.creationInfo.creators.append("Tool: OpenEmbedded Core create-spdx.bbclass") | 819 | doc.creationInfo.creators.append("Tool: OpenEmbedded Core create-spdx.bbclass") |
815 | doc.creationInfo.creators.append("Organization: %s" % d.getVar("SPDX_ORG")) | 820 | doc.creationInfo.creators.append("Organization: %s" % d.getVar("SPDX_ORG")) |
816 | doc.creationInfo.creators.append("Person: N/A ()") | 821 | doc.creationInfo.creators.append("Person: N/A ()") |
diff --git a/meta/classes/spdx-common.bbclass b/meta/classes/spdx-common.bbclass index e1528b6d0b..cd9cc0db98 100644 --- a/meta/classes/spdx-common.bbclass +++ b/meta/classes/spdx-common.bbclass | |||
@@ -39,12 +39,6 @@ SPDX_CUSTOM_ANNOTATION_VARS ??= "" | |||
39 | 39 | ||
40 | SPDX_MULTILIB_SSTATE_ARCHS ??= "${SSTATE_ARCHS}" | 40 | SPDX_MULTILIB_SSTATE_ARCHS ??= "${SSTATE_ARCHS}" |
41 | 41 | ||
42 | python() { | ||
43 | import oe.spdx_common | ||
44 | oe.spdx_common.load_spdx_license_data(d) | ||
45 | } | ||
46 | |||
47 | |||
48 | python do_collect_spdx_deps() { | 42 | python do_collect_spdx_deps() { |
49 | # This task calculates the build time dependencies of the recipe, and is | 43 | # This task calculates the build time dependencies of the recipe, and is |
50 | # required because while a task can deptask on itself, those dependencies | 44 | # required because while a task can deptask on itself, those dependencies |
diff --git a/meta/lib/oe/sbom30.py b/meta/lib/oe/sbom30.py index 27ed74f810..2cea56ac3e 100644 --- a/meta/lib/oe/sbom30.py +++ b/meta/lib/oe/sbom30.py | |||
@@ -558,8 +558,8 @@ class ObjectSet(oe.spdx30.SHACLObjectSet): | |||
558 | scope=scope, | 558 | scope=scope, |
559 | ) | 559 | ) |
560 | 560 | ||
561 | def new_license_expression(self, license_expression, license_text_map={}): | 561 | def new_license_expression(self, license_expression, license_data, license_text_map={}): |
562 | license_list_version = self.d.getVar("SPDX_LICENSE_DATA")["licenseListVersion"] | 562 | license_list_version = license_data["licenseListVersion"] |
563 | # SPDX 3 requires that the license list version be a semver | 563 | # SPDX 3 requires that the license list version be a semver |
564 | # MAJOR.MINOR.MICRO, but the actual license version might be | 564 | # MAJOR.MINOR.MICRO, but the actual license version might be |
565 | # MAJOR.MINOR on some older versions. As such, manually append a .0 | 565 | # MAJOR.MINOR on some older versions. As such, manually append a .0 |
@@ -607,14 +607,14 @@ class ObjectSet(oe.spdx30.SHACLObjectSet): | |||
607 | 607 | ||
608 | return lic | 608 | return lic |
609 | 609 | ||
610 | def scan_declared_licenses(self, spdx_file, filepath): | 610 | def scan_declared_licenses(self, spdx_file, filepath, license_data): |
611 | for e in spdx_file.extension: | 611 | for e in spdx_file.extension: |
612 | if isinstance(e, OELicenseScannedExtension): | 612 | if isinstance(e, OELicenseScannedExtension): |
613 | return | 613 | return |
614 | 614 | ||
615 | file_licenses = set() | 615 | file_licenses = set() |
616 | for extracted_lic in oe.spdx_common.extract_licenses(filepath): | 616 | for extracted_lic in oe.spdx_common.extract_licenses(filepath): |
617 | file_licenses.add(self.new_license_expression(extracted_lic)) | 617 | file_licenses.add(self.new_license_expression(extracted_lic, license_data)) |
618 | 618 | ||
619 | self.new_relationship( | 619 | self.new_relationship( |
620 | [spdx_file], | 620 | [spdx_file], |
diff --git a/meta/lib/oe/spdx30_tasks.py b/meta/lib/oe/spdx30_tasks.py index 9d5bbadc0f..03dc47db02 100644 --- a/meta/lib/oe/spdx30_tasks.py +++ b/meta/lib/oe/spdx30_tasks.py | |||
@@ -28,8 +28,7 @@ def set_timestamp_now(d, o, prop): | |||
28 | delattr(o, prop) | 28 | delattr(o, prop) |
29 | 29 | ||
30 | 30 | ||
31 | def add_license_expression(d, objset, license_expression): | 31 | def add_license_expression(d, objset, license_expression, license_data): |
32 | license_data = d.getVar("SPDX_LICENSE_DATA") | ||
33 | simple_license_text = {} | 32 | simple_license_text = {} |
34 | license_text_map = {} | 33 | license_text_map = {} |
35 | license_ref_idx = 0 | 34 | license_ref_idx = 0 |
@@ -120,7 +119,7 @@ def add_license_expression(d, objset, license_expression): | |||
120 | ) | 119 | ) |
121 | spdx_license_expression = " ".join(convert(l) for l in lic_split) | 120 | spdx_license_expression = " ".join(convert(l) for l in lic_split) |
122 | 121 | ||
123 | return objset.new_license_expression(spdx_license_expression, license_text_map) | 122 | return objset.new_license_expression(spdx_license_expression, license_data, license_text_map) |
124 | 123 | ||
125 | 124 | ||
126 | def add_package_files( | 125 | def add_package_files( |
@@ -129,6 +128,7 @@ def add_package_files( | |||
129 | topdir, | 128 | topdir, |
130 | get_spdxid, | 129 | get_spdxid, |
131 | get_purposes, | 130 | get_purposes, |
131 | license_data, | ||
132 | *, | 132 | *, |
133 | archive=None, | 133 | archive=None, |
134 | ignore_dirs=[], | 134 | ignore_dirs=[], |
@@ -165,7 +165,7 @@ def add_package_files( | |||
165 | spdx_files.add(spdx_file) | 165 | spdx_files.add(spdx_file) |
166 | 166 | ||
167 | if oe.spdx30.software_SoftwarePurpose.source in file_purposes: | 167 | if oe.spdx30.software_SoftwarePurpose.source in file_purposes: |
168 | objset.scan_declared_licenses(spdx_file, filepath) | 168 | objset.scan_declared_licenses(spdx_file, filepath, license_data) |
169 | 169 | ||
170 | if archive is not None: | 170 | if archive is not None: |
171 | with filepath.open("rb") as f: | 171 | with filepath.open("rb") as f: |
@@ -452,6 +452,8 @@ def create_spdx(d): | |||
452 | if val: | 452 | if val: |
453 | setattr(obj, name, val) | 453 | setattr(obj, name, val) |
454 | 454 | ||
455 | license_data = oe.spdx_common.load_spdx_license_data(d) | ||
456 | |||
455 | deploydir = Path(d.getVar("SPDXDEPLOY")) | 457 | deploydir = Path(d.getVar("SPDXDEPLOY")) |
456 | deploy_dir_spdx = Path(d.getVar("DEPLOY_DIR_SPDX")) | 458 | deploy_dir_spdx = Path(d.getVar("DEPLOY_DIR_SPDX")) |
457 | spdx_workdir = Path(d.getVar("SPDXWORK")) | 459 | spdx_workdir = Path(d.getVar("SPDXWORK")) |
@@ -508,7 +510,7 @@ def create_spdx(d): | |||
508 | source_files = add_download_files(d, build_objset) | 510 | source_files = add_download_files(d, build_objset) |
509 | build_inputs |= source_files | 511 | build_inputs |= source_files |
510 | 512 | ||
511 | recipe_spdx_license = add_license_expression(d, build_objset, d.getVar("LICENSE")) | 513 | recipe_spdx_license = add_license_expression(d, build_objset, d.getVar("LICENSE"), license_data) |
512 | build_objset.new_relationship( | 514 | build_objset.new_relationship( |
513 | source_files, | 515 | source_files, |
514 | oe.spdx30.RelationshipType.hasConcludedLicense, | 516 | oe.spdx30.RelationshipType.hasConcludedLicense, |
@@ -527,6 +529,7 @@ def create_spdx(d): | |||
527 | "sourcefile", str(file_counter) | 529 | "sourcefile", str(file_counter) |
528 | ), | 530 | ), |
529 | lambda filepath: [oe.spdx30.software_SoftwarePurpose.source], | 531 | lambda filepath: [oe.spdx30.software_SoftwarePurpose.source], |
532 | license_data, | ||
530 | ignore_dirs=[".git"], | 533 | ignore_dirs=[".git"], |
531 | ignore_top_level_dirs=["temp"], | 534 | ignore_top_level_dirs=["temp"], |
532 | archive=None, | 535 | archive=None, |
@@ -636,7 +639,7 @@ def create_spdx(d): | |||
636 | package_license = d.getVar("LICENSE:%s" % package) | 639 | package_license = d.getVar("LICENSE:%s" % package) |
637 | if package_license and package_license != d.getVar("LICENSE"): | 640 | if package_license and package_license != d.getVar("LICENSE"): |
638 | package_spdx_license = add_license_expression( | 641 | package_spdx_license = add_license_expression( |
639 | d, build_objset, package_license | 642 | d, build_objset, package_license, license_data |
640 | ) | 643 | ) |
641 | else: | 644 | else: |
642 | package_spdx_license = recipe_spdx_license | 645 | package_spdx_license = recipe_spdx_license |
@@ -708,6 +711,7 @@ def create_spdx(d): | |||
708 | ), | 711 | ), |
709 | # TODO: Can we know the purpose here? | 712 | # TODO: Can we know the purpose here? |
710 | lambda filepath: [], | 713 | lambda filepath: [], |
714 | license_data, | ||
711 | ignore_top_level_dirs=["CONTROL", "DEBIAN"], | 715 | ignore_top_level_dirs=["CONTROL", "DEBIAN"], |
712 | archive=None, | 716 | archive=None, |
713 | ) | 717 | ) |
@@ -739,6 +743,7 @@ def create_spdx(d): | |||
739 | d.expand("${COMPONENTS_DIR}/${PACKAGE_ARCH}/${PN}"), | 743 | d.expand("${COMPONENTS_DIR}/${PACKAGE_ARCH}/${PN}"), |
740 | lambda file_counter: build_objset.new_spdxid("sysroot", str(file_counter)), | 744 | lambda file_counter: build_objset.new_spdxid("sysroot", str(file_counter)), |
741 | lambda filepath: [], | 745 | lambda filepath: [], |
746 | license_data, | ||
742 | archive=None, | 747 | archive=None, |
743 | ) | 748 | ) |
744 | 749 | ||
diff --git a/meta/lib/oe/spdx_common.py b/meta/lib/oe/spdx_common.py index f23100fe03..dfe90f96cf 100644 --- a/meta/lib/oe/spdx_common.py +++ b/meta/lib/oe/spdx_common.py | |||
@@ -42,14 +42,13 @@ def is_work_shared_spdx(d): | |||
42 | 42 | ||
43 | 43 | ||
44 | def load_spdx_license_data(d): | 44 | def load_spdx_license_data(d): |
45 | if d.getVar("SPDX_LICENSE_DATA"): | ||
46 | return | ||
47 | 45 | ||
48 | with open(d.getVar("SPDX_LICENSES"), "r") as f: | 46 | with open(d.getVar("SPDX_LICENSES"), "r") as f: |
49 | data = json.load(f) | 47 | data = json.load(f) |
50 | # Transform the license array to a dictionary | 48 | # Transform the license array to a dictionary |
51 | data["licenses"] = {l["licenseId"]: l for l in data["licenses"]} | 49 | data["licenses"] = {l["licenseId"]: l for l in data["licenses"]} |
52 | d.setVar("SPDX_LICENSE_DATA", data) | 50 | |
51 | return data | ||
53 | 52 | ||
54 | 53 | ||
55 | def process_sources(d): | 54 | def process_sources(d): |