From 85721c4c56513e255fde7824c5520fde33f61ed3 Mon Sep 17 00:00:00 2001 From: Matthew Woehlke Date: Wed, 12 Feb 2025 11:25:24 -0500 Subject: install(PACKAGE_INFO): Export required components Modify cmExportPackageInfoGenerator to record not just what packages are required, but what targets (components) are used by those requirements, and to populate the requirements' component lists accordingly. --- Source/cmExportPackageInfoGenerator.cxx | 34 ++++++++++++++-------- Source/cmExportPackageInfoGenerator.h | 2 +- .../RunCMake/PackageInfo/Requirements-check.cmake | 6 ++-- 3 files changed, 27 insertions(+), 15 deletions(-) diff --git a/Source/cmExportPackageInfoGenerator.cxx b/Source/cmExportPackageInfoGenerator.cxx index 211347e..8616e10 100644 --- a/Source/cmExportPackageInfoGenerator.cxx +++ b/Source/cmExportPackageInfoGenerator.cxx @@ -127,9 +127,22 @@ void cmExportPackageInfoGenerator::GeneratePackageRequires( { if (!this->Requirements.empty()) { Json::Value& requirements = package["requires"]; + + // Build description for each requirement. for (auto const& requirement : this->Requirements) { + auto data = Json::Value{ Json::objectValue }; + + // Add required components. + if (!requirement.second.empty()) { + auto components = Json::Value{ Json::arrayValue }; + for (std::string const& component : requirement.second) { + components.append(component); + } + data["components"] = components; + } + // TODO: version, hint - requirements[requirement] = Json::Value{}; + requirements[requirement.first] = data; } } } @@ -257,10 +270,10 @@ bool cmExportPackageInfoGenerator::NoteLinkedTarget( return false; } + std::string component = linkedName.substr(prefix.length()); + this->LinkTargets.emplace(linkedName, cmStrCat(pkgName, ':', component)); // TODO: Record package version, hint. - this->Requirements.emplace(pkgName); - this->LinkTargets.emplace( - linkedName, cmStrCat(pkgName, ':', linkedName.substr(prefix.length()))); + this->Requirements[pkgName].emplace(std::move(component)); return true; } @@ -278,16 +291,13 @@ bool cmExportPackageInfoGenerator::NoteLinkedTarget( return false; } - auto pkgName = - cm::string_view{ linkNamespace.data(), linkNamespace.size() - 2 }; - + std::string pkgName{ linkNamespace.data(), linkNamespace.size() - 2 }; + std::string component = linkedTarget->GetExportName(); if (pkgName == this->GetPackageName()) { - this->LinkTargets.emplace(linkedName, - cmStrCat(':', linkedTarget->GetExportName())); + this->LinkTargets.emplace(linkedName, cmStrCat(':', component)); } else { - this->Requirements.emplace(pkgName); - this->LinkTargets.emplace( - linkedName, cmStrCat(pkgName, ':', linkedTarget->GetExportName())); + this->LinkTargets.emplace(linkedName, cmStrCat(pkgName, ':', component)); + this->Requirements[pkgName].emplace(std::move(component)); } return true; } diff --git a/Source/cmExportPackageInfoGenerator.h b/Source/cmExportPackageInfoGenerator.h index 6fe1e35..5014252 100644 --- a/Source/cmExportPackageInfoGenerator.h +++ b/Source/cmExportPackageInfoGenerator.h @@ -110,5 +110,5 @@ private: std::vector DefaultConfigurations; std::map LinkTargets; - std::set Requirements; + std::map> Requirements; }; diff --git a/Tests/RunCMake/PackageInfo/Requirements-check.cmake b/Tests/RunCMake/PackageInfo/Requirements-check.cmake index 59a212f..a082355 100644 --- a/Tests/RunCMake/PackageInfo/Requirements-check.cmake +++ b/Tests/RunCMake/PackageInfo/Requirements-check.cmake @@ -8,8 +8,10 @@ expect_value("${content}" "interface" "components" "libb" "type") file(READ "${out_dir}/bar.cps" content) expect_value("${content}" "bar" "name") -expect_null("${content}" "requires" "foo") -expect_null("${content}" "requires" "test") +expect_array("${content}" 1 "requires" "foo" "components") +expect_value("${content}" "libb" "requires" "foo" "components" 0) +expect_array("${content}" 1 "requires" "test" "components") +expect_value("${content}" "liba" "requires" "test" "components" 0) expect_value("${content}" "interface" "components" "libc" "type") expect_value("${content}" "interface" "components" "libd" "type") -- cgit v0.12