diff options
-rw-r--r-- | meta/classes/create-spdx-2.2.bbclass | 41 | ||||
-rw-r--r-- | meta/lib/oe/sbom.py | 34 |
2 files changed, 57 insertions, 18 deletions
diff --git a/meta/classes/create-spdx-2.2.bbclass b/meta/classes/create-spdx-2.2.bbclass index 9b28d124c7..a2b96da61a 100644 --- a/meta/classes/create-spdx-2.2.bbclass +++ b/meta/classes/create-spdx-2.2.bbclass | |||
@@ -349,6 +349,8 @@ def collect_dep_recipes(d, doc, spdx_recipe): | |||
349 | 349 | ||
350 | deploy_dir_spdx = Path(d.getVar("DEPLOY_DIR_SPDX")) | 350 | deploy_dir_spdx = Path(d.getVar("DEPLOY_DIR_SPDX")) |
351 | spdx_deps_file = Path(d.getVar("SPDXDEPS")) | 351 | spdx_deps_file = Path(d.getVar("SPDXDEPS")) |
352 | package_archs = d.getVar("SSTATE_ARCHS").split() | ||
353 | package_archs.reverse() | ||
352 | 354 | ||
353 | dep_recipes = [] | 355 | dep_recipes = [] |
354 | 356 | ||
@@ -356,7 +358,9 @@ def collect_dep_recipes(d, doc, spdx_recipe): | |||
356 | deps = json.load(f) | 358 | deps = json.load(f) |
357 | 359 | ||
358 | for dep_pn, dep_hashfn in deps: | 360 | for dep_pn, dep_hashfn in deps: |
359 | dep_recipe_path = oe.sbom.doc_path_by_hashfn(deploy_dir_spdx, "recipe-" + dep_pn, dep_hashfn) | 361 | dep_recipe_path = oe.sbom.doc_find_by_hashfn(deploy_dir_spdx, package_archs, "recipe-" + dep_pn, dep_hashfn) |
362 | if not dep_recipe_path: | ||
363 | bb.fatal("Cannot find any SPDX file for recipe %s, %s" % (dep_pn, dep_hashfn)) | ||
360 | 364 | ||
361 | spdx_dep_doc, spdx_dep_sha1 = oe.sbom.read_doc(dep_recipe_path) | 365 | spdx_dep_doc, spdx_dep_sha1 = oe.sbom.read_doc(dep_recipe_path) |
362 | 366 | ||
@@ -385,6 +389,7 @@ def collect_dep_recipes(d, doc, spdx_recipe): | |||
385 | 389 | ||
386 | return dep_recipes | 390 | return dep_recipes |
387 | 391 | ||
392 | collect_dep_recipes[vardepsexclude] = "SSTATE_ARCHS" | ||
388 | 393 | ||
389 | def collect_dep_sources(d, dep_recipes): | 394 | def collect_dep_sources(d, dep_recipes): |
390 | import oe.sbom | 395 | import oe.sbom |
@@ -533,6 +538,7 @@ python do_create_spdx() { | |||
533 | include_sources = d.getVar("SPDX_INCLUDE_SOURCES") == "1" | 538 | include_sources = d.getVar("SPDX_INCLUDE_SOURCES") == "1" |
534 | archive_sources = d.getVar("SPDX_ARCHIVE_SOURCES") == "1" | 539 | archive_sources = d.getVar("SPDX_ARCHIVE_SOURCES") == "1" |
535 | archive_packaged = d.getVar("SPDX_ARCHIVE_PACKAGED") == "1" | 540 | archive_packaged = d.getVar("SPDX_ARCHIVE_PACKAGED") == "1" |
541 | pkg_arch = d.getVar("SSTATE_PKGARCH") | ||
536 | 542 | ||
537 | creation_time = datetime.now(tz=timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ") | 543 | creation_time = datetime.now(tz=timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ") |
538 | 544 | ||
@@ -620,7 +626,7 @@ python do_create_spdx() { | |||
620 | 626 | ||
621 | dep_recipes = collect_dep_recipes(d, doc, recipe) | 627 | dep_recipes = collect_dep_recipes(d, doc, recipe) |
622 | 628 | ||
623 | doc_sha1 = oe.sbom.write_doc(d, doc, d.getVar("SSTATE_PKGARCH"), "recipes", indent=get_json_indent(d)) | 629 | doc_sha1 = oe.sbom.write_doc(d, doc, pkg_arch, "recipes", indent=get_json_indent(d)) |
624 | dep_recipes.append(oe.sbom.DepRecipe(doc, doc_sha1, recipe)) | 630 | dep_recipes.append(oe.sbom.DepRecipe(doc, doc_sha1, recipe)) |
625 | 631 | ||
626 | recipe_ref = oe.spdx.SPDXExternalDocumentRef() | 632 | recipe_ref = oe.spdx.SPDXExternalDocumentRef() |
@@ -685,7 +691,7 @@ python do_create_spdx() { | |||
685 | 691 | ||
686 | add_package_sources_from_debug(d, package_doc, spdx_package, package, package_files, sources) | 692 | add_package_sources_from_debug(d, package_doc, spdx_package, package, package_files, sources) |
687 | 693 | ||
688 | oe.sbom.write_doc(d, package_doc, d.getVar("SSTATE_PKGARCH"), "packages", indent=get_json_indent(d)) | 694 | oe.sbom.write_doc(d, package_doc, pkg_arch, "packages", indent=get_json_indent(d)) |
689 | } | 695 | } |
690 | do_create_spdx[vardepsexclude] += "BB_NUMBER_THREADS" | 696 | do_create_spdx[vardepsexclude] += "BB_NUMBER_THREADS" |
691 | # NOTE: depending on do_unpack is a hack that is necessary to get it's dependencies for archive the source | 697 | # NOTE: depending on do_unpack is a hack that is necessary to get it's dependencies for archive the source |
@@ -756,6 +762,9 @@ python do_create_runtime_spdx() { | |||
756 | creation_time = datetime.now(tz=timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ") | 762 | creation_time = datetime.now(tz=timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ") |
757 | 763 | ||
758 | providers = collect_package_providers(d) | 764 | providers = collect_package_providers(d) |
765 | pkg_arch = d.getVar("SSTATE_PKGARCH") | ||
766 | package_archs = d.getVar("SSTATE_ARCHS").split() | ||
767 | package_archs.reverse() | ||
759 | 768 | ||
760 | if not is_native: | 769 | if not is_native: |
761 | bb.build.exec_func("read_subpackage_metadata", d) | 770 | bb.build.exec_func("read_subpackage_metadata", d) |
@@ -772,7 +781,7 @@ python do_create_runtime_spdx() { | |||
772 | if not oe.packagedata.packaged(package, localdata): | 781 | if not oe.packagedata.packaged(package, localdata): |
773 | continue | 782 | continue |
774 | 783 | ||
775 | pkg_spdx_path = oe.sbom.doc_path(deploy_dir_spdx, pkg_name, d.getVar("SSTATE_PKGARCH"), "packages") | 784 | pkg_spdx_path = oe.sbom.doc_path(deploy_dir_spdx, pkg_name, pkg_arch, "packages") |
776 | 785 | ||
777 | package_doc, package_doc_sha1 = oe.sbom.read_doc(pkg_spdx_path) | 786 | package_doc, package_doc_sha1 = oe.sbom.read_doc(pkg_spdx_path) |
778 | 787 | ||
@@ -827,7 +836,9 @@ python do_create_runtime_spdx() { | |||
827 | if dep in dep_package_cache: | 836 | if dep in dep_package_cache: |
828 | (dep_spdx_package, dep_package_ref) = dep_package_cache[dep] | 837 | (dep_spdx_package, dep_package_ref) = dep_package_cache[dep] |
829 | else: | 838 | else: |
830 | dep_path = oe.sbom.doc_path_by_hashfn(deploy_dir_spdx, dep_pkg, dep_hashfn) | 839 | dep_path = oe.sbom.doc_find_by_hashfn(deploy_dir_spdx, package_archs, dep_pkg, dep_hashfn) |
840 | if not dep_path: | ||
841 | bb.fatal("No SPDX file found for package %s, %s" % (dep_pkg, dep_hashfn)) | ||
831 | 842 | ||
832 | spdx_dep_doc, spdx_dep_sha1 = oe.sbom.read_doc(dep_path) | 843 | spdx_dep_doc, spdx_dep_sha1 = oe.sbom.read_doc(dep_path) |
833 | 844 | ||
@@ -855,10 +866,10 @@ python do_create_runtime_spdx() { | |||
855 | ) | 866 | ) |
856 | seen_deps.add(dep) | 867 | seen_deps.add(dep) |
857 | 868 | ||
858 | oe.sbom.write_doc(d, runtime_doc, d.getVar("SSTATE_PKGARCH"), "runtime", spdx_deploy, indent=get_json_indent(d)) | 869 | oe.sbom.write_doc(d, runtime_doc, pkg_arch, "runtime", spdx_deploy, indent=get_json_indent(d)) |
859 | } | 870 | } |
860 | 871 | ||
861 | do_create_runtime_spdx[vardepsexclude] += "OVERRIDES" | 872 | do_create_runtime_spdx[vardepsexclude] += "OVERRIDES SSTATE_ARCHS" |
862 | 873 | ||
863 | addtask do_create_runtime_spdx after do_create_spdx before do_build do_rm_work | 874 | addtask do_create_runtime_spdx after do_create_spdx before do_build do_rm_work |
864 | SSTATETASKS += "do_create_runtime_spdx" | 875 | SSTATETASKS += "do_create_runtime_spdx" |
@@ -993,6 +1004,8 @@ def combine_spdx(d, rootfs_name, rootfs_deploydir, rootfs_spdxid, packages, spdx | |||
993 | import bb.compress.zstd | 1004 | import bb.compress.zstd |
994 | 1005 | ||
995 | providers = collect_package_providers(d) | 1006 | providers = collect_package_providers(d) |
1007 | package_archs = d.getVar("SSTATE_ARCHS").split() | ||
1008 | package_archs.reverse() | ||
996 | 1009 | ||
997 | creation_time = datetime.now(tz=timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ") | 1010 | creation_time = datetime.now(tz=timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ") |
998 | deploy_dir_spdx = Path(d.getVar("DEPLOY_DIR_SPDX")) | 1011 | deploy_dir_spdx = Path(d.getVar("DEPLOY_DIR_SPDX")) |
@@ -1022,7 +1035,10 @@ def combine_spdx(d, rootfs_name, rootfs_deploydir, rootfs_spdxid, packages, spdx | |||
1022 | 1035 | ||
1023 | pkg_name, pkg_hashfn = providers[name] | 1036 | pkg_name, pkg_hashfn = providers[name] |
1024 | 1037 | ||
1025 | pkg_spdx_path = oe.sbom.doc_path_by_hashfn(deploy_dir_spdx, pkg_name, pkg_hashfn) | 1038 | pkg_spdx_path = oe.sbom.doc_find_by_hashfn(deploy_dir_spdx, package_archs, pkg_name, pkg_hashfn) |
1039 | if not pkg_spdx_path: | ||
1040 | bb.fatal("No SPDX file found for package %s, %s" % (pkg_name, pkg_hashfn)) | ||
1041 | |||
1026 | pkg_doc, pkg_doc_sha1 = oe.sbom.read_doc(pkg_spdx_path) | 1042 | pkg_doc, pkg_doc_sha1 = oe.sbom.read_doc(pkg_spdx_path) |
1027 | 1043 | ||
1028 | for p in pkg_doc.packages: | 1044 | for p in pkg_doc.packages: |
@@ -1039,7 +1055,10 @@ def combine_spdx(d, rootfs_name, rootfs_deploydir, rootfs_spdxid, packages, spdx | |||
1039 | else: | 1055 | else: |
1040 | bb.fatal("Unable to find package with name '%s' in SPDX file %s" % (name, pkg_spdx_path)) | 1056 | bb.fatal("Unable to find package with name '%s' in SPDX file %s" % (name, pkg_spdx_path)) |
1041 | 1057 | ||
1042 | runtime_spdx_path = oe.sbom.doc_path_by_hashfn(deploy_dir_spdx, "runtime-" + name, pkg_hashfn) | 1058 | runtime_spdx_path = oe.sbom.doc_find_by_hashfn(deploy_dir_spdx, package_archs, "runtime-" + name, pkg_hashfn) |
1059 | if not runtime_spdx_path: | ||
1060 | bb.fatal("No runtime SPDX document found for %s, %s" % (name, pkg_hashfn)) | ||
1061 | |||
1043 | runtime_doc, runtime_doc_sha1 = oe.sbom.read_doc(runtime_spdx_path) | 1062 | runtime_doc, runtime_doc_sha1 = oe.sbom.read_doc(runtime_spdx_path) |
1044 | 1063 | ||
1045 | runtime_ref = oe.spdx.SPDXExternalDocumentRef() | 1064 | runtime_ref = oe.spdx.SPDXExternalDocumentRef() |
@@ -1111,7 +1130,7 @@ def combine_spdx(d, rootfs_name, rootfs_deploydir, rootfs_spdxid, packages, spdx | |||
1111 | }) | 1130 | }) |
1112 | 1131 | ||
1113 | for ref in doc.externalDocumentRefs: | 1132 | for ref in doc.externalDocumentRefs: |
1114 | ref_path = oe.sbom.doc_path_by_namespace(deploy_dir_spdx, ref.spdxDocument) | 1133 | ref_path = oe.sbom.doc_find_by_namespace(deploy_dir_spdx, package_archs, ref.spdxDocument) |
1115 | collect_spdx_document(ref_path) | 1134 | collect_spdx_document(ref_path) |
1116 | 1135 | ||
1117 | collect_spdx_document(image_spdx_path) | 1136 | collect_spdx_document(image_spdx_path) |
@@ -1134,4 +1153,4 @@ def combine_spdx(d, rootfs_name, rootfs_deploydir, rootfs_spdxid, packages, spdx | |||
1134 | 1153 | ||
1135 | tar.addfile(info, fileobj=index_str) | 1154 | tar.addfile(info, fileobj=index_str) |
1136 | 1155 | ||
1137 | combine_spdx[vardepsexclude] += "BB_NUMBER_THREADS" | 1156 | combine_spdx[vardepsexclude] += "BB_NUMBER_THREADS SSTATE_ARCHS" |
diff --git a/meta/lib/oe/sbom.py b/meta/lib/oe/sbom.py index 1130fa668b..fd4b6895d8 100644 --- a/meta/lib/oe/sbom.py +++ b/meta/lib/oe/sbom.py | |||
@@ -38,16 +38,34 @@ def get_sdk_spdxid(sdk): | |||
38 | return "SPDXRef-SDK-%s" % sdk | 38 | return "SPDXRef-SDK-%s" % sdk |
39 | 39 | ||
40 | 40 | ||
41 | def doc_path_by_namespace(spdx_deploy, doc_namespace): | 41 | def _doc_path_by_namespace(spdx_deploy, arch, doc_namespace): |
42 | return spdx_deploy / "by-namespace" / doc_namespace.replace("/", "_") | 42 | return spdx_deploy / "by-namespace" / arch / doc_namespace.replace("/", "_") |
43 | 43 | ||
44 | 44 | ||
45 | def doc_path_by_hashfn(spdx_deploy, doc_name, hashfn): | 45 | def doc_find_by_namespace(spdx_deploy, search_arches, doc_namespace): |
46 | return spdx_deploy / "by-hash" / hashfn.split()[1] / (doc_name + ".spdx.json") | 46 | for pkgarch in search_arches: |
47 | p = _doc_path_by_namespace(spdx_deploy, pkgarch, doc_namespace) | ||
48 | if os.path.exists(p): | ||
49 | return p | ||
50 | return None | ||
51 | |||
52 | |||
53 | def _doc_path_by_hashfn(spdx_deploy, arch, doc_name, hashfn): | ||
54 | return ( | ||
55 | spdx_deploy / "by-hash" / arch / hashfn.split()[1] / (doc_name + ".spdx.json") | ||
56 | ) | ||
57 | |||
58 | |||
59 | def doc_find_by_hashfn(spdx_deploy, search_arches, doc_name, hashfn): | ||
60 | for pkgarch in search_arches: | ||
61 | p = _doc_path_by_hashfn(spdx_deploy, pkgarch, doc_name, hashfn) | ||
62 | if os.path.exists(p): | ||
63 | return p | ||
64 | return None | ||
47 | 65 | ||
48 | 66 | ||
49 | def doc_path(spdx_deploy, doc_name, arch, subdir): | 67 | def doc_path(spdx_deploy, doc_name, arch, subdir): |
50 | return spdx_deploy / arch/ subdir / (doc_name + ".spdx.json") | 68 | return spdx_deploy / arch / subdir / (doc_name + ".spdx.json") |
51 | 69 | ||
52 | 70 | ||
53 | def write_doc(d, spdx_doc, arch, subdir, spdx_deploy=None, indent=None): | 71 | def write_doc(d, spdx_doc, arch, subdir, spdx_deploy=None, indent=None): |
@@ -61,11 +79,13 @@ def write_doc(d, spdx_doc, arch, subdir, spdx_deploy=None, indent=None): | |||
61 | with dest.open("wb") as f: | 79 | with dest.open("wb") as f: |
62 | doc_sha1 = spdx_doc.to_json(f, sort_keys=True, indent=indent) | 80 | doc_sha1 = spdx_doc.to_json(f, sort_keys=True, indent=indent) |
63 | 81 | ||
64 | l = doc_path_by_namespace(spdx_deploy, spdx_doc.documentNamespace) | 82 | l = _doc_path_by_namespace(spdx_deploy, arch, spdx_doc.documentNamespace) |
65 | l.parent.mkdir(exist_ok=True, parents=True) | 83 | l.parent.mkdir(exist_ok=True, parents=True) |
66 | l.symlink_to(os.path.relpath(dest, l.parent)) | 84 | l.symlink_to(os.path.relpath(dest, l.parent)) |
67 | 85 | ||
68 | l = doc_path_by_hashfn(spdx_deploy, spdx_doc.name, d.getVar("BB_HASHFILENAME")) | 86 | l = _doc_path_by_hashfn( |
87 | spdx_deploy, arch, spdx_doc.name, d.getVar("BB_HASHFILENAME") | ||
88 | ) | ||
69 | l.parent.mkdir(exist_ok=True, parents=True) | 89 | l.parent.mkdir(exist_ok=True, parents=True) |
70 | l.symlink_to(os.path.relpath(dest, l.parent)) | 90 | l.symlink_to(os.path.relpath(dest, l.parent)) |
71 | 91 | ||