diff options
author | Brad King <brad.king@kitware.com> | 2023-11-14 14:21:59 (GMT) |
---|---|---|
committer | Kitware Robot <kwrobot@kitware.com> | 2023-11-14 14:22:13 (GMT) |
commit | f22ecbacb6824881e755b19f498607793e19969c (patch) | |
tree | 5dfbeca647aac3bea51e5152d81ee3aa461bd81b /Source/cmExportFileGenerator.cxx | |
parent | 9b36209698819ec9f57c399d00c7a93105430cf2 (diff) | |
parent | 0ad8fc5a63835e477b4d70b44ac34fab4aeb96dc (diff) | |
download | CMake-f22ecbacb6824881e755b19f498607793e19969c.zip CMake-f22ecbacb6824881e755b19f498607793e19969c.tar.gz CMake-f22ecbacb6824881e755b19f498607793e19969c.tar.bz2 |
Merge topic 'export-find_dependency-calls'
0ad8fc5a63 FetchContent: Set CMAKE_EXPORT_FIND_PACKAGE_NAME
c6e6861e63 install(EXPORT): Export find_dependency() calls
2837f592ab cmExportFileGenerator: Add function to set required CMake version
e62a3b8625 Help/export: Add signature directives
Acked-by: Kitware Robot <kwrobot@kitware.com>
Acked-by: Brad King <brad.king@kitware.com>
Acked-by: Jason Juang <jasjuang@gmail.com>
Merge-request: !8957
Diffstat (limited to 'Source/cmExportFileGenerator.cxx')
-rw-r--r-- | Source/cmExportFileGenerator.cxx | 148 |
1 files changed, 129 insertions, 19 deletions
diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index bd87e11..205bf08 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -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" @@ -30,6 +34,7 @@ #include "cmSystemTools.h" #include "cmTarget.h" #include "cmValue.h" +#include "cmVersion.h" static std::string cmExportFileGeneratorEscape(std::string const& str) { @@ -93,17 +98,35 @@ bool cmExportFileGenerator::GenerateImportFile() return false; } std::ostream& os = *foutPtr; + std::stringstream mainFileWithHeadersAndFootersBuffer; // Start with the import file header. - this->GeneratePolicyHeaderCode(os); - this->GenerateImportHeaderCode(os); + this->GenerateImportHeaderCode(mainFileWithHeadersAndFootersBuffer); // Create all the imported targets. - bool result = this->GenerateMainFile(os); + 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(os); - this->GeneratePolicyFooterCode(os); + this->GenerateImportFooterCode(mainFileWithHeadersAndFootersBuffer); + this->GeneratePolicyFooterCode(mainFileWithHeadersAndFootersBuffer); + + // This has to be done last, after the minimum CMake version has been + // determined. + this->GeneratePolicyHeaderCode(os); + os << mainFileWithHeadersAndFootersBuffer.rdbuf(); return result; } @@ -156,17 +179,6 @@ void cmExportFileGenerator::PopulateInterfaceProperty( } } -void cmExportFileGenerator::GenerateRequiredCMakeVersion( - std::ostream& os, const char* versionString) -{ - /* clang-format off */ - os << "if(CMAKE_VERSION VERSION_LESS " << versionString << ")\n" - " message(FATAL_ERROR \"This file relies on consumers using " - "CMake " << versionString << " or greater.\")\n" - "endif()\n\n"; - /* clang-format on */ -} - bool cmExportFileGenerator::PopulateInterfaceLinkLibrariesProperty( cmGeneratorTarget const* target, cmGeneratorExpression::PreprocessContext preprocessRule, @@ -620,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; @@ -867,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 = @@ -953,8 +973,14 @@ void cmExportFileGenerator::GeneratePolicyHeaderCode(std::ostream& os) os << "if(\"${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}\" LESS 2.8)\n" << " message(FATAL_ERROR \"CMake >= 2.8.0 required\")\n" << "endif()\n" - << "if(CMAKE_VERSION VERSION_LESS \"2.8.3\")\n" - << " message(FATAL_ERROR \"CMake >= 2.8.3 required\")\n" + << "if(CMAKE_VERSION VERSION_LESS \"" + << this->RequiredCMakeVersionMajor << '.' + << this->RequiredCMakeVersionMinor << '.' + << this->RequiredCMakeVersionPatch << "\")\n" + << " message(FATAL_ERROR \"CMake >= " + << this->RequiredCMakeVersionMajor << '.' + << this->RequiredCMakeVersionMinor << '.' + << this->RequiredCMakeVersionPatch << " required\")\n" << "endif()\n"; /* clang-format on */ @@ -966,7 +992,10 @@ void cmExportFileGenerator::GeneratePolicyHeaderCode(std::ostream& os) // versions. /* clang-format off */ os << "cmake_policy(PUSH)\n" - << "cmake_policy(VERSION 2.8.3...3.27)\n"; + << "cmake_policy(VERSION " + << this->RequiredCMakeVersionMajor << '.' + << this->RequiredCMakeVersionMinor << '.' + << this->RequiredCMakeVersionPatch << "...3.27)\n"; /* clang-format on */ } @@ -1153,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()) { @@ -1485,3 +1581,17 @@ void cmExportFileGenerator::GenerateCxxModuleInformation(std::ostream& os) this->GenerateCxxModuleConfigInformation(ap); } + +void cmExportFileGenerator::SetRequiredCMakeVersion(unsigned int major, + unsigned int minor, + unsigned int patch) +{ + if (CMake_VERSION_ENCODE(major, minor, patch) > + CMake_VERSION_ENCODE(this->RequiredCMakeVersionMajor, + this->RequiredCMakeVersionMinor, + this->RequiredCMakeVersionPatch)) { + this->RequiredCMakeVersionMajor = major; + this->RequiredCMakeVersionMinor = minor; + this->RequiredCMakeVersionPatch = patch; + } +} |