diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index 106009ee85..fa80c31d8a 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -328,6 +328,7 @@ Properties on Targets /prop_tgt/LIBRARY_OUTPUT_DIRECTORY_CONFIG /prop_tgt/LIBRARY_OUTPUT_NAME /prop_tgt/LIBRARY_OUTPUT_NAME_CONFIG + /prop_tgt/SPDX_LICENSE /prop_tgt/LINK_DEPENDS /prop_tgt/LINK_DEPENDS_NO_SHARED /prop_tgt/LINK_DIRECTORIES diff --git a/Help/prop_tgt/SPDX_LICENSE.rst b/Help/prop_tgt/SPDX_LICENSE.rst new file mode 100644 index 0000000000..056c8606f9 --- /dev/null +++ b/Help/prop_tgt/SPDX_LICENSE.rst @@ -0,0 +1,14 @@ +SPDX_LICENSE +------------ + +.. versionadded:: 4.1 + +Specify the license of a target using a |SPDX|_ (SPDX) `License Expression`_. +See the SPDX `License List`_ for a list of commonly used licenses and their +identifiers. + +.. _SPDX: https://spdx.dev/ +.. |SPDX| replace:: System Package Data Exchange + +.. _License Expression: https://spdx.github.io/spdx-spec/v3.0.1/annexes/spdx-license-expressions/ +.. _License List: https://spdx.org/licenses/ diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index 3e69038ec5..477453dcd2 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -117,6 +117,9 @@ bool cmExportFileGenerator::PopulateInterfaceProperties( this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE", target, properties); + this->PopulateInterfaceProperty("SPDX_LICENSE", target, preprocessRule, + properties); + std::string errorMessage; if (!this->PopulateCxxModuleExportProperties( target, properties, preprocessRule, includesDestinationDirs, diff --git a/Source/cmExportPackageInfoGenerator.cxx b/Source/cmExportPackageInfoGenerator.cxx index d486fec207..9887b8d58d 100644 --- a/Source/cmExportPackageInfoGenerator.cxx +++ b/Source/cmExportPackageInfoGenerator.cxx @@ -205,7 +205,10 @@ bool cmExportPackageInfoGenerator::GenerateInterfaceProperties( this->GenerateInterfaceListProperty(result, component, target, "includes", "INCLUDE_DIRECTORIES"_s, properties); - // TODO: description, license + this->GenerateProperty(result, component, target, "license", "SPDX_LICENSE", + properties); + + // TODO: description return result; } @@ -464,6 +467,24 @@ void cmExportPackageInfoGenerator::GenerateInterfaceListProperty( } } +void cmExportPackageInfoGenerator::GenerateProperty( + bool& result, Json::Value& component, cmGeneratorTarget const* target, + std::string const& outName, std::string const& inName, + ImportPropertyMap const& properties) const +{ + auto const& iter = properties.find(inName); + if (iter == properties.end()) { + return; + } + + if (!ForbidGeneratorExpressions(target, inName, iter->second)) { + result = false; + return; + } + + component[outName] = iter->second; +} + Json::Value cmExportPackageInfoGenerator::GenerateInterfaceConfigProperties( std::string const& suffix, ImportPropertyMap const& properties) const { diff --git a/Source/cmExportPackageInfoGenerator.h b/Source/cmExportPackageInfoGenerator.h index 338547c579..1392ba3ecf 100644 --- a/Source/cmExportPackageInfoGenerator.h +++ b/Source/cmExportPackageInfoGenerator.h @@ -101,6 +101,11 @@ private: std::string const& outName, cm::string_view inName, ImportPropertyMap const& properties) const; + void GenerateProperty(bool& result, Json::Value& component, + cmGeneratorTarget const* target, + std::string const& outName, std::string const& inName, + ImportPropertyMap const& properties) const; + std::string const PackageName; std::string const PackageVersion; std::string const PackageVersionCompat; diff --git a/Source/cmPackageInfoReader.cxx b/Source/cmPackageInfoReader.cxx index 3d20c4844f..dd6a13ce33 100644 --- a/Source/cmPackageInfoReader.cxx +++ b/Source/cmPackageInfoReader.cxx @@ -564,10 +564,10 @@ std::string cmPackageInfoReader::ResolvePath(std::string path) const return path; } -void cmPackageInfoReader::SetOptionalProperty(cmTarget* target, - cm::string_view property, - cm::string_view configuration, - Json::Value const& value) const +void cmPackageInfoReader::SetImportProperty(cmTarget* target, + cm::string_view property, + cm::string_view configuration, + Json::Value const& value) const { if (!value.isNull()) { std::string fullprop; @@ -582,6 +582,15 @@ void cmPackageInfoReader::SetOptionalProperty(cmTarget* target, } } +void cmPackageInfoReader::SetMetaProperty(cmTarget* target, + cm::string_view property, + Json::Value const& value) const +{ + if (!value.isNull()) { + target->SetProperty(property.data(), value.asString()); + } +} + void cmPackageInfoReader::SetTargetProperties( cmMakefile* makefile, cmTarget* target, Json::Value const& data, std::string const& package, cm::string_view configuration) const @@ -630,14 +639,14 @@ void cmPackageInfoReader::SetTargetProperties( }); // Add link name/location(s). - this->SetOptionalProperty(target, "LOCATION"_s, configuration, - data["location"]); + this->SetImportProperty(target, "LOCATION"_s, configuration, + data["location"]); - this->SetOptionalProperty(target, "IMPLIB"_s, configuration, - data["link_location"]); + this->SetImportProperty(target, "IMPLIB"_s, configuration, + data["link_location"]); - this->SetOptionalProperty(target, "SONAME"_s, configuration, - data["link_name"]); + this->SetImportProperty(target, "SONAME"_s, configuration, + data["link_name"]); // Add link languages. for (std::string const& originalLang : ReadList(data, "link_languages")) { @@ -659,6 +668,11 @@ void cmPackageInfoReader::SetTargetProperties( cmStrCat("$'); AppendProperty(makefile, target, "LINK_LIBRARIES"_s, configuration, lib); } + + // Add other information. + if (configuration.empty()) { + this->SetMetaProperty(target, "SPDX_LICENSE"_s, data["license"]); + } } cmTarget* cmPackageInfoReader::AddLibraryComponent( diff --git a/Source/cmPackageInfoReader.h b/Source/cmPackageInfoReader.h index 1bb6f4de25..3173f6660d 100644 --- a/Source/cmPackageInfoReader.h +++ b/Source/cmPackageInfoReader.h @@ -94,9 +94,11 @@ private: void SetTargetProperties(cmMakefile* makefile, cmTarget* target, Json::Value const& data, std::string const& package, cm::string_view configuration) const; - void SetOptionalProperty(cmTarget* target, cm::string_view property, - cm::string_view configuration, - Json::Value const& value) const; + void SetImportProperty(cmTarget* target, cm::string_view property, + cm::string_view configuration, + Json::Value const& value) const; + void SetMetaProperty(cmTarget* target, cm::string_view property, + Json::Value const& value) const; std::string ResolvePath(std::string path) const; diff --git a/Tests/RunCMake/ExportImport/RunCMakeTest.cmake b/Tests/RunCMake/ExportImport/RunCMakeTest.cmake index b73004776e..9bc6f76515 100644 --- a/Tests/RunCMake/ExportImport/RunCMakeTest.cmake +++ b/Tests/RunCMake/ExportImport/RunCMakeTest.cmake @@ -22,6 +22,7 @@ function(run_ExportImport_test case) endfunction() run_ExportImport_test(SharedDep) +run_ExportImport_test(SpdxLicenseProperty) function(run_ExportImportBuildInstall_test case) set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${case}-export-build) diff --git a/Tests/RunCMake/ExportImport/SpdxLicenseProperty-export.cmake b/Tests/RunCMake/ExportImport/SpdxLicenseProperty-export.cmake new file mode 100644 index 0000000000..e5047f7653 --- /dev/null +++ b/Tests/RunCMake/ExportImport/SpdxLicenseProperty-export.cmake @@ -0,0 +1,6 @@ +add_library(foo INTERFACE) +set_property(TARGET foo PROPERTY SPDX_LICENSE "BSD-3-Clause") + +install(TARGETS foo EXPORT foo) +install(EXPORT foo DESTINATION lib/cmake/foo) +install(FILES foo-config.cmake.in RENAME foo-config.cmake DESTINATION lib/cmake/foo) diff --git a/Tests/RunCMake/ExportImport/SpdxLicenseProperty-import.cmake b/Tests/RunCMake/ExportImport/SpdxLicenseProperty-import.cmake new file mode 100644 index 0000000000..9f17fcdec4 --- /dev/null +++ b/Tests/RunCMake/ExportImport/SpdxLicenseProperty-import.cmake @@ -0,0 +1,6 @@ +find_package(foo REQUIRED CONFIG NO_DEFAULT_PATH) +get_property(SPDX_LICENSE TARGET foo PROPERTY SPDX_LICENSE) +if(NOT SPDX_LICENSE STREQUAL "BSD-3-Clause") + message(FATAL_ERROR + "Expected SPDX_LICENSE property to be 'BSD-3-Clause' but got '${SPDX_LICENSE}'") +endif() diff --git a/Tests/RunCMake/ExportPackageInfo/InterfaceProperties-check.cmake b/Tests/RunCMake/ExportPackageInfo/InterfaceProperties-check.cmake index 1573dd8b1c..faf3e7a61a 100644 --- a/Tests/RunCMake/ExportPackageInfo/InterfaceProperties-check.cmake +++ b/Tests/RunCMake/ExportPackageInfo/InterfaceProperties-check.cmake @@ -22,3 +22,4 @@ expect_array("${component}" 1 "link_flags") expect_value("${component}" "--needed" "link_flags" 0) expect_array("${component}" 1 "link_libraries") expect_value("${component}" "/usr/lib/libm.so" "link_libraries" 0) +expect_value("${component}" "BSD-3-Clause" "license") diff --git a/Tests/RunCMake/ExportPackageInfo/InterfaceProperties.cmake b/Tests/RunCMake/ExportPackageInfo/InterfaceProperties.cmake index 0b519eec4f..b8d34542f0 100644 --- a/Tests/RunCMake/ExportPackageInfo/InterfaceProperties.cmake +++ b/Tests/RunCMake/ExportPackageInfo/InterfaceProperties.cmake @@ -10,6 +10,7 @@ target_include_directories( target_link_directories(foo INTERFACE /opt/foo/lib) target_link_options(foo INTERFACE --needed) target_link_libraries(foo INTERFACE /usr/lib/libm.so) +set_property(TARGET foo PROPERTY SPDX_LICENSE "BSD-3-Clause") install(TARGETS foo EXPORT foo DESTINATION .) export(EXPORT foo PACKAGE_INFO foo) diff --git a/Tests/RunCMake/ExportPackageInfo/Minimal-check.cmake b/Tests/RunCMake/ExportPackageInfo/Minimal-check.cmake index deba94eb49..fc5326a639 100644 --- a/Tests/RunCMake/ExportPackageInfo/Minimal-check.cmake +++ b/Tests/RunCMake/ExportPackageInfo/Minimal-check.cmake @@ -16,3 +16,4 @@ expect_missing("${content}" "components" "foo" "link_features") expect_missing("${content}" "components" "foo" "link_flags") expect_missing("${content}" "components" "foo" "link_libraries") expect_missing("${content}" "components" "foo" "requires") +expect_missing("${content}" "components" "foo" "license") diff --git a/Tests/RunCMake/InstallPackageInfo/InterfaceProperties-check.cmake b/Tests/RunCMake/InstallPackageInfo/InterfaceProperties-check.cmake index 2c3272ec3c..365dd80e31 100644 --- a/Tests/RunCMake/InstallPackageInfo/InterfaceProperties-check.cmake +++ b/Tests/RunCMake/InstallPackageInfo/InterfaceProperties-check.cmake @@ -22,3 +22,4 @@ expect_array("${component}" 1 "link_flags") expect_value("${component}" "--needed" "link_flags" 0) expect_array("${component}" 1 "link_libraries") expect_value("${component}" "/usr/lib/libm.so" "link_libraries" 0) +expect_value("${component}" "BSD-3-Clause" "license") diff --git a/Tests/RunCMake/InstallPackageInfo/InterfaceProperties.cmake b/Tests/RunCMake/InstallPackageInfo/InterfaceProperties.cmake index 42edc21fff..58e5046672 100644 --- a/Tests/RunCMake/InstallPackageInfo/InterfaceProperties.cmake +++ b/Tests/RunCMake/InstallPackageInfo/InterfaceProperties.cmake @@ -10,6 +10,7 @@ target_include_directories( target_link_directories(foo INTERFACE /opt/foo/lib) target_link_options(foo INTERFACE --needed) target_link_libraries(foo INTERFACE /usr/lib/libm.so) +set_property(TARGET foo PROPERTY SPDX_LICENSE "BSD-3-Clause") install(TARGETS foo EXPORT foo DESTINATION .) install(PACKAGE_INFO foo DESTINATION cps EXPORT foo) diff --git a/Tests/RunCMake/InstallPackageInfo/Minimal-check.cmake b/Tests/RunCMake/InstallPackageInfo/Minimal-check.cmake index 9608ed8fa6..8e30fcd739 100644 --- a/Tests/RunCMake/InstallPackageInfo/Minimal-check.cmake +++ b/Tests/RunCMake/InstallPackageInfo/Minimal-check.cmake @@ -16,3 +16,4 @@ expect_missing("${content}" "components" "foo" "link_features") expect_missing("${content}" "components" "foo" "link_flags") expect_missing("${content}" "components" "foo" "link_libraries") expect_missing("${content}" "components" "foo" "requires") +expect_missing("${content}" "components" "foo" "license") diff --git a/Tests/RunCMake/find_package-CPS/RunCMakeTest.cmake b/Tests/RunCMake/find_package-CPS/RunCMakeTest.cmake index c77bed5b51..1bcdc8abc5 100644 --- a/Tests/RunCMake/find_package-CPS/RunCMakeTest.cmake +++ b/Tests/RunCMake/find_package-CPS/RunCMakeTest.cmake @@ -17,6 +17,9 @@ run_cmake(VersionLimit2) run_cmake(TransitiveVersion) run_cmake(CustomVersion) +# Metadata Tests +run_cmake(SupplementalAttributes) + # Version-matching failure tests run_cmake(MissingVersion1) run_cmake(MissingVersion2) diff --git a/Tests/RunCMake/find_package-CPS/SupplementalAttributes.cmake b/Tests/RunCMake/find_package-CPS/SupplementalAttributes.cmake new file mode 100644 index 0000000000..3d6d567baf --- /dev/null +++ b/Tests/RunCMake/find_package-CPS/SupplementalAttributes.cmake @@ -0,0 +1,13 @@ +cmake_minimum_required(VERSION 4.0) + +include(Setup.cmake) + +set(CMAKE_FIND_PACKAGE_SORT_ORDER NAME) +set(CMAKE_FIND_PACKAGE_SORT_DIRECTION DEC) + +find_package(SupplementalAttributesTest REQUIRED COMPONENTS Sample) + +get_target_property(license SupplementalAttributesTest::Sample "SPDX_LICENSE") +if (NOT "${license}" STREQUAL "BSD-3-Clause") + message(SEND_ERROR "SupplementalAttributesTest wrong license ${license} !") +endif() diff --git a/Tests/RunCMake/find_package-CPS/cps/supplementalattributestest.cps b/Tests/RunCMake/find_package-CPS/cps/supplementalattributestest.cps new file mode 100644 index 0000000000..c7f3ce44e0 --- /dev/null +++ b/Tests/RunCMake/find_package-CPS/cps/supplementalattributestest.cps @@ -0,0 +1,12 @@ +{ + "cps_version": "0.13", + "name": "SupplementalAttributesTest", + "version": "1.0", + "cps_path": "@prefix@/cps", + "components": { + "Sample": { + "type": "interface", + "license": "BSD-3-Clause" + } + } +}