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:
Kyle Edwards
2023-11-07 11:44:00 -05:00
parent 2837f592ab
commit c6e6861e63
53 changed files with 700 additions and 10 deletions
+54 -1
View File
@@ -15,6 +15,7 @@ Synopsis
export(`TARGETS`_ <target>... [...]) export(`TARGETS`_ <target>... [...])
export(`EXPORT`_ <export-name> [...]) export(`EXPORT`_ <export-name> [...])
export(`PACKAGE`_ <PackageName>) export(`PACKAGE`_ <PackageName>)
export(`SETUP`_ <export-name> [...])
Exporting Targets Exporting Targets
^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^
@@ -108,7 +109,7 @@ Exporting Targets matching install(EXPORT)
.. code-block:: cmake .. code-block:: cmake
export(EXPORT <export-name> [NAMESPACE <namespace>] [FILE <filename>] export(EXPORT <export-name> [NAMESPACE <namespace>] [FILE <filename>]
[CXX_MODULES_DIRECTORY <directory>]) [CXX_MODULES_DIRECTORY <directory>] [EXPORT_PACKAGE_DEPENDENCIES])
Creates a file ``<filename>`` that may be included by outside projects to Creates a file ``<filename>`` that may be included by outside projects to
import targets from the current project's build tree. This is the same import targets from the current project's build tree. This is the same
@@ -118,6 +119,12 @@ the installation export ``<export-name>``. Target installations may be
associated with the export ``<export-name>`` using the ``EXPORT`` option associated with the export ``<export-name>`` using the ``EXPORT`` option
of the :command:`install(TARGETS)` command. of the :command:`install(TARGETS)` command.
``EXPORT_PACKAGE_DEPENDENCIES``
.. versionadded:: 3.29
Specify that :command:`find_dependency` calls should be exported. See
:command:`install(EXPORT)` for details on how this works.
Exporting Packages Exporting Packages
^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^
@@ -149,3 +156,49 @@ registry.
outside the source and build trees. Set the outside the source and build trees. Set the
:variable:`CMAKE_EXPORT_PACKAGE_REGISTRY` variable to add build directories :variable:`CMAKE_EXPORT_PACKAGE_REGISTRY` variable to add build directories
to the CMake user package registry. to the CMake user package registry.
Configuring Exports
^^^^^^^^^^^^^^^^^^^
.. signature::
export(SETUP <export-name> [...])
.. code-block:: cmake
export(SETUP <export-name>
[PACKAGE_DEPENDENCY <dep>
[ENABLED (<bool-true>|<bool-false>|AUTO)]
[EXTRA_ARGS <args>...]
] [...]
)
.. versionadded:: 3.29
Configure the parameters of an export. The arguments are as follows:
``PACKAGE_DEPENDENCY <dep>``
Specify a package dependency to configure. This changes how
:command:`find_dependency` calls are written during
:command:`export(EXPORT)` and :command:`install(EXPORT)`. ``<dep>`` is the
name of a package to export. This argument accepts the following additional
arguments:
``ENABLED``
Manually control whether or not the dependency is exported. This accepts
the following values:
``<bool-true>``
Any value that CMake recognizes as "true". Always export the dependency,
even if no exported targets depend on it. This can be used to manually
add :command:`find_dependency` calls to the export.
``<bool-false>``
Any value that CMake recognizes as "false". Never export the dependency,
even if an exported target depends on it.
``AUTO``
Only export the dependency if an exported target depends on it.
``EXTRA_ARGS <args>``
Specify additional arguments to pass to :command:`find_dependency` after
the ``REQUIRED`` argument.
+30 -1
View File
@@ -784,7 +784,8 @@ Signatures
[CXX_MODULES_DIRECTORY <directory>] [CXX_MODULES_DIRECTORY <directory>]
[EXPORT_LINK_INTERFACE_LIBRARIES] [EXPORT_LINK_INTERFACE_LIBRARIES]
[COMPONENT <component>] [COMPONENT <component>]
[EXCLUDE_FROM_ALL]) [EXCLUDE_FROM_ALL]
[EXPORT_PACKAGE_DEPENDENCIES])
install(EXPORT_ANDROID_MK <export-name> DESTINATION <dir> [...]) install(EXPORT_ANDROID_MK <export-name> DESTINATION <dir> [...])
The ``EXPORT`` form generates and installs a CMake file containing code to The ``EXPORT`` form generates and installs a CMake file containing code to
@@ -848,6 +849,34 @@ Signatures
without this information, none of the C++ modules which are part of the without this information, none of the C++ modules which are part of the
targets in the export set will support being imported in consuming targets. targets in the export set will support being imported in consuming targets.
``EXPORT_PACKAGE_DEPENDENCIES``
.. versionadded:: 3.29
Specify that :command:`find_dependency` calls should be exported. If this
argument is specified, CMake examines all targets in the export set and
gathers their ``INTERFACE`` link targets. If any such targets either were
found with :command:`find_package` or have the
:prop_tgt:`EXPORT_FIND_PACKAGE_NAME` property set, and such package
dependency was not disabled by passing ``ENABLED OFF`` to
:command:`export(SETUP)`, then a :command:`find_dependency` call is
written with the target's corresponding package name, a ``REQUIRED``
argument, and any additional arguments specified by the ``EXTRA_ARGS``
argument of :command:`export(SETUP)`. Any package dependencies that were
manually specified by passing ``ENABLED ON`` to :command:`export(SETUP)`
are also added, even if the exported targets don't depend on any targets
from them.
The :command:`find_dependency` calls are written in the following order:
1. Any package dependencies that were listed in :command:`export(SETUP)`
are written in the order they were first specified, regardless of
whether or not they contain ``INTERFACE`` dependencies of the
exported targets.
2. Any package dependencies that contain ``INTERFACE`` link dependencies
of the exported targets and that were never specified in
:command:`export(SETUP)` are written in the order they were first
found.
The ``EXPORT`` form is useful to help outside projects use targets built The ``EXPORT`` form is useful to help outside projects use targets built
and installed by the current project. For example, the code and installed by the current project. For example, the code
+1
View File
@@ -211,6 +211,7 @@ Properties on Targets
/prop_tgt/EXCLUDE_FROM_DEFAULT_BUILD /prop_tgt/EXCLUDE_FROM_DEFAULT_BUILD
/prop_tgt/EXCLUDE_FROM_DEFAULT_BUILD_CONFIG /prop_tgt/EXCLUDE_FROM_DEFAULT_BUILD_CONFIG
/prop_tgt/EXPORT_COMPILE_COMMANDS /prop_tgt/EXPORT_COMPILE_COMMANDS
/prop_tgt/EXPORT_FIND_PACKAGE_NAME
/prop_tgt/EXPORT_NAME /prop_tgt/EXPORT_NAME
/prop_tgt/EXPORT_NO_SYSTEM /prop_tgt/EXPORT_NO_SYSTEM
/prop_tgt/EXPORT_PROPERTIES /prop_tgt/EXPORT_PROPERTIES
+1
View File
@@ -444,6 +444,7 @@ Variables that Control the Build
/variable/CMAKE_EXE_LINKER_FLAGS_CONFIG /variable/CMAKE_EXE_LINKER_FLAGS_CONFIG
/variable/CMAKE_EXE_LINKER_FLAGS_CONFIG_INIT /variable/CMAKE_EXE_LINKER_FLAGS_CONFIG_INIT
/variable/CMAKE_EXE_LINKER_FLAGS_INIT /variable/CMAKE_EXE_LINKER_FLAGS_INIT
/variable/CMAKE_EXPORT_FIND_PACKAGE_NAME
/variable/CMAKE_FOLDER /variable/CMAKE_FOLDER
/variable/CMAKE_Fortran_FORMAT /variable/CMAKE_Fortran_FORMAT
/variable/CMAKE_Fortran_MODULE_DIRECTORY /variable/CMAKE_Fortran_MODULE_DIRECTORY
@@ -0,0 +1,12 @@
EXPORT_FIND_PACKAGE_NAME
------------------------
.. versionadded:: 3.29
Control the package name associated with a dependency target when exporting a
:command:`find_dependency` call in :command:`install(EXPORT)` or
:command:`export(EXPORT)`. This can be used to assign a package name to a
package that is built by CMake and exported, or to override the package in the
:command:`find_package` call that created the target.
This property is initialized by :variable:`CMAKE_EXPORT_FIND_PACKAGE_NAME`.
@@ -0,0 +1,14 @@
export-find_dependency-calls
----------------------------
* :command:`install(EXPORT)` and :command:`export(EXPORT)` learned a new
``EXPORT_PACKAGE_DEPENDENCIES`` argument, which can be used to generate
:command:`find_dependency` calls based on what targets the exported targets
depend on.
* A new :command:`export(SETUP)` signature was created to configure export
sets. This can be used to configure how :command:`find_dependency` calls are
exported.
* A new :prop_tgt:`EXPORT_FIND_PACKAGE_NAME` target property was created to
allow targets to specify what package name to pass when exporting
:command:`find_dependency` calls. This property is initialized with a new
:variable:`CMAKE_EXPORT_FIND_PACKAGE_NAME` variable.
@@ -0,0 +1,6 @@
CMAKE_EXPORT_FIND_PACKAGE_NAME
------------------------------
.. versionadded:: 3.29
Initializes the value of :prop_tgt:`EXPORT_FIND_PACKAGE_NAME`.
+2
View File
@@ -558,6 +558,8 @@ add_library(
cmFindLibraryCommand.h cmFindLibraryCommand.h
cmFindPackageCommand.cxx cmFindPackageCommand.cxx
cmFindPackageCommand.h cmFindPackageCommand.h
cmFindPackageStack.cxx
cmFindPackageStack.h
cmFindPathCommand.cxx cmFindPathCommand.cxx
cmFindPathCommand.h cmFindPathCommand.h
cmFindProgramCommand.cxx cmFindProgramCommand.cxx
+1
View File
@@ -55,6 +55,7 @@ protected:
cmGeneratorTarget const* target, cmGeneratorTarget const* target,
ImportPropertyMap const& properties) override; ImportPropertyMap const& properties) override;
void GenerateMissingTargetsCheckCode(std::ostream& os) override; void GenerateMissingTargetsCheckCode(std::ostream& os) override;
void GenerateFindDependencyCalls(std::ostream&) override {}
void GenerateInterfaceProperties( void GenerateInterfaceProperties(
cmGeneratorTarget const* target, std::ostream& os, cmGeneratorTarget const* target, std::ostream& os,
const ImportPropertyMap& properties) override; const ImportPropertyMap& properties) override;
+1
View File
@@ -90,6 +90,7 @@ protected:
cmTargetExport* te) override; cmTargetExport* te) override;
std::string GetFileSetFiles(cmGeneratorTarget* gte, cmFileSet* fileSet, std::string GetFileSetFiles(cmGeneratorTarget* gte, cmFileSet* fileSet,
cmTargetExport* te) override; cmTargetExport* te) override;
cmExportSet* GetExportSet() const override { return this->ExportSet; }
std::string GetCxxModulesDirectory() const override; std::string GetCxxModulesDirectory() const override;
void GenerateCxxModuleConfigInformation(std::ostream&) const override; void GenerateCxxModuleConfigInformation(std::ostream&) const override;
+73 -1
View File
@@ -8,6 +8,7 @@
#include <cm/memory> #include <cm/memory>
#include <cm/optional> #include <cm/optional>
#include <cmext/algorithm>
#include <cmext/string_view> #include <cmext/string_view>
#include "cmsys/RegularExpression.hxx" #include "cmsys/RegularExpression.hxx"
@@ -24,10 +25,12 @@
#include "cmMakefile.h" #include "cmMakefile.h"
#include "cmMessageType.h" #include "cmMessageType.h"
#include "cmPolicies.h" #include "cmPolicies.h"
#include "cmRange.h"
#include "cmStateTypes.h" #include "cmStateTypes.h"
#include "cmStringAlgorithms.h" #include "cmStringAlgorithms.h"
#include "cmSystemTools.h" #include "cmSystemTools.h"
#include "cmTarget.h" #include "cmTarget.h"
#include "cmValue.h"
#if defined(__HAIKU__) #if defined(__HAIKU__)
# include <FindDirectory.h> # include <FindDirectory.h>
@@ -66,6 +69,9 @@ bool cmExportCommand(std::vector<std::string> const& args,
std::string CxxModulesDirectory; std::string CxxModulesDirectory;
bool Append = false; bool Append = false;
bool ExportOld = false; bool ExportOld = false;
std::vector<std::vector<std::string>> PackageDependencyArgs;
bool ExportPackageDependencies = false;
}; };
auto parser = auto parser =
@@ -75,7 +81,12 @@ bool cmExportCommand(std::vector<std::string> const& args,
.Bind("CXX_MODULES_DIRECTORY"_s, &Arguments::CxxModulesDirectory); .Bind("CXX_MODULES_DIRECTORY"_s, &Arguments::CxxModulesDirectory);
if (args[0] == "EXPORT") { 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 { } else {
parser.Bind("TARGETS"_s, &Arguments::Targets); parser.Bind("TARGETS"_s, &Arguments::Targets);
parser.Bind("ANDROID_MK"_s, &Arguments::AndroidMKFile); parser.Bind("ANDROID_MK"_s, &Arguments::AndroidMKFile);
@@ -91,6 +102,66 @@ bool cmExportCommand(std::vector<std::string> const& args,
return false; 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; std::string fname;
bool android = false; bool android = false;
if (!arguments.AndroidMKFile.empty()) { if (!arguments.AndroidMKFile.empty()) {
@@ -224,6 +295,7 @@ bool cmExportCommand(std::vector<std::string> const& args,
ebfg->SetTargets(targets); ebfg->SetTargets(targets);
} }
ebfg->SetExportOld(arguments.ExportOld); ebfg->SetExportOld(arguments.ExportOld);
ebfg->SetExportPackageDependencies(arguments.ExportPackageDependencies);
// Compute the set of configurations exported. // Compute the set of configurations exported.
std::vector<std::string> configurationTypes = std::vector<std::string> configurationTypes =
+93 -1
View File
@@ -2,6 +2,7 @@
file Copyright.txt or https://cmake.org/licensing for details. */ file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmExportFileGenerator.h" #include "cmExportFileGenerator.h"
#include <algorithm>
#include <array> #include <array>
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
@@ -9,12 +10,15 @@
#include <utility> #include <utility>
#include <cm/memory> #include <cm/memory>
#include <cm/optional>
#include <cmext/string_view> #include <cmext/string_view>
#include "cmsys/FStream.hxx" #include "cmsys/FStream.hxx"
#include "cmComputeLinkInformation.h" #include "cmComputeLinkInformation.h"
#include "cmExportSet.h"
#include "cmFileSet.h" #include "cmFileSet.h"
#include "cmFindPackageStack.h"
#include "cmGeneratedFileStream.h" #include "cmGeneratedFileStream.h"
#include "cmGeneratorTarget.h" #include "cmGeneratorTarget.h"
#include "cmLinkItem.h" #include "cmLinkItem.h"
@@ -100,7 +104,20 @@ bool cmExportFileGenerator::GenerateImportFile()
this->GenerateImportHeaderCode(mainFileWithHeadersAndFootersBuffer); this->GenerateImportHeaderCode(mainFileWithHeadersAndFootersBuffer);
// Create all the imported targets. // 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. // End with the import file footer.
this->GenerateImportFooterCode(mainFileWithHeadersAndFootersBuffer); this->GenerateImportFooterCode(mainFileWithHeadersAndFootersBuffer);
@@ -615,6 +632,12 @@ bool cmExportFileGenerator::AddTargetNamespace(std::string& input,
return false; 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()) { if (tgt->IsImported()) {
input = tgt->GetName(); input = tgt->GetName();
return true; return true;
@@ -862,12 +885,14 @@ void cmExportFileGenerator::SetImportDetailProperties(
// Export IMPORTED_LINK_DEPENDENT_LIBRARIES to help consuming linkers // Export IMPORTED_LINK_DEPENDENT_LIBRARIES to help consuming linkers
// find private dependencies of shared libraries. // find private dependencies of shared libraries.
std::size_t oldMissingTargetsSize = this->MissingTargets.size(); std::size_t oldMissingTargetsSize = this->MissingTargets.size();
auto oldExternalTargets = this->ExternalTargets;
this->SetImportLinkProperty( this->SetImportLinkProperty(
suffix, target, "IMPORTED_LINK_DEPENDENT_LIBRARIES", iface->SharedDeps, suffix, target, "IMPORTED_LINK_DEPENDENT_LIBRARIES", iface->SharedDeps,
properties, ImportLinkPropertyTargetNames::Yes); properties, ImportLinkPropertyTargetNames::Yes);
// Avoid enforcing shared library private dependencies as public package // Avoid enforcing shared library private dependencies as public package
// dependencies by ignoring missing targets added for them. // dependencies by ignoring missing targets added for them.
this->MissingTargets.resize(oldMissingTargetsSize); this->MissingTargets.resize(oldMissingTargetsSize);
this->ExternalTargets = std::move(oldExternalTargets);
if (iface->Multiplicity > 0) { if (iface->Multiplicity > 0) {
std::string prop = std::string prop =
@@ -1157,6 +1182,73 @@ void cmExportFileGenerator::GenerateImportPropertyCode(
<< "\n"; << "\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) void cmExportFileGenerator::GenerateMissingTargetsCheckCode(std::ostream& os)
{ {
if (this->MissingTargets.empty()) { if (this->MissingTargets.empty()) {
+13
View File
@@ -15,6 +15,7 @@
#include "cmVersion.h" #include "cmVersion.h"
#include "cmVersionConfig.h" #include "cmVersionConfig.h"
class cmExportSet;
class cmFileSet; class cmFileSet;
class cmGeneratorTarget; class cmGeneratorTarget;
class cmLocalGenerator; class cmLocalGenerator;
@@ -61,6 +62,11 @@ public:
error. */ error. */
bool GenerateImportFile(); bool GenerateImportFile();
void SetExportPackageDependencies(bool exportPackageDependencies)
{
this->ExportPackageDependencies = exportPackageDependencies;
}
protected: protected:
using ImportPropertyMap = std::map<std::string, std::string>; using ImportPropertyMap = std::map<std::string, std::string>;
@@ -88,6 +94,7 @@ protected:
const std::set<std::string>& importedLocations); const std::set<std::string>& importedLocations);
virtual void GenerateImportedFileCheckLoop(std::ostream& os); virtual void GenerateImportedFileCheckLoop(std::ostream& os);
virtual void GenerateMissingTargetsCheckCode(std::ostream& os); virtual void GenerateMissingTargetsCheckCode(std::ostream& os);
virtual void GenerateFindDependencyCalls(std::ostream& os);
virtual void GenerateExpectedTargetsCode(std::ostream& os, virtual void GenerateExpectedTargetsCode(std::ostream& os,
const std::string& expectedTargets); const std::string& expectedTargets);
@@ -193,6 +200,8 @@ protected:
cmFileSet* fileSet, cmFileSet* fileSet,
cmTargetExport* te) = 0; cmTargetExport* te) = 0;
virtual cmExportSet* GetExportSet() const { return nullptr; }
void SetRequiredCMakeVersion(unsigned int major, unsigned int minor, void SetRequiredCMakeVersion(unsigned int major, unsigned int minor,
unsigned int patch); unsigned int patch);
@@ -216,10 +225,14 @@ protected:
std::vector<std::string> MissingTargets; std::vector<std::string> MissingTargets;
std::set<cmGeneratorTarget const*> ExternalTargets;
unsigned int RequiredCMakeVersionMajor = 2; unsigned int RequiredCMakeVersionMajor = 2;
unsigned int RequiredCMakeVersionMinor = 8; unsigned int RequiredCMakeVersionMinor = 8;
unsigned int RequiredCMakeVersionPatch = 3; unsigned int RequiredCMakeVersionPatch = 3;
bool ExportPackageDependencies = false;
private: private:
void PopulateInterfaceProperty(const std::string&, const std::string&, void PopulateInterfaceProperty(const std::string&, const std::string&,
cmGeneratorTarget const* target, cmGeneratorTarget const* target,
@@ -49,6 +49,7 @@ protected:
cmGeneratorTarget const* target, cmGeneratorTarget const* target,
ImportPropertyMap const& properties) override; ImportPropertyMap const& properties) override;
void GenerateMissingTargetsCheckCode(std::ostream& os) override; void GenerateMissingTargetsCheckCode(std::ostream& os) override;
void GenerateFindDependencyCalls(std::ostream&) override {}
void GenerateInterfaceProperties( void GenerateInterfaceProperties(
cmGeneratorTarget const* target, std::ostream& os, cmGeneratorTarget const* target, std::ostream& os,
const ImportPropertyMap& properties) override; const ImportPropertyMap& properties) override;
+7 -1
View File
@@ -12,12 +12,13 @@
#include <vector> #include <vector>
#include "cmExportFileGenerator.h" #include "cmExportFileGenerator.h"
#include "cmInstallExportGenerator.h"
#include "cmStateTypes.h" #include "cmStateTypes.h"
class cmExportSet;
class cmFileSet; class cmFileSet;
class cmGeneratorTarget; class cmGeneratorTarget;
class cmGlobalGenerator; class cmGlobalGenerator;
class cmInstallExportGenerator;
class cmInstallTargetGenerator; class cmInstallTargetGenerator;
class cmTargetExport; class cmTargetExport;
@@ -121,6 +122,11 @@ protected:
void GenerateCxxModuleConfigInformation(std::ostream&) const override; void GenerateCxxModuleConfigInformation(std::ostream&) const override;
bool GenerateImportCxxModuleConfigTargetInclusion(std::string const&); bool GenerateImportCxxModuleConfigTargetInclusion(std::string const&);
cmExportSet* GetExportSet() const override
{
return this->IEGen->GetExportSet();
}
cmInstallExportGenerator* IEGen; cmInstallExportGenerator* IEGen;
// The import file generated for each configuration. // The import file generated for each configuration.
+11
View File
@@ -20,6 +20,17 @@ cmExportSet::cmExportSet(std::string name)
cmExportSet::~cmExportSet() = default; 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) bool cmExportSet::Compute(cmLocalGenerator* lg)
{ {
for (std::unique_ptr<cmTargetExport>& tgtExport : this->TargetExports) { for (std::unique_ptr<cmTargetExport>& tgtExport : this->TargetExports) {
+28
View File
@@ -9,6 +9,8 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <cm/optional>
class cmInstallExportGenerator; class cmInstallExportGenerator;
class cmLocalGenerator; class cmLocalGenerator;
class cmTargetExport; class cmTargetExport;
@@ -43,10 +45,36 @@ public:
return &this->Installations; 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: private:
std::vector<std::unique_ptr<cmTargetExport>> TargetExports; std::vector<std::unique_ptr<cmTargetExport>> TargetExports;
std::string Name; std::string Name;
std::vector<cmInstallExportGenerator const*> Installations; std::vector<cmInstallExportGenerator const*> Installations;
std::map<std::string, PackageDependency> PackageDependencies;
unsigned int NextPackageDependencyIndex = 0;
}; };
/// A name -> cmExportSet map with overloaded operator[]. /// A name -> cmExportSet map with overloaded operator[].
+2
View File
@@ -1044,6 +1044,8 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)
PushPopRootPathStack pushPopRootPathStack(*this); PushPopRootPathStack pushPopRootPathStack(*this);
SetRestoreFindDefinitions setRestoreFindDefinitions(*this, components, SetRestoreFindDefinitions setRestoreFindDefinitions(*this, components,
componentVarDefs); componentVarDefs);
cmMakefile::FindPackageStackRAII findPackageStackRAII(this->Makefile,
this->Name);
// See if we have been told to delegate to FetchContent or some other // See if we have been told to delegate to FetchContent or some other
// redirected config package first. We have to check all names that // redirected config package first. We have to check all names that
+7
View File
@@ -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>;
+33
View File
@@ -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
+5 -2
View File
@@ -2030,7 +2030,7 @@ bool HandleExportAndroidMKMode(std::vector<std::string> const& args,
cm::make_unique<cmInstallExportGenerator>( cm::make_unique<cmInstallExportGenerator>(
&exportSet, ica.GetDestination(), ica.GetPermissions(), &exportSet, ica.GetDestination(), ica.GetPermissions(),
ica.GetConfigurations(), ica.GetComponent(), message, ica.GetConfigurations(), ica.GetComponent(), message,
ica.GetExcludeFromAll(), fname, name_space, "", exportOld, true, ica.GetExcludeFromAll(), fname, name_space, "", exportOld, true, false,
helper.Makefile->GetBacktrace())); helper.Makefile->GetBacktrace()));
return true; return true;
@@ -2054,12 +2054,14 @@ bool HandleExportMode(std::vector<std::string> const& args,
bool exportOld = false; bool exportOld = false;
std::string filename; std::string filename;
std::string cxx_modules_directory; std::string cxx_modules_directory;
bool exportPackageDependencies = false;
ica.Bind("EXPORT"_s, exp); ica.Bind("EXPORT"_s, exp);
ica.Bind("NAMESPACE"_s, name_space); ica.Bind("NAMESPACE"_s, name_space);
ica.Bind("EXPORT_LINK_INTERFACE_LIBRARIES"_s, exportOld); ica.Bind("EXPORT_LINK_INTERFACE_LIBRARIES"_s, exportOld);
ica.Bind("FILE"_s, filename); ica.Bind("FILE"_s, filename);
ica.Bind("CXX_MODULES_DIRECTORY"_s, cxx_modules_directory); ica.Bind("CXX_MODULES_DIRECTORY"_s, cxx_modules_directory);
ica.Bind("EXPORT_PACKAGE_DEPENDENCIES"_s, exportPackageDependencies);
std::vector<std::string> unknownArgs; std::vector<std::string> unknownArgs;
ica.Parse(args, &unknownArgs); ica.Parse(args, &unknownArgs);
@@ -2147,7 +2149,8 @@ bool HandleExportMode(std::vector<std::string> const& args,
&exportSet, ica.GetDestination(), ica.GetPermissions(), &exportSet, ica.GetDestination(), ica.GetPermissions(),
ica.GetConfigurations(), ica.GetComponent(), message, ica.GetConfigurations(), ica.GetComponent(), message,
ica.GetExcludeFromAll(), fname, name_space, cxx_modules_directory, ica.GetExcludeFromAll(), fname, name_space, cxx_modules_directory,
exportOld, false, helper.Makefile->GetBacktrace())); exportOld, false, exportPackageDependencies,
helper.Makefile->GetBacktrace()));
return true; return true;
} }
+3 -1
View File
@@ -27,7 +27,7 @@ cmInstallExportGenerator::cmInstallExportGenerator(
std::string const& component, MessageLevel message, bool exclude_from_all, std::string const& component, MessageLevel message, bool exclude_from_all,
std::string filename, std::string name_space, std::string filename, std::string name_space,
std::string cxx_modules_directory, bool exportOld, bool android, std::string cxx_modules_directory, bool exportOld, bool android,
cmListFileBacktrace backtrace) bool exportPackageDependencies, cmListFileBacktrace backtrace)
: cmInstallGenerator(destination, configurations, component, message, : cmInstallGenerator(destination, configurations, component, message,
exclude_from_all, false, std::move(backtrace)) exclude_from_all, false, std::move(backtrace))
, ExportSet(exportSet) , ExportSet(exportSet)
@@ -36,6 +36,7 @@ cmInstallExportGenerator::cmInstallExportGenerator(
, Namespace(std::move(name_space)) , Namespace(std::move(name_space))
, CxxModulesDirectory(std::move(cxx_modules_directory)) , CxxModulesDirectory(std::move(cxx_modules_directory))
, ExportOld(exportOld) , ExportOld(exportOld)
, ExportPackageDependencies(exportPackageDependencies)
{ {
if (android) { if (android) {
#ifndef CMAKE_BOOTSTRAP #ifndef CMAKE_BOOTSTRAP
@@ -119,6 +120,7 @@ void cmInstallExportGenerator::GenerateScript(std::ostream& os)
this->EFGen->AddConfiguration(c); this->EFGen->AddConfiguration(c);
} }
} }
this->EFGen->SetExportPackageDependencies(this->ExportPackageDependencies);
this->EFGen->GenerateImportFile(); this->EFGen->GenerateImportFile();
// Perform the main install script generation. // Perform the main install script generation.
+3 -1
View File
@@ -29,7 +29,8 @@ public:
bool exclude_from_all, std::string filename, bool exclude_from_all, std::string filename,
std::string name_space, std::string name_space,
std::string cxx_modules_directory, bool exportOld, std::string cxx_modules_directory, bool exportOld,
bool android, cmListFileBacktrace backtrace); bool android, bool exportPackageDependencies,
cmListFileBacktrace backtrace);
cmInstallExportGenerator(const cmInstallExportGenerator&) = delete; cmInstallExportGenerator(const cmInstallExportGenerator&) = delete;
~cmInstallExportGenerator() override; ~cmInstallExportGenerator() override;
@@ -70,6 +71,7 @@ protected:
std::string const Namespace; std::string const Namespace;
std::string const CxxModulesDirectory; std::string const CxxModulesDirectory;
bool const ExportOld; bool const ExportOld;
bool const ExportPackageDependencies;
cmLocalGenerator* LocalGenerator = nullptr; cmLocalGenerator* LocalGenerator = nullptr;
std::string TempDir; std::string TempDir;
+35
View File
@@ -302,6 +302,11 @@ cmListFileBacktrace cmMakefile::GetBacktrace() const
return this->Backtrace; return this->Backtrace;
} }
cmFindPackageStack cmMakefile::GetFindPackageStack() const
{
return this->FindPackageStack;
}
void cmMakefile::PrintCommandTrace(cmListFileFunction const& lff, void cmMakefile::PrintCommandTrace(cmListFileFunction const& lff,
cmListFileBacktrace const& bt, cmListFileBacktrace const& bt,
CommandMissingFromStack missing) const CommandMissingFromStack missing) const
@@ -4771,6 +4776,36 @@ cmMakefile::MacroPushPop::~MacroPushPop()
this->Makefile->PopMacroScope(this->ReportError); 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, cmMakefile::DebugFindPkgRAII::DebugFindPkgRAII(cmMakefile* mf,
std::string const& pkg) std::string const& pkg)
: Makefile(mf) : Makefile(mf)
+18
View File
@@ -25,6 +25,7 @@
#include "cmAlgorithms.h" #include "cmAlgorithms.h"
#include "cmCustomCommand.h" #include "cmCustomCommand.h"
#include "cmFindPackageStack.h"
#include "cmFunctionBlocker.h" #include "cmFunctionBlocker.h"
#include "cmListFileCache.h" #include "cmListFileCache.h"
#include "cmMessageType.h" // IWYU pragma: keep #include "cmMessageType.h" // IWYU pragma: keep
@@ -659,6 +660,11 @@ public:
*/ */
cmListFileBacktrace GetBacktrace() const; cmListFileBacktrace GetBacktrace() const;
/**
* Get the current stack of find_package calls.
*/
cmFindPackageStack GetFindPackageStack() const;
/** /**
* Get the vector of files created by this makefile * Get the vector of files created by this makefile
*/ */
@@ -1020,6 +1026,15 @@ public:
// searches // searches
std::deque<std::vector<std::string>> FindPackageRootPathStack; std::deque<std::vector<std::string>> FindPackageRootPathStack;
class FindPackageStackRAII
{
cmMakefile* Makefile;
public:
FindPackageStackRAII(cmMakefile* mf, std::string const& pkg);
~FindPackageStackRAII();
};
class DebugFindPkgRAII class DebugFindPkgRAII
{ {
cmMakefile* Makefile; cmMakefile* Makefile;
@@ -1210,6 +1225,9 @@ private:
std::vector<BT<GeneratorAction>> GeneratorActions; std::vector<BT<GeneratorAction>> GeneratorActions;
bool GeneratorActionsInvoked = false; bool GeneratorActionsInvoked = false;
cmFindPackageStack FindPackageStack;
unsigned int FindPackageStackNextIndex = 0;
bool DebugFindPkg = false; bool DebugFindPkg = false;
bool CheckSystemVars; bool CheckSystemVars;
+11
View File
@@ -20,6 +20,7 @@
#include "cmAlgorithms.h" #include "cmAlgorithms.h"
#include "cmCustomCommand.h" #include "cmCustomCommand.h"
#include "cmFileSet.h" #include "cmFileSet.h"
#include "cmFindPackageStack.h"
#include "cmGeneratorExpression.h" #include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h" #include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h" #include "cmGlobalGenerator.h"
@@ -585,6 +586,7 @@ TargetProperty const StaticTargetProperties[] = {
// Usage requirement properties // Usage requirement properties
{ "LINK_INTERFACE_LIBRARIES"_s, IC::CanCompileSources }, { "LINK_INTERFACE_LIBRARIES"_s, IC::CanCompileSources },
{ "MAP_IMPORTED_CONFIG_"_s, IC::NormalTarget, R::PerConfig }, { "MAP_IMPORTED_CONFIG_"_s, IC::NormalTarget, R::PerConfig },
{ "EXPORT_FIND_PACKAGE_NAME"_s, IC::NormalTarget },
// Metadata // Metadata
{ "CROSSCOMPILING_EMULATOR"_s, IC::ExecutableTarget }, { "CROSSCOMPILING_EMULATOR"_s, IC::ExecutableTarget },
@@ -661,6 +663,7 @@ public:
TLLCommands; TLLCommands;
std::map<std::string, cmFileSet> FileSets; std::map<std::string, cmFileSet> FileSets;
cmListFileBacktrace Backtrace; cmListFileBacktrace Backtrace;
cmFindPackageStack FindPackageStack;
UsageRequirementProperty IncludeDirectories; UsageRequirementProperty IncludeDirectories;
UsageRequirementProperty CompileOptions; UsageRequirementProperty CompileOptions;
@@ -961,6 +964,9 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
// Save the backtrace of target construction. // Save the backtrace of target construction.
this->impl->Backtrace = this->impl->Makefile->GetBacktrace(); this->impl->Backtrace = this->impl->Makefile->GetBacktrace();
if (this->impl->IsImported()) {
this->impl->FindPackageStack = this->impl->Makefile->GetFindPackageStack();
}
if (this->IsNormal()) { if (this->IsNormal()) {
// Initialize the INCLUDE_DIRECTORIES property based on the current value // Initialize the INCLUDE_DIRECTORIES property based on the current value
@@ -1248,6 +1254,11 @@ cmListFileBacktrace const& cmTarget::GetBacktrace() const
return this->impl->Backtrace; return this->impl->Backtrace;
} }
cmFindPackageStack const& cmTarget::GetFindPackageStack() const
{
return this->impl->FindPackageStack;
}
bool cmTarget::IsExecutableWithExports() const bool cmTarget::IsExecutableWithExports() const
{ {
return (this->GetType() == cmStateEnums::EXECUTABLE && return (this->GetType() == cmStateEnums::EXECUTABLE &&
+4
View File
@@ -24,6 +24,7 @@
class cmCustomCommand; class cmCustomCommand;
class cmFileSet; class cmFileSet;
class cmFindPackageStack;
class cmGlobalGenerator; class cmGlobalGenerator;
class cmInstallTargetGenerator; class cmInstallTargetGenerator;
class cmMakefile; class cmMakefile;
@@ -239,6 +240,9 @@ public:
//! Get a backtrace from the creation of the target. //! Get a backtrace from the creation of the target.
cmListFileBacktrace const& GetBacktrace() const; 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 InsertInclude(BT<std::string> const& entry, bool before = false);
void InsertCompileOption(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); void InsertCompileDefinition(BT<std::string> const& entry);
+4 -1
View File
@@ -4,6 +4,8 @@ if(POLICY CMP0129)
endif() endif()
project(Export C CXX) project(Export C CXX)
find_package(Foo REQUIRED CONFIG NO_DEFAULT_PATH)
# Pretend that RelWithDebInfo should link to debug libraries to test # Pretend that RelWithDebInfo should link to debug libraries to test
# the DEBUG_CONFIGURATIONS property. # the DEBUG_CONFIGURATIONS property.
set_property(GLOBAL PROPERTY DEBUG_CONFIGURATIONS Debug RelWithDebInfo) set_property(GLOBAL PROPERTY DEBUG_CONFIGURATIONS Debug RelWithDebInfo)
@@ -110,6 +112,7 @@ add_library(testLib9ObjIface OBJECT testLib9ObjIface.c)
target_compile_definitions(testLib9ObjIface INTERFACE testLib9ObjIface_USED) target_compile_definitions(testLib9ObjIface INTERFACE testLib9ObjIface_USED)
add_library(testLib9 STATIC testLib9.c) add_library(testLib9 STATIC testLib9.c)
target_link_libraries(testLib9 INTERFACE testLib9ObjIface PUBLIC testLib9ObjPub PRIVATE testLib9ObjPriv) target_link_libraries(testLib9 INTERFACE testLib9ObjIface PUBLIC testLib9ObjPub PRIVATE testLib9ObjPriv)
target_link_libraries(testLib9 PUBLIC Foo::Foo)
cmake_policy(POP) cmake_policy(POP)
# Test using the target_link_libraries command to set the # Test using the target_link_libraries command to set the
@@ -624,7 +627,7 @@ install(
LIBRARY DESTINATION lib LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib ARCHIVE DESTINATION lib
) )
install(EXPORT exp NAMESPACE exp_ DESTINATION lib/exp) install(EXPORT exp NAMESPACE exp_ DESTINATION lib/exp EXPORT_PACKAGE_DEPENDENCIES)
# Install testLib5.dll outside the export. # Install testLib5.dll outside the export.
if(WIN32) if(WIN32)
+3
View File
@@ -0,0 +1,3 @@
if(NOT TARGET Foo::Foo)
add_library(Foo::Foo INTERFACE IMPORTED)
endif()
+1
View File
@@ -1,5 +1,6 @@
cmake_minimum_required (VERSION 2.7.20090711) cmake_minimum_required (VERSION 2.7.20090711)
cmake_policy(SET CMP0025 NEW) cmake_policy(SET CMP0025 NEW)
cmake_policy(SET CMP0028 NEW)
if(POLICY CMP0129) if(POLICY CMP0129)
cmake_policy(SET CMP0129 NEW) cmake_policy(SET CMP0129 NEW)
endif() endif()
+1
View File
@@ -15,3 +15,4 @@ set(CMAKE_INSTALL_PREFIX "@ExportImport_BINARY_DIR@/Root" CACHE STRING "Installa
set(CMAKE_SKIP_RPATH ON CACHE BOOL "No RPATH") set(CMAKE_SKIP_RPATH ON CACHE BOOL "No RPATH")
set(CMAKE_GNUtoMS "@ExportImport_GNUtoMS@" CACHE BOOL "CMAKE_GNUtoMS") set(CMAKE_GNUtoMS "@ExportImport_GNUtoMS@" CACHE BOOL "CMAKE_GNUtoMS")
set(CMake_TEST_CUDA "@CMake_TEST_CUDA@" CACHE BOOL "CMake_TEST_CUDA") set(CMake_TEST_CUDA "@CMake_TEST_CUDA@" CACHE BOOL "CMake_TEST_CUDA")
set(Foo_DIR "@CMAKE_CURRENT_SOURCE_DIR@/External" CACHE PATH "Foo cmake package directory")
@@ -0,0 +1,17 @@
find_package(Threads REQUIRED)
find_package(P4 REQUIRED)
add_library(HasDeps::interface IMPORTED INTERFACE)
target_link_libraries(HasDeps::interface INTERFACE Threads::Threads l4)
add_library(HasDeps::A IMPORTED UNKNOWN)
target_link_libraries(HasDeps::A INTERFACE HasDeps::interface)
file(TOUCH "${CMAKE_CURRENT_BINARY_DIR}/a.so")
set_property(TARGET HasDeps::A PROPERTY IMPORTED_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/a.so")
add_library(HasDeps::B IMPORTED UNKNOWN)
target_link_libraries(HasDeps::B INTERFACE HasDeps::interface)
file(TOUCH "${CMAKE_CURRENT_BINARY_DIR}/b.so")
set_property(TARGET HasDeps::B PROPERTY IMPORTED_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/b.so")
set(HASDEPS_FOUND TRUE)
+2
View File
@@ -0,0 +1,2 @@
add_library(l1 IMPORTED INTERFACE)
set(P1_FOUND TRUE)
+2
View File
@@ -0,0 +1,2 @@
add_library(l2 IMPORTED INTERFACE)
set(P2_FOUND TRUE)
+2
View File
@@ -0,0 +1,2 @@
add_library(l3 IMPORTED INTERFACE)
set(P3_FOUND TRUE)
+2
View File
@@ -0,0 +1,2 @@
add_library(l4 IMPORTED INTERFACE)
set(P4_FOUND TRUE)
+2
View File
@@ -0,0 +1,2 @@
add_library(l9 IMPORTED INTERFACE)
set(P9_FOUND TRUE)
@@ -0,0 +1,35 @@
file(READ "${RunCMake_TEST_BINARY_DIR}/mytargets.cmake" mytargets)
if("${mytargets}" MATCHES "find_dependency\\(P1")
string(APPEND RunCMake_TEST_FAILED "P1 dependency should not be exported but it is\n")
endif()
if(NOT "${mytargets}" MATCHES "find_dependency\\(P2 REQUIRED \"VERSION\" \"1\\.0\"\\)")
string(APPEND RunCMake_TEST_FAILED "P2 dependency should be exported but it is not\n")
endif()
if(NOT "${mytargets}" MATCHES "find_dependency\\(P3 REQUIRED\\)")
string(APPEND RunCMake_TEST_FAILED "P3 dependency should be exported but it is not\n")
endif()
if(NOT "${mytargets}" MATCHES "find_dependency\\(P4 REQUIRED\\)")
string(APPEND RunCMake_TEST_FAILED "P4 dependency should be exported but it is not\n")
endif()
if("${mytargets}" MATCHES "find_dependency\\(P5")
string(APPEND RunCMake_TEST_FAILED "P5 dependency should not be exported but it is\n")
endif()
if(NOT "${mytargets}" MATCHES "find_dependency\\(P6 REQUIRED\\)")
string(APPEND RunCMake_TEST_FAILED "P6 dependency should be exported but it is not\n")
endif()
if("${mytargets}" MATCHES "find_dependency\\(P7")
string(APPEND RunCMake_TEST_FAILED "P7 dependency should not be exported but it is\n")
endif()
if(NOT "${mytargets}" MATCHES "find_dependency\\(P3[^
]*\\)
find_dependency\\(P2[^
]*\\)
find_dependency\\(P8[^
]*\\)
find_dependency\\(P6[^
]*\\)
find_dependency\\(P9[^
]*\\)
find_dependency\\(P4")
string(APPEND RunCMake_TEST_FAILED "Dependencies are not in the correct order\n")
endif()
@@ -0,0 +1,30 @@
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/CMake)
find_package(P1)
find_package(P2)
find_package(P9)
find_package(P4)
find_package(P3)
add_library(mylib INTERFACE)
target_link_libraries(mylib INTERFACE l1 l2 l3 l4 l9)
install(TARGETS mylib EXPORT mytargets)
export(SETUP mytargets
PACKAGE_DEPENDENCY P1
ENABLED OFF
PACKAGE_DEPENDENCY P3
ENABLED AUTO
PACKAGE_DEPENDENCY P2
ENABLED ON
EXTRA_ARGS VERSION 1.0
PACKAGE_DEPENDENCY P5
ENABLED FALSE
PACKAGE_DEPENDENCY P8
ENABLED TRUE
PACKAGE_DEPENDENCY P6
ENABLED 1
PACKAGE_DEPENDENCY P7
ENABLED AUTO
)
export(EXPORT mytargets EXPORT_PACKAGE_DEPENDENCIES FILE mytargets.cmake)
@@ -0,0 +1,14 @@
file(READ "${RunCMake_TEST_BINARY_DIR}/my_private_targets.cmake" my_private_targets)
if(NOT "${my_private_targets}" MATCHES "find_dependency\\(HasDeps")
string(APPEND RunCMake_TEST_FAILED "HasDeps dependency should be exported but it is not\n")
endif()
file(READ "${RunCMake_TEST_BINARY_DIR}/my_static_targets.cmake" my_static_targets)
if(NOT "${my_static_targets}" MATCHES "find_dependency\\(MyPrivate")
string(APPEND RunCMake_TEST_FAILED "HasDeps dependency should be exported but it is not\n")
endif()
file(READ "${RunCMake_TEST_BINARY_DIR}/my_shared_targets.cmake" my_shared_targets)
if(NOT "${my_shared_targets}" MATCHES "find_dependency\\(MyPrivate")
string(APPEND RunCMake_TEST_FAILED "MyStatic dependency should be exported but it is not\n")
endif()
@@ -0,0 +1,37 @@
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/CMake)
enable_language(CXX)
find_package(HasDeps)
# replicates FetchContent where a dependency is brought
# in via source. In these cases we need to extend the `install`
# `export` commands to allow markup on what `Find<Project>` will
# map to the export set
add_library(my_private_lib STATIC empty.cpp)
target_link_libraries(my_private_lib PUBLIC HasDeps::A)
set_target_properties(my_private_lib PROPERTIES EXPORT_FIND_PACKAGE_NAME "MyPrivate")
install(TARGETS my_private_lib EXPORT my_private_targets)
install(EXPORT my_private_targets
FILE my_private.cmake
DESTINATION lib)
export(EXPORT my_private_targets EXPORT_PACKAGE_DEPENDENCIES FILE my_private_targets.cmake)
add_library(my_static_lib STATIC empty.cpp)
target_link_libraries(my_static_lib PRIVATE my_private_lib)
install(TARGETS my_static_lib EXPORT my_static_targets)
install(EXPORT my_static_targets
FILE my_static.cmake
DESTINATION lib)
export(EXPORT my_static_targets EXPORT_PACKAGE_DEPENDENCIES FILE my_static_targets.cmake)
add_library(my_shared_lib SHARED empty.cpp)
target_link_libraries(my_shared_lib PUBLIC my_private_lib)
install(TARGETS my_shared_lib EXPORT my_shared_targets)
install(EXPORT my_shared_targets
FILE my_shared.cmake
DESTINATION lib)
export(EXPORT my_shared_targets EXPORT_PACKAGE_DEPENDENCIES FILE my_shared_targets.cmake)
@@ -0,0 +1,4 @@
file(READ "${RunCMake_TEST_BINARY_DIR}/mytargets.cmake" mytargets)
if("${mytargets}" MATCHES "find_dependency")
string(APPEND RunCMake_TEST_FAILED "No dependencies should not be exported\n")
endif()
@@ -0,0 +1,14 @@
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/CMake)
enable_language(CXX)
find_package(P1)
find_package(P2)
find_package(P3)
find_package(P4)
add_library(mylib SHARED empty.cpp)
target_link_libraries(mylib PRIVATE l1 l2 l3 l4)
install(TARGETS mylib EXPORT mytargets)
export(EXPORT mytargets EXPORT_PACKAGE_DEPENDENCIES FILE mytargets.cmake)
@@ -0,0 +1,13 @@
file(READ "${RunCMake_TEST_BINARY_DIR}/mytargets.cmake" mytargets)
if(NOT "${mytargets}" MATCHES "find_dependency\\(P1")
string(APPEND RunCMake_TEST_FAILED "P1 dependency should be exported but it is not\n")
endif()
if(NOT "${mytargets}" MATCHES "find_dependency\\(P2")
string(APPEND RunCMake_TEST_FAILED "P2 dependency should be exported but it is not\n")
endif()
if(NOT "${mytargets}" MATCHES "find_dependency\\(P3")
string(APPEND RunCMake_TEST_FAILED "P3 dependency should be exported but it is not\n")
endif()
if(NOT "${mytargets}" MATCHES "find_dependency\\(P4")
string(APPEND RunCMake_TEST_FAILED "P4 dependency should be exported but it is not\n")
endif()
@@ -0,0 +1,14 @@
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/CMake)
enable_language(CXX)
find_package(P1)
find_package(P2)
find_package(P3)
find_package(P4)
add_library(mylib STATIC empty.cpp)
target_link_libraries(mylib PRIVATE l1 l2 l3 l4)
install(TARGETS mylib EXPORT mytargets)
export(EXPORT mytargets EXPORT_PACKAGE_DEPENDENCIES FILE mytargets.cmake)
+4
View File
@@ -19,3 +19,7 @@ run_cmake(UnknownExport)
run_cmake(NamelinkOnlyExport) run_cmake(NamelinkOnlyExport)
run_cmake(SeparateNamelinkExport) run_cmake(SeparateNamelinkExport)
run_cmake(TryCompileExport) run_cmake(TryCompileExport)
run_cmake(FindDependencyExport)
run_cmake(FindDependencyExportStatic)
run_cmake(FindDependencyExportShared)
run_cmake(FindDependencyExportFetchContent)
@@ -0,0 +1,4 @@
file(READ "${RunCMake_TEST_BINARY_DIR}/root-all/lib/cmake/mylib/mylib-targets.cmake" contents)
if(NOT contents MATCHES "include\\(CMakeFindDependencyMacro\\)\nfind_dependency\\(P2 REQUIRED\\)\nfind_dependency\\(P1 REQUIRED\\)\n")
set(RunCMake_TEST_FAILED "Dependencies were not properly exported")
endif()
@@ -0,0 +1,18 @@
enable_language(C)
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
find_package(P1 REQUIRED)
find_package(P2 REQUIRED)
find_package(P3 REQUIRED)
add_library(mylib INTERFACE)
target_link_libraries(mylib INTERFACE lib1 lib2 lib3)
install(TARGETS mylib EXPORT mylib-targets)
export(SETUP mylib-targets
PACKAGE_DEPENDENCY P2
ENABLED AUTO
PACKAGE_DEPENDENCY P3
ENABLED OFF
)
install(EXPORT mylib-targets EXPORT_PACKAGE_DEPENDENCIES FILE mylib-targets.cmake DESTINATION lib/cmake/mylib)
@@ -176,6 +176,7 @@ run_install_test(TARGETS-Parts)
run_install_test(FILES-PERMISSIONS) run_install_test(FILES-PERMISSIONS)
run_install_test(TARGETS-RPATH) run_install_test(TARGETS-RPATH)
run_install_test(InstallRequiredSystemLibraries) run_install_test(InstallRequiredSystemLibraries)
run_install_test(EXPORT-FindDependencyExport)
set(RunCMake_TEST_OPTIONS "-DCMAKE_POLICY_DEFAULT_CMP0087:STRING=NEW") set(RunCMake_TEST_OPTIONS "-DCMAKE_POLICY_DEFAULT_CMP0087:STRING=NEW")
run_install_test(SCRIPT) run_install_test(SCRIPT)
@@ -0,0 +1,2 @@
add_library(lib1 IMPORTED INTERFACE)
set(P1_FOUND TRUE)
@@ -0,0 +1,2 @@
add_library(lib2 IMPORTED INTERFACE)
set(P2_FOUND TRUE)
@@ -0,0 +1,2 @@
add_library(lib3 IMPORTED INTERFACE)
set(P3_FOUND TRUE)
+1
View File
@@ -364,6 +364,7 @@ CMAKE_CXX_SOURCES="\
cmFindFileCommand \ cmFindFileCommand \
cmFindLibraryCommand \ cmFindLibraryCommand \
cmFindPackageCommand \ cmFindPackageCommand \
cmFindPackageStack \
cmFindPathCommand \ cmFindPathCommand \
cmFindProgramCommand \ cmFindProgramCommand \
cmForEachCommand \ cmForEachCommand \