mirror of
https://github.com/Kitware/CMake.git
synced 2026-05-04 05:10:10 -05:00
install(EXPORT): Export find_dependency() calls
Issue: #20511 Co-Authored-by: Brad King <brad.king@kitware.com> Co-Authored-by: Robert Maynard <rmaynard@nvidia.com>
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
#include "cmExportFileGenerator.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
@@ -9,12 +10,15 @@
|
||||
#include <utility>
|
||||
|
||||
#include <cm/memory>
|
||||
#include <cm/optional>
|
||||
#include <cmext/string_view>
|
||||
|
||||
#include "cmsys/FStream.hxx"
|
||||
|
||||
#include "cmComputeLinkInformation.h"
|
||||
#include "cmExportSet.h"
|
||||
#include "cmFileSet.h"
|
||||
#include "cmFindPackageStack.h"
|
||||
#include "cmGeneratedFileStream.h"
|
||||
#include "cmGeneratorTarget.h"
|
||||
#include "cmLinkItem.h"
|
||||
@@ -100,7 +104,20 @@ bool cmExportFileGenerator::GenerateImportFile()
|
||||
this->GenerateImportHeaderCode(mainFileWithHeadersAndFootersBuffer);
|
||||
|
||||
// Create all the imported targets.
|
||||
bool result = this->GenerateMainFile(mainFileWithHeadersAndFootersBuffer);
|
||||
std::stringstream mainFileBuffer;
|
||||
bool result = this->GenerateMainFile(mainFileBuffer);
|
||||
|
||||
// Export find_dependency() calls. Must be done after GenerateMainFile(),
|
||||
// because that's when target dependencies are gathered, which we need for
|
||||
// the find_dependency() calls.
|
||||
if (!this->AppendMode && this->GetExportSet() &&
|
||||
this->ExportPackageDependencies) {
|
||||
this->SetRequiredCMakeVersion(3, 9, 0);
|
||||
this->GenerateFindDependencyCalls(mainFileWithHeadersAndFootersBuffer);
|
||||
}
|
||||
|
||||
// Write cached import code.
|
||||
mainFileWithHeadersAndFootersBuffer << mainFileBuffer.rdbuf();
|
||||
|
||||
// End with the import file footer.
|
||||
this->GenerateImportFooterCode(mainFileWithHeadersAndFootersBuffer);
|
||||
@@ -615,6 +632,12 @@ bool cmExportFileGenerator::AddTargetNamespace(std::string& input,
|
||||
return false;
|
||||
}
|
||||
|
||||
cmFindPackageStack const& pkgStack = tgt->Target->GetFindPackageStack();
|
||||
if (!pkgStack.Empty() ||
|
||||
tgt->Target->GetProperty("EXPORT_FIND_PACKAGE_NAME")) {
|
||||
this->ExternalTargets.emplace(tgt);
|
||||
}
|
||||
|
||||
if (tgt->IsImported()) {
|
||||
input = tgt->GetName();
|
||||
return true;
|
||||
@@ -862,12 +885,14 @@ void cmExportFileGenerator::SetImportDetailProperties(
|
||||
// Export IMPORTED_LINK_DEPENDENT_LIBRARIES to help consuming linkers
|
||||
// find private dependencies of shared libraries.
|
||||
std::size_t oldMissingTargetsSize = this->MissingTargets.size();
|
||||
auto oldExternalTargets = this->ExternalTargets;
|
||||
this->SetImportLinkProperty(
|
||||
suffix, target, "IMPORTED_LINK_DEPENDENT_LIBRARIES", iface->SharedDeps,
|
||||
properties, ImportLinkPropertyTargetNames::Yes);
|
||||
// Avoid enforcing shared library private dependencies as public package
|
||||
// dependencies by ignoring missing targets added for them.
|
||||
this->MissingTargets.resize(oldMissingTargetsSize);
|
||||
this->ExternalTargets = std::move(oldExternalTargets);
|
||||
|
||||
if (iface->Multiplicity > 0) {
|
||||
std::string prop =
|
||||
@@ -1157,6 +1182,73 @@ void cmExportFileGenerator::GenerateImportPropertyCode(
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
void cmExportFileGenerator::GenerateFindDependencyCalls(std::ostream& os)
|
||||
{
|
||||
os << "include(CMakeFindDependencyMacro)\n";
|
||||
std::map<std::string, cmExportSet::PackageDependency> packageDependencies;
|
||||
auto* exportSet = this->GetExportSet();
|
||||
if (exportSet) {
|
||||
packageDependencies = exportSet->GetPackageDependencies();
|
||||
}
|
||||
|
||||
for (cmGeneratorTarget const* gt : this->ExternalTargets) {
|
||||
std::string findPackageName;
|
||||
auto exportFindPackageName = gt->GetProperty("EXPORT_FIND_PACKAGE_NAME");
|
||||
cmFindPackageStack pkgStack = gt->Target->GetFindPackageStack();
|
||||
if (!exportFindPackageName.IsEmpty()) {
|
||||
findPackageName = *exportFindPackageName;
|
||||
} else {
|
||||
if (!pkgStack.Empty()) {
|
||||
cmFindPackageCall const& fpc = pkgStack.Top();
|
||||
findPackageName = fpc.Name;
|
||||
}
|
||||
}
|
||||
if (!findPackageName.empty()) {
|
||||
auto& dep = packageDependencies[findPackageName];
|
||||
if (!pkgStack.Empty()) {
|
||||
dep.FindPackageIndex = pkgStack.Top().Index;
|
||||
}
|
||||
if (dep.Enabled == cmExportSet::PackageDependencyExportEnabled::Auto) {
|
||||
dep.Enabled = cmExportSet::PackageDependencyExportEnabled::On;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::pair<std::string, cmExportSet::PackageDependency>>
|
||||
packageDependenciesSorted(packageDependencies.begin(),
|
||||
packageDependencies.end());
|
||||
std::sort(
|
||||
packageDependenciesSorted.begin(), packageDependenciesSorted.end(),
|
||||
[](const std::pair<std::string, cmExportSet::PackageDependency>& lhs,
|
||||
const std::pair<std::string, cmExportSet::PackageDependency>& rhs)
|
||||
-> bool {
|
||||
if (lhs.second.SpecifiedIndex) {
|
||||
if (rhs.second.SpecifiedIndex) {
|
||||
return lhs.second.SpecifiedIndex < rhs.second.SpecifiedIndex;
|
||||
}
|
||||
assert(rhs.second.FindPackageIndex);
|
||||
return true;
|
||||
}
|
||||
assert(lhs.second.FindPackageIndex);
|
||||
if (rhs.second.SpecifiedIndex) {
|
||||
return false;
|
||||
}
|
||||
assert(rhs.second.FindPackageIndex);
|
||||
return lhs.second.FindPackageIndex < rhs.second.FindPackageIndex;
|
||||
});
|
||||
|
||||
for (auto const& it : packageDependenciesSorted) {
|
||||
if (it.second.Enabled == cmExportSet::PackageDependencyExportEnabled::On) {
|
||||
os << "find_dependency(" << it.first << " REQUIRED";
|
||||
for (auto const& arg : it.second.ExtraArguments) {
|
||||
os << " " << cmOutputConverter::EscapeForCMake(arg);
|
||||
}
|
||||
os << ")\n";
|
||||
}
|
||||
}
|
||||
os << "\n\n";
|
||||
}
|
||||
|
||||
void cmExportFileGenerator::GenerateMissingTargetsCheckCode(std::ostream& os)
|
||||
{
|
||||
if (this->MissingTargets.empty()) {
|
||||
|
||||
Reference in New Issue
Block a user