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