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 | |
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')
-rw-r--r-- | Source/CMakeLists.txt | 2 | ||||
-rw-r--r-- | Source/cmExportBuildAndroidMKGenerator.h | 1 | ||||
-rw-r--r-- | Source/cmExportBuildFileGenerator.cxx | 2 | ||||
-rw-r--r-- | Source/cmExportBuildFileGenerator.h | 1 | ||||
-rw-r--r-- | Source/cmExportCommand.cxx | 74 | ||||
-rw-r--r-- | Source/cmExportFileGenerator.cxx | 148 | ||||
-rw-r--r-- | Source/cmExportFileGenerator.h | 23 | ||||
-rw-r--r-- | Source/cmExportInstallAndroidMKGenerator.cxx | 5 | ||||
-rw-r--r-- | Source/cmExportInstallAndroidMKGenerator.h | 3 | ||||
-rw-r--r-- | Source/cmExportInstallFileGenerator.cxx | 17 | ||||
-rw-r--r-- | Source/cmExportInstallFileGenerator.h | 8 | ||||
-rw-r--r-- | Source/cmExportSet.cxx | 11 | ||||
-rw-r--r-- | Source/cmExportSet.h | 28 | ||||
-rw-r--r-- | Source/cmFindPackageCommand.cxx | 2 | ||||
-rw-r--r-- | Source/cmFindPackageStack.cxx | 7 | ||||
-rw-r--r-- | Source/cmFindPackageStack.h | 33 | ||||
-rw-r--r-- | Source/cmInstallCommand.cxx | 7 | ||||
-rw-r--r-- | Source/cmInstallExportGenerator.cxx | 4 | ||||
-rw-r--r-- | Source/cmInstallExportGenerator.h | 4 | ||||
-rw-r--r-- | Source/cmMakefile.cxx | 35 | ||||
-rw-r--r-- | Source/cmMakefile.h | 18 | ||||
-rw-r--r-- | Source/cmTarget.cxx | 11 | ||||
-rw-r--r-- | Source/cmTarget.h | 4 |
23 files changed, 398 insertions, 50 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 1bc855e..13eade3 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -558,6 +558,8 @@ add_library( cmFindLibraryCommand.h cmFindPackageCommand.cxx cmFindPackageCommand.h + cmFindPackageStack.cxx + cmFindPackageStack.h cmFindPathCommand.cxx cmFindPathCommand.h cmFindProgramCommand.cxx diff --git a/Source/cmExportBuildAndroidMKGenerator.h b/Source/cmExportBuildAndroidMKGenerator.h index 7067488..8918ce1 100644 --- a/Source/cmExportBuildAndroidMKGenerator.h +++ b/Source/cmExportBuildAndroidMKGenerator.h @@ -55,6 +55,7 @@ protected: cmGeneratorTarget const* target, ImportPropertyMap const& properties) override; void GenerateMissingTargetsCheckCode(std::ostream& os) override; + void GenerateFindDependencyCalls(std::ostream&) override {} void GenerateInterfaceProperties( cmGeneratorTarget const* target, std::ostream& os, const ImportPropertyMap& properties) override; diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index bf3bb8b..eae3a74 100644 --- a/Source/cmExportBuildFileGenerator.cxx +++ b/Source/cmExportBuildFileGenerator.cxx @@ -76,7 +76,7 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) } if (generatedInterfaceRequired) { - this->GenerateRequiredCMakeVersion(os, "3.0.0"); + this->SetRequiredCMakeVersion(3, 0, 0); } this->GenerateExpectedTargetsCode(os, expectedTargets); } diff --git a/Source/cmExportBuildFileGenerator.h b/Source/cmExportBuildFileGenerator.h index 4636196..c5bb0df 100644 --- a/Source/cmExportBuildFileGenerator.h +++ b/Source/cmExportBuildFileGenerator.h @@ -90,6 +90,7 @@ protected: cmTargetExport* te) override; std::string GetFileSetFiles(cmGeneratorTarget* gte, cmFileSet* fileSet, cmTargetExport* te) override; + cmExportSet* GetExportSet() const override { return this->ExportSet; } std::string GetCxxModulesDirectory() const override; void GenerateCxxModuleConfigInformation(std::ostream&) const override; diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx index e78b869..cf1f4ad 100644 --- a/Source/cmExportCommand.cxx +++ b/Source/cmExportCommand.cxx @@ -8,6 +8,7 @@ #include <cm/memory> #include <cm/optional> +#include <cmext/algorithm> #include <cmext/string_view> #include "cmsys/RegularExpression.hxx" @@ -24,10 +25,12 @@ #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" +#include "cmRange.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" +#include "cmValue.h" #if defined(__HAIKU__) # include <FindDirectory.h> @@ -66,6 +69,9 @@ bool cmExportCommand(std::vector<std::string> const& args, std::string CxxModulesDirectory; bool Append = false; bool ExportOld = false; + + std::vector<std::vector<std::string>> PackageDependencyArgs; + bool ExportPackageDependencies = false; }; auto parser = @@ -75,7 +81,12 @@ bool cmExportCommand(std::vector<std::string> const& args, .Bind("CXX_MODULES_DIRECTORY"_s, &Arguments::CxxModulesDirectory); if (args[0] == "EXPORT") { - parser.Bind("EXPORT"_s, &Arguments::ExportSetName); + parser.Bind("EXPORT"_s, &Arguments::ExportSetName) + .Bind("EXPORT_PACKAGE_DEPENDENCIES"_s, + &Arguments::ExportPackageDependencies); + } else if (args[0] == "SETUP") { + parser.Bind("SETUP"_s, &Arguments::ExportSetName); + parser.Bind("PACKAGE_DEPENDENCY"_s, &Arguments::PackageDependencyArgs); } else { parser.Bind("TARGETS"_s, &Arguments::Targets); parser.Bind("ANDROID_MK"_s, &Arguments::AndroidMKFile); @@ -91,6 +102,66 @@ bool cmExportCommand(std::vector<std::string> const& args, return false; } + if (args[0] == "SETUP") { + cmMakefile& mf = status.GetMakefile(); + cmGlobalGenerator* gg = mf.GetGlobalGenerator(); + + cmExportSetMap& setMap = gg->GetExportSets(); + auto& exportSet = setMap[arguments.ExportSetName]; + + struct PackageDependencyArguments + { + std::string Enabled; + ArgumentParser::MaybeEmpty<std::vector<std::string>> ExtraArgs; + }; + + auto packageDependencyParser = + cmArgumentParser<PackageDependencyArguments>{} + .Bind("ENABLED"_s, &PackageDependencyArguments::Enabled) + .Bind("EXTRA_ARGS"_s, &PackageDependencyArguments::ExtraArgs); + + for (auto const& packageDependencyArgs : arguments.PackageDependencyArgs) { + if (packageDependencyArgs.empty()) { + continue; + } + + PackageDependencyArguments const packageDependencyArguments = + packageDependencyParser.Parse( + cmMakeRange(packageDependencyArgs).advance(1), &unknownArgs); + + if (!unknownArgs.empty()) { + status.SetError("Unknown argument: \"" + unknownArgs.front() + "\"."); + return false; + } + + auto& packageDependency = + exportSet.GetPackageDependencyForSetup(packageDependencyArgs.front()); + + if (!packageDependencyArguments.Enabled.empty()) { + if (packageDependencyArguments.Enabled == "AUTO") { + packageDependency.Enabled = + cmExportSet::PackageDependencyExportEnabled::Auto; + } else if (cmIsOff(packageDependencyArguments.Enabled)) { + packageDependency.Enabled = + cmExportSet::PackageDependencyExportEnabled::Off; + } else if (cmIsOn(packageDependencyArguments.Enabled)) { + packageDependency.Enabled = + cmExportSet::PackageDependencyExportEnabled::On; + } else { + status.SetError( + cmStrCat("Invalid enable setting for package dependency: \"", + packageDependencyArguments.Enabled, "\"")); + return false; + } + } + + cm::append(packageDependency.ExtraArguments, + packageDependencyArguments.ExtraArgs); + } + + return true; + } + std::string fname; bool android = false; if (!arguments.AndroidMKFile.empty()) { @@ -224,6 +295,7 @@ bool cmExportCommand(std::vector<std::string> const& args, ebfg->SetTargets(targets); } ebfg->SetExportOld(arguments.ExportOld); + ebfg->SetExportPackageDependencies(arguments.ExportPackageDependencies); // Compute the set of configurations exported. std::vector<std::string> configurationTypes = 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; + } +} diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h index f396e0e..ccc10d8 100644 --- a/Source/cmExportFileGenerator.h +++ b/Source/cmExportFileGenerator.h @@ -15,6 +15,7 @@ #include "cmVersion.h" #include "cmVersionConfig.h" +class cmExportSet; class cmFileSet; class cmGeneratorTarget; class cmLocalGenerator; @@ -61,6 +62,11 @@ public: error. */ bool GenerateImportFile(); + void SetExportPackageDependencies(bool exportPackageDependencies) + { + this->ExportPackageDependencies = exportPackageDependencies; + } + protected: using ImportPropertyMap = std::map<std::string, std::string>; @@ -88,6 +94,7 @@ protected: const std::set<std::string>& importedLocations); virtual void GenerateImportedFileCheckLoop(std::ostream& os); virtual void GenerateMissingTargetsCheckCode(std::ostream& os); + virtual void GenerateFindDependencyCalls(std::ostream& os); virtual void GenerateExpectedTargetsCode(std::ostream& os, const std::string& expectedTargets); @@ -173,9 +180,6 @@ protected: std::string& input, cmGeneratorTarget const* target, FreeTargetsReplace replace = NoReplaceFreeTargets); - virtual void GenerateRequiredCMakeVersion(std::ostream& os, - const char* versionString); - bool PopulateCxxModuleExportProperties( cmGeneratorTarget const* gte, ImportPropertyMap& properties, cmGeneratorExpression::PreprocessContext ctx, @@ -196,6 +200,11 @@ protected: cmFileSet* fileSet, cmTargetExport* te) = 0; + virtual cmExportSet* GetExportSet() const { return nullptr; } + + void SetRequiredCMakeVersion(unsigned int major, unsigned int minor, + unsigned int patch); + // The namespace in which the exports are placed in the generated file. std::string Namespace; @@ -216,6 +225,14 @@ protected: std::vector<std::string> MissingTargets; + std::set<cmGeneratorTarget const*> ExternalTargets; + + unsigned int RequiredCMakeVersionMajor = 2; + unsigned int RequiredCMakeVersionMinor = 8; + unsigned int RequiredCMakeVersionPatch = 3; + + bool ExportPackageDependencies = false; + private: void PopulateInterfaceProperty(const std::string&, const std::string&, cmGeneratorTarget const* target, diff --git a/Source/cmExportInstallAndroidMKGenerator.cxx b/Source/cmExportInstallAndroidMKGenerator.cxx index d53254d..7dfdc0e 100644 --- a/Source/cmExportInstallAndroidMKGenerator.cxx +++ b/Source/cmExportInstallAndroidMKGenerator.cxx @@ -110,11 +110,6 @@ void cmExportInstallAndroidMKGenerator::GenerateImportPrefix(std::ostream&) { } -void cmExportInstallAndroidMKGenerator::GenerateRequiredCMakeVersion( - std::ostream&, const char*) -{ -} - void cmExportInstallAndroidMKGenerator::CleanupTemporaryVariables( std::ostream&) { diff --git a/Source/cmExportInstallAndroidMKGenerator.h b/Source/cmExportInstallAndroidMKGenerator.h index 061358d..9454cdf 100644 --- a/Source/cmExportInstallAndroidMKGenerator.h +++ b/Source/cmExportInstallAndroidMKGenerator.h @@ -49,13 +49,12 @@ protected: cmGeneratorTarget const* target, ImportPropertyMap const& properties) override; void GenerateMissingTargetsCheckCode(std::ostream& os) override; + void GenerateFindDependencyCalls(std::ostream&) override {} void GenerateInterfaceProperties( cmGeneratorTarget const* target, std::ostream& os, const ImportPropertyMap& properties) override; void GenerateImportPrefix(std::ostream& os) override; void LoadConfigFiles(std::ostream&) override; - void GenerateRequiredCMakeVersion(std::ostream& os, - const char* versionString) override; void CleanupTemporaryVariables(std::ostream&) override; void GenerateImportedFileCheckLoop(std::ostream& os) override; void GenerateImportedFileChecksCode( diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx index a264f5e..b829edd 100644 --- a/Source/cmExportInstallFileGenerator.cxx +++ b/Source/cmExportInstallFileGenerator.cxx @@ -76,9 +76,6 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) // Compute the relative import prefix for the file this->GenerateImportPrefix(os); - bool require2_8_12 = false; - bool require3_0_0 = false; - bool require3_1_0 = false; bool requiresConfigFiles = false; // Create all the imported targets. for (cmTargetExport* te : allTargets) { @@ -147,16 +144,16 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) if (this->PopulateInterfaceLinkLibrariesProperty( gt, cmGeneratorExpression::InstallInterface, properties) && !this->ExportOld) { - require2_8_12 = true; + this->SetRequiredCMakeVersion(2, 8, 12); } } if (targetType == cmStateEnums::INTERFACE_LIBRARY) { - require3_0_0 = true; + this->SetRequiredCMakeVersion(3, 0, 0); } if (gt->GetProperty("INTERFACE_SOURCES")) { // We can only generate INTERFACE_SOURCES in CMake 3.3, but CMake 3.1 // can consume them. - require3_1_0 = true; + this->SetRequiredCMakeVersion(3, 1, 0); } this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE", gt, @@ -169,14 +166,6 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) this->GenerateTargetFileSets(gt, os, te); } - if (require3_1_0) { - this->GenerateRequiredCMakeVersion(os, "3.1.0"); - } else if (require3_0_0) { - this->GenerateRequiredCMakeVersion(os, "3.0.0"); - } else if (require2_8_12) { - this->GenerateRequiredCMakeVersion(os, "2.8.12"); - } - this->LoadConfigFiles(os); bool result = true; diff --git a/Source/cmExportInstallFileGenerator.h b/Source/cmExportInstallFileGenerator.h index e073a31..9de0c8e 100644 --- a/Source/cmExportInstallFileGenerator.h +++ b/Source/cmExportInstallFileGenerator.h @@ -12,12 +12,13 @@ #include <vector> #include "cmExportFileGenerator.h" +#include "cmInstallExportGenerator.h" #include "cmStateTypes.h" +class cmExportSet; class cmFileSet; class cmGeneratorTarget; class cmGlobalGenerator; -class cmInstallExportGenerator; class cmInstallTargetGenerator; class cmTargetExport; @@ -121,6 +122,11 @@ protected: void GenerateCxxModuleConfigInformation(std::ostream&) const override; bool GenerateImportCxxModuleConfigTargetInclusion(std::string const&); + cmExportSet* GetExportSet() const override + { + return this->IEGen->GetExportSet(); + } + cmInstallExportGenerator* IEGen; // The import file generated for each configuration. diff --git a/Source/cmExportSet.cxx b/Source/cmExportSet.cxx index c890168..aa32394 100644 --- a/Source/cmExportSet.cxx +++ b/Source/cmExportSet.cxx @@ -20,6 +20,17 @@ cmExportSet::cmExportSet(std::string name) cmExportSet::~cmExportSet() = default; +cmExportSet::PackageDependency& cmExportSet::GetPackageDependencyForSetup( + const std::string& name) +{ + auto& dep = this->PackageDependencies[name]; + if (!dep.SpecifiedIndex) { + dep.SpecifiedIndex = this->NextPackageDependencyIndex; + this->NextPackageDependencyIndex++; + } + return dep; +} + bool cmExportSet::Compute(cmLocalGenerator* lg) { for (std::unique_ptr<cmTargetExport>& tgtExport : this->TargetExports) { diff --git a/Source/cmExportSet.h b/Source/cmExportSet.h index b75a26d..c5fc91f 100644 --- a/Source/cmExportSet.h +++ b/Source/cmExportSet.h @@ -9,6 +9,8 @@ #include <string> #include <vector> +#include <cm/optional> + class cmInstallExportGenerator; class cmLocalGenerator; class cmTargetExport; @@ -43,10 +45,36 @@ public: return &this->Installations; } + enum class PackageDependencyExportEnabled + { + Auto, + Off, + On, + }; + + struct PackageDependency + { + PackageDependencyExportEnabled Enabled = + PackageDependencyExportEnabled::Auto; + std::vector<std::string> ExtraArguments; + cm::optional<unsigned int> SpecifiedIndex; + cm::optional<unsigned int> FindPackageIndex; + }; + + PackageDependency& GetPackageDependencyForSetup(const std::string& name); + + const std::map<std::string, PackageDependency>& GetPackageDependencies() + const + { + return this->PackageDependencies; + } + private: std::vector<std::unique_ptr<cmTargetExport>> TargetExports; std::string Name; std::vector<cmInstallExportGenerator const*> Installations; + std::map<std::string, PackageDependency> PackageDependencies; + unsigned int NextPackageDependencyIndex = 0; }; /// A name -> cmExportSet map with overloaded operator[]. diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx index 30458cd..9b51b1a 100644 --- a/Source/cmFindPackageCommand.cxx +++ b/Source/cmFindPackageCommand.cxx @@ -1044,6 +1044,8 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args) PushPopRootPathStack pushPopRootPathStack(*this); SetRestoreFindDefinitions setRestoreFindDefinitions(*this, components, componentVarDefs); + cmMakefile::FindPackageStackRAII findPackageStackRAII(this->Makefile, + this->Name); // See if we have been told to delegate to FetchContent or some other // redirected config package first. We have to check all names that diff --git a/Source/cmFindPackageStack.cxx b/Source/cmFindPackageStack.cxx new file mode 100644 index 0000000..1aeb2a7 --- /dev/null +++ b/Source/cmFindPackageStack.cxx @@ -0,0 +1,7 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#define cmFindPackageStack_cxx +#include "cmFindPackageStack.h" + +#include "cmConstStack.tcc" // IWYU pragma: keep +template class cmConstStack<cmFindPackageCall, cmFindPackageStack>; diff --git a/Source/cmFindPackageStack.h b/Source/cmFindPackageStack.h new file mode 100644 index 0000000..2062fbc --- /dev/null +++ b/Source/cmFindPackageStack.h @@ -0,0 +1,33 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#pragma once + +#include "cmConfigure.h" // IWYU pragma: keep + +#include <memory> +#include <string> + +#include "cmConstStack.h" + +/** + * Represents one call to find_package. + */ +class cmFindPackageCall +{ +public: + std::string Name; + unsigned int Index; +}; + +/** + * Represents a stack of find_package calls with efficient value semantics. + */ +class cmFindPackageStack + : public cmConstStack<cmFindPackageCall, cmFindPackageStack> +{ + using cmConstStack::cmConstStack; + friend class cmConstStack<cmFindPackageCall, cmFindPackageStack>; +}; +#ifndef cmFindPackageStack_cxx +extern template class cmConstStack<cmFindPackageCall, cmFindPackageStack>; +#endif diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index 0fc4011..e2755da 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -2030,7 +2030,7 @@ bool HandleExportAndroidMKMode(std::vector<std::string> const& args, cm::make_unique<cmInstallExportGenerator>( &exportSet, ica.GetDestination(), ica.GetPermissions(), ica.GetConfigurations(), ica.GetComponent(), message, - ica.GetExcludeFromAll(), fname, name_space, "", exportOld, true, + ica.GetExcludeFromAll(), fname, name_space, "", exportOld, true, false, helper.Makefile->GetBacktrace())); return true; @@ -2054,12 +2054,14 @@ bool HandleExportMode(std::vector<std::string> const& args, bool exportOld = false; std::string filename; std::string cxx_modules_directory; + bool exportPackageDependencies = false; ica.Bind("EXPORT"_s, exp); ica.Bind("NAMESPACE"_s, name_space); ica.Bind("EXPORT_LINK_INTERFACE_LIBRARIES"_s, exportOld); ica.Bind("FILE"_s, filename); ica.Bind("CXX_MODULES_DIRECTORY"_s, cxx_modules_directory); + ica.Bind("EXPORT_PACKAGE_DEPENDENCIES"_s, exportPackageDependencies); std::vector<std::string> unknownArgs; ica.Parse(args, &unknownArgs); @@ -2147,7 +2149,8 @@ bool HandleExportMode(std::vector<std::string> const& args, &exportSet, ica.GetDestination(), ica.GetPermissions(), ica.GetConfigurations(), ica.GetComponent(), message, ica.GetExcludeFromAll(), fname, name_space, cxx_modules_directory, - exportOld, false, helper.Makefile->GetBacktrace())); + exportOld, false, exportPackageDependencies, + helper.Makefile->GetBacktrace())); return true; } diff --git a/Source/cmInstallExportGenerator.cxx b/Source/cmInstallExportGenerator.cxx index 71d5471..72f0ac7 100644 --- a/Source/cmInstallExportGenerator.cxx +++ b/Source/cmInstallExportGenerator.cxx @@ -27,7 +27,7 @@ cmInstallExportGenerator::cmInstallExportGenerator( std::string const& component, MessageLevel message, bool exclude_from_all, std::string filename, std::string name_space, std::string cxx_modules_directory, bool exportOld, bool android, - cmListFileBacktrace backtrace) + bool exportPackageDependencies, cmListFileBacktrace backtrace) : cmInstallGenerator(destination, configurations, component, message, exclude_from_all, false, std::move(backtrace)) , ExportSet(exportSet) @@ -36,6 +36,7 @@ cmInstallExportGenerator::cmInstallExportGenerator( , Namespace(std::move(name_space)) , CxxModulesDirectory(std::move(cxx_modules_directory)) , ExportOld(exportOld) + , ExportPackageDependencies(exportPackageDependencies) { if (android) { #ifndef CMAKE_BOOTSTRAP @@ -119,6 +120,7 @@ void cmInstallExportGenerator::GenerateScript(std::ostream& os) this->EFGen->AddConfiguration(c); } } + this->EFGen->SetExportPackageDependencies(this->ExportPackageDependencies); this->EFGen->GenerateImportFile(); // Perform the main install script generation. diff --git a/Source/cmInstallExportGenerator.h b/Source/cmInstallExportGenerator.h index f2d4a05..5f92851 100644 --- a/Source/cmInstallExportGenerator.h +++ b/Source/cmInstallExportGenerator.h @@ -29,7 +29,8 @@ public: bool exclude_from_all, std::string filename, std::string name_space, std::string cxx_modules_directory, bool exportOld, - bool android, cmListFileBacktrace backtrace); + bool android, bool exportPackageDependencies, + cmListFileBacktrace backtrace); cmInstallExportGenerator(const cmInstallExportGenerator&) = delete; ~cmInstallExportGenerator() override; @@ -70,6 +71,7 @@ protected: std::string const Namespace; std::string const CxxModulesDirectory; bool const ExportOld; + bool const ExportPackageDependencies; cmLocalGenerator* LocalGenerator = nullptr; std::string TempDir; diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 9ed422d..e055a34 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -302,6 +302,11 @@ cmListFileBacktrace cmMakefile::GetBacktrace() const return this->Backtrace; } +cmFindPackageStack cmMakefile::GetFindPackageStack() const +{ + return this->FindPackageStack; +} + void cmMakefile::PrintCommandTrace(cmListFileFunction const& lff, cmListFileBacktrace const& bt, CommandMissingFromStack missing) const @@ -4771,6 +4776,36 @@ cmMakefile::MacroPushPop::~MacroPushPop() this->Makefile->PopMacroScope(this->ReportError); } +cmMakefile::FindPackageStackRAII::FindPackageStackRAII(cmMakefile* mf, + std::string const& name) + : Makefile(mf) +{ + this->Makefile->FindPackageStack = + this->Makefile->FindPackageStack.Push(cmFindPackageCall{ + name, + this->Makefile->FindPackageStackNextIndex, + }); + this->Makefile->FindPackageStackNextIndex++; +} + +cmMakefile::FindPackageStackRAII::~FindPackageStackRAII() +{ + this->Makefile->FindPackageStackNextIndex = + this->Makefile->FindPackageStack.Top().Index + 1; + this->Makefile->FindPackageStack = this->Makefile->FindPackageStack.Pop(); + + if (!this->Makefile->FindPackageStack.Empty()) { + auto top = this->Makefile->FindPackageStack.Top(); + this->Makefile->FindPackageStack = this->Makefile->FindPackageStack.Pop(); + + top.Index = this->Makefile->FindPackageStackNextIndex; + this->Makefile->FindPackageStackNextIndex++; + + this->Makefile->FindPackageStack = + this->Makefile->FindPackageStack.Push(top); + } +} + cmMakefile::DebugFindPkgRAII::DebugFindPkgRAII(cmMakefile* mf, std::string const& pkg) : Makefile(mf) diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 24daa72..e5edbae 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -25,6 +25,7 @@ #include "cmAlgorithms.h" #include "cmCustomCommand.h" +#include "cmFindPackageStack.h" #include "cmFunctionBlocker.h" #include "cmListFileCache.h" #include "cmMessageType.h" // IWYU pragma: keep @@ -660,6 +661,11 @@ public: cmListFileBacktrace GetBacktrace() const; /** + * Get the current stack of find_package calls. + */ + cmFindPackageStack GetFindPackageStack() const; + + /** * Get the vector of files created by this makefile */ const std::vector<std::string>& GetOutputFiles() const @@ -1020,6 +1026,15 @@ public: // searches std::deque<std::vector<std::string>> FindPackageRootPathStack; + class FindPackageStackRAII + { + cmMakefile* Makefile; + + public: + FindPackageStackRAII(cmMakefile* mf, std::string const& pkg); + ~FindPackageStackRAII(); + }; + class DebugFindPkgRAII { cmMakefile* Makefile; @@ -1210,6 +1225,9 @@ private: std::vector<BT<GeneratorAction>> GeneratorActions; bool GeneratorActionsInvoked = false; + cmFindPackageStack FindPackageStack; + unsigned int FindPackageStackNextIndex = 0; + bool DebugFindPkg = false; bool CheckSystemVars; diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index d93f658..e373319 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -20,6 +20,7 @@ #include "cmAlgorithms.h" #include "cmCustomCommand.h" #include "cmFileSet.h" +#include "cmFindPackageStack.h" #include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" @@ -585,6 +586,7 @@ TargetProperty const StaticTargetProperties[] = { // Usage requirement properties { "LINK_INTERFACE_LIBRARIES"_s, IC::CanCompileSources }, { "MAP_IMPORTED_CONFIG_"_s, IC::NormalTarget, R::PerConfig }, + { "EXPORT_FIND_PACKAGE_NAME"_s, IC::NormalTarget }, // Metadata { "CROSSCOMPILING_EMULATOR"_s, IC::ExecutableTarget }, @@ -661,6 +663,7 @@ public: TLLCommands; std::map<std::string, cmFileSet> FileSets; cmListFileBacktrace Backtrace; + cmFindPackageStack FindPackageStack; UsageRequirementProperty IncludeDirectories; UsageRequirementProperty CompileOptions; @@ -961,6 +964,9 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, // Save the backtrace of target construction. this->impl->Backtrace = this->impl->Makefile->GetBacktrace(); + if (this->impl->IsImported()) { + this->impl->FindPackageStack = this->impl->Makefile->GetFindPackageStack(); + } if (this->IsNormal()) { // Initialize the INCLUDE_DIRECTORIES property based on the current value @@ -1248,6 +1254,11 @@ cmListFileBacktrace const& cmTarget::GetBacktrace() const return this->impl->Backtrace; } +cmFindPackageStack const& cmTarget::GetFindPackageStack() const +{ + return this->impl->FindPackageStack; +} + bool cmTarget::IsExecutableWithExports() const { return (this->GetType() == cmStateEnums::EXECUTABLE && diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 584856a..385dfe7 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -24,6 +24,7 @@ class cmCustomCommand; class cmFileSet; +class cmFindPackageStack; class cmGlobalGenerator; class cmInstallTargetGenerator; class cmMakefile; @@ -239,6 +240,9 @@ public: //! Get a backtrace from the creation of the target. cmListFileBacktrace const& GetBacktrace() const; + //! Get a find_package call stack from the creation of the target. + cmFindPackageStack const& GetFindPackageStack() const; + void InsertInclude(BT<std::string> const& entry, bool before = false); void InsertCompileOption(BT<std::string> const& entry, bool before = false); void InsertCompileDefinition(BT<std::string> const& entry); |