diff --git a/Help/command/export.rst b/Help/command/export.rst index 775282f553..5b98ecfad6 100644 --- a/Help/command/export.rst +++ b/Help/command/export.rst @@ -178,7 +178,8 @@ Exporting Software Bill of Materials (SBOM) Documents [FORMAT ] [PROJECT |NO_PROJECT_METADATA] [VERSION [.[.[.]]]] - [LICENSE ] + [DATA_LICENSE ] + [DEFAULT_LICENSE ] [DESCRIPTION ] [HOMEPAGE_URL ] [PACKAGE_URL ]) diff --git a/Help/command/install.rst b/Help/command/install.rst index 75016b0cca..cb8db41cd2 100644 --- a/Help/command/install.rst +++ b/Help/command/install.rst @@ -1217,7 +1217,8 @@ Signatures [PROJECT |NO_PROJECT_METADATA] [DESTINATION ] [VERSION [.[.[.]]]] - [LICENSE ] + [DATA_LICENSE ] + [DEFAULT_LICENSE ] [DESCRIPTION ] [HOMEPAGE_URL ] [PACKAGE_URL ] @@ -1260,16 +1261,21 @@ Signatures An informational canonical package URL for the project. - ``LICENSE `` + ``DATA_LICENSE `` A |SPDX|_ (SPDX) `License Expression`_ that describes the license(s) of the - project as a whole, including documentation, resources, or other materials - distributed with the project, in addition to software artifacts. See the - SPDX `License List`_ for a list of commonly used licenses and their - identifiers. + SBOM data itself in the generated document. See the SPDX `License List`_ + for a list of commonly used licenses and their identifiers. In the SPDX + format, it corresponds to the `dataLicense`_ property. The license of individual components is taken from the - :prop_tgt:`SPDX_LICENSE` property of their respective targets. + :prop_tgt:`SPDX_LICENSE` property of their respective targets if set and + the ``DEFAULT_LICENSE`` otherwise. + + ``DEFAULT_LICENSE `` + + A |SPDX|_ (SPDX) `License Expression`_ that describes the license(s) of any + components which do not otherwise specify their license(s). ``DESCRIPTION `` @@ -1420,5 +1426,6 @@ and by CPack. You can also invoke this script manually with .. _License Expression: https://spdx.github.io/spdx-spec/v3.0.1/annexes/spdx-license-expressions/ .. _License List: https://spdx.org/licenses/ +.. _dataLicense: https://spdx.github.io/spdx-spec/v3.0.1/model/Core/Properties/dataLicense/ .. |SBOM| replace:: Software Bill of Material diff --git a/Help/dev/experimental.rst b/Help/dev/experimental.rst index 60955f1112..6a3b7f799e 100644 --- a/Help/dev/experimental.rst +++ b/Help/dev/experimental.rst @@ -109,7 +109,7 @@ In order to activate support for the :command:`install(SBOM)` command, set * variable ``CMAKE_EXPERIMENTAL_GENERATE_SBOM`` to -* value ``2d856d6d-53e8-488b-a17f-d486d2cac317``. +* value ``248471c2-d905-4c9e-81b5-b89cd27965e1``. This UUID may change in future versions of CMake. Be sure to use the value documented here by the source tree of the version of CMake with which you are diff --git a/Source/cmExperimental.cxx b/Source/cmExperimental.cxx index 2d9232c5d3..3d50bf1714 100644 --- a/Source/cmExperimental.cxx +++ b/Source/cmExperimental.cxx @@ -55,7 +55,7 @@ cmExperimental::FeatureData const LookupTable[] = { {}, cmExperimental::TryCompileCondition::Never }, { "GenerateSbom", - "2d856d6d-53e8-488b-a17f-d486d2cac317", + "248471c2-d905-4c9e-81b5-b89cd27965e1", "CMAKE_EXPERIMENTAL_GENERATE_SBOM", "CMake's support for generating software bill of materials (Sbom) " "information in SPDX format is experimental. It is meant only for " diff --git a/Source/cmSbomArguments.cxx b/Source/cmSbomArguments.cxx index 155aefd1d2..b5c48fa6aa 100644 --- a/Source/cmSbomArguments.cxx +++ b/Source/cmSbomArguments.cxx @@ -65,6 +65,14 @@ bool cmSbomArguments::Check(cmExecutionStatus& status) const return false; } } + + if (!this->License.empty()) { + // Do not allow the license argument to be provided as SBOM only accepts a + // DEFAULT_LICENSE + status.SetError("SBOM given unknown argument: \"LICENSE\"."); + return false; + } + return true; } diff --git a/Source/cmSbomArguments.h b/Source/cmSbomArguments.h index ab62226e97..a45d52ed1d 100644 --- a/Source/cmSbomArguments.h +++ b/Source/cmSbomArguments.h @@ -41,6 +41,8 @@ public: ArgumentParser::NonEmpty Format; ArgumentParser::NonEmpty PackageUrl; + ArgumentParser::NonEmpty DefaultLicense; + ArgumentParser::NonEmpty DataLicense; protected: cm::string_view CommandName() const override; @@ -55,6 +57,8 @@ private: Bind(base, parser, "SBOM"_s, &cmProjectInfoArguments::PackageName); Bind(self, parser, "FORMAT"_s, &cmSbomArguments::Format); Bind(self, parser, "PACKAGE_URL"_s, &cmSbomArguments::PackageUrl); + Bind(self, parser, "DEFAULT_LICENSE"_s, &cmSbomArguments::DefaultLicense); + Bind(self, parser, "DATA_LICENSE"_s, &cmSbomArguments::DataLicense); cmProjectInfoArguments::Bind(parser, self); } }; diff --git a/Source/cmSbomBuilder.cxx b/Source/cmSbomBuilder.cxx index 16397a23d8..aed9b1554f 100644 --- a/Source/cmSbomBuilder.cxx +++ b/Source/cmSbomBuilder.cxx @@ -70,7 +70,8 @@ cmSbomBuilder::cmSbomBuilder(cmSbomArguments args, , PackageDescription(std::move(args.Description)) , PackageWebsite(std::move(args.Website)) , PackageUrl(std::move(args.PackageUrl)) - , PackageLicense(std::move(args.License)) + , DataLicense(std::move(args.DataLicense)) + , DefaultLicense(std::move(args.DefaultLicense)) , PackageFormat(args.GetFormat()) { } @@ -222,8 +223,12 @@ cmSpdxDocument cmSbomBuilder::GenerateSbom(cmSpdxCreationInfo const* ci) const proj.Description = this->PackageDescription; } - if (!this->PackageLicense.empty()) { - proj.DataLicense = this->PackageLicense; + if (!this->DataLicense.empty()) { + cmSpdxLicenseExpression license; + license.SpdxId = cmStrCat("urn:", PackageName, "#LicenseExpression"); + license.CreationInfo = ci; + license.LicenseExpression = this->DataLicense; + proj.DataLicense = license; } return proj; @@ -319,7 +324,31 @@ bool cmSbomBuilder::GenerateLinkProperties( this->AddPackageInformation(pkg, pkgIt->first, pkgIt->second); } } - return { true, insert_back(project->Elements, std::move(pkg)) }; + + cmSpdxPackage const* pkgPtr = + insert_back(project->Elements, std::move(pkg)); + if (!linkInfo.License.empty() && + !cm::contains(this->GeneratedLinkLicenses, name)) { + this->GeneratedLinkLicenses.emplace(name); + + cmSpdxLicenseExpression license; + license.SpdxId = cmStrCat("urn:", name, "#LicenseExpression"); + license.CreationInfo = ci; + license.LicenseExpression = linkInfo.License; + + cmSpdxRelationship relHasLicense; + relHasLicense.SpdxId = + cmStrCat("urn:", name, "#DeclaredLicenseRelationship"); + relHasLicense.CreationInfo = ci; + relHasLicense.RelationshipType = + cmSpdxRelationship::HAS_DECLARED_LICENSE; + relHasLicense.From = pkgPtr; + relHasLicense.To.emplace_back(std::move(license)); + + insert_back(doc.Graph, std::move(relHasLicense)); + } + + return { true, pkgPtr }; } cmSpdxPackage pkg; @@ -368,10 +397,40 @@ bool cmSbomBuilder::GenerateProperties( current, allTargets, config); status &= this->GenerateLinkProperties( doc, proj, ci, "INTERFACE_LINK_LIBRARIES", current, allTargets, config); - + status &= this->GenerateMetaProperties(doc, proj, ci, current); return status; } +bool cmSbomBuilder::GenerateMetaProperties( + cmSbomDocument& doc, cmSpdxDocument* /*project*/, + cmSpdxCreationInfo const* ci, TargetProperties const& current) const +{ + std::string licenseExpr = this->DefaultLicense; + cmValue licenseExprProp = current.Target->GetProperty("SPDX_LICENSE"); + if (licenseExprProp) { + licenseExpr = licenseExprProp; + } + if (!licenseExpr.empty()) { + auto const& tgtName = current.Target->GetName(); + + cmSpdxLicenseExpression license; + license.SpdxId = cmStrCat("urn:", tgtName, "#LicenseExpression"); + license.CreationInfo = ci; + license.LicenseExpression = std::move(licenseExpr); + + cmSpdxRelationship relHasLicense; + relHasLicense.SpdxId = + cmStrCat("urn:", tgtName, "#DeclaredLicenseRelationship"); + relHasLicense.CreationInfo = ci; + relHasLicense.RelationshipType = cmSpdxRelationship::HAS_DECLARED_LICENSE; + relHasLicense.From = current.Package; + relHasLicense.To.emplace_back(std::move(license)); + + insert_back(doc.Graph, std::move(relHasLicense)); + } + return true; +} + bool cmSbomBuilder::PopulateLinkLibrariesProperty( cmGeneratorTarget const* target, cmGeneratorExpression::PreprocessContext preprocessRule, @@ -428,9 +487,12 @@ bool cmSbomBuilder::NoteLinkedTarget(cmGeneratorTarget const* target, std::string const& linkedName, cmGeneratorTarget const* linkedTarget) { + auto linkedLicense = linkedTarget->GetSafeProperty("SPDX_LICENSE"); + if (cm::contains(this->SbomTargets, linkedTarget)) { - this->LinkTargets.emplace(linkedName, - LinkInfo{ "", linkedTarget->GetExportName() }); + this->LinkTargets.emplace( + linkedName, + LinkInfo{ "", linkedTarget->GetExportName(), linkedLicense }); return true; } @@ -468,7 +530,8 @@ bool cmSbomBuilder::NoteLinkedTarget(cmGeneratorTarget const* target, } else { component = linkedName.substr(prefix.length()); } - this->LinkTargets.emplace(linkedName, LinkInfo{ pkgName, component }); + this->LinkTargets.emplace(linkedName, + LinkInfo{ pkgName, component, linkedLicense }); cmPackageInformation& req = this->Requirements.insert(std::move(*pkgInfo)).first->second; req.Components.emplace(std::move(component)); @@ -494,9 +557,11 @@ bool cmSbomBuilder::NoteLinkedTarget(cmGeneratorTarget const* target, std::string pkgName{ linkNamespace.data(), linkNamespace.size() - 2 }; std::string component = linkedTarget->GetExportName(); if (pkgName == this->GetPackageName()) { - this->LinkTargets.emplace(linkedName, LinkInfo{ "", component }); + this->LinkTargets.emplace(linkedName, + LinkInfo{ "", component, linkedLicense }); } else { - this->LinkTargets.emplace(linkedName, LinkInfo{ pkgName, component }); + this->LinkTargets.emplace(linkedName, + LinkInfo{ pkgName, component, linkedLicense }); this->Requirements[pkgName].Components.emplace(std::move(component)); } return true; @@ -535,7 +600,8 @@ bool cmSbomBuilder::NoteLinkedTarget(cmGeneratorTarget const* target, "\" (first alphabetically).")); } std::string component = linkedTarget->GetExportName(); - this->LinkTargets.emplace(linkedName, LinkInfo{ pkgName, component }); + this->LinkTargets.emplace(linkedName, + LinkInfo{ pkgName, component, linkedLicense }); this->Requirements[pkgName].Components.emplace(std::move(component)); return true; } diff --git a/Source/cmSbomBuilder.h b/Source/cmSbomBuilder.h index 961e9db815..f092e3fb60 100644 --- a/Source/cmSbomBuilder.h +++ b/Source/cmSbomBuilder.h @@ -129,6 +129,9 @@ protected: TargetProperties const& current, std::vector const& allTargets, std::string const& config) const; + bool GenerateMetaProperties(cmSbomDocument& doc, cmSpdxDocument* project, + cmSpdxCreationInfo const* ci, + TargetProperties const& current) const; bool NoteLinkedTarget(cmGeneratorTarget const* target, std::string const& linkedName, @@ -163,6 +166,7 @@ private: { std::string Package; std::string Component; + std::string License; }; // Metadata @@ -172,7 +176,8 @@ private: std::string const PackageDescription; std::string const PackageWebsite; std::string const PackageUrl; - std::string const PackageLicense; + std::string const DataLicense; + std::string const DefaultLicense; cmSbomArguments::SbomFormat const PackageFormat; // Derived from inputs at generate time @@ -182,4 +187,7 @@ private: std::map LinkTargets; std::map Requirements; std::vector Configurations; + + // Targets for which license data has been generated + mutable std::set GeneratedLinkLicenses; }; diff --git a/Source/cmSpdx.cxx b/Source/cmSpdx.cxx index 870eec4e1c..492c9a3f7b 100644 --- a/Source/cmSpdx.cxx +++ b/Source/cmSpdx.cxx @@ -128,6 +128,8 @@ std::string to_string(cmSpdxRelationship::RelationshipTypeId id) return "contains"; case cmSpdxRelationship::RelationshipTypeId::DEPENDS_ON: return "dependsOn"; + case cmSpdxRelationship::RelationshipTypeId::HAS_DECLARED_LICENSE: + return "hasDeclaredLicense"; case cmSpdxRelationship::RelationshipTypeId::OTHER: return "other"; } @@ -497,6 +499,20 @@ void cmSpdxSnippet::Serialize(cmSbomSerializer& serializer) const } } +void cmSpdxAnyLicenseInfo::Serialize(cmSbomSerializer& serializer) const +{ + cmSpdxElement::Serialize(serializer); + serializer.AddString("type", "simplelicensing_AnyLicenseInfo"); +} + +void cmSpdxLicenseExpression::Serialize(cmSbomSerializer& serializer) const +{ + cmSpdxAnyLicenseInfo::Serialize(serializer); + serializer.AddString("type", "simplelicensing_LicenseExpression"); + SerializeIfPresent(serializer, "simplelicensing_licenseExpression", + LicenseExpression); +} + void cmSpdxDocument::Serialize(cmSbomSerializer& serializer) const { cmSpdxElementCollection::Serialize(serializer); @@ -508,7 +524,9 @@ void cmSpdxDocument::Serialize(cmSbomSerializer& serializer) const if (NamespaceMap) { serializer.AddVisitable("namespaceMap", *NamespaceMap); } - SerializeIfPresent(serializer, "dataLicense", DataLicense); + if (DataLicense) { + serializer.AddVisitable("dataLicense", *DataLicense); + } } void cmSbomDocument::Serialize(cmSbomSerializer& serializer) const diff --git a/Source/cmSpdx.h b/Source/cmSpdx.h index adaa26a986..f792e7aafd 100644 --- a/Source/cmSpdx.h +++ b/Source/cmSpdx.h @@ -159,6 +159,7 @@ struct cmSpdxRelationship : cmSpdxElement DESCRIBES, CONTAINS, DEPENDS_ON, + HAS_DECLARED_LICENSE, OTHER }; @@ -343,11 +344,23 @@ struct cmSpdxPackage final : cmSpdxSoftwareArtifact void Serialize(cmSbomSerializer&) const override; }; +struct cmSpdxAnyLicenseInfo : cmSpdxElement +{ + void Serialize(cmSbomSerializer&) const override; +}; + +struct cmSpdxLicenseExpression final : cmSpdxAnyLicenseInfo +{ + cm::optional LicenseExpression; + + void Serialize(cmSbomSerializer&) const override; +}; + struct cmSpdxDocument final : cmSpdxElementCollection { cm::optional ExternalMap; cm::optional NamespaceMap; - std::string DataLicense; + cm::optional DataLicense; void Serialize(cmSbomSerializer& serializer) const override; }; diff --git a/Tests/CMakeLib/testSpdxSerializer.cxx b/Tests/CMakeLib/testSpdxSerializer.cxx index 7a5f6bee85..95e6caa2cc 100644 --- a/Tests/CMakeLib/testSpdxSerializer.cxx +++ b/Tests/CMakeLib/testSpdxSerializer.cxx @@ -28,7 +28,6 @@ bool testSerializeSpdxJson() cmSpdxDocument spdxValue; spdxValue.SpdxId = "_:SPDXRef-Document"; - spdxValue.DataLicense = "CC0-1.0"; auto spdx = insert_back(doc.Graph, std::move(spdxValue)); { diff --git a/Tests/RunCMake/EnvSbom/RunCMakeTest.cmake b/Tests/RunCMake/EnvSbom/RunCMakeTest.cmake index 78debd2078..39bd58c723 100644 --- a/Tests/RunCMake/EnvSbom/RunCMakeTest.cmake +++ b/Tests/RunCMake/EnvSbom/RunCMakeTest.cmake @@ -2,7 +2,7 @@ include(RunCMake) set(common_test_options -Wno-author - "-DCMAKE_EXPERIMENTAL_GENERATE_SBOM:STRING=2d856d6d-53e8-488b-a17f-d486d2cac317" + "-DCMAKE_EXPERIMENTAL_GENERATE_SBOM:STRING=248471c2-d905-4c9e-81b5-b89cd27965e1" "-DCMAKE_INSTALL_SBOM_FORMATS:STRING=JSON" "-DCMAKE_INSTALL_LIBDIR=lib" ) diff --git a/Tests/RunCMake/ExportSbom/ProjectMetadata.cmake b/Tests/RunCMake/ExportSbom/ProjectMetadata.cmake index 02b5ce3db4..43678f2cd6 100644 --- a/Tests/RunCMake/ExportSbom/ProjectMetadata.cmake +++ b/Tests/RunCMake/ExportSbom/ProjectMetadata.cmake @@ -4,7 +4,7 @@ export( SBOM test_targets EXPORTS test_targets DESCRIPTION "An eloquent description" - LICENSE "BSD-3" + DATA_LICENSE "BSD-3" HOMEPAGE_URL "www.example.com" PACKAGE_URL "https://example.com/test_targets.tar.gz" VERSION "1.3.4" diff --git a/Tests/RunCMake/ExportSbom/RunCMakeTest.cmake b/Tests/RunCMake/ExportSbom/RunCMakeTest.cmake index 4f1f0ef835..41b8a45b29 100644 --- a/Tests/RunCMake/ExportSbom/RunCMakeTest.cmake +++ b/Tests/RunCMake/ExportSbom/RunCMakeTest.cmake @@ -2,7 +2,7 @@ include(RunCMake) set(common_test_options -Wno-author - "-DCMAKE_EXPERIMENTAL_GENERATE_SBOM:STRING=2d856d6d-53e8-488b-a17f-d486d2cac317" + "-DCMAKE_EXPERIMENTAL_GENERATE_SBOM:STRING=248471c2-d905-4c9e-81b5-b89cd27965e1" ) function(run_cmake_error test) diff --git a/Tests/RunCMake/InstallSbom/ProjectMetadata.cmake b/Tests/RunCMake/InstallSbom/ProjectMetadata.cmake index daaf3b47e5..d1f99b7b69 100644 --- a/Tests/RunCMake/InstallSbom/ProjectMetadata.cmake +++ b/Tests/RunCMake/InstallSbom/ProjectMetadata.cmake @@ -3,7 +3,7 @@ include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/ProjectMetadata.cmake) install( SBOM test_targets DESCRIPTION "An eloquent description" - LICENSE "BSD-3" + DATA_LICENSE "BSD-3" HOMEPAGE_URL "www.example.com" PACKAGE_URL "https://example.com/test_targets.tar.gz" VERSION "1.3.4" diff --git a/Tests/RunCMake/InstallSbom/RunCMakeTest.cmake b/Tests/RunCMake/InstallSbom/RunCMakeTest.cmake index fd567a8336..bc1bddc1d7 100644 --- a/Tests/RunCMake/InstallSbom/RunCMakeTest.cmake +++ b/Tests/RunCMake/InstallSbom/RunCMakeTest.cmake @@ -2,7 +2,7 @@ include(RunCMake) set(common_test_options -Wno-author - "-DCMAKE_EXPERIMENTAL_GENERATE_SBOM:STRING=2d856d6d-53e8-488b-a17f-d486d2cac317" + "-DCMAKE_EXPERIMENTAL_GENERATE_SBOM:STRING=248471c2-d905-4c9e-81b5-b89cd27965e1" ) function(run_cmake_error test) diff --git a/Tests/RunCMake/Sbom/ProjectMetadata-install-check.cmake b/Tests/RunCMake/Sbom/ProjectMetadata-install-check.cmake index 697eb7029c..83ffda697e 100644 --- a/Tests/RunCMake/Sbom/ProjectMetadata-install-check.cmake +++ b/Tests/RunCMake/Sbom/ProjectMetadata-install-check.cmake @@ -36,6 +36,25 @@ set(APPLICATION_EXPECTED [=[ } ]=]) +set(LICENSE_EXPECTED [=[ +{ + "creationInfo" : "_:Build#CreationInfo", + "from" : "urn:test#Package", + "relationshipType" : "hasDeclaredLicense", + "spdxId" : "urn:test#DeclaredLicenseRelationship", + "to" : + [ + { + "creationInfo" : "_:Build#CreationInfo", + "simplelicensing_licenseExpression" : "license-for-test-target", + "spdxId" : "urn:test#LicenseExpression", + "type" : "simplelicensing_LicenseExpression" + } + ], + "type" : "Relationship" +} +]=]) + expect_value("${content}" "https://spdx.org/rdf/3.0.1/spdx-context.jsonld" "@context") string(JSON CREATION_INFO GET "${content}" "@graph" "0") @@ -44,3 +63,6 @@ expect_object("${CREATION_INFO}" CREATION_INFO_EXPECTED) string(JSON SPDX_DOCUMENT GET "${content}" "@graph" "1") expect_object("${SPDX_DOCUMENT}" SPDX_DOCUMENT_EXPECTED) expect_object("${SPDX_DOCUMENT}" APPLICATION_EXPECTED "rootElement") + +string(JSON LICENSE_RELATIONSHIP GET "${content}" "@graph" "2") +expect_object("${LICENSE_RELATIONSHIP}" LICENSE_EXPECTED) diff --git a/Tests/RunCMake/Sbom/ProjectMetadata.cmake b/Tests/RunCMake/Sbom/ProjectMetadata.cmake index 02604fcb0b..c56c0e2a0a 100644 --- a/Tests/RunCMake/Sbom/ProjectMetadata.cmake +++ b/Tests/RunCMake/Sbom/ProjectMetadata.cmake @@ -10,6 +10,7 @@ project(test LANGUAGES C VERSION 1.2.0) add_library(test INTERFACE) +set_target_properties(test PROPERTIES SPDX_LICENSE license-for-test-target) install( TARGETS test diff --git a/Tests/RunCMake/Sbom/ProjectMetadataExplicitAssertions.cmake b/Tests/RunCMake/Sbom/ProjectMetadataExplicitAssertions.cmake index 33fca83d9e..6d3247c904 100644 --- a/Tests/RunCMake/Sbom/ProjectMetadataExplicitAssertions.cmake +++ b/Tests/RunCMake/Sbom/ProjectMetadataExplicitAssertions.cmake @@ -3,7 +3,13 @@ include(${CMAKE_CURRENT_LIST_DIR}/Assertions.cmake) set(DOCUMENT_METADATA_EXPECTED [=[ { "description" : "An eloquent description", - "dataLicense" : "BSD-3" + "dataLicense" : + { + "creationInfo" : "_:Build#CreationInfo", + "simplelicensing_licenseExpression" : "BSD-3", + "spdxId" : "urn:test_targets#LicenseExpression", + "type" : "simplelicensing_LicenseExpression" + } } ]=]) diff --git a/Tests/RunCMake/Sbom/Requirements-install-check.cmake b/Tests/RunCMake/Sbom/Requirements-install-check.cmake index 92f2010239..5e5aa14833 100644 --- a/Tests/RunCMake/Sbom/Requirements-install-check.cmake +++ b/Tests/RunCMake/Sbom/Requirements-install-check.cmake @@ -119,6 +119,24 @@ set(BAR_DEPENDENCY_FOO [=[ } ]=]) +set(TEST_LIBA_LINKED_LICENSE_EXPECTED [=[ +{ + "creationInfo" : "_:Build#CreationInfo", + "from" : "urn:test:liba#Package", + "relationshipType" : "hasDeclaredLicense", + "spdxId" : "urn:test::liba#DeclaredLicenseRelationship", + "to" : + [ + { + "creationInfo" : "_:Build#CreationInfo", + "simplelicensing_licenseExpression" : "license-for-test-liba", + "spdxId" : "urn:test::liba#LicenseExpression", + "type" : "simplelicensing_LicenseExpression" + } + ], + "type" : "Relationship" +} +]=]) set(CREATION_INFO_EXPECTED [=[ { @@ -147,3 +165,7 @@ expect_object("${BAR_SPDX_DOCUMENT}" BAR_LIBC "rootElement") expect_object("${BAR_SPDX_DOCUMENT}" BAR_LIBD "rootElement") expect_object("${BAR_SPDX_DOCUMENT}" BAR_DEPENDENCY_TEST "element") expect_object("${BAR_SPDX_DOCUMENT}" BAR_DEPENDENCY_FOO "element") + +# Check that the license target property imported from cmake config is reported +string(JSON LICENSE_RELATIONSHIP GET "${BAR_CONTENT}" "@graph" "2") +expect_object("${LICENSE_RELATIONSHIP}" TEST_LIBA_LINKED_LICENSE_EXPECTED) diff --git a/Tests/RunCMake/Sbom/SharedTarget-install-check.cmake b/Tests/RunCMake/Sbom/SharedTarget-install-check.cmake index 7114364e04..1c698e8546 100644 --- a/Tests/RunCMake/Sbom/SharedTarget-install-check.cmake +++ b/Tests/RunCMake/Sbom/SharedTarget-install-check.cmake @@ -67,6 +67,25 @@ set(BUILD_LINKED_LIBRARIES_EXPECTED [=[ } ]=]) +set(LICENSE_EXPECTED [=[ +{ + "creationInfo" : "_:Build#CreationInfo", + "from" : "urn:foo:foo#Package", + "relationshipType" : "hasDeclaredLicense", + "spdxId" : "urn:foo::foo#DeclaredLicenseRelationship", + "to" : + [ + { + "creationInfo" : "_:Build#CreationInfo", + "simplelicensing_licenseExpression" : "BSD-3-Clause", + "spdxId" : "urn:foo::foo#LicenseExpression", + "type" : "simplelicensing_LicenseExpression" + } + ], + "type" : "Relationship" +} +]=]) + expect_value("${content}" "https://spdx.org/rdf/3.0.1/spdx-context.jsonld" "@context") string(JSON CREATION_INFO GET "${content}" "@graph" "0") @@ -76,5 +95,9 @@ string(JSON SPDX_DOCUMENT GET "${content}" "@graph" "1") expect_object("${SPDX_DOCUMENT}" SPDX_DOCUMENT_EXPECTED) expect_object("${SPDX_DOCUMENT}" APPLICATION_EXPECTED "rootElement") expect_object("${SPDX_DOCUMENT}" DEPENDENCY_EXPECTED "element") -string(JSON LINKED_LIBRARIES GET "${content}" "@graph" "2") +string(JSON LINKED_LIBRARIES GET "${content}" "@graph" "3") expect_object("${LINKED_LIBRARIES}" BUILD_LINKED_LIBRARIES_EXPECTED) + +# Check that default_license from the imported CPS package is reported +string(JSON LICENSE_RELATIONSHIP GET "${content}" "@graph" "2") +expect_object("${LICENSE_RELATIONSHIP}" LICENSE_EXPECTED) diff --git a/Tests/RunCMake/Sbom/cmake/test-config.cmake b/Tests/RunCMake/Sbom/cmake/test-config.cmake index 3c46ea684d..12cea73fcb 100644 --- a/Tests/RunCMake/Sbom/cmake/test-config.cmake +++ b/Tests/RunCMake/Sbom/cmake/test-config.cmake @@ -1 +1,2 @@ add_library(test::liba INTERFACE IMPORTED) +set_target_properties(test::liba PROPERTIES SPDX_LICENSE license-for-test-liba) diff --git a/Tests/RunCMake/install/RunCMakeTest.cmake b/Tests/RunCMake/install/RunCMakeTest.cmake index 94084438df..b62859770b 100644 --- a/Tests/RunCMake/install/RunCMakeTest.cmake +++ b/Tests/RunCMake/install/RunCMakeTest.cmake @@ -95,7 +95,7 @@ run_cmake_with_options(EXPORT_ANDROID_MK-AbsoluteDest-warn -Winstall-absolute-de run_cmake_with_options(PACKAGE_INFO-AbsoluteDest-error -Werror=install-absolute-destination) run_cmake_with_options(SBOM-AbsoluteDest-warn -Winstall-absolute-destination - -DCMAKE_EXPERIMENTAL_GENERATE_SBOM=2d856d6d-53e8-488b-a17f-d486d2cac317) + -DCMAKE_EXPERIMENTAL_GENERATE_SBOM=248471c2-d905-4c9e-81b5-b89cd27965e1) run_cmake_with_options(IMPORTED_RUNTIME_ARTIFACTS-AbsoluteDest-warn -Winstall-absolute-destination) if(CMAKE_SYSTEM_NAME MATCHES "^(Linux|Darwin|Windows)$") run_cmake_with_options(RUNTIME_DEPENDENCY_SET-AbsoluteDest-warn -Winstall-absolute-destination)