summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Woehlke <matthew.woehlke@kitware.com>2024-07-18 16:07:26 (GMT)
committerMatthew Woehlke <matthew.woehlke@kitware.com>2024-07-23 16:13:39 (GMT)
commit20fa4ce8d89369441dc4f8a74d62611e8dfa36ea (patch)
tree6c23718e1cb92ad7003f2157dd233bbc7333c5e6
parent6c66340a647fc7fa59e3f63e9344c05d3e760bfb (diff)
downloadCMake-20fa4ce8d89369441dc4f8a74d62611e8dfa36ea.zip
CMake-20fa4ce8d89369441dc4f8a74d62611e8dfa36ea.tar.gz
CMake-20fa4ce8d89369441dc4f8a74d62611e8dfa36ea.tar.bz2
export: Factor out CMake-specific export generation (2/2)
In order to support generation of Common Package Specifications, the mechanisms CMake uses to export package information need to be made more abstract. The prior commits began this refactoring; this continues by (actually) restructuring the classes used to generate the actual export files. To minimize churn, this introduces virtual base classes and diamond inheritance in order to separate logic which is format-agnostic but depends on the export mode (build-tree versus install-tree) from logic which is format-specific but mode-agnostic. This could probably be refactored further to use helper classes instead, and a future commit may do that, however an initial attempt to do that was proving even more invasive, such that this approach was deemed more manageable. While we're at it, add 'const' in more places where possible.
-rw-r--r--Source/CMakeLists.txt8
-rw-r--r--Source/cmExportAndroidMKGenerator.cxx71
-rw-r--r--Source/cmExportAndroidMKGenerator.h81
-rw-r--r--Source/cmExportBuildAndroidMKGenerator.cxx193
-rw-r--r--Source/cmExportBuildAndroidMKGenerator.h39
-rw-r--r--Source/cmExportBuildCMakeConfigGenerator.cxx279
-rw-r--r--Source/cmExportBuildCMakeConfigGenerator.h101
-rw-r--r--Source/cmExportBuildFileGenerator.cxx435
-rw-r--r--Source/cmExportBuildFileGenerator.h53
-rw-r--r--Source/cmExportCMakeConfigGenerator.cxx1041
-rw-r--r--Source/cmExportCMakeConfigGenerator.h197
-rw-r--r--Source/cmExportCommand.cxx14
-rw-r--r--Source/cmExportFileGenerator.cxx1076
-rw-r--r--Source/cmExportFileGenerator.h192
-rw-r--r--Source/cmExportInstallAndroidMKGenerator.cxx114
-rw-r--r--Source/cmExportInstallAndroidMKGenerator.h60
-rw-r--r--Source/cmExportInstallCMakeConfigGenerator.cxx335
-rw-r--r--Source/cmExportInstallCMakeConfigGenerator.h101
-rw-r--r--Source/cmExportInstallFileGenerator.cxx900
-rw-r--r--Source/cmExportInstallFileGenerator.h111
-rw-r--r--Source/cmExportTryCompileFileGenerator.cxx11
-rw-r--r--Source/cmExportTryCompileFileGenerator.h12
-rw-r--r--Source/cmInstallAndroidMKExportGenerator.cxx10
-rw-r--r--Source/cmInstallAndroidMKExportGenerator.h14
-rw-r--r--Source/cmInstallCMakeConfigExportGenerator.cxx9
-rw-r--r--Source/cmInstallCMakeConfigExportGenerator.h2
-rw-r--r--Source/cmInstallCommand.cxx2
-rw-r--r--Source/cmInstallExportGenerator.cxx75
-rw-r--r--Source/cmInstallExportGenerator.h4
-rwxr-xr-xbootstrap3
30 files changed, 1066 insertions, 4477 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index ae22d56..f4ff102 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -199,14 +199,22 @@ add_library(
cmEvaluatedTargetProperty.cxx
cmEvaluatedTargetProperty.h
cmExprParserHelper.cxx
+ cmExportAndroidMKGenerator.h
+ cmExportAndroidMKGenerator.cxx
cmExportBuildAndroidMKGenerator.h
cmExportBuildAndroidMKGenerator.cxx
+ cmExportBuildCMakeConfigGenerator.h
+ cmExportBuildCMakeConfigGenerator.cxx
cmExportBuildFileGenerator.h
cmExportBuildFileGenerator.cxx
+ cmExportCMakeConfigGenerator.h
+ cmExportCMakeConfigGenerator.cxx
cmExportFileGenerator.h
cmExportFileGenerator.cxx
cmExportInstallAndroidMKGenerator.h
cmExportInstallAndroidMKGenerator.cxx
+ cmExportInstallCMakeConfigGenerator.h
+ cmExportInstallCMakeConfigGenerator.cxx
cmExportInstallFileGenerator.h
cmExportInstallFileGenerator.cxx
cmExportTryCompileFileGenerator.h
diff --git a/Source/cmExportAndroidMKGenerator.cxx b/Source/cmExportAndroidMKGenerator.cxx
index 297c8b6..34dc1a7 100644
--- a/Source/cmExportAndroidMKGenerator.cxx
+++ b/Source/cmExportAndroidMKGenerator.cxx
@@ -2,12 +2,12 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmExportAndroidMKGenerator.h"
-#include <map>
#include <sstream>
#include <utility>
#include <vector>
#include <cmext/algorithm>
+#include <cmext/string_view>
#include "cmGeneratorTarget.h"
#include "cmLinkItem.h"
@@ -20,75 +20,44 @@
#include "cmSystemTools.h"
#include "cmTarget.h"
-cmExportAndroidMKGenerator::cmExportAndroidMKGenerator()
-{
- this->LG = nullptr;
- this->ExportSet = nullptr;
-}
+cmExportAndroidMKGenerator::cmExportAndroidMKGenerator() = default;
-void cmExportAndroidMKGenerator::GenerateImportHeaderCode(std::ostream& os,
- std::string const&)
+cm::string_view cmExportAndroidMKGenerator::GetImportPrefixWithSlash() const
{
- os << "LOCAL_PATH := $(call my-dir)\n\n";
+ return "$(_IMPORT_PREFIX)/"_s;
}
-void cmExportAndroidMKGenerator::GenerateImportFooterCode(std::ostream&)
+bool cmExportAndroidMKGenerator::GenerateImportFile(std::ostream& os)
{
-}
+ if (!this->AppendMode) {
+ // Start with the import file header.
+ this->GenerateImportHeaderCode(os);
+ }
-void cmExportAndroidMKGenerator::GenerateExpectedTargetsCode(
- std::ostream&, std::string const&)
-{
-}
+ // Create all the imported targets.
+ std::stringstream mainFileBuffer;
+ bool result = this->GenerateMainFile(mainFileBuffer);
-void cmExportAndroidMKGenerator::GenerateImportTargetCode(
- std::ostream& os, cmGeneratorTarget const* target,
- cmStateEnums::TargetType /*targetType*/)
-{
- std::string targetName = cmStrCat(this->Namespace, target->GetExportName());
- os << "include $(CLEAR_VARS)\n";
- os << "LOCAL_MODULE := ";
- os << targetName << "\n";
- os << "LOCAL_SRC_FILES := ";
- std::string const noConfig; // FIXME: What config to use here?
- std::string path =
- cmSystemTools::ConvertToOutputPath(target->GetFullPath(noConfig));
- os << path << "\n";
-}
+ // Write cached import code.
+ os << mainFileBuffer.rdbuf();
-void cmExportAndroidMKGenerator::GenerateImportPropertyCode(
- std::ostream&, std::string const&, std::string const&,
- cmGeneratorTarget const*, ImportPropertyMap const&, std::string const&)
-{
-}
-
-void cmExportAndroidMKGenerator::GenerateMissingTargetsCheckCode(std::ostream&)
-{
+ return result;
}
void cmExportAndroidMKGenerator::GenerateInterfaceProperties(
cmGeneratorTarget const* target, std::ostream& os,
ImportPropertyMap const& properties)
{
- std::string config;
- if (!this->Configurations.empty()) {
- config = this->Configurations[0];
- }
- cmExportAndroidMKGenerator::GenerateInterfaceProperties(
- target, os, properties, cmExportAndroidMKGenerator::BUILD, config);
-}
+ std::string const config =
+ (this->Configurations.empty() ? std::string{} : this->Configurations[0]);
+ GenerateType const type = this->GetGenerateType();
-void cmExportAndroidMKGenerator::GenerateInterfaceProperties(
- cmGeneratorTarget const* target, std::ostream& os,
- ImportPropertyMap const& properties, GenerateType type,
- std::string const& config)
-{
bool const newCMP0022Behavior =
target->GetPolicyStatusCMP0022() != cmPolicies::WARN &&
target->GetPolicyStatusCMP0022() != cmPolicies::OLD;
if (!newCMP0022Behavior) {
std::ostringstream w;
- if (type == cmExportAndroidMKGenerator::BUILD) {
+ if (type == BUILD) {
w << "export(TARGETS ... ANDROID_MK) called with policy CMP0022";
} else {
w << "install( EXPORT_ANDROID_MK ...) called with policy CMP0022";
@@ -123,7 +92,7 @@ void cmExportAndroidMKGenerator::GenerateInterfaceProperties(
}
} else {
bool relpath = false;
- if (type == cmExportAndroidMKGenerator::INSTALL) {
+ if (type == INSTALL) {
relpath = cmHasLiteralPrefix(lib, "../");
}
// check for full path or if it already has a -l, or
diff --git a/Source/cmExportAndroidMKGenerator.h b/Source/cmExportAndroidMKGenerator.h
index f1e74ee..fb0f03b 100644
--- a/Source/cmExportAndroidMKGenerator.h
+++ b/Source/cmExportAndroidMKGenerator.h
@@ -5,58 +5,69 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
+#include <map>
#include <string>
-#include "cmExportBuildFileGenerator.h"
+#include <cm/string_view>
+
+#include "cmExportFileGenerator.h"
#include "cmStateTypes.h"
class cmGeneratorTarget;
/** \class cmExportAndroidMKGenerator
- * \brief Generate a file exporting targets from a build tree.
- *
- * cmExportAndroidMKGenerator generates a file exporting targets from
- * a build tree. This exports the targets to the Android ndk build tool
- * makefile format for prebuilt libraries.
+ * \brief Generate CMake configuration files exporting targets from a build or
+ * install tree.
*
- * This is used to implement the export() command.
+ * cmExportAndroidMKGenerator is the superclass for
+ * cmExportBuildAndroidMKGenerator and cmExportInstallAndroidMKGenerator.
+ * It contains common code generation routines for the two kinds of export
+ * implementations.
*/
-class cmExportAndroidMKGenerator : public cmExportBuildFileGenerator
+class cmExportAndroidMKGenerator : virtual public cmExportFileGenerator
{
public:
cmExportAndroidMKGenerator();
- // this is so cmExportInstallAndroidMKGenerator can share this
- // function as they are almost the same
+
+ using cmExportFileGenerator::GenerateImportFile;
+
+protected:
enum GenerateType
{
BUILD,
INSTALL
};
- static void GenerateInterfaceProperties(cmGeneratorTarget const* target,
- std::ostream& os,
- ImportPropertyMap const& properties,
- GenerateType type,
- std::string const& config);
+ virtual GenerateType GetGenerateType() const = 0;
-protected:
- // Implement virtual methods from the superclass.
- void GeneratePolicyHeaderCode(std::ostream&) override {}
- void GeneratePolicyFooterCode(std::ostream&) override {}
- void GenerateImportHeaderCode(std::ostream& os,
- std::string const& config = "") override;
- void GenerateImportFooterCode(std::ostream& os) override;
- void GenerateImportTargetCode(
+ using ImportPropertyMap = std::map<std::string, std::string>;
+
+ cm::string_view GetImportPrefixWithSlash() const override;
+
+ void GenerateInterfaceProperties(cmGeneratorTarget const* target,
+ std::ostream& os,
+ ImportPropertyMap const& properties);
+
+ // Methods to implement export file code generation.
+ bool GenerateImportFile(std::ostream& os) override;
+ virtual void GenerateImportHeaderCode(std::ostream& os,
+ std::string const& config = "") = 0;
+ virtual void GenerateImportTargetCode(
std::ostream& os, cmGeneratorTarget const* target,
- cmStateEnums::TargetType /*targetType*/) override;
- void GenerateExpectedTargetsCode(
- std::ostream& os, std::string const& expectedTargets) override;
- void GenerateImportPropertyCode(
- std::ostream& os, std::string const& config, std::string const& suffix,
- cmGeneratorTarget const* target, ImportPropertyMap const& properties,
- std::string const& importedXcFrameworkLocation) override;
- void GenerateMissingTargetsCheckCode(std::ostream& os) override;
- void GenerateFindDependencyCalls(std::ostream&) override {}
- void GenerateInterfaceProperties(
- cmGeneratorTarget const* target, std::ostream& os,
- ImportPropertyMap const& properties) override;
+ cmStateEnums::TargetType targetType) = 0;
+
+ void GenerateImportTargetsConfig(std::ostream& /*os*/,
+ std::string const& /*config*/,
+ std::string const& /*suffix*/) override
+ {
+ }
+
+ std::string GetCxxModuleFile(std::string const& /*name*/) const override
+ {
+ return {};
+ }
+
+ void GenerateCxxModuleConfigInformation(std::string const& /*name*/,
+ std::ostream& /*os*/) const override
+ {
+ }
};
diff --git a/Source/cmExportBuildAndroidMKGenerator.cxx b/Source/cmExportBuildAndroidMKGenerator.cxx
index 4fdbbc4..a5f6ca3 100644
--- a/Source/cmExportBuildAndroidMKGenerator.cxx
+++ b/Source/cmExportBuildAndroidMKGenerator.cxx
@@ -2,28 +2,50 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmExportBuildAndroidMKGenerator.h"
-#include <map>
#include <sstream>
-#include <utility>
#include <vector>
-#include <cmext/algorithm>
-
+#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
-#include "cmLinkItem.h"
-#include "cmList.h"
-#include "cmMakefile.h"
-#include "cmMessageType.h"
#include "cmPolicies.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
-cmExportBuildAndroidMKGenerator::cmExportBuildAndroidMKGenerator()
+cmExportBuildAndroidMKGenerator::cmExportBuildAndroidMKGenerator() = default;
+
+bool cmExportBuildAndroidMKGenerator::GenerateMainFile(std::ostream& os)
{
- this->LG = nullptr;
- this->ExportSet = nullptr;
+ if (!this->CollectExports([&](cmGeneratorTarget const*) {})) {
+ return false;
+ }
+
+ // Create all the imported targets.
+ for (auto const& exp : this->Exports) {
+ cmGeneratorTarget* gte = exp.Target;
+
+ this->GenerateImportTargetCode(os, gte, this->GetExportTargetType(gte));
+
+ gte->Target->AppendBuildInterfaceIncludes();
+
+ ImportPropertyMap properties;
+ if (!this->PopulateInterfaceProperties(gte, properties)) {
+ return false;
+ }
+
+ bool const newCMP0022Behavior =
+ gte->GetPolicyStatusCMP0022() != cmPolicies::WARN &&
+ gte->GetPolicyStatusCMP0022() != cmPolicies::OLD;
+ if (newCMP0022Behavior) {
+ this->PopulateInterfaceLinkLibrariesProperty(
+ gte, cmGeneratorExpression::BuildInterface, properties);
+ }
+
+ this->GenerateInterfaceProperties(gte, os, properties);
+ }
+
+ return true;
}
void cmExportBuildAndroidMKGenerator::GenerateImportHeaderCode(
@@ -32,15 +54,6 @@ void cmExportBuildAndroidMKGenerator::GenerateImportHeaderCode(
os << "LOCAL_PATH := $(call my-dir)\n\n";
}
-void cmExportBuildAndroidMKGenerator::GenerateImportFooterCode(std::ostream&)
-{
-}
-
-void cmExportBuildAndroidMKGenerator::GenerateExpectedTargetsCode(
- std::ostream&, std::string const&)
-{
-}
-
void cmExportBuildAndroidMKGenerator::GenerateImportTargetCode(
std::ostream& os, cmGeneratorTarget const* target,
cmStateEnums::TargetType /*targetType*/)
@@ -55,143 +68,3 @@ void cmExportBuildAndroidMKGenerator::GenerateImportTargetCode(
cmSystemTools::ConvertToOutputPath(target->GetFullPath(noConfig));
os << path << "\n";
}
-
-void cmExportBuildAndroidMKGenerator::GenerateImportPropertyCode(
- std::ostream&, std::string const&, std::string const&,
- cmGeneratorTarget const*, ImportPropertyMap const&, std::string const&)
-{
-}
-
-void cmExportBuildAndroidMKGenerator::GenerateMissingTargetsCheckCode(
- std::ostream&)
-{
-}
-
-void cmExportBuildAndroidMKGenerator::GenerateInterfaceProperties(
- cmGeneratorTarget const* target, std::ostream& os,
- ImportPropertyMap const& properties)
-{
- std::string config;
- if (!this->Configurations.empty()) {
- config = this->Configurations[0];
- }
- cmExportBuildAndroidMKGenerator::GenerateInterfaceProperties(
- target, os, properties, cmExportBuildAndroidMKGenerator::BUILD, config);
-}
-
-void cmExportBuildAndroidMKGenerator::GenerateInterfaceProperties(
- cmGeneratorTarget const* target, std::ostream& os,
- ImportPropertyMap const& properties, GenerateType type,
- std::string const& config)
-{
- bool const newCMP0022Behavior =
- target->GetPolicyStatusCMP0022() != cmPolicies::WARN &&
- target->GetPolicyStatusCMP0022() != cmPolicies::OLD;
- if (!newCMP0022Behavior) {
- std::ostringstream w;
- if (type == cmExportBuildAndroidMKGenerator::BUILD) {
- w << "export(TARGETS ... ANDROID_MK) called with policy CMP0022";
- } else {
- w << "install( EXPORT_ANDROID_MK ...) called with policy CMP0022";
- }
- w << " set to OLD for target " << target->Target->GetName() << ". "
- << "The export will only work with CMP0022 set to NEW.";
- target->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, w.str());
- }
- if (!properties.empty()) {
- os << "LOCAL_CPP_FEATURES := rtti exceptions\n";
- for (auto const& property : properties) {
- if (property.first == "INTERFACE_COMPILE_OPTIONS") {
- os << "LOCAL_CPP_FEATURES += ";
- os << (property.second) << "\n";
- } else if (property.first == "INTERFACE_LINK_LIBRARIES") {
- std::string staticLibs;
- std::string sharedLibs;
- std::string ldlibs;
- cmLinkInterfaceLibraries const* linkIFace =
- target->GetLinkInterfaceLibraries(config, target,
- cmGeneratorTarget::UseTo::Link);
- for (cmLinkItem const& item : linkIFace->Libraries) {
- cmGeneratorTarget const* gt = item.Target;
- std::string const& lib = item.AsStr();
- if (gt) {
-
- if (gt->GetType() == cmStateEnums::SHARED_LIBRARY ||
- gt->GetType() == cmStateEnums::MODULE_LIBRARY) {
- sharedLibs += " " + lib;
- } else {
- staticLibs += " " + lib;
- }
- } else {
- bool relpath = false;
- if (type == cmExportBuildAndroidMKGenerator::INSTALL) {
- relpath = cmHasLiteralPrefix(lib, "../");
- }
- // check for full path or if it already has a -l, or
- // in the case of an install check for relative paths
- // if it is full or a link library then use string directly
- if (cmSystemTools::FileIsFullPath(lib) ||
- cmHasLiteralPrefix(lib, "-l") || relpath) {
- ldlibs += " " + lib;
- // if it is not a path and does not have a -l then add -l
- } else if (!lib.empty()) {
- ldlibs += " -l" + lib;
- }
- }
- }
- if (!sharedLibs.empty()) {
- os << "LOCAL_SHARED_LIBRARIES :=" << sharedLibs << "\n";
- }
- if (!staticLibs.empty()) {
- os << "LOCAL_STATIC_LIBRARIES :=" << staticLibs << "\n";
- }
- if (!ldlibs.empty()) {
- os << "LOCAL_EXPORT_LDLIBS :=" << ldlibs << "\n";
- }
- } else if (property.first == "INTERFACE_INCLUDE_DIRECTORIES") {
- std::string includes = property.second;
- cmList includeList{ includes };
- os << "LOCAL_EXPORT_C_INCLUDES := ";
- std::string end;
- for (std::string const& i : includeList) {
- os << end << i;
- end = "\\\n";
- }
- os << "\n";
- } else if (property.first == "INTERFACE_LINK_OPTIONS") {
- os << "LOCAL_EXPORT_LDFLAGS := ";
- cmList linkFlagsList{ property.second };
- os << linkFlagsList.join(" ") << "\n";
- } else {
- os << "# " << property.first << " " << (property.second) << "\n";
- }
- }
- }
-
- // Tell the NDK build system if prebuilt static libraries use C++.
- if (target->GetType() == cmStateEnums::STATIC_LIBRARY) {
- cmLinkImplementation const* li =
- target->GetLinkImplementation(config, cmGeneratorTarget::UseTo::Link);
- if (cm::contains(li->Languages, "CXX")) {
- os << "LOCAL_HAS_CPP := true\n";
- }
- }
-
- switch (target->GetType()) {
- case cmStateEnums::SHARED_LIBRARY:
- case cmStateEnums::MODULE_LIBRARY:
- os << "include $(PREBUILT_SHARED_LIBRARY)\n";
- break;
- case cmStateEnums::STATIC_LIBRARY:
- os << "include $(PREBUILT_STATIC_LIBRARY)\n";
- break;
- case cmStateEnums::EXECUTABLE:
- case cmStateEnums::UTILITY:
- case cmStateEnums::OBJECT_LIBRARY:
- case cmStateEnums::GLOBAL_TARGET:
- case cmStateEnums::INTERFACE_LIBRARY:
- case cmStateEnums::UNKNOWN_LIBRARY:
- break;
- }
- os << "\n";
-}
diff --git a/Source/cmExportBuildAndroidMKGenerator.h b/Source/cmExportBuildAndroidMKGenerator.h
index 2f5a301..deb3893 100644
--- a/Source/cmExportBuildAndroidMKGenerator.h
+++ b/Source/cmExportBuildAndroidMKGenerator.h
@@ -7,6 +7,7 @@
#include <iosfwd>
#include <string>
+#include "cmExportAndroidMKGenerator.h"
#include "cmExportBuildFileGenerator.h"
#include "cmStateTypes.h"
@@ -21,42 +22,26 @@ class cmGeneratorTarget;
*
* This is used to implement the export() command.
*/
-class cmExportBuildAndroidMKGenerator : public cmExportBuildFileGenerator
+class cmExportBuildAndroidMKGenerator
+ : public cmExportBuildFileGenerator
+ , public cmExportAndroidMKGenerator
{
public:
cmExportBuildAndroidMKGenerator();
- // this is so cmExportInstallAndroidMKGenerator can share this
- // function as they are almost the same
- enum GenerateType
- {
- BUILD,
- INSTALL
- };
- static void GenerateInterfaceProperties(cmGeneratorTarget const* target,
- std::ostream& os,
- ImportPropertyMap const& properties,
- GenerateType type,
- std::string const& config);
+
+ /** Set whether to append generated code to the output file. */
+ void SetAppendMode(bool append) { this->AppendMode = append; }
protected:
+ GenerateType GetGenerateType() const override { return BUILD; }
+
// Implement virtual methods from the superclass.
- void GeneratePolicyHeaderCode(std::ostream&) override {}
- void GeneratePolicyFooterCode(std::ostream&) override {}
+ bool GenerateMainFile(std::ostream& os) override;
void GenerateImportHeaderCode(std::ostream& os,
std::string const& config = "") override;
- void GenerateImportFooterCode(std::ostream& os) override;
void GenerateImportTargetCode(
std::ostream& os, cmGeneratorTarget const* target,
cmStateEnums::TargetType /*targetType*/) override;
- void GenerateExpectedTargetsCode(
- std::ostream& os, std::string const& expectedTargets) override;
- void GenerateImportPropertyCode(
- std::ostream& os, std::string const& config, std::string const& suffix,
- cmGeneratorTarget const* target, ImportPropertyMap const& properties,
- std::string const& importedXcFrameworkLocation) override;
- void GenerateMissingTargetsCheckCode(std::ostream& os) override;
- void GenerateFindDependencyCalls(std::ostream&) override {}
- void GenerateInterfaceProperties(
- cmGeneratorTarget const* target, std::ostream& os,
- ImportPropertyMap const& properties) override;
+
+ std::string GetCxxModulesDirectory() const override { return {}; }
};
diff --git a/Source/cmExportBuildCMakeConfigGenerator.cxx b/Source/cmExportBuildCMakeConfigGenerator.cxx
index cb4f80b..87aeb3c 100644
--- a/Source/cmExportBuildCMakeConfigGenerator.cxx
+++ b/Source/cmExportBuildCMakeConfigGenerator.cxx
@@ -9,6 +9,7 @@
#include <set>
#include <sstream>
#include <utility>
+#include <vector>
#include <cm/string_view>
#include <cmext/string_view>
@@ -19,8 +20,6 @@
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
-#include "cmGlobalGenerator.h"
-#include "cmList.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
@@ -30,11 +29,6 @@
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
-#include "cmTargetExport.h"
-#include "cmValue.h"
-#include "cmake.h"
-
-class cmSourceFile;
cmExportBuildCMakeConfigGenerator::cmExportBuildCMakeConfigGenerator()
{
@@ -42,38 +36,22 @@ cmExportBuildCMakeConfigGenerator::cmExportBuildCMakeConfigGenerator()
this->ExportSet = nullptr;
}
-void cmExportBuildCMakeConfigGenerator::Compute(cmLocalGenerator* lg)
-{
- this->LG = lg;
- if (this->ExportSet) {
- this->ExportSet->Compute(lg);
- }
-}
-
bool cmExportBuildCMakeConfigGenerator::GenerateMainFile(std::ostream& os)
{
{
std::string expectedTargets;
std::string sep;
- std::vector<TargetExport> targets;
bool generatedInterfaceRequired = false;
- this->GetTargets(targets);
- for (auto const& tei : targets) {
- cmGeneratorTarget* te = this->LG->FindGeneratorTargetToUse(tei.Name);
+ auto visitor = [&](cmGeneratorTarget const* te) {
expectedTargets += sep + this->Namespace + te->GetExportName();
sep = " ";
- if (this->ExportedTargets.insert(te).second) {
- this->Exports.emplace_back(te, tei.XcFrameworkLocation);
- } else {
- std::ostringstream e;
- e << "given target \"" << te->GetName() << "\" more than once.";
- this->LG->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage(
- MessageType::FATAL_ERROR, e.str(),
- this->LG->GetMakefile()->GetBacktrace());
- return false;
- }
+
generatedInterfaceRequired |=
this->GetExportTargetType(te) == cmStateEnums::INTERFACE_LIBRARY;
+ };
+
+ if (!this->CollectExports(visitor)) {
+ return false;
}
if (generatedInterfaceRequired) {
@@ -90,57 +68,7 @@ bool cmExportBuildCMakeConfigGenerator::GenerateMainFile(std::ostream& os)
gte->Target->AppendBuildInterfaceIncludes();
ImportPropertyMap properties;
-
- this->PopulateInterfaceProperty("INTERFACE_INCLUDE_DIRECTORIES", gte,
- cmGeneratorExpression::BuildInterface,
- properties);
- this->PopulateInterfaceProperty("INTERFACE_SOURCES", gte,
- cmGeneratorExpression::BuildInterface,
- properties);
- this->PopulateInterfaceProperty("INTERFACE_COMPILE_DEFINITIONS", gte,
- cmGeneratorExpression::BuildInterface,
- properties);
- this->PopulateInterfaceProperty("INTERFACE_COMPILE_OPTIONS", gte,
- cmGeneratorExpression::BuildInterface,
- properties);
- this->PopulateInterfaceProperty("INTERFACE_PRECOMPILE_HEADERS", gte,
- cmGeneratorExpression::BuildInterface,
- properties);
- this->PopulateInterfaceProperty("INTERFACE_AUTOUIC_OPTIONS", gte,
- cmGeneratorExpression::BuildInterface,
- properties);
- this->PopulateInterfaceProperty("INTERFACE_AUTOMOC_MACRO_NAMES", gte,
- cmGeneratorExpression::BuildInterface,
- properties);
- this->PopulateInterfaceProperty("INTERFACE_COMPILE_FEATURES", gte,
- cmGeneratorExpression::BuildInterface,
- properties);
- this->PopulateInterfaceProperty("INTERFACE_LINK_OPTIONS", gte,
- cmGeneratorExpression::BuildInterface,
- properties);
- this->PopulateInterfaceProperty("INTERFACE_LINK_DIRECTORIES", gte,
- cmGeneratorExpression::BuildInterface,
- properties);
- this->PopulateInterfaceProperty("INTERFACE_LINK_DEPENDS", gte,
- cmGeneratorExpression::BuildInterface,
- properties);
- this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE", gte,
- properties);
-
- std::string errorMessage;
- if (!this->PopulateCxxModuleExportProperties(
- gte, properties, cmGeneratorExpression::BuildInterface, {},
- errorMessage)) {
- this->LG->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage(
- MessageType::FATAL_ERROR, errorMessage,
- this->LG->GetMakefile()->GetBacktrace());
- return false;
- }
-
- if (!this->PopulateExportProperties(gte, properties, errorMessage)) {
- this->LG->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage(
- MessageType::FATAL_ERROR, errorMessage,
- this->LG->GetMakefile()->GetBacktrace());
+ if (!this->PopulateInterfaceProperties(gte, properties)) {
return false;
}
@@ -151,9 +79,6 @@ bool cmExportBuildCMakeConfigGenerator::GenerateMainFile(std::ostream& os)
this->PopulateInterfaceLinkLibrariesProperty(
gte, cmGeneratorExpression::BuildInterface, properties);
}
- this->PopulateCompatibleInterfaceProperties(gte, properties);
- this->PopulateCustomTransitiveInterfaceProperties(
- gte, cmGeneratorExpression::BuildInterface, properties);
this->GenerateInterfaceProperties(gte, os, properties);
@@ -239,185 +164,6 @@ void cmExportBuildCMakeConfigGenerator::GenerateImportTargetsConfig(
}
}
-cmStateEnums::TargetType
-cmExportBuildCMakeConfigGenerator::GetExportTargetType(
- cmGeneratorTarget const* target) const
-{
- cmStateEnums::TargetType targetType = target->GetType();
- // An object library exports as an interface library if we cannot
- // tell clients where to find the objects. This is sufficient
- // to support transitive usage requirements on other targets that
- // use the object library.
- if (targetType == cmStateEnums::OBJECT_LIBRARY &&
- !target->Target->HasKnownObjectFileLocation(nullptr)) {
- targetType = cmStateEnums::INTERFACE_LIBRARY;
- }
- return targetType;
-}
-
-void cmExportBuildCMakeConfigGenerator::SetExportSet(cmExportSet* exportSet)
-{
- this->ExportSet = exportSet;
-}
-
-void cmExportBuildCMakeConfigGenerator::SetImportLocationProperty(
- std::string const& config, std::string const& suffix,
- cmGeneratorTarget* target, ImportPropertyMap& properties)
-{
- // Get the makefile in which to lookup target information.
- cmMakefile* mf = target->Makefile;
-
- if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
- std::string prop = cmStrCat("IMPORTED_OBJECTS", suffix);
-
- // Compute all the object files inside this target and setup
- // IMPORTED_OBJECTS as a list of object files
- std::vector<cmSourceFile const*> objectSources;
- target->GetObjectSources(objectSources, config);
- std::string const obj_dir = target->GetObjectDirectory(config);
- std::vector<std::string> objects;
- for (cmSourceFile const* sf : objectSources) {
- std::string const& obj = target->GetObjectName(sf);
- objects.push_back(obj_dir + obj);
- }
-
- // Store the property.
- properties[prop] = cmList::to_string(objects);
- } else {
- // Add the main target file.
- {
- std::string prop = cmStrCat("IMPORTED_LOCATION", suffix);
- std::string value;
- if (target->IsAppBundleOnApple()) {
- value =
- target->GetFullPath(config, cmStateEnums::RuntimeBinaryArtifact);
- } else {
- value = target->GetFullPath(config,
- cmStateEnums::RuntimeBinaryArtifact, true);
- }
- properties[prop] = value;
- }
-
- // Add the import library for windows DLLs.
- if (target->HasImportLibrary(config)) {
- std::string prop = cmStrCat("IMPORTED_IMPLIB", suffix);
- std::string value =
- target->GetFullPath(config, cmStateEnums::ImportLibraryArtifact, true);
- if (mf->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX")) {
- target->GetImplibGNUtoMS(config, value, value,
- "${CMAKE_IMPORT_LIBRARY_SUFFIX}");
- }
- properties[prop] = value;
- }
- }
-}
-
-void cmExportBuildCMakeConfigGenerator::HandleMissingTarget(
- std::string& link_libs, cmGeneratorTarget const* depender,
- cmGeneratorTarget* dependee)
-{
- // The target is not in the export.
- if (!this->AppendMode) {
- std::string const name = dependee->GetName();
- cmGlobalGenerator* gg =
- dependee->GetLocalGenerator()->GetGlobalGenerator();
- auto exportInfo = this->FindBuildExportInfo(gg, name);
- std::vector<std::string> const& exportFiles = exportInfo.first;
-
- if (exportFiles.size() == 1) {
- std::string missingTarget = exportInfo.second;
-
- missingTarget += dependee->GetExportName();
- link_libs += missingTarget;
- this->MissingTargets.emplace_back(std::move(missingTarget));
- return;
- }
- // We are not appending, so all exported targets should be
- // known here. This is probably user-error.
- this->ComplainAboutMissingTarget(depender, dependee, exportFiles);
- }
- // Assume the target will be exported by another command.
- // Append it with the export namespace.
- link_libs += this->Namespace;
- link_libs += dependee->GetExportName();
-}
-
-void cmExportBuildCMakeConfigGenerator::GetTargets(
- std::vector<TargetExport>& targets) const
-{
- if (this->ExportSet) {
- for (std::unique_ptr<cmTargetExport> const& te :
- this->ExportSet->GetTargetExports()) {
- if (te->NamelinkOnly) {
- continue;
- }
- targets.emplace_back(te->TargetName, te->XcFrameworkLocation);
- }
- return;
- }
- targets = this->Targets;
-}
-
-std::pair<std::vector<std::string>, std::string>
-cmExportBuildCMakeConfigGenerator::FindBuildExportInfo(cmGlobalGenerator* gg,
- std::string const& name)
-{
- std::vector<std::string> exportFiles;
- std::string ns;
-
- auto& exportSets = gg->GetBuildExportSets();
-
- for (auto const& exp : exportSets) {
- auto const& exportSet = exp.second;
- std::vector<TargetExport> targets;
- exportSet->GetTargets(targets);
- if (std::any_of(
- targets.begin(), targets.end(),
- [&name](TargetExport const& te) { return te.Name == name; })) {
- exportFiles.push_back(exp.first);
- ns = exportSet->GetNamespace();
- }
- }
-
- return { exportFiles, ns };
-}
-
-void cmExportBuildCMakeConfigGenerator::ComplainAboutMissingTarget(
- cmGeneratorTarget const* depender, cmGeneratorTarget const* dependee,
- std::vector<std::string> const& exportFiles)
-{
- std::ostringstream e;
- e << "export called with target \"" << depender->GetName()
- << "\" which requires target \"" << dependee->GetName() << "\" ";
- if (exportFiles.empty()) {
- e << "that is not in any export set.";
- } else {
- e << "that is not in this export set, but in multiple other export sets: "
- << cmJoin(exportFiles, ", ") << ".\n";
- e << "An exported target cannot depend upon another target which is "
- "exported multiple times. Consider consolidating the exports of the "
- "\""
- << dependee->GetName() << "\" target to a single export.";
- }
-
- this->LG->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage(
- MessageType::FATAL_ERROR, e.str(),
- this->LG->GetMakefile()->GetBacktrace());
-}
-
-std::string cmExportBuildCMakeConfigGenerator::InstallNameDir(
- cmGeneratorTarget const* target, std::string const& config)
-{
- std::string install_name_dir;
-
- cmMakefile* mf = target->Target->GetMakefile();
- if (mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) {
- install_name_dir = target->GetInstallNameDirForBuildTree(config);
- }
-
- return install_name_dir;
-}
-
namespace {
bool EntryIsContextSensitive(
std::unique_ptr<cmCompiledGeneratorExpression> const& cge)
@@ -427,7 +173,7 @@ bool EntryIsContextSensitive(
}
std::string cmExportBuildCMakeConfigGenerator::GetFileSetDirectories(
- cmGeneratorTarget* gte, cmFileSet* fileSet, cmTargetExport* /*te*/)
+ cmGeneratorTarget* gte, cmFileSet* fileSet, cmTargetExport const* /*te*/)
{
std::vector<std::string> resultVector;
@@ -475,7 +221,7 @@ std::string cmExportBuildCMakeConfigGenerator::GetFileSetDirectories(
}
std::string cmExportBuildCMakeConfigGenerator::GetFileSetFiles(
- cmGeneratorTarget* gte, cmFileSet* fileSet, cmTargetExport* /*te*/)
+ cmGeneratorTarget* gte, cmFileSet* fileSet, cmTargetExport const* /*te*/)
{
std::vector<std::string> resultVector;
@@ -536,11 +282,6 @@ std::string cmExportBuildCMakeConfigGenerator::GetFileSetFiles(
return cmJoin(resultVector, " ");
}
-std::string cmExportBuildCMakeConfigGenerator::GetCxxModulesDirectory() const
-{
- return this->CxxModulesDirectory;
-}
-
void cmExportBuildCMakeConfigGenerator::GenerateCxxModuleConfigInformation(
std::string const& name, std::ostream& os) const
{
diff --git a/Source/cmExportBuildCMakeConfigGenerator.h b/Source/cmExportBuildCMakeConfigGenerator.h
index 0ba2a2b..0648dc3 100644
--- a/Source/cmExportBuildCMakeConfigGenerator.h
+++ b/Source/cmExportBuildCMakeConfigGenerator.h
@@ -6,130 +6,47 @@
#include <iosfwd>
#include <string>
-#include <utility>
-#include <vector>
-#include <cmext/algorithm>
+#include "cmExportBuildFileGenerator.h"
+#include "cmExportCMakeConfigGenerator.h"
-#include "cmExportFileGenerator.h"
-#include "cmStateTypes.h"
-
-class cmExportSet;
class cmFileSet;
class cmGeneratorTarget;
-class cmGlobalGenerator;
-class cmLocalGenerator;
class cmTargetExport;
/** \class cmExportBuildCMakeConfigGenerator
* \brief Generate a file exporting targets from a build tree.
*
* cmExportBuildCMakeConfigGenerator generates a file exporting targets from
- * a build tree. A single file exports information for all
+ * a build tree. This exports the targets to CMake's native package
+ * configuration format. A single file exports information for all
* configurations built.
*
* This is used to implement the export() command.
*/
-class cmExportBuildCMakeConfigGenerator : public cmExportFileGenerator
+class cmExportBuildCMakeConfigGenerator
+ : public cmExportCMakeConfigGenerator
+ , public cmExportBuildFileGenerator
{
public:
- struct TargetExport
- {
- TargetExport(std::string name, std::string xcFrameworkLocation)
- : Name(std::move(name))
- , XcFrameworkLocation(std::move(xcFrameworkLocation))
- {
- }
-
- std::string Name;
- std::string XcFrameworkLocation;
- };
-
cmExportBuildCMakeConfigGenerator();
- /** Set the list of targets to export. */
- void SetTargets(std::vector<TargetExport> const& targets)
- {
- this->Targets = targets;
- }
- void GetTargets(std::vector<TargetExport>& targets) const;
- void AppendTargets(std::vector<TargetExport> const& targets)
- {
- cm::append(this->Targets, targets);
- }
- void SetExportSet(cmExportSet*);
-
- /** Set the name of the C++ module directory. */
- void SetCxxModuleDirectory(std::string cxx_module_dir)
- {
- this->CxxModulesDirectory = std::move(cxx_module_dir);
- }
- std::string const& GetCxxModuleDirectory() const
- {
- return this->CxxModulesDirectory;
- }
-
/** Set whether to append generated code to the output file. */
void SetAppendMode(bool append) { this->AppendMode = append; }
- void Compute(cmLocalGenerator* lg);
-
protected:
// Implement virtual methods from the superclass.
bool GenerateMainFile(std::ostream& os) override;
void GenerateImportTargetsConfig(std::ostream& os, std::string const& config,
std::string const& suffix) override;
- cmStateEnums::TargetType GetExportTargetType(
- cmGeneratorTarget const* target) const;
- void HandleMissingTarget(std::string& link_libs,
- cmGeneratorTarget const* depender,
- cmGeneratorTarget* dependee) override;
-
- void ComplainAboutMissingTarget(cmGeneratorTarget const* depender,
- cmGeneratorTarget const* dependee,
- std::vector<std::string> const& namespaces);
-
- /** Fill in properties indicating built file locations. */
- void SetImportLocationProperty(std::string const& config,
- std::string const& suffix,
- cmGeneratorTarget* target,
- ImportPropertyMap& properties);
-
- std::string InstallNameDir(cmGeneratorTarget const* target,
- std::string const& config) override;
std::string GetFileSetDirectories(cmGeneratorTarget* gte, cmFileSet* fileSet,
- cmTargetExport* te) override;
+ cmTargetExport const* te) override;
std::string GetFileSetFiles(cmGeneratorTarget* gte, cmFileSet* fileSet,
- cmTargetExport* te) override;
- cmExportSet* GetExportSet() const override { return this->ExportSet; }
+ cmTargetExport const* te) override;
- std::string GetCxxModulesDirectory() const override;
void GenerateCxxModuleConfigInformation(std::string const&,
std::ostream&) const override;
bool GenerateImportCxxModuleConfigTargetInclusion(std::string const&,
std::string) const;
-
- std::pair<std::vector<std::string>, std::string> FindBuildExportInfo(
- cmGlobalGenerator* gg, std::string const& name);
-
- struct TargetExportPrivate
- {
- TargetExportPrivate(cmGeneratorTarget* target,
- std::string xcFrameworkLocation)
- : Target(target)
- , XcFrameworkLocation(std::move(xcFrameworkLocation))
- {
- }
-
- cmGeneratorTarget* Target;
- std::string XcFrameworkLocation;
- };
-
- std::vector<TargetExport> Targets;
- cmExportSet* ExportSet;
- std::vector<TargetExportPrivate> Exports;
- cmLocalGenerator* LG;
- // The directory for C++ module information.
- std::string CxxModulesDirectory;
};
diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx
index 2885de0..73a4585 100644
--- a/Source/cmExportBuildFileGenerator.cxx
+++ b/Source/cmExportBuildFileGenerator.cxx
@@ -3,20 +3,13 @@
#include "cmExportBuildFileGenerator.h"
#include <algorithm>
-#include <cstddef>
#include <map>
#include <memory>
#include <set>
#include <sstream>
#include <utility>
-#include <cm/string_view>
-#include <cmext/string_view>
-
-#include "cmCryptoHash.h"
#include "cmExportSet.h"
-#include "cmFileSet.h"
-#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
@@ -24,11 +17,8 @@
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
-#include "cmOutputConverter.h"
-#include "cmPolicies.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
-#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTargetExport.h"
#include "cmValue.h"
@@ -50,195 +40,6 @@ void cmExportBuildFileGenerator::Compute(cmLocalGenerator* lg)
}
}
-bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
-{
- {
- std::string expectedTargets;
- std::string sep;
- std::vector<TargetExport> targets;
- bool generatedInterfaceRequired = false;
- this->GetTargets(targets);
- for (auto const& tei : targets) {
- cmGeneratorTarget* te = this->LG->FindGeneratorTargetToUse(tei.Name);
- expectedTargets += sep + this->Namespace + te->GetExportName();
- sep = " ";
- if (this->ExportedTargets.insert(te).second) {
- this->Exports.emplace_back(te, tei.XcFrameworkLocation);
- } else {
- std::ostringstream e;
- e << "given target \"" << te->GetName() << "\" more than once.";
- this->LG->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage(
- MessageType::FATAL_ERROR, e.str(),
- this->LG->GetMakefile()->GetBacktrace());
- return false;
- }
- generatedInterfaceRequired |=
- this->GetExportTargetType(te) == cmStateEnums::INTERFACE_LIBRARY;
- }
-
- if (generatedInterfaceRequired) {
- this->SetRequiredCMakeVersion(3, 0, 0);
- }
- this->GenerateExpectedTargetsCode(os, expectedTargets);
- }
-
- // Create all the imported targets.
- for (auto const& exp : this->Exports) {
- cmGeneratorTarget* gte = exp.Target;
- this->GenerateImportTargetCode(os, gte, this->GetExportTargetType(gte));
-
- gte->Target->AppendBuildInterfaceIncludes();
-
- ImportPropertyMap properties;
-
- this->PopulateInterfaceProperty("INTERFACE_INCLUDE_DIRECTORIES", gte,
- cmGeneratorExpression::BuildInterface,
- properties);
- this->PopulateInterfaceProperty("INTERFACE_SOURCES", gte,
- cmGeneratorExpression::BuildInterface,
- properties);
- this->PopulateInterfaceProperty("INTERFACE_COMPILE_DEFINITIONS", gte,
- cmGeneratorExpression::BuildInterface,
- properties);
- this->PopulateInterfaceProperty("INTERFACE_COMPILE_OPTIONS", gte,
- cmGeneratorExpression::BuildInterface,
- properties);
- this->PopulateInterfaceProperty("INTERFACE_PRECOMPILE_HEADERS", gte,
- cmGeneratorExpression::BuildInterface,
- properties);
- this->PopulateInterfaceProperty("INTERFACE_AUTOUIC_OPTIONS", gte,
- cmGeneratorExpression::BuildInterface,
- properties);
- this->PopulateInterfaceProperty("INTERFACE_AUTOMOC_MACRO_NAMES", gte,
- cmGeneratorExpression::BuildInterface,
- properties);
- this->PopulateInterfaceProperty("INTERFACE_COMPILE_FEATURES", gte,
- cmGeneratorExpression::BuildInterface,
- properties);
- this->PopulateInterfaceProperty("INTERFACE_LINK_OPTIONS", gte,
- cmGeneratorExpression::BuildInterface,
- properties);
- this->PopulateInterfaceProperty("INTERFACE_LINK_DIRECTORIES", gte,
- cmGeneratorExpression::BuildInterface,
- properties);
- this->PopulateInterfaceProperty("INTERFACE_LINK_DEPENDS", gte,
- cmGeneratorExpression::BuildInterface,
- properties);
- this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE", gte,
- properties);
-
- std::string errorMessage;
- if (!this->PopulateCxxModuleExportProperties(
- gte, properties, cmGeneratorExpression::BuildInterface, {},
- errorMessage)) {
- this->LG->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage(
- MessageType::FATAL_ERROR, errorMessage,
- this->LG->GetMakefile()->GetBacktrace());
- return false;
- }
-
- if (!this->PopulateExportProperties(gte, properties, errorMessage)) {
- this->LG->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage(
- MessageType::FATAL_ERROR, errorMessage,
- this->LG->GetMakefile()->GetBacktrace());
- return false;
- }
-
- bool const newCMP0022Behavior =
- gte->GetPolicyStatusCMP0022() != cmPolicies::WARN &&
- gte->GetPolicyStatusCMP0022() != cmPolicies::OLD;
- if (newCMP0022Behavior) {
- this->PopulateInterfaceLinkLibrariesProperty(
- gte, cmGeneratorExpression::BuildInterface, properties);
- }
- this->PopulateCompatibleInterfaceProperties(gte, properties);
- this->PopulateCustomTransitiveInterfaceProperties(
- gte, cmGeneratorExpression::BuildInterface, properties);
-
- this->GenerateInterfaceProperties(gte, os, properties);
-
- this->GenerateTargetFileSets(gte, os);
- }
-
- std::string cxx_modules_name;
- if (this->ExportSet) {
- cxx_modules_name = this->ExportSet->GetName();
- } else {
- cmCryptoHash hasher(cmCryptoHash::AlgoSHA3_512);
- constexpr std::size_t HASH_TRUNCATION = 12;
- for (auto const& target : this->Targets) {
- hasher.Append(target.Name);
- }
- cxx_modules_name = hasher.FinalizeHex().substr(0, HASH_TRUNCATION);
- }
-
- this->GenerateCxxModuleInformation(cxx_modules_name, os);
-
- // Generate import file content for each configuration.
- for (std::string const& c : this->Configurations) {
- this->GenerateImportConfig(os, c);
- }
-
- // Generate import file content for each configuration.
- for (std::string const& c : this->Configurations) {
- this->GenerateImportCxxModuleConfigTargetInclusion(cxx_modules_name, c);
- }
-
- this->GenerateMissingTargetsCheckCode(os);
-
- return true;
-}
-
-void cmExportBuildFileGenerator::GenerateImportTargetsConfig(
- std::ostream& os, std::string const& config, std::string const& suffix)
-{
- for (auto const& exp : this->Exports) {
- cmGeneratorTarget* target = exp.Target;
-
- // Collect import properties for this target.
- ImportPropertyMap properties;
-
- if (this->GetExportTargetType(target) != cmStateEnums::INTERFACE_LIBRARY) {
- this->SetImportLocationProperty(config, suffix, target, properties);
- }
- if (!properties.empty()) {
- // Get the rest of the target details.
- if (this->GetExportTargetType(target) !=
- cmStateEnums::INTERFACE_LIBRARY) {
- this->SetImportDetailProperties(config, suffix, target, properties);
- this->SetImportLinkInterface(config, suffix,
- cmGeneratorExpression::BuildInterface,
- target, properties);
- }
-
- // TODO: PUBLIC_HEADER_LOCATION
- // This should wait until the build feature propagation stuff
- // is done. Then this can be a propagated include directory.
- // this->GenerateImportProperty(config, te->HeaderGenerator,
- // properties);
-
- // Generate code in the export file.
- std::string importedXcFrameworkLocation = exp.XcFrameworkLocation;
- if (!importedXcFrameworkLocation.empty()) {
- importedXcFrameworkLocation = cmGeneratorExpression::Preprocess(
- importedXcFrameworkLocation,
- cmGeneratorExpression::PreprocessContext::BuildInterface);
- importedXcFrameworkLocation = cmGeneratorExpression::Evaluate(
- importedXcFrameworkLocation, exp.Target->GetLocalGenerator(), config,
- exp.Target, nullptr, exp.Target);
- if (!importedXcFrameworkLocation.empty() &&
- !cmSystemTools::FileIsFullPath(importedXcFrameworkLocation)) {
- importedXcFrameworkLocation =
- cmStrCat(this->LG->GetCurrentBinaryDirectory(), '/',
- importedXcFrameworkLocation);
- }
- }
- this->GenerateImportPropertyCode(os, config, suffix, target, properties,
- importedXcFrameworkLocation);
- }
- }
-}
-
cmStateEnums::TargetType cmExportBuildFileGenerator::GetExportTargetType(
cmGeneratorTarget const* target) const
{
@@ -311,13 +112,32 @@ void cmExportBuildFileGenerator::SetImportLocationProperty(
}
}
+bool cmExportBuildFileGenerator::CollectExports(
+ std::function<void(cmGeneratorTarget const*)> visitor)
+{
+ std::vector<TargetExport> targets;
+ this->GetTargets(targets);
+ for (auto const& tei : targets) {
+ cmGeneratorTarget* te = this->LG->FindGeneratorTargetToUse(tei.Name);
+ if (this->ExportedTargets.insert(te).second) {
+ this->Exports.emplace_back(te, tei.XcFrameworkLocation);
+ visitor(te);
+ } else {
+ this->ComplainAboutDuplicateTarget(te->GetName());
+ return false;
+ }
+ }
+
+ return true;
+}
+
void cmExportBuildFileGenerator::HandleMissingTarget(
std::string& link_libs, cmGeneratorTarget const* depender,
cmGeneratorTarget* dependee)
{
// The target is not in the export.
if (!this->AppendMode) {
- std::string const name = dependee->GetName();
+ std::string const& name = dependee->GetName();
cmGlobalGenerator* gg =
dependee->GetLocalGenerator()->GetGlobalGenerator();
auto exportInfo = this->FindBuildExportInfo(gg, name);
@@ -383,7 +203,7 @@ cmExportBuildFileGenerator::FindBuildExportInfo(cmGlobalGenerator* gg,
void cmExportBuildFileGenerator::ComplainAboutMissingTarget(
cmGeneratorTarget const* depender, cmGeneratorTarget const* dependee,
- std::vector<std::string> const& exportFiles)
+ std::vector<std::string> const& exportFiles) const
{
std::ostringstream e;
e << "export called with target \"" << depender->GetName()
@@ -399,8 +219,22 @@ void cmExportBuildFileGenerator::ComplainAboutMissingTarget(
<< dependee->GetName() << "\" target to a single export.";
}
+ this->ReportError(e.str());
+}
+
+void cmExportBuildFileGenerator::ComplainAboutDuplicateTarget(
+ std::string const& targetName) const
+{
+ std::ostringstream e;
+ e << "given target \"" << targetName << "\" more than once.";
+ this->ReportError(e.str());
+}
+
+void cmExportBuildFileGenerator::ReportError(
+ std::string const& errorMessage) const
+{
this->LG->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage(
- MessageType::FATAL_ERROR, e.str(),
+ MessageType::FATAL_ERROR, errorMessage,
this->LG->GetMakefile()->GetBacktrace());
}
@@ -417,185 +251,22 @@ std::string cmExportBuildFileGenerator::InstallNameDir(
return install_name_dir;
}
-namespace {
-bool EntryIsContextSensitive(
- std::unique_ptr<cmCompiledGeneratorExpression> const& cge)
-{
- return cge->GetHadContextSensitiveCondition();
-}
-}
-
-std::string cmExportBuildFileGenerator::GetFileSetDirectories(
- cmGeneratorTarget* gte, cmFileSet* fileSet, cmTargetExport* /*te*/)
-{
- std::vector<std::string> resultVector;
-
- auto configs =
- gte->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
- auto directoryEntries = fileSet->CompileDirectoryEntries();
-
- for (auto const& config : configs) {
- auto directories = fileSet->EvaluateDirectoryEntries(
- directoryEntries, gte->LocalGenerator, config, gte);
-
- bool const contextSensitive =
- std::any_of(directoryEntries.begin(), directoryEntries.end(),
- EntryIsContextSensitive);
-
- auto const& type = fileSet->GetType();
- // C++ modules do not support interface file sets which are dependent upon
- // the configuration.
- if (contextSensitive && type == "CXX_MODULES"_s) {
- auto* mf = this->LG->GetMakefile();
- std::ostringstream e;
- e << "The \"" << gte->GetName() << "\" target's interface file set \""
- << fileSet->GetName() << "\" of type \"" << type
- << "\" contains context-sensitive base directory entries which is not "
- "supported.";
- mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
- return std::string{};
- }
-
- for (auto const& directory : directories) {
- auto dest = cmOutputConverter::EscapeForCMake(
- directory, cmOutputConverter::WrapQuotes::NoWrap);
-
- if (contextSensitive && configs.size() != 1) {
- resultVector.push_back(
- cmStrCat("\"$<$<CONFIG:", config, ">:", dest, ">\""));
- } else {
- resultVector.emplace_back(cmStrCat('"', dest, '"'));
- break;
- }
- }
- }
-
- return cmJoin(resultVector, " ");
-}
-
-std::string cmExportBuildFileGenerator::GetFileSetFiles(cmGeneratorTarget* gte,
- cmFileSet* fileSet,
- cmTargetExport* /*te*/)
-{
- std::vector<std::string> resultVector;
-
- auto configs =
- gte->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
-
- auto fileEntries = fileSet->CompileFileEntries();
- auto directoryEntries = fileSet->CompileDirectoryEntries();
-
- for (auto const& config : configs) {
- auto directories = fileSet->EvaluateDirectoryEntries(
- directoryEntries, gte->LocalGenerator, config, gte);
-
- std::map<std::string, std::vector<std::string>> files;
- for (auto const& entry : fileEntries) {
- fileSet->EvaluateFileEntry(directories, files, entry,
- gte->LocalGenerator, config, gte);
- }
-
- bool const contextSensitive =
- std::any_of(directoryEntries.begin(), directoryEntries.end(),
- EntryIsContextSensitive) ||
- std::any_of(fileEntries.begin(), fileEntries.end(),
- EntryIsContextSensitive);
-
- auto const& type = fileSet->GetType();
- // C++ modules do not support interface file sets which are dependent upon
- // the configuration.
- if (contextSensitive && type == "CXX_MODULES"_s) {
- auto* mf = this->LG->GetMakefile();
- std::ostringstream e;
- e << "The \"" << gte->GetName() << "\" target's interface file set \""
- << fileSet->GetName() << "\" of type \"" << type
- << "\" contains context-sensitive file entries which is not "
- "supported.";
- mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
- return std::string{};
- }
-
- for (auto const& it : files) {
- for (auto const& filename : it.second) {
- auto escapedFile = cmOutputConverter::EscapeForCMake(
- filename, cmOutputConverter::WrapQuotes::NoWrap);
- if (contextSensitive && configs.size() != 1) {
- resultVector.push_back(
- cmStrCat("\"$<$<CONFIG:", config, ">:", escapedFile, ">\""));
- } else {
- resultVector.emplace_back(cmStrCat('"', escapedFile, '"'));
- }
- }
- }
-
- if (!(contextSensitive && configs.size() != 1)) {
- break;
- }
- }
-
- return cmJoin(resultVector, " ");
-}
-
-std::string cmExportBuildFileGenerator::GetCxxModulesDirectory() const
-{
- return this->CxxModulesDirectory;
-}
-
-void cmExportBuildFileGenerator::GenerateCxxModuleConfigInformation(
- std::string const& name, std::ostream& os) const
+bool cmExportBuildFileGenerator::PopulateInterfaceProperties(
+ cmGeneratorTarget const* target, ImportPropertyMap& properties)
{
- char const* opt = "";
- if (this->Configurations.size() > 1) {
- // With more than one configuration, each individual file is optional.
- opt = " OPTIONAL";
- }
-
- // Generate import file content for each configuration.
- for (std::string c : this->Configurations) {
- if (c.empty()) {
- c = "noconfig";
- }
- os << "include(\"${CMAKE_CURRENT_LIST_DIR}/cxx-modules-" << name << '-'
- << c << ".cmake\"" << opt << ")\n";
- }
-}
-
-bool cmExportBuildFileGenerator::GenerateImportCxxModuleConfigTargetInclusion(
- std::string const& name, std::string config) const
-{
- auto cxx_modules_dirname = this->GetCxxModulesDirectory();
- if (cxx_modules_dirname.empty()) {
- return true;
- }
-
- if (config.empty()) {
- config = "noconfig";
- }
-
- std::string fileName =
- cmStrCat(this->FileDir, '/', cxx_modules_dirname, "/cxx-modules-", name,
- '-', config, ".cmake");
-
- cmGeneratedFileStream os(fileName, true);
- if (!os) {
- std::string se = cmSystemTools::GetLastSystemError();
- std::ostringstream e;
- e << "cannot write to file \"" << fileName << "\": " << se;
- cmSystemTools::Error(e.str());
- return false;
- }
- os.SetCopyIfDifferent(true);
-
- for (auto const* tgt : this->ExportedTargets) {
- // Only targets with C++ module sources will have a
- // collator-generated install script.
- if (!tgt->HaveCxx20ModuleSources()) {
- continue;
- }
-
- os << "include(\"${CMAKE_CURRENT_LIST_DIR}/target-"
- << tgt->GetFilesystemExportName() << '-' << config << ".cmake\")\n";
- }
-
- return true;
+ this->PopulateInterfaceProperty("INTERFACE_INCLUDE_DIRECTORIES", target,
+ cmGeneratorExpression::BuildInterface,
+ properties);
+ this->PopulateInterfaceProperty("INTERFACE_LINK_DIRECTORIES", target,
+ cmGeneratorExpression::BuildInterface,
+ properties);
+ this->PopulateInterfaceProperty("INTERFACE_LINK_DEPENDS", target,
+ cmGeneratorExpression::BuildInterface,
+ properties);
+ this->PopulateInterfaceProperty("INTERFACE_SOURCES", target,
+ cmGeneratorExpression::BuildInterface,
+ properties);
+
+ return this->PopulateInterfaceProperties(
+ target, {}, cmGeneratorExpression::BuildInterface, properties);
}
diff --git a/Source/cmExportBuildFileGenerator.h b/Source/cmExportBuildFileGenerator.h
index 3c3d0b2..a4f8c5f 100644
--- a/Source/cmExportBuildFileGenerator.h
+++ b/Source/cmExportBuildFileGenerator.h
@@ -4,7 +4,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
-#include <iosfwd>
+#include <functional>
#include <string>
#include <utility>
#include <vector>
@@ -15,22 +15,19 @@
#include "cmStateTypes.h"
class cmExportSet;
-class cmFileSet;
class cmGeneratorTarget;
class cmGlobalGenerator;
class cmLocalGenerator;
-class cmTargetExport;
-/** \class cmExportBuildFileGenerator
+/** \class cmExportBuildCMakeConfigGenerator
* \brief Generate a file exporting targets from a build tree.
*
- * cmExportBuildFileGenerator generates a file exporting targets from
- * a build tree. A single file exports information for all
- * configurations built.
+ * cmExportBuildCMakeConfigGenerator is the interface class for generating a
+ * file exporting targets from a build tree.
*
* This is used to implement the export() command.
*/
-class cmExportBuildFileGenerator : public cmExportFileGenerator
+class cmExportBuildFileGenerator : virtual public cmExportFileGenerator
{
public:
struct TargetExport
@@ -69,25 +66,28 @@ public:
return this->CxxModulesDirectory;
}
- /** Set whether to append generated code to the output file. */
- void SetAppendMode(bool append) { this->AppendMode = append; }
-
void Compute(cmLocalGenerator* lg);
protected:
- // Implement virtual methods from the superclass.
- bool GenerateMainFile(std::ostream& os) override;
- void GenerateImportTargetsConfig(std::ostream& os, std::string const& config,
- std::string const& suffix) override;
cmStateEnums::TargetType GetExportTargetType(
cmGeneratorTarget const* target) const;
+
+ /** Walk the list of targets to be exported. Returns true iff no duplicates
+ are found. */
+ bool CollectExports(std::function<void(cmGeneratorTarget const*)> visitor);
+
void HandleMissingTarget(std::string& link_libs,
cmGeneratorTarget const* depender,
cmGeneratorTarget* dependee) override;
- void ComplainAboutMissingTarget(cmGeneratorTarget const* depender,
- cmGeneratorTarget const* dependee,
- std::vector<std::string> const& namespaces);
+ void ComplainAboutMissingTarget(
+ cmGeneratorTarget const* depender, cmGeneratorTarget const* dependee,
+ std::vector<std::string> const& namespaces) const;
+
+ void ComplainAboutDuplicateTarget(
+ std::string const& targetName) const override;
+
+ void ReportError(std::string const& errorMessage) const override;
/** Fill in properties indicating built file locations. */
void SetImportLocationProperty(std::string const& config,
@@ -98,21 +98,20 @@ protected:
std::string InstallNameDir(cmGeneratorTarget const* target,
std::string const& config) override;
- std::string GetFileSetDirectories(cmGeneratorTarget* gte, cmFileSet* fileSet,
- 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::string const&,
- std::ostream&) const override;
- bool GenerateImportCxxModuleConfigTargetInclusion(std::string const&,
- std::string) const;
+ std::string GetCxxModulesDirectory() const override
+ {
+ return this->CxxModulesDirectory;
+ }
std::pair<std::vector<std::string>, std::string> FindBuildExportInfo(
cmGlobalGenerator* gg, std::string const& name);
+ using cmExportFileGenerator::PopulateInterfaceProperties;
+ bool PopulateInterfaceProperties(cmGeneratorTarget const* target,
+ ImportPropertyMap& properties);
+
struct TargetExportPrivate
{
TargetExportPrivate(cmGeneratorTarget* target,
diff --git a/Source/cmExportCMakeConfigGenerator.cxx b/Source/cmExportCMakeConfigGenerator.cxx
index b7849a0..4f4765c 100644
--- a/Source/cmExportCMakeConfigGenerator.cxx
+++ b/Source/cmExportCMakeConfigGenerator.cxx
@@ -3,33 +3,26 @@
#include "cmExportCMakeConfigGenerator.h"
#include <algorithm>
-#include <array>
#include <cassert>
-#include <cstring>
#include <sstream>
#include <utility>
+#include <vector>
-#include <cm/memory>
#include <cm/optional>
#include <cm/string_view>
#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"
-#include "cmList.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmOutputConverter.h"
#include "cmPolicies.h"
-#include "cmPropertyMap.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -37,7 +30,7 @@
#include "cmValue.h"
#include "cmVersion.h"
-static std::string cmExportCMakeConfigGeneratorEscape(std::string const& str)
+static std::string cmExportFileGeneratorEscape(std::string const& str)
{
// Escape a property value for writing into a .cmake file.
std::string result = cmOutputConverter::EscapeForCMake(str);
@@ -49,56 +42,15 @@ static std::string cmExportCMakeConfigGeneratorEscape(std::string const& str)
return result;
}
-cmExportCMakeConfigGenerator::cmExportCMakeConfigGenerator()
-{
- this->AppendMode = false;
- this->ExportOld = false;
-}
-
-void cmExportCMakeConfigGenerator::AddConfiguration(std::string const& config)
-{
- this->Configurations.push_back(config);
-}
+cmExportCMakeConfigGenerator::cmExportCMakeConfigGenerator() = default;
-void cmExportCMakeConfigGenerator::SetExportFile(char const* mainFile)
+cm::string_view cmExportCMakeConfigGenerator::GetImportPrefixWithSlash() const
{
- this->MainImportFile = mainFile;
- this->FileDir = cmSystemTools::GetFilenamePath(this->MainImportFile);
- this->FileBase =
- cmSystemTools::GetFilenameWithoutLastExtension(this->MainImportFile);
- this->FileExt =
- cmSystemTools::GetFilenameLastExtension(this->MainImportFile);
+ return "${_IMPORT_PREFIX}/"_s;
}
-std::string const& cmExportCMakeConfigGenerator::GetMainExportFileName() const
+bool cmExportCMakeConfigGenerator::GenerateImportFile(std::ostream& os)
{
- return this->MainImportFile;
-}
-
-bool cmExportCMakeConfigGenerator::GenerateImportFile()
-{
- // Open the output file to generate it.
- std::unique_ptr<cmsys::ofstream> foutPtr;
- if (this->AppendMode) {
- // Open for append.
- auto openmodeApp = std::ios::app;
- foutPtr = cm::make_unique<cmsys::ofstream>(this->MainImportFile.c_str(),
- openmodeApp);
- } else {
- // Generate atomically and with copy-if-different.
- std::unique_ptr<cmGeneratedFileStream> ap(
- new cmGeneratedFileStream(this->MainImportFile, true));
- ap->SetCopyIfDifferent(true);
- foutPtr = std::move(ap);
- }
- if (!foutPtr || !*foutPtr) {
- std::string se = cmSystemTools::GetLastSystemError();
- std::ostringstream e;
- e << "cannot write to file \"" << this->MainImportFile << "\": " << se;
- cmSystemTools::Error(e.str());
- return false;
- }
- std::ostream& os = *foutPtr;
std::stringstream mainFileWithHeadersAndFootersBuffer;
// Start with the import file header.
@@ -132,499 +84,6 @@ bool cmExportCMakeConfigGenerator::GenerateImportFile()
return result;
}
-void cmExportCMakeConfigGenerator::GenerateImportConfig(
- std::ostream& os, std::string const& config)
-{
- // Construct the property configuration suffix.
- std::string suffix = "_";
- if (!config.empty()) {
- suffix += cmSystemTools::UpperCase(config);
- } else {
- suffix += "NOCONFIG";
- }
-
- // Generate the per-config target information.
- this->GenerateImportTargetsConfig(os, config, suffix);
-}
-
-void cmExportCMakeConfigGenerator::PopulateInterfaceProperty(
- std::string const& propName, cmGeneratorTarget const* target,
- ImportPropertyMap& properties)
-{
- cmValue input = target->GetProperty(propName);
- if (input) {
- properties[propName] = *input;
- }
-}
-
-void cmExportCMakeConfigGenerator::PopulateInterfaceProperty(
- std::string const& propName, std::string const& outputName,
- cmGeneratorTarget const* target,
- cmGeneratorExpression::PreprocessContext preprocessRule,
- ImportPropertyMap& properties)
-{
- cmValue input = target->GetProperty(propName);
- if (input) {
- if (input->empty()) {
- // Set to empty
- properties[outputName].clear();
- return;
- }
-
- std::string prepro =
- cmGeneratorExpression::Preprocess(*input, preprocessRule);
- if (!prepro.empty()) {
- this->ResolveTargetsInGeneratorExpressions(prepro, target);
- properties[outputName] = prepro;
- }
- }
-}
-
-bool cmExportCMakeConfigGenerator::PopulateInterfaceLinkLibrariesProperty(
- cmGeneratorTarget const* target,
- cmGeneratorExpression::PreprocessContext preprocessRule,
- ImportPropertyMap& properties)
-{
- if (!target->IsLinkable()) {
- return false;
- }
- static std::array<std::string, 3> const linkIfaceProps = {
- { "INTERFACE_LINK_LIBRARIES", "INTERFACE_LINK_LIBRARIES_DIRECT",
- "INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE" }
- };
- bool hadINTERFACE_LINK_LIBRARIES = false;
- for (std::string const& linkIfaceProp : linkIfaceProps) {
- if (cmValue input = target->GetProperty(linkIfaceProp)) {
- std::string prepro =
- cmGeneratorExpression::Preprocess(*input, preprocessRule);
- if (!prepro.empty()) {
- this->ResolveTargetsInGeneratorExpressions(prepro, target,
- ReplaceFreeTargets);
- properties[linkIfaceProp] = prepro;
- hadINTERFACE_LINK_LIBRARIES = true;
- }
- }
- }
- return hadINTERFACE_LINK_LIBRARIES;
-}
-
-static bool isSubDirectory(std::string const& a, std::string const& b)
-{
- return (cmSystemTools::ComparePath(a, b) ||
- cmSystemTools::IsSubDirectory(a, b));
-}
-
-static bool checkInterfaceDirs(std::string const& prepro,
- cmGeneratorTarget const* target,
- std::string const& prop)
-{
- std::string const& installDir =
- target->Makefile->GetSafeDefinition("CMAKE_INSTALL_PREFIX");
- std::string const& topSourceDir =
- target->GetLocalGenerator()->GetSourceDirectory();
- std::string const& topBinaryDir =
- target->GetLocalGenerator()->GetBinaryDirectory();
-
- std::vector<std::string> parts;
- cmGeneratorExpression::Split(prepro, parts);
-
- bool const inSourceBuild = topSourceDir == topBinaryDir;
-
- bool hadFatalError = false;
-
- for (std::string const& li : parts) {
- size_t genexPos = cmGeneratorExpression::Find(li);
- if (genexPos == 0) {
- continue;
- }
- if (cmHasLiteralPrefix(li, "${_IMPORT_PREFIX}")) {
- continue;
- }
- MessageType messageType = MessageType::FATAL_ERROR;
- std::ostringstream e;
- if (genexPos != std::string::npos) {
- if (prop == "INTERFACE_INCLUDE_DIRECTORIES") {
- switch (target->GetPolicyStatusCMP0041()) {
- case cmPolicies::WARN:
- messageType = MessageType::WARNING;
- e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0041) << "\n";
- break;
- case cmPolicies::OLD:
- continue;
- case cmPolicies::REQUIRED_IF_USED:
- case cmPolicies::REQUIRED_ALWAYS:
- case cmPolicies::NEW:
- hadFatalError = true;
- break; // Issue fatal message.
- }
- } else {
- hadFatalError = true;
- }
- }
- if (!cmSystemTools::FileIsFullPath(li)) {
- /* clang-format off */
- e << "Target \"" << target->GetName() << "\" " << prop <<
- " property contains relative path:\n"
- " \"" << li << "\"";
- /* clang-format on */
- target->GetLocalGenerator()->IssueMessage(messageType, e.str());
- }
- bool inBinary = isSubDirectory(li, topBinaryDir);
- bool inSource = isSubDirectory(li, topSourceDir);
- if (isSubDirectory(li, installDir)) {
- // The include directory is inside the install tree. If the
- // install tree is not inside the source tree or build tree then
- // fall through to the checks below that the include directory is not
- // also inside the source tree or build tree.
- bool shouldContinue =
- (!inBinary || isSubDirectory(installDir, topBinaryDir)) &&
- (!inSource || isSubDirectory(installDir, topSourceDir));
-
- if (prop == "INTERFACE_INCLUDE_DIRECTORIES") {
- if (!shouldContinue) {
- switch (target->GetPolicyStatusCMP0052()) {
- case cmPolicies::WARN: {
- std::ostringstream s;
- s << cmPolicies::GetPolicyWarning(cmPolicies::CMP0052) << "\n";
- s << "Directory:\n \"" << li
- << "\"\nin "
- "INTERFACE_INCLUDE_DIRECTORIES of target \""
- << target->GetName()
- << "\" is a subdirectory of the install "
- "directory:\n \""
- << installDir
- << "\"\nhowever it is also "
- "a subdirectory of the "
- << (inBinary ? "build" : "source") << " tree:\n \""
- << (inBinary ? topBinaryDir : topSourceDir) << "\"\n";
- target->GetLocalGenerator()->IssueMessage(
- MessageType::AUTHOR_WARNING, s.str());
- CM_FALLTHROUGH;
- }
- case cmPolicies::OLD:
- shouldContinue = true;
- break;
- case cmPolicies::REQUIRED_ALWAYS:
- case cmPolicies::REQUIRED_IF_USED:
- case cmPolicies::NEW:
- break;
- }
- }
- }
- if (shouldContinue) {
- continue;
- }
- }
- if (inBinary) {
- /* clang-format off */
- e << "Target \"" << target->GetName() << "\" " << prop <<
- " property contains path:\n"
- " \"" << li << "\"\nwhich is prefixed in the build directory.";
- /* clang-format on */
- target->GetLocalGenerator()->IssueMessage(messageType, e.str());
- }
- if (!inSourceBuild) {
- if (inSource) {
- e << "Target \"" << target->GetName() << "\" " << prop
- << " property contains path:\n"
- " \""
- << li << "\"\nwhich is prefixed in the source directory.";
- target->GetLocalGenerator()->IssueMessage(messageType, e.str());
- }
- }
- }
- return !hadFatalError;
-}
-
-static void prefixItems(std::string& exportDirs)
-{
- std::vector<std::string> entries;
- cmGeneratorExpression::Split(exportDirs, entries);
- exportDirs.clear();
- char const* sep = "";
- for (std::string const& e : entries) {
- exportDirs += sep;
- sep = ";";
- if (!cmSystemTools::FileIsFullPath(e) &&
- e.find("${_IMPORT_PREFIX}") == std::string::npos) {
- exportDirs += "${_IMPORT_PREFIX}/";
- }
- exportDirs += e;
- }
-}
-
-void cmExportCMakeConfigGenerator::PopulateSourcesInterface(
- cmGeneratorTarget const* gt,
- cmGeneratorExpression::PreprocessContext preprocessRule,
- ImportPropertyMap& properties)
-{
- assert(preprocessRule == cmGeneratorExpression::InstallInterface);
-
- char const* propName = "INTERFACE_SOURCES";
- cmValue input = gt->GetProperty(propName);
-
- if (!input) {
- return;
- }
-
- if (input->empty()) {
- properties[propName].clear();
- return;
- }
-
- std::string prepro =
- cmGeneratorExpression::Preprocess(*input, preprocessRule, true);
- if (!prepro.empty()) {
- this->ResolveTargetsInGeneratorExpressions(prepro, gt);
-
- if (!checkInterfaceDirs(prepro, gt, propName)) {
- return;
- }
- properties[propName] = prepro;
- }
-}
-
-void cmExportCMakeConfigGenerator::PopulateIncludeDirectoriesInterface(
- cmGeneratorTarget const* target,
- cmGeneratorExpression::PreprocessContext preprocessRule,
- ImportPropertyMap& properties, cmTargetExport const& te,
- std::string& includesDestinationDirs)
-{
- assert(preprocessRule == cmGeneratorExpression::InstallInterface);
-
- includesDestinationDirs.clear();
-
- char const* propName = "INTERFACE_INCLUDE_DIRECTORIES";
- cmValue input = target->GetProperty(propName);
-
- cmGeneratorExpression ge(*target->Makefile->GetCMakeInstance());
-
- std::string dirs = cmGeneratorExpression::Preprocess(
- cmList::to_string(target->Target->GetInstallIncludeDirectoriesEntries(te)),
- preprocessRule, true);
- this->ReplaceInstallPrefix(dirs);
- std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(dirs);
- std::string exportDirs =
- cge->Evaluate(target->GetLocalGenerator(), "", target);
-
- if (cge->GetHadContextSensitiveCondition()) {
- cmLocalGenerator* lg = target->GetLocalGenerator();
- std::ostringstream e;
- e << "Target \"" << target->GetName()
- << "\" is installed with "
- "INCLUDES DESTINATION set to a context sensitive path. Paths which "
- "depend on the configuration, policy values or the link interface "
- "are "
- "not supported. Consider using target_include_directories instead.";
- lg->IssueMessage(MessageType::FATAL_ERROR, e.str());
- return;
- }
-
- if (!input && exportDirs.empty()) {
- return;
- }
- if ((input && input->empty()) && exportDirs.empty()) {
- // Set to empty
- properties[propName].clear();
- return;
- }
-
- prefixItems(exportDirs);
- includesDestinationDirs = exportDirs;
-
- std::string includes = (input ? *input : "");
- char const* sep = input ? ";" : "";
- includes += sep + exportDirs;
- std::string prepro =
- cmGeneratorExpression::Preprocess(includes, preprocessRule, true);
- if (!prepro.empty()) {
- this->ResolveTargetsInGeneratorExpressions(prepro, target);
-
- if (!checkInterfaceDirs(prepro, target, propName)) {
- return;
- }
- properties[propName] = prepro;
- }
-}
-
-void cmExportCMakeConfigGenerator::PopulateLinkDependsInterface(
- cmGeneratorTarget const* gt,
- cmGeneratorExpression::PreprocessContext preprocessRule,
- ImportPropertyMap& properties)
-{
- assert(preprocessRule == cmGeneratorExpression::InstallInterface);
-
- char const* propName = "INTERFACE_LINK_DEPENDS";
- cmValue input = gt->GetProperty(propName);
-
- if (!input) {
- return;
- }
-
- if (input->empty()) {
- properties[propName].clear();
- return;
- }
-
- std::string prepro =
- cmGeneratorExpression::Preprocess(*input, preprocessRule, true);
- if (!prepro.empty()) {
- this->ResolveTargetsInGeneratorExpressions(prepro, gt);
-
- if (!checkInterfaceDirs(prepro, gt, propName)) {
- return;
- }
- properties[propName] = prepro;
- }
-}
-
-void cmExportCMakeConfigGenerator::PopulateLinkDirectoriesInterface(
- cmGeneratorTarget const* gt,
- cmGeneratorExpression::PreprocessContext preprocessRule,
- ImportPropertyMap& properties)
-{
- assert(preprocessRule == cmGeneratorExpression::InstallInterface);
-
- char const* propName = "INTERFACE_LINK_DIRECTORIES";
- cmValue input = gt->GetProperty(propName);
-
- if (!input) {
- return;
- }
-
- if (input->empty()) {
- properties[propName].clear();
- return;
- }
-
- std::string prepro =
- cmGeneratorExpression::Preprocess(*input, preprocessRule, true);
- if (!prepro.empty()) {
- this->ResolveTargetsInGeneratorExpressions(prepro, gt);
-
- if (!checkInterfaceDirs(prepro, gt, propName)) {
- return;
- }
- properties[propName] = prepro;
- }
-}
-
-void cmExportCMakeConfigGenerator::PopulateInterfaceProperty(
- std::string const& propName, cmGeneratorTarget const* target,
- cmGeneratorExpression::PreprocessContext preprocessRule,
- ImportPropertyMap& properties)
-{
- this->PopulateInterfaceProperty(propName, propName, target, preprocessRule,
- properties);
-}
-
-static void getPropertyContents(cmGeneratorTarget const* tgt,
- std::string const& prop,
- std::set<std::string>& ifaceProperties)
-{
- cmValue p = tgt->GetProperty(prop);
- if (!p) {
- return;
- }
- cmList content{ *p };
- ifaceProperties.insert(content.begin(), content.end());
-}
-
-static void getCompatibleInterfaceProperties(
- cmGeneratorTarget const* target, std::set<std::string>& ifaceProperties,
- std::string const& config)
-{
- if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
- // object libraries have no link information, so nothing to compute
- return;
- }
-
- cmComputeLinkInformation* info = target->GetLinkInformation(config);
-
- if (!info) {
- cmLocalGenerator* lg = target->GetLocalGenerator();
- std::ostringstream e;
- e << "Exporting the target \"" << target->GetName()
- << "\" is not "
- "allowed since its linker language cannot be determined";
- lg->IssueMessage(MessageType::FATAL_ERROR, e.str());
- return;
- }
-
- cmComputeLinkInformation::ItemVector const& deps = info->GetItems();
-
- for (auto const& dep : deps) {
- if (!dep.Target || dep.Target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
- continue;
- }
- getPropertyContents(dep.Target, "COMPATIBLE_INTERFACE_BOOL",
- ifaceProperties);
- getPropertyContents(dep.Target, "COMPATIBLE_INTERFACE_STRING",
- ifaceProperties);
- getPropertyContents(dep.Target, "COMPATIBLE_INTERFACE_NUMBER_MIN",
- ifaceProperties);
- getPropertyContents(dep.Target, "COMPATIBLE_INTERFACE_NUMBER_MAX",
- ifaceProperties);
- }
-}
-
-void cmExportCMakeConfigGenerator::PopulateCompatibleInterfaceProperties(
- cmGeneratorTarget const* gtarget, ImportPropertyMap& properties)
-{
- this->PopulateInterfaceProperty("COMPATIBLE_INTERFACE_BOOL", gtarget,
- properties);
- this->PopulateInterfaceProperty("COMPATIBLE_INTERFACE_STRING", gtarget,
- properties);
- this->PopulateInterfaceProperty("COMPATIBLE_INTERFACE_NUMBER_MIN", gtarget,
- properties);
- this->PopulateInterfaceProperty("COMPATIBLE_INTERFACE_NUMBER_MAX", gtarget,
- properties);
-
- std::set<std::string> ifaceProperties;
-
- getPropertyContents(gtarget, "COMPATIBLE_INTERFACE_BOOL", ifaceProperties);
- getPropertyContents(gtarget, "COMPATIBLE_INTERFACE_STRING", ifaceProperties);
- getPropertyContents(gtarget, "COMPATIBLE_INTERFACE_NUMBER_MIN",
- ifaceProperties);
- getPropertyContents(gtarget, "COMPATIBLE_INTERFACE_NUMBER_MAX",
- ifaceProperties);
-
- if (gtarget->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
- std::vector<std::string> configNames =
- gtarget->Target->GetMakefile()->GetGeneratorConfigs(
- cmMakefile::IncludeEmptyConfig);
-
- for (std::string const& cn : configNames) {
- getCompatibleInterfaceProperties(gtarget, ifaceProperties, cn);
- }
- }
-
- for (std::string const& ip : ifaceProperties) {
- this->PopulateInterfaceProperty("INTERFACE_" + ip, gtarget, properties);
- }
-}
-
-void cmExportCMakeConfigGenerator::PopulateCustomTransitiveInterfaceProperties(
- cmGeneratorTarget const* target,
- cmGeneratorExpression::PreprocessContext preprocessRule,
- ImportPropertyMap& properties)
-{
- this->PopulateInterfaceProperty("TRANSITIVE_COMPILE_PROPERTIES", target,
- properties);
- this->PopulateInterfaceProperty("TRANSITIVE_LINK_PROPERTIES", target,
- properties);
- std::set<std::string> ifaceProperties;
- for (std::string const& config : this->Configurations) {
- for (auto const& i : target->GetCustomTransitiveProperties(
- config, cmGeneratorTarget::PropertyFor::Interface)) {
- ifaceProperties.emplace(i.second.InterfaceName);
- }
- }
- for (std::string const& ip : ifaceProperties) {
- this->PopulateInterfaceProperty(ip, target, preprocessRule, properties);
- }
-}
-
void cmExportCMakeConfigGenerator::GenerateInterfaceProperties(
cmGeneratorTarget const* target, std::ostream& os,
ImportPropertyMap const& properties)
@@ -635,181 +94,12 @@ void cmExportCMakeConfigGenerator::GenerateInterfaceProperties(
os << "set_target_properties(" << targetName << " PROPERTIES\n";
for (auto const& property : properties) {
os << " " << property.first << " "
- << cmExportCMakeConfigGeneratorEscape(property.second) << "\n";
+ << cmExportFileGeneratorEscape(property.second) << "\n";
}
os << ")\n\n";
}
}
-bool cmExportCMakeConfigGenerator::AddTargetNamespace(
- std::string& input, cmGeneratorTarget const* target,
- cmLocalGenerator const* lg)
-{
- cmGeneratorTarget::TargetOrString resolved =
- target->ResolveTargetReference(input, lg);
-
- cmGeneratorTarget* tgt = resolved.Target;
- if (!tgt) {
- input = resolved.String;
- 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;
- }
- if (this->ExportedTargets.find(tgt) != this->ExportedTargets.end()) {
- input = this->Namespace + tgt->GetExportName();
- } else {
- std::string namespacedTarget;
- this->HandleMissingTarget(namespacedTarget, target, tgt);
- if (!namespacedTarget.empty()) {
- input = namespacedTarget;
- } else {
- input = tgt->GetName();
- }
- }
- return true;
-}
-
-void cmExportCMakeConfigGenerator::ResolveTargetsInGeneratorExpressions(
- std::string& input, cmGeneratorTarget const* target,
- FreeTargetsReplace replace)
-{
- cmLocalGenerator const* lg = target->GetLocalGenerator();
- if (replace == NoReplaceFreeTargets) {
- this->ResolveTargetsInGeneratorExpression(input, target, lg);
- return;
- }
- std::vector<std::string> parts;
- cmGeneratorExpression::Split(input, parts);
-
- std::string sep;
- input.clear();
- for (std::string& li : parts) {
- if (target->IsLinkLookupScope(li, lg)) {
- continue;
- }
- if (cmGeneratorExpression::Find(li) == std::string::npos) {
- this->AddTargetNamespace(li, target, lg);
- } else {
- this->ResolveTargetsInGeneratorExpression(li, target, lg);
- }
- input += sep + li;
- sep = ";";
- }
-}
-
-void cmExportCMakeConfigGenerator::ResolveTargetsInGeneratorExpression(
- std::string& input, cmGeneratorTarget const* target,
- cmLocalGenerator const* lg)
-{
- std::string::size_type pos = 0;
- std::string::size_type lastPos = pos;
-
- while ((pos = input.find("$<TARGET_PROPERTY:", lastPos)) !=
- std::string::npos) {
- std::string::size_type nameStartPos = pos + cmStrLen("$<TARGET_PROPERTY:");
- std::string::size_type closePos = input.find('>', nameStartPos);
- std::string::size_type commaPos = input.find(',', nameStartPos);
- std::string::size_type nextOpenPos = input.find("$<", nameStartPos);
- if (commaPos == std::string::npos // Implied 'this' target
- || closePos == std::string::npos // Incomplete expression.
- || closePos < commaPos // Implied 'this' target
- || nextOpenPos < commaPos) // Non-literal
- {
- lastPos = nameStartPos;
- continue;
- }
-
- std::string targetName =
- input.substr(nameStartPos, commaPos - nameStartPos);
-
- if (this->AddTargetNamespace(targetName, target, lg)) {
- input.replace(nameStartPos, commaPos - nameStartPos, targetName);
- }
- lastPos = nameStartPos + targetName.size() + 1;
- }
-
- std::string errorString;
- pos = 0;
- lastPos = pos;
- while ((pos = input.find("$<TARGET_NAME:", lastPos)) != std::string::npos) {
- std::string::size_type nameStartPos = pos + cmStrLen("$<TARGET_NAME:");
- std::string::size_type endPos = input.find('>', nameStartPos);
- if (endPos == std::string::npos) {
- errorString = "$<TARGET_NAME:...> expression incomplete";
- break;
- }
- std::string targetName = input.substr(nameStartPos, endPos - nameStartPos);
- if (targetName.find("$<") != std::string::npos) {
- errorString = "$<TARGET_NAME:...> requires its parameter to be a "
- "literal.";
- break;
- }
- if (!this->AddTargetNamespace(targetName, target, lg)) {
- errorString = "$<TARGET_NAME:...> requires its parameter to be a "
- "reachable target.";
- break;
- }
- input.replace(pos, endPos - pos + 1, targetName);
- lastPos = pos + targetName.size();
- }
-
- pos = 0;
- lastPos = pos;
- while (errorString.empty() &&
- (pos = input.find("$<LINK_ONLY:", lastPos)) != std::string::npos) {
- std::string::size_type nameStartPos = pos + cmStrLen("$<LINK_ONLY:");
- std::string::size_type endPos = input.find('>', nameStartPos);
- if (endPos == std::string::npos) {
- errorString = "$<LINK_ONLY:...> expression incomplete";
- break;
- }
- std::string libName = input.substr(nameStartPos, endPos - nameStartPos);
- if (cmGeneratorExpression::IsValidTargetName(libName) &&
- this->AddTargetNamespace(libName, target, lg)) {
- input.replace(nameStartPos, endPos - nameStartPos, libName);
- }
- lastPos = nameStartPos + libName.size() + 1;
- }
-
- while (errorString.empty() &&
- (pos = input.find("$<COMPILE_ONLY:", lastPos)) != std::string::npos) {
- std::string::size_type nameStartPos = pos + cmStrLen("$<COMPILE_ONLY:");
- std::string::size_type endPos = input.find('>', nameStartPos);
- if (endPos == std::string::npos) {
- errorString = "$<COMPILE_ONLY:...> expression incomplete";
- break;
- }
- std::string libName = input.substr(nameStartPos, endPos - nameStartPos);
- if (cmGeneratorExpression::IsValidTargetName(libName) &&
- this->AddTargetNamespace(libName, target, lg)) {
- input.replace(nameStartPos, endPos - nameStartPos, libName);
- }
- lastPos = nameStartPos + libName.size() + 1;
- }
-
- this->ReplaceInstallPrefix(input);
-
- if (!errorString.empty()) {
- target->GetLocalGenerator()->IssueMessage(MessageType::FATAL_ERROR,
- errorString);
- }
-}
-
-void cmExportCMakeConfigGenerator::ReplaceInstallPrefix(
- std::string& /*unused*/)
-{
- // Do nothing
-}
-
void cmExportCMakeConfigGenerator::SetImportLinkInterface(
std::string const& config, std::string const& suffix,
cmGeneratorExpression::PreprocessContext preprocessRule,
@@ -870,131 +160,16 @@ void cmExportCMakeConfigGenerator::SetImportLinkInterface(
}
}
-void cmExportCMakeConfigGenerator::SetImportDetailProperties(
- std::string const& config, std::string const& suffix,
- cmGeneratorTarget* target, ImportPropertyMap& properties)
-{
- // Get the makefile in which to lookup target information.
- cmMakefile* mf = target->Makefile;
-
- // Add the soname for unix shared libraries.
- if (target->GetType() == cmStateEnums::SHARED_LIBRARY ||
- target->GetType() == cmStateEnums::MODULE_LIBRARY) {
- if (!target->IsDLLPlatform()) {
- std::string prop;
- std::string value;
- if (target->HasSOName(config)) {
- if (mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) {
- value = this->InstallNameDir(target, config);
- }
- prop = "IMPORTED_SONAME";
- value += target->GetSOName(config);
- } else {
- prop = "IMPORTED_NO_SONAME";
- value = "TRUE";
- }
- prop += suffix;
- properties[prop] = value;
- }
- }
-
- // Add the transitive link dependencies for this configuration.
- if (cmLinkInterface const* iface =
- target->GetLinkInterface(config, target)) {
- this->SetImportLinkProperty(
- suffix, target, "IMPORTED_LINK_INTERFACE_LANGUAGES", iface->Languages,
- properties, ImportLinkPropertyTargetNames::No);
-
- // 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 =
- cmStrCat("IMPORTED_LINK_INTERFACE_MULTIPLICITY", suffix);
- properties[prop] = std::to_string(iface->Multiplicity);
- }
- }
-
- // Add information if this target is a managed target
- if (target->GetManagedType(config) !=
- cmGeneratorTarget::ManagedType::Native) {
- std::string prop = cmStrCat("IMPORTED_COMMON_LANGUAGE_RUNTIME", suffix);
- std::string propval;
- if (cmValue p = target->GetProperty("COMMON_LANGUAGE_RUNTIME")) {
- propval = *p;
- } else if (target->IsCSharpOnly()) {
- // C# projects do not have the /clr flag, so we set the property
- // here to mark the target as (only) managed (i.e. no .lib file
- // to link to). Otherwise the COMMON_LANGUAGE_RUNTIME target
- // property would have to be set manually for C# targets to make
- // exporting/importing work.
- propval = "CSharp";
- }
- properties[prop] = propval;
- }
-}
-
-static std::string const& asString(std::string const& l)
-{
- return l;
-}
-
-static std::string const& asString(cmLinkItem const& l)
-{
- return l.AsStr();
-}
-
-template <typename T>
-void cmExportCMakeConfigGenerator::SetImportLinkProperty(
- std::string const& suffix, cmGeneratorTarget const* target,
- std::string const& propName, std::vector<T> const& entries,
- ImportPropertyMap& properties, ImportLinkPropertyTargetNames targetNames)
-{
- // Skip the property if there are no entries.
- if (entries.empty()) {
- return;
- }
-
- cmLocalGenerator const* lg = target->GetLocalGenerator();
-
- // Construct the property value.
- std::string link_entries;
- char const* sep = "";
- for (T const& l : entries) {
- // Separate this from the previous entry.
- link_entries += sep;
- sep = ";";
-
- if (targetNames == ImportLinkPropertyTargetNames::Yes) {
- std::string temp = asString(l);
- this->AddTargetNamespace(temp, target, lg);
- link_entries += temp;
- } else {
- link_entries += asString(l);
- }
- }
-
- // Store the property.
- std::string prop = cmStrCat(propName, suffix);
- properties[prop] = link_entries;
-}
-
void cmExportCMakeConfigGenerator::GeneratePolicyHeaderCode(std::ostream& os)
{
// Protect that file against use with older CMake versions.
/* clang-format off */
os << "# Generated by CMake\n\n";
os << "if(\"${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}\" LESS 2.8)\n"
- << " message(FATAL_ERROR \"CMake >= 2.8.0 required\")\n"
+ << " message(FATAL_ERROR \"CMake >= "
+ << this->RequiredCMakeVersionMajor << '.'
+ << this->RequiredCMakeVersionMinor << '.'
+ << this->RequiredCMakeVersionPatch << " required\")\n"
<< "endif()\n"
<< "if(CMAKE_VERSION VERSION_LESS \""
<< this->RequiredCMakeVersionMajor << '.'
@@ -1010,7 +185,7 @@ void cmExportCMakeConfigGenerator::GeneratePolicyHeaderCode(std::ostream& os)
// Isolate the file policy level.
// Support CMake versions as far back as the
// RequiredCMakeVersion{Major,Minor,Patch}, but also support using NEW
- // policy settings for up to CMake 3.28 (this upper limit may be reviewed
+ // policy settings for up to CMake 3.29 (this upper limit may be reviewed
// and increased from time to time). This reduces the opportunity for CMake
// warnings when an older export file is later used with newer CMake
// versions.
@@ -1019,7 +194,7 @@ void cmExportCMakeConfigGenerator::GeneratePolicyHeaderCode(std::ostream& os)
<< "cmake_policy(VERSION "
<< this->RequiredCMakeVersionMajor << '.'
<< this->RequiredCMakeVersionMinor << '.'
- << this->RequiredCMakeVersionPatch << "...3.28)\n";
+ << this->RequiredCMakeVersionPatch << "...3.29)\n";
/* clang-format on */
}
@@ -1162,8 +337,7 @@ void cmExportCMakeConfigGenerator::GenerateImportTargetCode(
// generate DEPRECATION
if (target->IsDeprecated()) {
os << "set_property(TARGET " << targetName << " PROPERTY DEPRECATION "
- << cmExportCMakeConfigGeneratorEscape(target->GetDeprecation())
- << ")\n";
+ << cmExportFileGeneratorEscape(target->GetDeprecation()) << ")\n";
}
if (target->GetPropertyAsBool("IMPORTED_NO_SYSTEM")) {
@@ -1205,7 +379,7 @@ void cmExportCMakeConfigGenerator::GenerateImportPropertyCode(
if (importedXcFrameworkLocation.empty() ||
property.first != importedLocationProp) {
os << " " << property.first << " "
- << cmExportCMakeConfigGeneratorEscape(property.second) << "\n";
+ << cmExportFileGeneratorEscape(property.second) << "\n";
}
}
os << " )\n";
@@ -1213,14 +387,14 @@ void cmExportCMakeConfigGenerator::GenerateImportPropertyCode(
auto importedLocationIt = properties.find(importedLocationProp);
if (importedLocationIt != properties.end()) {
os << "if(NOT CMAKE_VERSION VERSION_LESS \"3.28\" AND IS_DIRECTORY "
- << cmExportCMakeConfigGeneratorEscape(importedXcFrameworkLocation)
+ << cmExportFileGeneratorEscape(importedXcFrameworkLocation)
<< ")\n"
" set_property(TARGET "
<< targetName << " PROPERTY " << importedLocationProp << " "
- << cmExportCMakeConfigGeneratorEscape(importedXcFrameworkLocation)
+ << cmExportFileGeneratorEscape(importedXcFrameworkLocation)
<< ")\nelse()\n set_property(TARGET " << targetName << " PROPERTY "
<< importedLocationProp << " "
- << cmExportCMakeConfigGeneratorEscape(importedLocationIt->second)
+ << cmExportFileGeneratorEscape(importedLocationIt->second)
<< ")\nendif()\n";
}
}
@@ -1389,7 +563,7 @@ void cmExportCMakeConfigGenerator::GenerateImportedFileCheckLoop(
}
void cmExportCMakeConfigGenerator::GenerateImportedFileChecksCode(
- std::ostream& os, cmGeneratorTarget* target,
+ std::ostream& os, cmGeneratorTarget const* target,
ImportPropertyMap const& properties,
std::set<std::string> const& importedLocations,
std::string const& importedXcFrameworkLocation)
@@ -1400,193 +574,22 @@ void cmExportCMakeConfigGenerator::GenerateImportedFileChecksCode(
os << "list(APPEND _cmake_import_check_targets " << targetName << " )\n";
if (!importedXcFrameworkLocation.empty()) {
os << "set(_cmake_import_check_xcframework_for_" << targetName << ' '
- << cmExportCMakeConfigGeneratorEscape(importedXcFrameworkLocation)
- << ")\n";
+ << cmExportFileGeneratorEscape(importedXcFrameworkLocation) << ")\n";
}
os << "list(APPEND _cmake_import_check_files_for_" << targetName << " ";
for (std::string const& li : importedLocations) {
auto pi = properties.find(li);
if (pi != properties.end()) {
- os << cmExportCMakeConfigGeneratorEscape(pi->second) << " ";
+ os << cmExportFileGeneratorEscape(pi->second) << " ";
}
}
os << ")\n\n";
}
-enum class ExportWhen
-{
- Defined,
- Always,
-};
-
-enum class PropertyType
-{
- Strings,
- Paths,
- IncludePaths,
-};
-
-namespace {
-bool PropertyTypeIsForPaths(PropertyType pt)
-{
- switch (pt) {
- case PropertyType::Strings:
- return false;
- case PropertyType::Paths:
- case PropertyType::IncludePaths:
- return true;
- }
- return false;
-}
-}
-
-struct ModuleTargetPropertyTable
-{
- cm::static_string_view Name;
- ExportWhen Cond;
-};
-
-struct ModulePropertyTable
-{
- cm::static_string_view Name;
- PropertyType Type;
-};
-
-bool cmExportCMakeConfigGenerator::PopulateCxxModuleExportProperties(
- cmGeneratorTarget const* gte, ImportPropertyMap& properties,
- cmGeneratorExpression::PreprocessContext ctx,
- std::string const& includesDestinationDirs, std::string& errorMessage)
-{
- if (!gte->HaveCxx20ModuleSources(&errorMessage)) {
- return true;
- }
-
- ModuleTargetPropertyTable const exportedDirectModuleProperties[] = {
- { "CXX_EXTENSIONS"_s, ExportWhen::Defined },
- // Always define this property as it is an intrinsic property of the target
- // and should not be inherited from the in-scope `CMAKE_CXX_MODULE_STD`
- // variable.
- //
- // TODO(cxxmodules): A future policy may make this "ON" based on the target
- // policies if unset. Add a new `ExportWhen` condition to handle it when
- // this happens.
- { "CXX_MODULE_STD"_s, ExportWhen::Always },
- };
- for (auto const& prop : exportedDirectModuleProperties) {
- auto const propNameStr = std::string(prop.Name);
- cmValue propValue = gte->Target->GetComputedProperty(
- propNameStr, *gte->Target->GetMakefile());
- if (!propValue) {
- propValue = gte->Target->GetProperty(propNameStr);
- }
- if (propValue) {
- properties[propNameStr] =
- cmGeneratorExpression::Preprocess(*propValue, ctx);
- } else if (prop.Cond == ExportWhen::Always) {
- properties[propNameStr] = "";
- }
- }
-
- ModulePropertyTable const exportedModuleProperties[] = {
- { "INCLUDE_DIRECTORIES"_s, PropertyType::IncludePaths },
- { "COMPILE_DEFINITIONS"_s, PropertyType::Strings },
- { "COMPILE_OPTIONS"_s, PropertyType::Strings },
- { "COMPILE_FEATURES"_s, PropertyType::Strings },
- };
- for (auto const& propEntry : exportedModuleProperties) {
- auto const propNameStr = std::string(propEntry.Name);
- cmValue prop = gte->Target->GetComputedProperty(
- propNameStr, *gte->Target->GetMakefile());
- if (!prop) {
- prop = gte->Target->GetProperty(propNameStr);
- }
- if (prop) {
- auto const exportedPropName =
- cmStrCat("IMPORTED_CXX_MODULES_", propEntry.Name);
- properties[exportedPropName] =
- cmGeneratorExpression::Preprocess(*prop, ctx);
- if (ctx == cmGeneratorExpression::InstallInterface &&
- PropertyTypeIsForPaths(propEntry.Type)) {
- this->ReplaceInstallPrefix(properties[exportedPropName]);
- prefixItems(properties[exportedPropName]);
- if (propEntry.Type == PropertyType::IncludePaths &&
- !includesDestinationDirs.empty()) {
- if (!properties[exportedPropName].empty()) {
- properties[exportedPropName] += ';';
- }
- properties[exportedPropName] += includesDestinationDirs;
- }
- }
- }
- }
-
- cm::static_string_view const exportedLinkModuleProperties[] = {
- "LINK_LIBRARIES"_s,
- };
- for (auto const& propName : exportedLinkModuleProperties) {
- auto const propNameStr = std::string(propName);
- cmValue prop = gte->Target->GetComputedProperty(
- propNameStr, *gte->Target->GetMakefile());
- if (!prop) {
- prop = gte->Target->GetProperty(propNameStr);
- }
- if (prop) {
- auto const exportedPropName =
- cmStrCat("IMPORTED_CXX_MODULES_", propName);
- auto value = cmGeneratorExpression::Preprocess(*prop, ctx);
- this->ResolveTargetsInGeneratorExpressions(
- value, gte, cmExportCMakeConfigGenerator::ReplaceFreeTargets);
- properties[exportedPropName] = value;
- }
- }
-
- return true;
-}
-
-bool cmExportCMakeConfigGenerator::PopulateExportProperties(
- cmGeneratorTarget const* gte, ImportPropertyMap& properties,
- std::string& errorMessage)
-{
- auto const& targetProperties = gte->Target->GetProperties();
- if (cmValue exportProperties =
- targetProperties.GetPropertyValue("EXPORT_PROPERTIES")) {
- for (auto& prop : cmList{ *exportProperties }) {
- /* Black list reserved properties */
- if (cmHasLiteralPrefix(prop, "IMPORTED_") ||
- cmHasLiteralPrefix(prop, "INTERFACE_")) {
- std::ostringstream e;
- e << "Target \"" << gte->Target->GetName() << "\" contains property \""
- << prop << "\" in EXPORT_PROPERTIES but IMPORTED_* and INTERFACE_* "
- << "properties are reserved.";
- errorMessage = e.str();
- return false;
- }
- cmValue propertyValue = targetProperties.GetPropertyValue(prop);
- if (!propertyValue) {
- // Asked to export a property that isn't defined on the target. Do not
- // consider this an error, there's just nothing to export.
- continue;
- }
- std::string evaluatedValue = cmGeneratorExpression::Preprocess(
- *propertyValue, cmGeneratorExpression::StripAllGeneratorExpressions);
- if (evaluatedValue != *propertyValue) {
- std::ostringstream e;
- e << "Target \"" << gte->Target->GetName() << "\" contains property \""
- << prop << "\" in EXPORT_PROPERTIES but this property contains a "
- << "generator expression. This is not allowed.";
- errorMessage = e.str();
- return false;
- }
- properties[prop] = *propertyValue;
- }
- }
- return true;
-}
-
void cmExportCMakeConfigGenerator::GenerateTargetFileSets(
- cmGeneratorTarget* gte, std::ostream& os, cmTargetExport* te)
+ cmGeneratorTarget* gte, std::ostream& os, cmTargetExport const* te)
{
auto interfaceFileSets = gte->Target->GetAllInterfaceFileSets();
if (!interfaceFileSets.empty()) {
diff --git a/Source/cmExportCMakeConfigGenerator.h b/Source/cmExportCMakeConfigGenerator.h
index 331cd3f..90f7aa7 100644
--- a/Source/cmExportCMakeConfigGenerator.h
+++ b/Source/cmExportCMakeConfigGenerator.h
@@ -8,73 +8,45 @@
#include <map>
#include <set>
#include <string>
-#include <vector>
+#include <cm/string_view>
+
+#include "cmExportFileGenerator.h"
#include "cmGeneratorExpression.h"
#include "cmStateTypes.h"
-#include "cmVersion.h"
-#include "cmVersionConfig.h"
-class cmExportSet;
class cmFileSet;
class cmGeneratorTarget;
-class cmLocalGenerator;
class cmTargetExport;
-#define STRINGIFY_HELPER(X) #X
-#define STRINGIFY(X) STRINGIFY_HELPER(X)
-
-#define DEVEL_CMAKE_VERSION(major, minor) \
- (CMake_VERSION_ENCODE(major, minor, 0) > \
- CMake_VERSION_ENCODE(CMake_VERSION_MAJOR, CMake_VERSION_MINOR, 0) \
- ? STRINGIFY(CMake_VERSION_MAJOR) "." STRINGIFY( \
- CMake_VERSION_MINOR) "." STRINGIFY(CMake_VERSION_PATCH) \
- : #major "." #minor ".0")
-
/** \class cmExportCMakeConfigGenerator
- * \brief Generate a file exporting targets from a build or install tree.
+ * \brief Generate CMake configuration files exporting targets from a build or
+ * install tree.
*
* cmExportCMakeConfigGenerator is the superclass for
- * cmExportBuildFileGenerator and cmExportInstallFileGenerator. It
- * contains common code generation routines for the two kinds of
- * export implementations.
+ * cmExportBuildCMakeConfigGenerator and cmExportInstallCMakeConfigGenerator.
+ * It contains common code generation routines for the two kinds of export
+ * implementations.
*/
-class cmExportCMakeConfigGenerator
+class cmExportCMakeConfigGenerator : virtual public cmExportFileGenerator
{
public:
cmExportCMakeConfigGenerator();
- virtual ~cmExportCMakeConfigGenerator() = default;
-
- /** Set the full path to the export file to generate. */
- void SetExportFile(char const* mainFile);
- std::string const& GetMainExportFileName() const;
-
- /** Set the namespace in which to place exported target names. */
- void SetNamespace(std::string const& ns) { this->Namespace = ns; }
- std::string GetNamespace() const { return this->Namespace; }
void SetExportOld(bool exportOld) { this->ExportOld = exportOld; }
- /** Add a configuration to be exported. */
- void AddConfiguration(std::string const& config);
-
- /** Actually generate the export file. Returns whether there was an
- error. */
- bool GenerateImportFile();
-
void SetExportPackageDependencies(bool exportPackageDependencies)
{
this->ExportPackageDependencies = exportPackageDependencies;
}
+ using cmExportFileGenerator::GenerateImportFile;
+
protected:
using ImportPropertyMap = std::map<std::string, std::string>;
- // Generate per-configuration target information to the given output
- // stream.
- void GenerateImportConfig(std::ostream& os, std::string const& config);
-
// Methods to implement export file code generation.
+ bool GenerateImportFile(std::ostream& os) override;
virtual void GeneratePolicyHeaderCode(std::ostream& os);
virtual void GeneratePolicyFooterCode(std::ostream& os);
virtual void GenerateImportHeaderCode(std::ostream& os,
@@ -89,7 +61,7 @@ protected:
cmGeneratorTarget const* target, ImportPropertyMap const& properties,
std::string const& importedXcFrameworkLocation);
virtual void GenerateImportedFileChecksCode(
- std::ostream& os, cmGeneratorTarget* target,
+ std::ostream& os, cmGeneratorTarget const* target,
ImportPropertyMap const& properties,
std::set<std::string> const& importedLocations,
std::string const& importedXcFrameworkLocation);
@@ -100,165 +72,38 @@ protected:
virtual void GenerateExpectedTargetsCode(std::ostream& os,
std::string const& expectedTargets);
- // Collect properties with detailed information about targets beyond
- // their location on disk.
- void SetImportDetailProperties(std::string const& config,
- std::string const& suffix,
- cmGeneratorTarget* target,
- ImportPropertyMap& properties);
-
- enum class ImportLinkPropertyTargetNames
- {
- Yes,
- No,
- };
- template <typename T>
- void SetImportLinkProperty(std::string const& suffix,
- cmGeneratorTarget const* target,
- std::string const& propName,
- std::vector<T> const& entries,
- ImportPropertyMap& properties,
- ImportLinkPropertyTargetNames targetNames);
-
- /** Each subclass knows how to generate its kind of export file. */
- virtual bool GenerateMainFile(std::ostream& os) = 0;
-
- /** Each subclass knows where the target files are located. */
- virtual void GenerateImportTargetsConfig(std::ostream& os,
- std::string const& config,
- std::string const& suffix) = 0;
+ cm::string_view GetImportPrefixWithSlash() const override;
- /** Each subclass knows how to deal with a target that is missing from an
- * export set. */
- virtual void HandleMissingTarget(std::string& link_libs,
- cmGeneratorTarget const* depender,
- cmGeneratorTarget* dependee) = 0;
- void PopulateInterfaceProperty(std::string const&,
- cmGeneratorTarget const* target,
- cmGeneratorExpression::PreprocessContext,
- ImportPropertyMap& properties);
- bool PopulateInterfaceLinkLibrariesProperty(
- cmGeneratorTarget const* target, cmGeneratorExpression::PreprocessContext,
- ImportPropertyMap& properties);
- void PopulateInterfaceProperty(std::string const& propName,
- cmGeneratorTarget const* target,
- ImportPropertyMap& properties);
- void PopulateCompatibleInterfaceProperties(cmGeneratorTarget const* target,
- ImportPropertyMap& properties);
- void PopulateCustomTransitiveInterfaceProperties(
- cmGeneratorTarget const* target,
- cmGeneratorExpression::PreprocessContext preprocessRule,
- ImportPropertyMap& properties);
virtual void GenerateInterfaceProperties(
cmGeneratorTarget const* target, std::ostream& os,
ImportPropertyMap const& properties);
- void PopulateIncludeDirectoriesInterface(
- cmGeneratorTarget const* target,
- cmGeneratorExpression::PreprocessContext preprocessRule,
- ImportPropertyMap& properties, cmTargetExport const& te,
- std::string& includesDestinationDirs);
- void PopulateSourcesInterface(
- cmGeneratorTarget const* target,
- cmGeneratorExpression::PreprocessContext preprocessRule,
- ImportPropertyMap& properties);
- void PopulateLinkDirectoriesInterface(
- cmGeneratorTarget const* target,
- cmGeneratorExpression::PreprocessContext preprocessRule,
- ImportPropertyMap& properties);
- void PopulateLinkDependsInterface(
- cmGeneratorTarget const* target,
- cmGeneratorExpression::PreprocessContext preprocessRule,
- ImportPropertyMap& properties);
void SetImportLinkInterface(
std::string const& config, std::string const& suffix,
cmGeneratorExpression::PreprocessContext preprocessRule,
cmGeneratorTarget const* target, ImportPropertyMap& properties);
- enum FreeTargetsReplace
- {
- ReplaceFreeTargets,
- NoReplaceFreeTargets
- };
-
- void ResolveTargetsInGeneratorExpressions(
- std::string& input, cmGeneratorTarget const* target,
- FreeTargetsReplace replace = NoReplaceFreeTargets);
-
- bool PopulateCxxModuleExportProperties(
- cmGeneratorTarget const* gte, ImportPropertyMap& properties,
- cmGeneratorExpression::PreprocessContext ctx,
- std::string const& includesDestinationDirs, std::string& errorMessage);
- bool PopulateExportProperties(cmGeneratorTarget const* gte,
- ImportPropertyMap& properties,
- std::string& errorMessage);
-
void GenerateTargetFileSets(cmGeneratorTarget* gte, std::ostream& os,
- cmTargetExport* te = nullptr);
+ cmTargetExport const* te = nullptr);
+
+ std::string GetCxxModuleFile(std::string const& name) const override;
void GenerateCxxModuleInformation(std::string const& name, std::ostream& os);
virtual std::string GetFileSetDirectories(cmGeneratorTarget* gte,
cmFileSet* fileSet,
- cmTargetExport* te) = 0;
+ cmTargetExport const* te) = 0;
virtual std::string GetFileSetFiles(cmGeneratorTarget* gte,
cmFileSet* fileSet,
- cmTargetExport* te) = 0;
-
- virtual cmExportSet* GetExportSet() const { return nullptr; }
-
- std::string GetCxxModuleFile(std::string const& name) const;
+ cmTargetExport const* te) = 0;
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;
-
- bool ExportOld;
-
- // The set of configurations to export.
- std::vector<std::string> Configurations;
-
- // The file to generate.
- std::string MainImportFile;
- std::string FileDir;
- std::string FileBase;
- std::string FileExt;
- bool AppendMode;
-
- // The set of targets included in the export.
- std::set<cmGeneratorTarget*> ExportedTargets;
-
- std::vector<std::string> MissingTargets;
-
- std::set<cmGeneratorTarget const*> ExternalTargets;
+ bool ExportOld = false;
+ bool ExportPackageDependencies = false;
unsigned int RequiredCMakeVersionMajor = 2;
unsigned int RequiredCMakeVersionMinor = 8;
unsigned int RequiredCMakeVersionPatch = 3;
-
- bool ExportPackageDependencies = false;
-
-private:
- void PopulateInterfaceProperty(std::string const&, std::string const&,
- cmGeneratorTarget const* target,
- cmGeneratorExpression::PreprocessContext,
- ImportPropertyMap& properties);
-
- bool AddTargetNamespace(std::string& input, cmGeneratorTarget const* target,
- cmLocalGenerator const* lg);
-
- void ResolveTargetsInGeneratorExpression(std::string& input,
- cmGeneratorTarget const* target,
- cmLocalGenerator const* lg);
-
- virtual void ReplaceInstallPrefix(std::string& input);
-
- virtual std::string InstallNameDir(cmGeneratorTarget const* target,
- std::string const& config) = 0;
-
- virtual std::string GetCxxModulesDirectory() const = 0;
- virtual void GenerateCxxModuleConfigInformation(std::string const&,
- std::ostream& os) const = 0;
};
diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx
index 0cb0011..00f3c74 100644
--- a/Source/cmExportCommand.cxx
+++ b/Source/cmExportCommand.cxx
@@ -19,6 +19,7 @@
#include "cmExecutionStatus.h"
#include "cmExperimental.h"
#include "cmExportBuildAndroidMKGenerator.h"
+#include "cmExportBuildCMakeConfigGenerator.h"
#include "cmExportBuildFileGenerator.h"
#include "cmExportSet.h"
#include "cmGeneratedFileStream.h"
@@ -318,21 +319,24 @@ bool cmExportCommand(std::vector<std::string> const& args,
// Setup export file generation.
std::unique_ptr<cmExportBuildFileGenerator> ebfg = nullptr;
if (android) {
- ebfg = cm::make_unique<cmExportBuildAndroidMKGenerator>();
+ auto ebag = cm::make_unique<cmExportBuildAndroidMKGenerator>();
+ ebag->SetAppendMode(arguments.Append);
+ ebfg = std::move(ebag);
} else {
- ebfg = cm::make_unique<cmExportBuildFileGenerator>();
+ auto ebcg = cm::make_unique<cmExportBuildCMakeConfigGenerator>();
+ ebcg->SetAppendMode(arguments.Append);
+ ebcg->SetExportOld(arguments.ExportOld);
+ ebcg->SetExportPackageDependencies(arguments.ExportPackageDependencies);
+ ebfg = std::move(ebcg);
}
ebfg->SetExportFile(fname.c_str());
ebfg->SetNamespace(arguments.Namespace);
ebfg->SetCxxModuleDirectory(arguments.CxxModulesDirectory);
- ebfg->SetAppendMode(arguments.Append);
if (exportSet != nullptr) {
ebfg->SetExportSet(exportSet);
} else {
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 e0d43b8..24ed273 100644
--- a/Source/cmExportFileGenerator.cxx
+++ b/Source/cmExportFileGenerator.cxx
@@ -2,23 +2,18 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmExportFileGenerator.h"
-#include <algorithm>
#include <array>
-#include <cassert>
-#include <cstring>
+#include <cstddef>
#include <sstream>
#include <utility>
#include <cm/memory>
-#include <cm/optional>
#include <cm/string_view>
#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"
@@ -27,33 +22,14 @@
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
-#include "cmOutputConverter.h"
-#include "cmPolicies.h"
#include "cmPropertyMap.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmValue.h"
-#include "cmVersion.h"
-static std::string cmExportFileGeneratorEscape(std::string const& str)
-{
- // Escape a property value for writing into a .cmake file.
- std::string result = cmOutputConverter::EscapeForCMake(str);
- // Un-escape variable references generated by our own export code.
- cmSystemTools::ReplaceString(result, "\\${_IMPORT_PREFIX}",
- "${_IMPORT_PREFIX}");
- cmSystemTools::ReplaceString(result, "\\${CMAKE_IMPORT_LIBRARY_SUFFIX}",
- "${CMAKE_IMPORT_LIBRARY_SUFFIX}");
- return result;
-}
-
-cmExportFileGenerator::cmExportFileGenerator()
-{
- this->AppendMode = false;
- this->ExportOld = false;
-}
+cmExportFileGenerator::cmExportFileGenerator() = default;
void cmExportFileGenerator::AddConfiguration(std::string const& config)
{
@@ -98,38 +74,8 @@ bool cmExportFileGenerator::GenerateImportFile()
cmSystemTools::Error(e.str());
return false;
}
- std::ostream& os = *foutPtr;
- std::stringstream mainFileWithHeadersAndFootersBuffer;
-
- // Start with the import file header.
- this->GenerateImportHeaderCode(mainFileWithHeadersAndFootersBuffer);
-
- // Create all the imported targets.
- 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);
- 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;
+ return this->GenerateImportFile(*foutPtr);
}
void cmExportFileGenerator::GenerateImportConfig(std::ostream& os,
@@ -147,9 +93,50 @@ void cmExportFileGenerator::GenerateImportConfig(std::ostream& os,
this->GenerateImportTargetsConfig(os, config, suffix);
}
+bool cmExportFileGenerator::PopulateInterfaceProperties(
+ cmGeneratorTarget const* target, std::string const& includesDestinationDirs,
+ cmGeneratorExpression::PreprocessContext preprocessRule,
+ ImportPropertyMap& properties)
+{
+ this->PopulateInterfaceProperty("INTERFACE_COMPILE_DEFINITIONS", target,
+ preprocessRule, properties);
+ this->PopulateInterfaceProperty("INTERFACE_COMPILE_OPTIONS", target,
+ preprocessRule, properties);
+ this->PopulateInterfaceProperty("INTERFACE_PRECOMPILE_HEADERS", target,
+ preprocessRule, properties);
+ this->PopulateInterfaceProperty("INTERFACE_AUTOUIC_OPTIONS", target,
+ preprocessRule, properties);
+ this->PopulateInterfaceProperty("INTERFACE_AUTOMOC_MACRO_NAMES", target,
+ preprocessRule, properties);
+ this->PopulateInterfaceProperty("INTERFACE_COMPILE_FEATURES", target,
+ preprocessRule, properties);
+ this->PopulateInterfaceProperty("INTERFACE_LINK_OPTIONS", target,
+ preprocessRule, properties);
+ this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE",
+ target, properties);
+
+ std::string errorMessage;
+ if (!this->PopulateCxxModuleExportProperties(
+ target, properties, preprocessRule, includesDestinationDirs,
+ errorMessage)) {
+ this->ReportError(errorMessage);
+ return false;
+ }
+
+ if (!this->PopulateExportProperties(target, properties, errorMessage)) {
+ this->ReportError(errorMessage);
+ return false;
+ }
+ this->PopulateCompatibleInterfaceProperties(target, properties);
+ this->PopulateCustomTransitiveInterfaceProperties(target, preprocessRule,
+ properties);
+
+ return true;
+}
+
void cmExportFileGenerator::PopulateInterfaceProperty(
std::string const& propName, cmGeneratorTarget const* target,
- ImportPropertyMap& properties)
+ ImportPropertyMap& properties) const
{
cmValue input = target->GetProperty(propName);
if (input) {
@@ -180,6 +167,15 @@ void cmExportFileGenerator::PopulateInterfaceProperty(
}
}
+void cmExportFileGenerator::PopulateInterfaceProperty(
+ std::string const& propName, cmGeneratorTarget const* target,
+ cmGeneratorExpression::PreprocessContext preprocessRule,
+ ImportPropertyMap& properties)
+{
+ this->PopulateInterfaceProperty(propName, propName, target, preprocessRule,
+ properties);
+}
+
bool cmExportFileGenerator::PopulateInterfaceLinkLibrariesProperty(
cmGeneratorTarget const* target,
cmGeneratorExpression::PreprocessContext preprocessRule,
@@ -208,319 +204,27 @@ bool cmExportFileGenerator::PopulateInterfaceLinkLibrariesProperty(
return hadINTERFACE_LINK_LIBRARIES;
}
-static bool isSubDirectory(std::string const& a, std::string const& b)
-{
- return (cmSystemTools::ComparePath(a, b) ||
- cmSystemTools::IsSubDirectory(a, b));
-}
-
-static bool checkInterfaceDirs(std::string const& prepro,
- cmGeneratorTarget const* target,
- std::string const& prop)
-{
- std::string const& installDir =
- target->Makefile->GetSafeDefinition("CMAKE_INSTALL_PREFIX");
- std::string const& topSourceDir =
- target->GetLocalGenerator()->GetSourceDirectory();
- std::string const& topBinaryDir =
- target->GetLocalGenerator()->GetBinaryDirectory();
-
- std::vector<std::string> parts;
- cmGeneratorExpression::Split(prepro, parts);
-
- bool const inSourceBuild = topSourceDir == topBinaryDir;
-
- bool hadFatalError = false;
-
- for (std::string const& li : parts) {
- size_t genexPos = cmGeneratorExpression::Find(li);
- if (genexPos == 0) {
- continue;
- }
- if (cmHasLiteralPrefix(li, "${_IMPORT_PREFIX}")) {
- continue;
- }
- MessageType messageType = MessageType::FATAL_ERROR;
- std::ostringstream e;
- if (genexPos != std::string::npos) {
- if (prop == "INTERFACE_INCLUDE_DIRECTORIES") {
- switch (target->GetPolicyStatusCMP0041()) {
- case cmPolicies::WARN:
- messageType = MessageType::WARNING;
- e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0041) << "\n";
- break;
- case cmPolicies::OLD:
- continue;
- case cmPolicies::REQUIRED_IF_USED:
- case cmPolicies::REQUIRED_ALWAYS:
- case cmPolicies::NEW:
- hadFatalError = true;
- break; // Issue fatal message.
- }
- } else {
- hadFatalError = true;
- }
- }
- if (!cmSystemTools::FileIsFullPath(li)) {
- /* clang-format off */
- e << "Target \"" << target->GetName() << "\" " << prop <<
- " property contains relative path:\n"
- " \"" << li << "\"";
- /* clang-format on */
- target->GetLocalGenerator()->IssueMessage(messageType, e.str());
- }
- bool inBinary = isSubDirectory(li, topBinaryDir);
- bool inSource = isSubDirectory(li, topSourceDir);
- if (isSubDirectory(li, installDir)) {
- // The include directory is inside the install tree. If the
- // install tree is not inside the source tree or build tree then
- // fall through to the checks below that the include directory is not
- // also inside the source tree or build tree.
- bool shouldContinue =
- (!inBinary || isSubDirectory(installDir, topBinaryDir)) &&
- (!inSource || isSubDirectory(installDir, topSourceDir));
-
- if (prop == "INTERFACE_INCLUDE_DIRECTORIES") {
- if (!shouldContinue) {
- switch (target->GetPolicyStatusCMP0052()) {
- case cmPolicies::WARN: {
- std::ostringstream s;
- s << cmPolicies::GetPolicyWarning(cmPolicies::CMP0052) << "\n";
- s << "Directory:\n \"" << li
- << "\"\nin "
- "INTERFACE_INCLUDE_DIRECTORIES of target \""
- << target->GetName()
- << "\" is a subdirectory of the install "
- "directory:\n \""
- << installDir
- << "\"\nhowever it is also "
- "a subdirectory of the "
- << (inBinary ? "build" : "source") << " tree:\n \""
- << (inBinary ? topBinaryDir : topSourceDir) << "\"\n";
- target->GetLocalGenerator()->IssueMessage(
- MessageType::AUTHOR_WARNING, s.str());
- CM_FALLTHROUGH;
- }
- case cmPolicies::OLD:
- shouldContinue = true;
- break;
- case cmPolicies::REQUIRED_ALWAYS:
- case cmPolicies::REQUIRED_IF_USED:
- case cmPolicies::NEW:
- break;
- }
- }
- }
- if (shouldContinue) {
- continue;
- }
- }
- if (inBinary) {
- /* clang-format off */
- e << "Target \"" << target->GetName() << "\" " << prop <<
- " property contains path:\n"
- " \"" << li << "\"\nwhich is prefixed in the build directory.";
- /* clang-format on */
- target->GetLocalGenerator()->IssueMessage(messageType, e.str());
- }
- if (!inSourceBuild) {
- if (inSource) {
- e << "Target \"" << target->GetName() << "\" " << prop
- << " property contains path:\n"
- " \""
- << li << "\"\nwhich is prefixed in the source directory.";
- target->GetLocalGenerator()->IssueMessage(messageType, e.str());
- }
- }
- }
- return !hadFatalError;
-}
-
-static void prefixItems(std::string& exportDirs)
+void cmExportFileGenerator::AddImportPrefix(std::string& exportDirs) const
{
std::vector<std::string> entries;
cmGeneratorExpression::Split(exportDirs, entries);
exportDirs.clear();
char const* sep = "";
+ cm::string_view const& prefixWithSlash = this->GetImportPrefixWithSlash();
for (std::string const& e : entries) {
exportDirs += sep;
sep = ";";
if (!cmSystemTools::FileIsFullPath(e) &&
- e.find("${_IMPORT_PREFIX}") == std::string::npos) {
- exportDirs += "${_IMPORT_PREFIX}/";
+ !cmHasPrefix(e, prefixWithSlash)) {
+ exportDirs += prefixWithSlash;
}
exportDirs += e;
}
}
-void cmExportFileGenerator::PopulateSourcesInterface(
- cmGeneratorTarget const* gt,
- cmGeneratorExpression::PreprocessContext preprocessRule,
- ImportPropertyMap& properties)
-{
- assert(preprocessRule == cmGeneratorExpression::InstallInterface);
-
- char const* propName = "INTERFACE_SOURCES";
- cmValue input = gt->GetProperty(propName);
-
- if (!input) {
- return;
- }
-
- if (input->empty()) {
- properties[propName].clear();
- return;
- }
-
- std::string prepro =
- cmGeneratorExpression::Preprocess(*input, preprocessRule, true);
- if (!prepro.empty()) {
- this->ResolveTargetsInGeneratorExpressions(prepro, gt);
-
- if (!checkInterfaceDirs(prepro, gt, propName)) {
- return;
- }
- properties[propName] = prepro;
- }
-}
-
-void cmExportFileGenerator::PopulateIncludeDirectoriesInterface(
- cmGeneratorTarget const* target,
- cmGeneratorExpression::PreprocessContext preprocessRule,
- ImportPropertyMap& properties, cmTargetExport const& te,
- std::string& includesDestinationDirs)
-{
- assert(preprocessRule == cmGeneratorExpression::InstallInterface);
-
- includesDestinationDirs.clear();
-
- char const* propName = "INTERFACE_INCLUDE_DIRECTORIES";
- cmValue input = target->GetProperty(propName);
-
- cmGeneratorExpression ge(*target->Makefile->GetCMakeInstance());
-
- std::string dirs = cmGeneratorExpression::Preprocess(
- cmList::to_string(target->Target->GetInstallIncludeDirectoriesEntries(te)),
- preprocessRule, true);
- this->ReplaceInstallPrefix(dirs);
- std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(dirs);
- std::string exportDirs =
- cge->Evaluate(target->GetLocalGenerator(), "", target);
-
- if (cge->GetHadContextSensitiveCondition()) {
- cmLocalGenerator* lg = target->GetLocalGenerator();
- std::ostringstream e;
- e << "Target \"" << target->GetName()
- << "\" is installed with "
- "INCLUDES DESTINATION set to a context sensitive path. Paths which "
- "depend on the configuration, policy values or the link interface "
- "are "
- "not supported. Consider using target_include_directories instead.";
- lg->IssueMessage(MessageType::FATAL_ERROR, e.str());
- return;
- }
-
- if (!input && exportDirs.empty()) {
- return;
- }
- if ((input && input->empty()) && exportDirs.empty()) {
- // Set to empty
- properties[propName].clear();
- return;
- }
-
- prefixItems(exportDirs);
- includesDestinationDirs = exportDirs;
-
- std::string includes = (input ? *input : "");
- char const* sep = input ? ";" : "";
- includes += sep + exportDirs;
- std::string prepro =
- cmGeneratorExpression::Preprocess(includes, preprocessRule, true);
- if (!prepro.empty()) {
- this->ResolveTargetsInGeneratorExpressions(prepro, target);
-
- if (!checkInterfaceDirs(prepro, target, propName)) {
- return;
- }
- properties[propName] = prepro;
- }
-}
-
-void cmExportFileGenerator::PopulateLinkDependsInterface(
- cmGeneratorTarget const* gt,
- cmGeneratorExpression::PreprocessContext preprocessRule,
- ImportPropertyMap& properties)
-{
- assert(preprocessRule == cmGeneratorExpression::InstallInterface);
-
- char const* propName = "INTERFACE_LINK_DEPENDS";
- cmValue input = gt->GetProperty(propName);
-
- if (!input) {
- return;
- }
-
- if (input->empty()) {
- properties[propName].clear();
- return;
- }
-
- std::string prepro =
- cmGeneratorExpression::Preprocess(*input, preprocessRule, true);
- if (!prepro.empty()) {
- this->ResolveTargetsInGeneratorExpressions(prepro, gt);
-
- if (!checkInterfaceDirs(prepro, gt, propName)) {
- return;
- }
- properties[propName] = prepro;
- }
-}
-
-void cmExportFileGenerator::PopulateLinkDirectoriesInterface(
- cmGeneratorTarget const* gt,
- cmGeneratorExpression::PreprocessContext preprocessRule,
- ImportPropertyMap& properties)
-{
- assert(preprocessRule == cmGeneratorExpression::InstallInterface);
-
- char const* propName = "INTERFACE_LINK_DIRECTORIES";
- cmValue input = gt->GetProperty(propName);
-
- if (!input) {
- return;
- }
-
- if (input->empty()) {
- properties[propName].clear();
- return;
- }
-
- std::string prepro =
- cmGeneratorExpression::Preprocess(*input, preprocessRule, true);
- if (!prepro.empty()) {
- this->ResolveTargetsInGeneratorExpressions(prepro, gt);
-
- if (!checkInterfaceDirs(prepro, gt, propName)) {
- return;
- }
- properties[propName] = prepro;
- }
-}
-
-void cmExportFileGenerator::PopulateInterfaceProperty(
- std::string const& propName, cmGeneratorTarget const* target,
- cmGeneratorExpression::PreprocessContext preprocessRule,
- ImportPropertyMap& properties)
-{
- this->PopulateInterfaceProperty(propName, propName, target, preprocessRule,
- properties);
-}
-
-static void getPropertyContents(cmGeneratorTarget const* tgt,
- std::string const& prop,
- std::set<std::string>& ifaceProperties)
+namespace {
+void getPropertyContents(cmGeneratorTarget const* tgt, std::string const& prop,
+ std::set<std::string>& ifaceProperties)
{
cmValue p = tgt->GetProperty(prop);
if (!p) {
@@ -530,9 +234,9 @@ static void getPropertyContents(cmGeneratorTarget const* tgt,
ifaceProperties.insert(content.begin(), content.end());
}
-static void getCompatibleInterfaceProperties(
- cmGeneratorTarget const* target, std::set<std::string>& ifaceProperties,
- std::string const& config)
+void getCompatibleInterfaceProperties(cmGeneratorTarget const* target,
+ std::set<std::string>& ifaceProperties,
+ std::string const& config)
{
if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
// object libraries have no link information, so nothing to compute
@@ -567,9 +271,10 @@ static void getCompatibleInterfaceProperties(
ifaceProperties);
}
}
+}
void cmExportFileGenerator::PopulateCompatibleInterfaceProperties(
- cmGeneratorTarget const* gtarget, ImportPropertyMap& properties)
+ cmGeneratorTarget const* gtarget, ImportPropertyMap& properties) const
{
this->PopulateInterfaceProperty("COMPATIBLE_INTERFACE_BOOL", gtarget,
properties);
@@ -626,22 +331,6 @@ void cmExportFileGenerator::PopulateCustomTransitiveInterfaceProperties(
}
}
-void cmExportFileGenerator::GenerateInterfaceProperties(
- cmGeneratorTarget const* target, std::ostream& os,
- ImportPropertyMap const& properties)
-{
- if (!properties.empty()) {
- std::string targetName =
- cmStrCat(this->Namespace, target->GetExportName());
- os << "set_target_properties(" << targetName << " PROPERTIES\n";
- for (auto const& property : properties) {
- os << " " << property.first << " "
- << cmExportFileGeneratorEscape(property.second) << "\n";
- }
- os << ")\n\n";
- }
-}
-
bool cmExportFileGenerator::AddTargetNamespace(std::string& input,
cmGeneratorTarget const* target,
cmLocalGenerator const* lg)
@@ -805,74 +494,14 @@ void cmExportFileGenerator::ResolveTargetsInGeneratorExpression(
}
}
-void cmExportFileGenerator::ReplaceInstallPrefix(std::string& /*unused*/)
+void cmExportFileGenerator::ReplaceInstallPrefix(std::string& /*unused*/) const
{
// Do nothing
}
-void cmExportFileGenerator::SetImportLinkInterface(
- std::string const& config, std::string const& suffix,
- cmGeneratorExpression::PreprocessContext preprocessRule,
- cmGeneratorTarget const* target, ImportPropertyMap& properties)
-{
- // Add the transitive link dependencies for this configuration.
- cmLinkInterface const* iface = target->GetLinkInterface(config, target);
- if (!iface) {
- return;
- }
-
- if (iface->ImplementationIsInterface) {
- // Policy CMP0022 must not be NEW.
- this->SetImportLinkProperty(
- suffix, target, "IMPORTED_LINK_INTERFACE_LIBRARIES", iface->Libraries,
- properties, ImportLinkPropertyTargetNames::Yes);
- return;
- }
-
- cmValue propContent;
-
- if (cmValue prop_suffixed =
- target->GetProperty("LINK_INTERFACE_LIBRARIES" + suffix)) {
- propContent = prop_suffixed;
- } else if (cmValue prop = target->GetProperty("LINK_INTERFACE_LIBRARIES")) {
- propContent = prop;
- } else {
- return;
- }
-
- bool const newCMP0022Behavior =
- target->GetPolicyStatusCMP0022() != cmPolicies::WARN &&
- target->GetPolicyStatusCMP0022() != cmPolicies::OLD;
-
- if (newCMP0022Behavior && !this->ExportOld) {
- cmLocalGenerator* lg = target->GetLocalGenerator();
- std::ostringstream e;
- e << "Target \"" << target->GetName()
- << "\" has policy CMP0022 enabled, "
- "but also has old-style LINK_INTERFACE_LIBRARIES properties "
- "populated, but it was exported without the "
- "EXPORT_LINK_INTERFACE_LIBRARIES to export the old-style properties";
- lg->IssueMessage(MessageType::FATAL_ERROR, e.str());
- return;
- }
-
- if (propContent->empty()) {
- properties["IMPORTED_LINK_INTERFACE_LIBRARIES" + suffix].clear();
- return;
- }
-
- std::string prepro =
- cmGeneratorExpression::Preprocess(*propContent, preprocessRule);
- if (!prepro.empty()) {
- this->ResolveTargetsInGeneratorExpressions(prepro, target,
- ReplaceFreeTargets);
- properties["IMPORTED_LINK_INTERFACE_LIBRARIES" + suffix] = prepro;
- }
-}
-
void cmExportFileGenerator::SetImportDetailProperties(
std::string const& config, std::string const& suffix,
- cmGeneratorTarget* target, ImportPropertyMap& properties)
+ cmGeneratorTarget const* target, ImportPropertyMap& properties)
{
// Get the makefile in which to lookup target information.
cmMakefile* mf = target->Makefile;
@@ -943,15 +572,17 @@ void cmExportFileGenerator::SetImportDetailProperties(
}
}
-static std::string const& asString(std::string const& l)
+namespace {
+std::string const& asString(std::string const& l)
{
return l;
}
-static std::string const& asString(cmLinkItem const& l)
+std::string const& asString(cmLinkItem const& l)
{
return l.AsStr();
}
+}
template <typename T>
void cmExportFileGenerator::SetImportLinkProperty(
@@ -988,431 +619,17 @@ void cmExportFileGenerator::SetImportLinkProperty(
properties[prop] = link_entries;
}
-void cmExportFileGenerator::GeneratePolicyHeaderCode(std::ostream& os)
-{
- // Protect that file against use with older CMake versions.
- /* clang-format off */
- os << "# Generated by CMake\n\n";
- os << "if(\"${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}\" LESS 2.8)\n"
- << " message(FATAL_ERROR \"CMake >= "
- << this->RequiredCMakeVersionMajor << '.'
- << this->RequiredCMakeVersionMinor << '.'
- << this->RequiredCMakeVersionPatch << " required\")\n"
- << "endif()\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 */
-
- // Isolate the file policy level.
- // Support CMake versions as far back as the
- // RequiredCMakeVersion{Major,Minor,Patch}, but also support using NEW
- // policy settings for up to CMake 3.29 (this upper limit may be reviewed
- // and increased from time to time). This reduces the opportunity for CMake
- // warnings when an older export file is later used with newer CMake
- // versions.
- /* clang-format off */
- os << "cmake_policy(PUSH)\n"
- << "cmake_policy(VERSION "
- << this->RequiredCMakeVersionMajor << '.'
- << this->RequiredCMakeVersionMinor << '.'
- << this->RequiredCMakeVersionPatch << "...3.29)\n";
- /* clang-format on */
-}
+template void cmExportFileGenerator::SetImportLinkProperty<std::string>(
+ std::string const&, cmGeneratorTarget const*, std::string const&,
+ std::vector<std::string> const&, ImportPropertyMap& properties,
+ ImportLinkPropertyTargetNames);
-void cmExportFileGenerator::GeneratePolicyFooterCode(std::ostream& os)
-{
- os << "cmake_policy(POP)\n";
-}
-
-void cmExportFileGenerator::GenerateImportHeaderCode(std::ostream& os,
- std::string const& config)
-{
- os << "#----------------------------------------------------------------\n"
- << "# Generated CMake target import file";
- if (!config.empty()) {
- os << " for configuration \"" << config << "\".\n";
- } else {
- os << ".\n";
- }
- os << "#----------------------------------------------------------------\n"
- << "\n";
- this->GenerateImportVersionCode(os);
-}
-
-void cmExportFileGenerator::GenerateImportFooterCode(std::ostream& os)
-{
- os << "# Commands beyond this point should not need to know the version.\n"
- << "set(CMAKE_IMPORT_FILE_VERSION)\n";
-}
-
-void cmExportFileGenerator::GenerateImportVersionCode(std::ostream& os)
-{
- // Store an import file format version. This will let us change the
- // format later while still allowing old import files to work.
- /* clang-format off */
- os << "# Commands may need to know the format version.\n"
- << "set(CMAKE_IMPORT_FILE_VERSION 1)\n"
- << "\n";
- /* clang-format on */
-}
-
-void cmExportFileGenerator::GenerateExpectedTargetsCode(
- std::ostream& os, std::string const& expectedTargets)
-{
- /* clang-format off */
- os << "# Protect against multiple inclusion, which would fail when already "
- "imported targets are added once more.\n"
- "set(_cmake_targets_defined \"\")\n"
- "set(_cmake_targets_not_defined \"\")\n"
- "set(_cmake_expected_targets \"\")\n"
- "foreach(_cmake_expected_target IN ITEMS " << expectedTargets << ")\n"
- " list(APPEND _cmake_expected_targets \"${_cmake_expected_target}\")\n"
- " if(TARGET \"${_cmake_expected_target}\")\n"
- " list(APPEND _cmake_targets_defined \"${_cmake_expected_target}\")\n"
- " else()\n"
- " list(APPEND _cmake_targets_not_defined \"${_cmake_expected_target}\")\n"
- " endif()\n"
- "endforeach()\n"
- "unset(_cmake_expected_target)\n"
- "if(_cmake_targets_defined STREQUAL _cmake_expected_targets)\n"
- " unset(_cmake_targets_defined)\n"
- " unset(_cmake_targets_not_defined)\n"
- " unset(_cmake_expected_targets)\n"
- " unset(CMAKE_IMPORT_FILE_VERSION)\n"
- " cmake_policy(POP)\n"
- " return()\n"
- "endif()\n"
- "if(NOT _cmake_targets_defined STREQUAL \"\")\n"
- " string(REPLACE \";\" \", \" _cmake_targets_defined_text \"${_cmake_targets_defined}\")\n"
- " string(REPLACE \";\" \", \" _cmake_targets_not_defined_text \"${_cmake_targets_not_defined}\")\n"
- " message(FATAL_ERROR \"Some (but not all) targets in this export "
- "set were already defined.\\nTargets Defined: ${_cmake_targets_defined_text}\\n"
- "Targets not yet defined: ${_cmake_targets_not_defined_text}\\n\")\n"
- "endif()\n"
- "unset(_cmake_targets_defined)\n"
- "unset(_cmake_targets_not_defined)\n"
- "unset(_cmake_expected_targets)\n"
- "\n\n";
- /* clang-format on */
-}
-
-void cmExportFileGenerator::GenerateImportTargetCode(
- std::ostream& os, cmGeneratorTarget const* target,
- cmStateEnums::TargetType targetType)
-{
- // Construct the imported target name.
- std::string targetName = this->Namespace;
-
- targetName += target->GetExportName();
-
- // Create the imported target.
- os << "# Create imported target " << targetName << "\n";
- switch (targetType) {
- case cmStateEnums::EXECUTABLE:
- os << "add_executable(" << targetName << " IMPORTED)\n";
- break;
- case cmStateEnums::STATIC_LIBRARY:
- os << "add_library(" << targetName << " STATIC IMPORTED)\n";
- break;
- case cmStateEnums::SHARED_LIBRARY:
- os << "add_library(" << targetName << " SHARED IMPORTED)\n";
- break;
- case cmStateEnums::MODULE_LIBRARY:
- os << "add_library(" << targetName << " MODULE IMPORTED)\n";
- break;
- case cmStateEnums::UNKNOWN_LIBRARY:
- os << "add_library(" << targetName << " UNKNOWN IMPORTED)\n";
- break;
- case cmStateEnums::OBJECT_LIBRARY:
- os << "add_library(" << targetName << " OBJECT IMPORTED)\n";
- break;
- case cmStateEnums::INTERFACE_LIBRARY:
- os << "add_library(" << targetName << " INTERFACE IMPORTED)\n";
- break;
- default: // should never happen
- break;
- }
-
- // Mark the imported executable if it has exports.
- if (target->IsExecutableWithExports() ||
- (target->IsSharedLibraryWithExports() && target->HasImportLibrary(""))) {
- os << "set_property(TARGET " << targetName
- << " PROPERTY ENABLE_EXPORTS 1)\n";
- }
-
- // Mark the imported library if it is a framework.
- if (target->IsFrameworkOnApple()) {
- os << "set_property(TARGET " << targetName << " PROPERTY FRAMEWORK 1)\n";
- }
-
- // Mark the imported executable if it is an application bundle.
- if (target->IsAppBundleOnApple()) {
- os << "set_property(TARGET " << targetName
- << " PROPERTY MACOSX_BUNDLE 1)\n";
- }
-
- if (target->IsCFBundleOnApple()) {
- os << "set_property(TARGET " << targetName << " PROPERTY BUNDLE 1)\n";
- }
-
- // generate DEPRECATION
- if (target->IsDeprecated()) {
- os << "set_property(TARGET " << targetName << " PROPERTY DEPRECATION "
- << cmExportFileGeneratorEscape(target->GetDeprecation()) << ")\n";
- }
-
- if (target->GetPropertyAsBool("IMPORTED_NO_SYSTEM")) {
- os << "set_property(TARGET " << targetName
- << " PROPERTY IMPORTED_NO_SYSTEM 1)\n";
- }
-
- if (target->GetPropertyAsBool("EXPORT_NO_SYSTEM")) {
- os << "set_property(TARGET " << targetName << " PROPERTY SYSTEM 0)\n";
- }
-
- os << "\n";
-}
-
-void cmExportFileGenerator::GenerateImportPropertyCode(
- std::ostream& os, std::string const& config, std::string const& suffix,
- cmGeneratorTarget const* target, ImportPropertyMap const& properties,
- std::string const& importedXcFrameworkLocation)
-{
- // Construct the imported target name.
- std::string targetName = this->Namespace;
-
- targetName += target->GetExportName();
-
- // Set the import properties.
- os << "# Import target \"" << targetName << "\" for configuration \""
- << config << "\"\n";
- os << "set_property(TARGET " << targetName
- << " APPEND PROPERTY IMPORTED_CONFIGURATIONS ";
- if (!config.empty()) {
- os << cmSystemTools::UpperCase(config);
- } else {
- os << "NOCONFIG";
- }
- os << ")\n";
- os << "set_target_properties(" << targetName << " PROPERTIES\n";
- std::string importedLocationProp = cmStrCat("IMPORTED_LOCATION", suffix);
- for (auto const& property : properties) {
- if (importedXcFrameworkLocation.empty() ||
- property.first != importedLocationProp) {
- os << " " << property.first << " "
- << cmExportFileGeneratorEscape(property.second) << "\n";
- }
- }
- os << " )\n";
- if (!importedXcFrameworkLocation.empty()) {
- auto importedLocationIt = properties.find(importedLocationProp);
- if (importedLocationIt != properties.end()) {
- os << "if(NOT CMAKE_VERSION VERSION_LESS \"3.28\" AND IS_DIRECTORY "
- << cmExportFileGeneratorEscape(importedXcFrameworkLocation)
- << ")\n"
- " set_property(TARGET "
- << targetName << " PROPERTY " << importedLocationProp << " "
- << cmExportFileGeneratorEscape(importedXcFrameworkLocation)
- << ")\nelse()\n set_property(TARGET " << targetName << " PROPERTY "
- << importedLocationProp << " "
- << cmExportFileGeneratorEscape(importedLocationIt->second)
- << ")\nendif()\n";
- }
- }
- os << "\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(),
- [](std::pair<std::string, cmExportSet::PackageDependency> const& lhs,
- std::pair<std::string, cmExportSet::PackageDependency> const& 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;
- 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()) {
- /* clang-format off */
- os << "# This file does not depend on other imported targets which have\n"
- "# been exported from the same project but in a separate "
- "export set.\n\n";
- /* clang-format on */
- return;
- }
- /* clang-format off */
- os << "# Make sure the targets which have been exported in some other\n"
- "# export set exist.\n"
- "unset(${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets)\n"
- "foreach(_target ";
- /* clang-format on */
- std::set<std::string> emitted;
- for (std::string const& missingTarget : this->MissingTargets) {
- if (emitted.insert(missingTarget).second) {
- os << "\"" << missingTarget << "\" ";
- }
- }
- /* clang-format off */
- os << ")\n"
- " if(NOT TARGET \"${_target}\" )\n"
- " set(${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets \""
- "${${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets} ${_target}\")"
- "\n"
- " endif()\n"
- "endforeach()\n"
- "\n"
- "if(DEFINED ${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets)\n"
- " if(CMAKE_FIND_PACKAGE_NAME)\n"
- " set( ${CMAKE_FIND_PACKAGE_NAME}_FOUND FALSE)\n"
- " set( ${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE "
- "\"The following imported targets are "
- "referenced, but are missing: "
- "${${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets}\")\n"
- " else()\n"
- " message(FATAL_ERROR \"The following imported targets are "
- "referenced, but are missing: "
- "${${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets}\")\n"
- " endif()\n"
- "endif()\n"
- "unset(${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets)\n"
- "\n";
- /* clang-format on */
-}
-
-void cmExportFileGenerator::GenerateImportedFileCheckLoop(std::ostream& os)
-{
- // Add code which verifies at cmake time that the file which is being
- // imported actually exists on disk. This should in theory always be theory
- // case, but still when packages are split into normal and development
- // packages this might get broken (e.g. the Config.cmake could be part of
- // the non-development package, something similar happened to me without
- // on SUSE with a mysql pkg-config file, which claimed everything is fine,
- // but the development package was not installed.).
- /* clang-format off */
- os << "# Loop over all imported files and verify that they actually exist\n"
- "foreach(_cmake_target IN LISTS _cmake_import_check_targets)\n"
- " if(CMAKE_VERSION VERSION_LESS \"3.28\"\n"
- " OR NOT DEFINED "
- "_cmake_import_check_xcframework_for_${_cmake_target}\n"
- " OR NOT IS_DIRECTORY "
- "\"${_cmake_import_check_xcframework_for_${_cmake_target}}\")\n"
- " foreach(_cmake_file IN LISTS "
- "\"_cmake_import_check_files_for_${_cmake_target}\")\n"
- " if(NOT EXISTS \"${_cmake_file}\")\n"
- " message(FATAL_ERROR \"The imported target "
- "\\\"${_cmake_target}\\\" references the file\n"
- " \\\"${_cmake_file}\\\"\n"
- "but this file does not exist. Possible reasons include:\n"
- "* The file was deleted, renamed, or moved to another location.\n"
- "* An install or uninstall procedure did not complete successfully.\n"
- "* The installation package was faulty and contained\n"
- " \\\"${CMAKE_CURRENT_LIST_FILE}\\\"\n"
- "but not all the files it references.\n"
- "\")\n"
- " endif()\n"
- " endforeach()\n"
- " endif()\n"
- " unset(_cmake_file)\n"
- " unset(\"_cmake_import_check_files_for_${_cmake_target}\")\n"
- "endforeach()\n"
- "unset(_cmake_target)\n"
- "unset(_cmake_import_check_targets)\n"
- "\n";
- /* clang-format on */
-}
-
-void cmExportFileGenerator::GenerateImportedFileChecksCode(
- std::ostream& os, cmGeneratorTarget* target,
- ImportPropertyMap const& properties,
- std::set<std::string> const& importedLocations,
- std::string const& importedXcFrameworkLocation)
-{
- // Construct the imported target name.
- std::string targetName = cmStrCat(this->Namespace, target->GetExportName());
-
- os << "list(APPEND _cmake_import_check_targets " << targetName << " )\n";
- if (!importedXcFrameworkLocation.empty()) {
- os << "set(_cmake_import_check_xcframework_for_" << targetName << ' '
- << cmExportFileGeneratorEscape(importedXcFrameworkLocation) << ")\n";
- }
- os << "list(APPEND _cmake_import_check_files_for_" << targetName << " ";
-
- for (std::string const& li : importedLocations) {
- auto pi = properties.find(li);
- if (pi != properties.end()) {
- os << cmExportFileGeneratorEscape(pi->second) << " ";
- }
- }
-
- os << ")\n\n";
-}
+template void cmExportFileGenerator::SetImportLinkProperty<cmLinkItem>(
+ std::string const&, cmGeneratorTarget const*, std::string const&,
+ std::vector<cmLinkItem> const&, ImportPropertyMap& properties,
+ ImportLinkPropertyTargetNames);
+namespace {
enum class ExportWhen
{
Defined,
@@ -1426,7 +643,6 @@ enum class PropertyType
IncludePaths,
};
-namespace {
bool PropertyTypeIsForPaths(PropertyType pt)
{
switch (pt) {
@@ -1440,18 +656,6 @@ bool PropertyTypeIsForPaths(PropertyType pt)
}
}
-struct ModuleTargetPropertyTable
-{
- cm::static_string_view Name;
- ExportWhen Cond;
-};
-
-struct ModulePropertyTable
-{
- cm::static_string_view Name;
- PropertyType Type;
-};
-
bool cmExportFileGenerator::PopulateCxxModuleExportProperties(
cmGeneratorTarget const* gte, ImportPropertyMap& properties,
cmGeneratorExpression::PreprocessContext ctx,
@@ -1461,6 +665,12 @@ bool cmExportFileGenerator::PopulateCxxModuleExportProperties(
return true;
}
+ struct ModuleTargetPropertyTable
+ {
+ cm::static_string_view Name;
+ ExportWhen Cond;
+ };
+
ModuleTargetPropertyTable const exportedDirectModuleProperties[] = {
{ "CXX_EXTENSIONS"_s, ExportWhen::Defined },
// Always define this property as it is an intrinsic property of the target
@@ -1487,6 +697,12 @@ bool cmExportFileGenerator::PopulateCxxModuleExportProperties(
}
}
+ struct ModulePropertyTable
+ {
+ cm::static_string_view Name;
+ PropertyType Type;
+ };
+
ModulePropertyTable const exportedModuleProperties[] = {
{ "INCLUDE_DIRECTORIES"_s, PropertyType::IncludePaths },
{ "COMPILE_DEFINITIONS"_s, PropertyType::Strings },
@@ -1508,7 +724,7 @@ bool cmExportFileGenerator::PopulateCxxModuleExportProperties(
if (ctx == cmGeneratorExpression::InstallInterface &&
PropertyTypeIsForPaths(propEntry.Type)) {
this->ReplaceInstallPrefix(properties[exportedPropName]);
- prefixItems(properties[exportedPropName]);
+ this->AddImportPrefix(properties[exportedPropName]);
if (propEntry.Type == PropertyType::IncludePaths &&
!includesDestinationDirs.empty()) {
if (!properties[exportedPropName].empty()) {
@@ -1534,8 +750,8 @@ bool cmExportFileGenerator::PopulateCxxModuleExportProperties(
auto const exportedPropName =
cmStrCat("IMPORTED_CXX_MODULES_", propName);
auto value = cmGeneratorExpression::Preprocess(*prop, ctx);
- this->ResolveTargetsInGeneratorExpressions(
- value, gte, cmExportFileGenerator::ReplaceFreeTargets);
+ this->ResolveTargetsInGeneratorExpressions(value, gte,
+ ReplaceFreeTargets);
properties[exportedPropName] = value;
}
}
@@ -1545,7 +761,7 @@ bool cmExportFileGenerator::PopulateCxxModuleExportProperties(
bool cmExportFileGenerator::PopulateExportProperties(
cmGeneratorTarget const* gte, ImportPropertyMap& properties,
- std::string& errorMessage)
+ std::string& errorMessage) const
{
auto const& targetProperties = gte->Target->GetProperties();
if (cmValue exportProperties =
@@ -1582,101 +798,3 @@ bool cmExportFileGenerator::PopulateExportProperties(
}
return true;
}
-
-void cmExportFileGenerator::GenerateTargetFileSets(cmGeneratorTarget* gte,
- std::ostream& os,
- cmTargetExport* te)
-{
- auto interfaceFileSets = gte->Target->GetAllInterfaceFileSets();
- if (!interfaceFileSets.empty()) {
- std::string targetName = cmStrCat(this->Namespace, gte->GetExportName());
- os << "if(NOT CMAKE_VERSION VERSION_LESS \"3.23.0\")\n"
- " target_sources("
- << targetName << "\n";
-
- for (auto const& name : interfaceFileSets) {
- auto* fileSet = gte->Target->GetFileSet(name);
- if (!fileSet) {
- gte->Makefile->IssueMessage(
- MessageType::FATAL_ERROR,
- cmStrCat("File set \"", name,
- "\" is listed in interface file sets of ", gte->GetName(),
- " but has not been created"));
- return;
- }
-
- os << " INTERFACE"
- << "\n FILE_SET " << cmOutputConverter::EscapeForCMake(name)
- << "\n TYPE "
- << cmOutputConverter::EscapeForCMake(fileSet->GetType())
- << "\n BASE_DIRS "
- << this->GetFileSetDirectories(gte, fileSet, te) << "\n FILES "
- << this->GetFileSetFiles(gte, fileSet, te) << "\n";
- }
-
- os << " )\nelse()\n set_property(TARGET " << targetName
- << "\n APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES";
- for (auto const& name : interfaceFileSets) {
- auto* fileSet = gte->Target->GetFileSet(name);
- if (!fileSet) {
- gte->Makefile->IssueMessage(
- MessageType::FATAL_ERROR,
- cmStrCat("File set \"", name,
- "\" is listed in interface file sets of ", gte->GetName(),
- " but has not been created"));
- return;
- }
-
- if (fileSet->GetType() == "HEADERS"_s) {
- os << "\n " << this->GetFileSetDirectories(gte, fileSet, te);
- }
- }
- os << "\n )\nendif()\n\n";
- }
-}
-
-std::string cmExportFileGenerator::GetCxxModuleFile(
- std::string const& name) const
-{
- auto const& cxxModuleDirname = this->GetCxxModulesDirectory();
- if (cxxModuleDirname.empty()) {
- return {};
- }
-
- return cmStrCat(cmSystemTools::GetFilenamePath(this->MainImportFile), '/',
- cxxModuleDirname, "/cxx-modules-", name, ".cmake");
-}
-
-void cmExportFileGenerator::GenerateCxxModuleInformation(
- std::string const& name, std::ostream& os)
-{
- auto const cxx_module_dirname = this->GetCxxModulesDirectory();
- if (cxx_module_dirname.empty()) {
- return;
- }
-
- // Write the include.
- os << "# Include C++ module properties\n"
- << "include(\"${CMAKE_CURRENT_LIST_DIR}/" << cxx_module_dirname
- << "/cxx-modules-" << name << ".cmake\")\n\n";
-
- // Include all configuration-specific include files.
- cmGeneratedFileStream ap(this->GetCxxModuleFile(name), true);
- ap.SetCopyIfDifferent(true);
-
- this->GenerateCxxModuleConfigInformation(name, 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 7a100bd..89295f5 100644
--- a/Source/cmExportFileGenerator.h
+++ b/Source/cmExportFileGenerator.h
@@ -10,16 +10,13 @@
#include <string>
#include <vector>
+#include <cm/string_view>
+
#include "cmGeneratorExpression.h"
-#include "cmStateTypes.h"
-#include "cmVersion.h"
-#include "cmVersionConfig.h"
class cmExportSet;
-class cmFileSet;
class cmGeneratorTarget;
class cmLocalGenerator;
-class cmTargetExport;
#define STRINGIFY_HELPER(X) #X
#define STRINGIFY(X) STRINGIFY_HELPER(X)
@@ -32,12 +29,9 @@ class cmTargetExport;
: #major "." #minor ".0")
/** \class cmExportFileGenerator
- * \brief Generate a file exporting targets from a build or install tree.
+ * \brief Generate files exporting targets from a build or install tree.
*
- * cmExportFileGenerator is the superclass for
- * cmExportBuildFileGenerator and cmExportInstallFileGenerator. It
- * contains common code generation routines for the two kinds of
- * export implementations.
+ * cmExportFileGenerator is the interface class for generating export files.
*/
class cmExportFileGenerator
{
@@ -53,58 +47,21 @@ public:
void SetNamespace(std::string const& ns) { this->Namespace = ns; }
std::string GetNamespace() const { return this->Namespace; }
- void SetExportOld(bool exportOld) { this->ExportOld = exportOld; }
-
/** Add a configuration to be exported. */
void AddConfiguration(std::string const& config);
- /** Actually generate the export file. Returns whether there was an
- error. */
+ /** Create and actually generate the export file. Returns whether there was
+ an error. */
bool GenerateImportFile();
- void SetExportPackageDependencies(bool exportPackageDependencies)
- {
- this->ExportPackageDependencies = exportPackageDependencies;
- }
-
protected:
using ImportPropertyMap = std::map<std::string, std::string>;
- // Generate per-configuration target information to the given output
- // stream.
- void GenerateImportConfig(std::ostream& os, std::string const& config);
-
- // Methods to implement export file code generation.
- virtual void GeneratePolicyHeaderCode(std::ostream& os);
- virtual void GeneratePolicyFooterCode(std::ostream& os);
- virtual void GenerateImportHeaderCode(std::ostream& os,
- std::string const& config = "");
- virtual void GenerateImportFooterCode(std::ostream& os);
- void GenerateImportVersionCode(std::ostream& os);
- virtual void GenerateImportTargetCode(std::ostream& os,
- cmGeneratorTarget const* target,
- cmStateEnums::TargetType targetType);
- virtual void GenerateImportPropertyCode(
- std::ostream& os, std::string const& config, std::string const& suffix,
- cmGeneratorTarget const* target, ImportPropertyMap const& properties,
- std::string const& importedXcFrameworkLocation);
- virtual void GenerateImportedFileChecksCode(
- std::ostream& os, cmGeneratorTarget* target,
- ImportPropertyMap const& properties,
- std::set<std::string> const& importedLocations,
- std::string const& importedXcFrameworkLocation);
- virtual void GenerateImportedFileCheckLoop(std::ostream& os);
- virtual void GenerateMissingTargetsCheckCode(std::ostream& os);
- virtual void GenerateFindDependencyCalls(std::ostream& os);
-
- virtual void GenerateExpectedTargetsCode(std::ostream& os,
- std::string const& expectedTargets);
-
// Collect properties with detailed information about targets beyond
// their location on disk.
void SetImportDetailProperties(std::string const& config,
std::string const& suffix,
- cmGeneratorTarget* target,
+ cmGeneratorTarget const* target,
ImportPropertyMap& properties);
enum class ImportLinkPropertyTargetNames
@@ -120,9 +77,17 @@ protected:
ImportPropertyMap& properties,
ImportLinkPropertyTargetNames targetNames);
+ /** Generate the export file to the given output stream. Returns whether
+ there was an error. */
+ virtual bool GenerateImportFile(std::ostream& os) = 0;
+
/** Each subclass knows how to generate its kind of export file. */
virtual bool GenerateMainFile(std::ostream& os) = 0;
+ /** Generate per-configuration target information to the given output
+ stream. */
+ void GenerateImportConfig(std::ostream& os, std::string const& config);
+
/** Each subclass knows where the target files are located. */
virtual void GenerateImportTargetsConfig(std::ostream& os,
std::string const& config,
@@ -133,47 +98,33 @@ protected:
virtual void HandleMissingTarget(std::string& link_libs,
cmGeneratorTarget const* depender,
cmGeneratorTarget* dependee) = 0;
- void PopulateInterfaceProperty(std::string const&,
+
+ /** Complain when a duplicate target is encountered. */
+ virtual void ComplainAboutDuplicateTarget(
+ std::string const& targetName) const = 0;
+
+ virtual cm::string_view GetImportPrefixWithSlash() const = 0;
+
+ void AddImportPrefix(std::string& exportDirs) const;
+
+ void PopulateInterfaceProperty(std::string const& propName,
+ cmGeneratorTarget const* target,
+ ImportPropertyMap& properties) const;
+ void PopulateInterfaceProperty(std::string const& propName,
cmGeneratorTarget const* target,
cmGeneratorExpression::PreprocessContext,
ImportPropertyMap& properties);
bool PopulateInterfaceLinkLibrariesProperty(
cmGeneratorTarget const* target, cmGeneratorExpression::PreprocessContext,
ImportPropertyMap& properties);
- void PopulateInterfaceProperty(std::string const& propName,
- cmGeneratorTarget const* target,
- ImportPropertyMap& properties);
- void PopulateCompatibleInterfaceProperties(cmGeneratorTarget const* target,
- ImportPropertyMap& properties);
- void PopulateCustomTransitiveInterfaceProperties(
- cmGeneratorTarget const* target,
- cmGeneratorExpression::PreprocessContext preprocessRule,
- ImportPropertyMap& properties);
- virtual void GenerateInterfaceProperties(
- cmGeneratorTarget const* target, std::ostream& os,
- ImportPropertyMap const& properties);
- void PopulateIncludeDirectoriesInterface(
- cmGeneratorTarget const* target,
- cmGeneratorExpression::PreprocessContext preprocessRule,
- ImportPropertyMap& properties, cmTargetExport const& te,
- std::string& includesDestinationDirs);
- void PopulateSourcesInterface(
- cmGeneratorTarget const* target,
- cmGeneratorExpression::PreprocessContext preprocessRule,
- ImportPropertyMap& properties);
- void PopulateLinkDirectoriesInterface(
- cmGeneratorTarget const* target,
- cmGeneratorExpression::PreprocessContext preprocessRule,
- ImportPropertyMap& properties);
- void PopulateLinkDependsInterface(
+
+ bool PopulateInterfaceProperties(
cmGeneratorTarget const* target,
+ std::string const& includesDestinationDirs,
cmGeneratorExpression::PreprocessContext preprocessRule,
ImportPropertyMap& properties);
- void SetImportLinkInterface(
- std::string const& config, std::string const& suffix,
- cmGeneratorExpression::PreprocessContext preprocessRule,
- cmGeneratorTarget const* target, ImportPropertyMap& properties);
+ virtual void ReportError(std::string const& errorMessage) const = 0;
enum FreeTargetsReplace
{
@@ -185,38 +136,26 @@ protected:
std::string& input, cmGeneratorTarget const* target,
FreeTargetsReplace replace = NoReplaceFreeTargets);
- bool PopulateCxxModuleExportProperties(
- cmGeneratorTarget const* gte, ImportPropertyMap& properties,
- cmGeneratorExpression::PreprocessContext ctx,
- std::string const& includesDestinationDirs, std::string& errorMessage);
- bool PopulateExportProperties(cmGeneratorTarget const* gte,
- ImportPropertyMap& properties,
- std::string& errorMessage);
-
- void GenerateTargetFileSets(cmGeneratorTarget* gte, std::ostream& os,
- cmTargetExport* te = nullptr);
+ virtual cmExportSet* GetExportSet() const { return nullptr; }
- void GenerateCxxModuleInformation(std::string const& name, std::ostream& os);
+ virtual void ReplaceInstallPrefix(std::string& input) const;
- virtual std::string GetFileSetDirectories(cmGeneratorTarget* gte,
- cmFileSet* fileSet,
- cmTargetExport* te) = 0;
- virtual std::string GetFileSetFiles(cmGeneratorTarget* gte,
- cmFileSet* fileSet,
- cmTargetExport* te) = 0;
+ virtual std::string InstallNameDir(cmGeneratorTarget const* target,
+ std::string const& config) = 0;
- virtual cmExportSet* GetExportSet() const { return nullptr; }
+ /** Get the temporary location of the config-agnostic C++ module file. */
+ virtual std::string GetCxxModuleFile(std::string const& name) const = 0;
- std::string GetCxxModuleFile(std::string const& name) const;
+ virtual std::string GetCxxModulesDirectory() const = 0;
+ virtual void GenerateCxxModuleConfigInformation(std::string const&,
+ std::ostream& os) const = 0;
- void SetRequiredCMakeVersion(unsigned int major, unsigned int minor,
- unsigned int patch);
+ bool AddTargetNamespace(std::string& input, cmGeneratorTarget const* target,
+ cmLocalGenerator const* lg);
// The namespace in which the exports are placed in the generated file.
std::string Namespace;
- bool ExportOld;
-
// The set of configurations to export.
std::vector<std::string> Configurations;
@@ -225,40 +164,47 @@ protected:
std::string FileDir;
std::string FileBase;
std::string FileExt;
- bool AppendMode;
+ bool AppendMode = false;
// The set of targets included in the export.
- std::set<cmGeneratorTarget*> ExportedTargets;
+ std::set<cmGeneratorTarget const*> ExportedTargets;
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(std::string const&, std::string const&,
+ void PopulateInterfaceProperty(std::string const& propName,
+ std::string const& outputName,
cmGeneratorTarget const* target,
cmGeneratorExpression::PreprocessContext,
ImportPropertyMap& properties);
- bool AddTargetNamespace(std::string& input, cmGeneratorTarget const* target,
- cmLocalGenerator const* lg);
+ void PopulateCompatibleInterfaceProperties(
+ cmGeneratorTarget const* target, ImportPropertyMap& properties) const;
+ void PopulateCustomTransitiveInterfaceProperties(
+ cmGeneratorTarget const* target,
+ cmGeneratorExpression::PreprocessContext preprocessRule,
+ ImportPropertyMap& properties);
+ bool PopulateCxxModuleExportProperties(
+ cmGeneratorTarget const* gte, ImportPropertyMap& properties,
+ cmGeneratorExpression::PreprocessContext ctx,
+ std::string const& includesDestinationDirs, std::string& errorMessage);
+ bool PopulateExportProperties(cmGeneratorTarget const* gte,
+ ImportPropertyMap& properties,
+ std::string& errorMessage) const;
void ResolveTargetsInGeneratorExpression(std::string& input,
cmGeneratorTarget const* target,
cmLocalGenerator const* lg);
+};
- virtual void ReplaceInstallPrefix(std::string& input);
-
- virtual std::string InstallNameDir(cmGeneratorTarget const* target,
- std::string const& config) = 0;
+extern template void cmExportFileGenerator::SetImportLinkProperty<std::string>(
+ std::string const&, cmGeneratorTarget const*, std::string const&,
+ std::vector<std::string> const&, ImportPropertyMap& properties,
+ ImportLinkPropertyTargetNames);
- virtual std::string GetCxxModulesDirectory() const = 0;
- virtual void GenerateCxxModuleConfigInformation(std::string const&,
- std::ostream& os) const = 0;
-};
+extern template void cmExportFileGenerator::SetImportLinkProperty<cmLinkItem>(
+ std::string const&, cmGeneratorTarget const*, std::string const&,
+ std::vector<cmLinkItem> const&, ImportPropertyMap& properties,
+ ImportLinkPropertyTargetNames);
diff --git a/Source/cmExportInstallAndroidMKGenerator.cxx b/Source/cmExportInstallAndroidMKGenerator.cxx
index b172bba..c9c2f4e 100644
--- a/Source/cmExportInstallAndroidMKGenerator.cxx
+++ b/Source/cmExportInstallAndroidMKGenerator.cxx
@@ -4,14 +4,15 @@
#include <cstddef>
#include <memory>
-#include <ostream>
+#include <sstream>
#include <vector>
-#include "cmExportBuildAndroidMKGenerator.h"
#include "cmExportSet.h"
+#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmInstallExportGenerator.h"
#include "cmInstallTargetGenerator.h"
+#include "cmPolicies.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -24,6 +25,53 @@ cmExportInstallAndroidMKGenerator::cmExportInstallAndroidMKGenerator(
{
}
+void cmExportInstallAndroidMKGenerator::ReportDuplicateTarget(
+ std::string const& targetName) const
+{
+ std::ostringstream e;
+ e << "install(EXPORT_ANDROID_MK \"" << this->GetExportSet()->GetName()
+ << "\" ...) "
+ << "includes target \"" << targetName
+ << "\" more than once in the export set.";
+ this->ReportError(e.str());
+}
+
+bool cmExportInstallAndroidMKGenerator::GenerateMainFile(std::ostream& os)
+{
+ std::vector<cmTargetExport const*> allTargets;
+ {
+ auto visitor = [&](cmTargetExport const* te) { allTargets.push_back(te); };
+
+ if (!this->CollectExports(visitor)) {
+ return false;
+ }
+ }
+
+ // Create all the imported targets.
+ for (cmTargetExport const* te : allTargets) {
+ cmGeneratorTarget const* gt = te->Target;
+
+ this->GenerateImportTargetCode(os, gt, this->GetExportTargetType(te));
+
+ ImportPropertyMap properties;
+ if (!this->PopulateInterfaceProperties(te, properties)) {
+ return false;
+ }
+
+ bool const newCMP0022Behavior =
+ gt->GetPolicyStatusCMP0022() != cmPolicies::WARN &&
+ gt->GetPolicyStatusCMP0022() != cmPolicies::OLD;
+ if (newCMP0022Behavior) {
+ this->PopulateInterfaceLinkLibrariesProperty(
+ gt, cmGeneratorExpression::InstallInterface, properties);
+ }
+
+ this->GenerateInterfaceProperties(gt, os, properties);
+ }
+
+ return true;
+}
+
void cmExportInstallAndroidMKGenerator::GenerateImportHeaderCode(
std::ostream& os, std::string const&)
{
@@ -53,10 +101,6 @@ void cmExportInstallAndroidMKGenerator::GenerateImportHeaderCode(
}
}
-void cmExportInstallAndroidMKGenerator::GenerateImportFooterCode(std::ostream&)
-{
-}
-
void cmExportInstallAndroidMKGenerator::GenerateImportTargetCode(
std::ostream& os, cmGeneratorTarget const* target,
cmStateEnums::TargetType /*targetType*/)
@@ -73,61 +117,3 @@ void cmExportInstallAndroidMKGenerator::GenerateImportTargetCode(
}
os << target->GetFullName(config) << "\n";
}
-
-void cmExportInstallAndroidMKGenerator::GenerateExpectedTargetsCode(
- std::ostream&, std::string const&)
-{
-}
-
-void cmExportInstallAndroidMKGenerator::GenerateImportPropertyCode(
- std::ostream&, std::string const&, std::string const&,
- cmGeneratorTarget const*, ImportPropertyMap const&, std::string const&)
-{
-}
-
-void cmExportInstallAndroidMKGenerator::GenerateMissingTargetsCheckCode(
- std::ostream&)
-{
-}
-
-void cmExportInstallAndroidMKGenerator::GenerateInterfaceProperties(
- cmGeneratorTarget const* target, std::ostream& os,
- ImportPropertyMap const& properties)
-{
- std::string config;
- if (!this->Configurations.empty()) {
- config = this->Configurations[0];
- }
- cmExportBuildAndroidMKGenerator::GenerateInterfaceProperties(
- target, os, properties, cmExportBuildAndroidMKGenerator::INSTALL, config);
-}
-
-void cmExportInstallAndroidMKGenerator::LoadConfigFiles(std::ostream&)
-{
-}
-
-void cmExportInstallAndroidMKGenerator::GenerateImportPrefix(std::ostream&)
-{
-}
-
-void cmExportInstallAndroidMKGenerator::CleanupTemporaryVariables(
- std::ostream&)
-{
-}
-
-void cmExportInstallAndroidMKGenerator::GenerateImportedFileCheckLoop(
- std::ostream&)
-{
-}
-
-void cmExportInstallAndroidMKGenerator::GenerateImportedFileChecksCode(
- std::ostream&, cmGeneratorTarget*, ImportPropertyMap const&,
- std::set<std::string> const&, std::string const&)
-{
-}
-
-bool cmExportInstallAndroidMKGenerator::GenerateImportFileConfig(
- std::string const&)
-{
- return true;
-}
diff --git a/Source/cmExportInstallAndroidMKGenerator.h b/Source/cmExportInstallAndroidMKGenerator.h
index 0c3eef6..8fa3d3e 100644
--- a/Source/cmExportInstallAndroidMKGenerator.h
+++ b/Source/cmExportInstallAndroidMKGenerator.h
@@ -5,9 +5,10 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
-#include <set>
#include <string>
+#include <vector>
+#include "cmExportAndroidMKGenerator.h"
#include "cmExportInstallFileGenerator.h"
#include "cmStateTypes.h"
@@ -15,52 +16,49 @@ class cmGeneratorTarget;
class cmInstallExportGenerator;
/** \class cmExportInstallAndroidMKGenerator
- * \brief Generate a file exporting targets from an install tree.
+ * \brief Generate files exporting targets from an install tree.
*
* cmExportInstallAndroidMKGenerator generates files exporting targets from
- * install an installation tree. The files are placed in a temporary
- * location for installation by cmInstallExportGenerator. The file format
- * is for the ndk build system and is a makefile fragment specifying prebuilt
- * libraries to the ndk build system.
+ * an installation tree. The files are placed in a temporary location for
+ * installation by cmInstallExportGenerator. The file format is for the ndk
+ * build system and is a makefile fragment specifying prebuilt libraries to the
+ * ndk build system.
*
* This is used to implement the INSTALL(EXPORT_ANDROID_MK) command.
*/
-class cmExportInstallAndroidMKGenerator : public cmExportInstallFileGenerator
+class cmExportInstallAndroidMKGenerator
+ : public cmExportAndroidMKGenerator
+ , public cmExportInstallFileGenerator
{
public:
/** Construct with the export installer that will install the
files. */
cmExportInstallAndroidMKGenerator(cmInstallExportGenerator* iegen);
+ std::string GetConfigImportFileGlob() const override { return {}; }
+
protected:
+ GenerateType GetGenerateType() const override { return INSTALL; }
+
// Implement virtual methods from the superclass.
- void GeneratePolicyHeaderCode(std::ostream&) override {}
- void GeneratePolicyFooterCode(std::ostream&) override {}
+ void ReportDuplicateTarget(std::string const& targetName) const;
+ bool GenerateMainFile(std::ostream& os) override;
void GenerateImportHeaderCode(std::ostream& os,
std::string const& config = "") override;
- void GenerateImportFooterCode(std::ostream& os) override;
void GenerateImportTargetCode(
std::ostream& os, cmGeneratorTarget const* target,
cmStateEnums::TargetType /*targetType*/) override;
- void GenerateExpectedTargetsCode(
- std::ostream& os, std::string const& expectedTargets) override;
- void GenerateImportPropertyCode(
- std::ostream& os, std::string const& config, std::string const& suffix,
- cmGeneratorTarget const* target, ImportPropertyMap const& properties,
- std::string const& importedXcFrameworkLocation) override;
- void GenerateMissingTargetsCheckCode(std::ostream& os) override;
- void GenerateFindDependencyCalls(std::ostream&) override {}
- void GenerateInterfaceProperties(
- cmGeneratorTarget const* target, std::ostream& os,
- ImportPropertyMap const& properties) override;
- void GenerateImportPrefix(std::ostream& os) override;
- void LoadConfigFiles(std::ostream&) override;
- void CleanupTemporaryVariables(std::ostream&) override;
- void GenerateImportedFileCheckLoop(std::ostream& os) override;
- void GenerateImportedFileChecksCode(
- std::ostream& os, cmGeneratorTarget* target,
- ImportPropertyMap const& properties,
- std::set<std::string> const& importedLocations,
- std::string const& importedXcFrameworkLocation) override;
- bool GenerateImportFileConfig(std::string const& config) override;
+
+ void ComplainAboutMissingTarget(cmGeneratorTarget const* depender,
+ cmGeneratorTarget const* dependee,
+ std::vector<std::string> const& namespaces);
+
+ void GenerateImportTargetsConfig(std::ostream& os, std::string const& config,
+ std::string const& suffix) override
+ {
+ this->cmExportAndroidMKGenerator::GenerateImportTargetsConfig(os, config,
+ suffix);
+ }
+
+ std::string GetCxxModulesDirectory() const override { return {}; }
};
diff --git a/Source/cmExportInstallCMakeConfigGenerator.cxx b/Source/cmExportInstallCMakeConfigGenerator.cxx
index 940a42b..e2185ed 100644
--- a/Source/cmExportInstallCMakeConfigGenerator.cxx
+++ b/Source/cmExportInstallCMakeConfigGenerator.cxx
@@ -3,9 +3,12 @@
#include "cmExportInstallCMakeConfigGenerator.h"
#include <algorithm>
+#include <map>
#include <memory>
+#include <set>
#include <sstream>
#include <utility>
+#include <vector>
#include <cm/string_view>
#include <cmext/string_view>
@@ -15,11 +18,8 @@
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
-#include "cmGlobalGenerator.h"
#include "cmInstallExportGenerator.h"
#include "cmInstallFileSetGenerator.h"
-#include "cmInstallTargetGenerator.h"
-#include "cmList.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
@@ -28,17 +28,17 @@
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#include "cmTarget.h"
#include "cmTargetExport.h"
#include "cmValue.h"
cmExportInstallCMakeConfigGenerator::cmExportInstallCMakeConfigGenerator(
cmInstallExportGenerator* iegen)
- : IEGen(iegen)
+ : cmExportInstallFileGenerator(iegen)
{
}
std::string cmExportInstallCMakeConfigGenerator::GetConfigImportFileGlob()
+ const
{
std::string glob = cmStrCat(this->FileBase, "-*", this->FileExt);
return glob;
@@ -46,28 +46,18 @@ std::string cmExportInstallCMakeConfigGenerator::GetConfigImportFileGlob()
bool cmExportInstallCMakeConfigGenerator::GenerateMainFile(std::ostream& os)
{
- std::vector<cmTargetExport*> allTargets;
+ std::vector<cmTargetExport const*> allTargets;
{
std::string expectedTargets;
std::string sep;
- for (std::unique_ptr<cmTargetExport> const& te :
- this->GetExportSet()->GetTargetExports()) {
- if (te->NamelinkOnly) {
- continue;
- }
+ auto visitor = [&](cmTargetExport const* te) {
+ allTargets.push_back(te);
expectedTargets += sep + this->Namespace + te->Target->GetExportName();
sep = " ";
- if (this->ExportedTargets.insert(te->Target).second) {
- allTargets.push_back(te.get());
- } else {
- std::ostringstream e;
- e << "install(EXPORT \"" << this->GetExportSet()->GetName()
- << "\" ...) "
- << "includes target \"" << te->Target->GetName()
- << "\" more than once in the export set.";
- cmSystemTools::Error(e.str());
- return false;
- }
+ };
+
+ if (!this->CollectExports(visitor)) {
+ return false;
}
this->GenerateExpectedTargetsCode(os, expectedTargets);
@@ -78,7 +68,7 @@ bool cmExportInstallCMakeConfigGenerator::GenerateMainFile(std::ostream& os)
bool requiresConfigFiles = false;
// Create all the imported targets.
- for (cmTargetExport* te : allTargets) {
+ for (cmTargetExport const* te : allTargets) {
cmGeneratorTarget* gt = te->Target;
cmStateEnums::TargetType targetType = this->GetExportTargetType(te);
@@ -88,52 +78,7 @@ bool cmExportInstallCMakeConfigGenerator::GenerateMainFile(std::ostream& os)
this->GenerateImportTargetCode(os, gt, targetType);
ImportPropertyMap properties;
-
- std::string includesDestinationDirs;
- this->PopulateIncludeDirectoriesInterface(
- gt, cmGeneratorExpression::InstallInterface, properties, *te,
- includesDestinationDirs);
- this->PopulateSourcesInterface(gt, cmGeneratorExpression::InstallInterface,
- properties);
- this->PopulateInterfaceProperty("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES", gt,
- cmGeneratorExpression::InstallInterface,
- properties);
- this->PopulateInterfaceProperty("INTERFACE_COMPILE_DEFINITIONS", gt,
- cmGeneratorExpression::InstallInterface,
- properties);
- this->PopulateInterfaceProperty("INTERFACE_COMPILE_OPTIONS", gt,
- cmGeneratorExpression::InstallInterface,
- properties);
- this->PopulateInterfaceProperty("INTERFACE_PRECOMPILE_HEADERS", gt,
- cmGeneratorExpression::InstallInterface,
- properties);
- this->PopulateInterfaceProperty("INTERFACE_AUTOUIC_OPTIONS", gt,
- cmGeneratorExpression::InstallInterface,
- properties);
- this->PopulateInterfaceProperty("INTERFACE_AUTOMOC_MACRO_NAMES", gt,
- cmGeneratorExpression::InstallInterface,
- properties);
- this->PopulateInterfaceProperty("INTERFACE_COMPILE_FEATURES", gt,
- cmGeneratorExpression::InstallInterface,
- properties);
- this->PopulateInterfaceProperty("INTERFACE_LINK_OPTIONS", gt,
- cmGeneratorExpression::InstallInterface,
- properties);
- this->PopulateLinkDirectoriesInterface(
- gt, cmGeneratorExpression::InstallInterface, properties);
- this->PopulateLinkDependsInterface(
- gt, cmGeneratorExpression::InstallInterface, properties);
-
- std::string errorMessage;
- if (!this->PopulateCxxModuleExportProperties(
- gt, properties, cmGeneratorExpression::InstallInterface,
- includesDestinationDirs, errorMessage)) {
- cmSystemTools::Error(errorMessage);
- return false;
- }
-
- if (!this->PopulateExportProperties(gt, properties, errorMessage)) {
- cmSystemTools::Error(errorMessage);
+ if (!this->PopulateInterfaceProperties(te, properties)) {
return false;
}
@@ -156,13 +101,6 @@ bool cmExportInstallCMakeConfigGenerator::GenerateMainFile(std::ostream& os)
this->SetRequiredCMakeVersion(3, 1, 0);
}
- this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE", gt,
- properties);
-
- this->PopulateCompatibleInterfaceProperties(gt, properties);
- this->PopulateCustomTransitiveInterfaceProperties(
- gt, cmGeneratorExpression::InstallInterface, properties);
-
this->GenerateInterfaceProperties(gt, os, properties);
this->GenerateTargetFileSets(gt, os, te);
@@ -286,12 +224,6 @@ void cmExportInstallCMakeConfigGenerator::LoadConfigFiles(std::ostream& os)
/* clang-format on */
}
-void cmExportInstallCMakeConfigGenerator::ReplaceInstallPrefix(
- std::string& input)
-{
- cmGeneratorExpression::ReplaceInstallPrefix(input, "${_IMPORT_PREFIX}");
-}
-
bool cmExportInstallCMakeConfigGenerator::GenerateImportFileConfig(
std::string const& config)
{
@@ -351,53 +283,20 @@ void cmExportInstallCMakeConfigGenerator::GenerateImportTargetsConfig(
ImportPropertyMap properties;
std::set<std::string> importedLocations;
- this->SetImportLocationProperty(config, suffix, te->ArchiveGenerator,
- properties, importedLocations);
- this->SetImportLocationProperty(config, suffix, te->LibraryGenerator,
- properties, importedLocations);
- this->SetImportLocationProperty(config, suffix, te->RuntimeGenerator,
- properties, importedLocations);
- this->SetImportLocationProperty(config, suffix, te->ObjectsGenerator,
- properties, importedLocations);
- this->SetImportLocationProperty(config, suffix, te->FrameworkGenerator,
- properties, importedLocations);
- this->SetImportLocationProperty(config, suffix, te->BundleGenerator,
- properties, importedLocations);
+ this->PopulateImportProperties(config, suffix, te.get(), properties,
+ importedLocations);
// If any file location was set for the target add it to the
// import file.
if (!properties.empty()) {
- // Get the rest of the target details.
- cmGeneratorTarget* gtgt = te->Target;
- this->SetImportDetailProperties(config, suffix, gtgt, properties);
+ cmGeneratorTarget const* const gtgt = te->Target;
+ std::string const importedXcFrameworkLocation =
+ this->GetImportXcFrameworkLocation(config, te.get());
this->SetImportLinkInterface(config, suffix,
cmGeneratorExpression::InstallInterface,
gtgt, properties);
- // TODO: PUBLIC_HEADER_LOCATION
- // This should wait until the build feature propagation stuff
- // is done. Then this can be a propagated include directory.
- // this->GenerateImportProperty(config, te->HeaderGenerator,
- // properties);
-
- // Generate code in the export file.
- std::string importedXcFrameworkLocation = te->XcFrameworkLocation;
- if (!importedXcFrameworkLocation.empty()) {
- importedXcFrameworkLocation = cmGeneratorExpression::Preprocess(
- importedXcFrameworkLocation,
- cmGeneratorExpression::PreprocessContext::InstallInterface, true);
- importedXcFrameworkLocation = cmGeneratorExpression::Evaluate(
- importedXcFrameworkLocation, te->Target->GetLocalGenerator(), config,
- te->Target, nullptr, te->Target);
- if (!importedXcFrameworkLocation.empty() &&
- !cmSystemTools::FileIsFullPath(importedXcFrameworkLocation) &&
- !cmHasLiteralPrefix(importedXcFrameworkLocation,
- "${_IMPORT_PREFIX}/")) {
- importedXcFrameworkLocation =
- cmStrCat("${_IMPORT_PREFIX}/", importedXcFrameworkLocation);
- }
- }
this->GenerateImportPropertyCode(os, config, suffix, gtgt, properties,
importedXcFrameworkLocation);
this->GenerateImportedFileChecksCode(
@@ -406,193 +305,6 @@ void cmExportInstallCMakeConfigGenerator::GenerateImportTargetsConfig(
}
}
-void cmExportInstallCMakeConfigGenerator::SetImportLocationProperty(
- std::string const& config, std::string const& suffix,
- cmInstallTargetGenerator* itgen, ImportPropertyMap& properties,
- std::set<std::string>& importedLocations)
-{
- // Skip rules that do not match this configuration.
- if (!(itgen && itgen->InstallsForConfig(config))) {
- return;
- }
-
- // Get the target to be installed.
- cmGeneratorTarget* target = itgen->GetTarget();
-
- // Construct the installed location of the target.
- std::string dest = itgen->GetDestination(config);
- std::string value;
- if (!cmSystemTools::FileIsFullPath(dest)) {
- // The target is installed relative to the installation prefix.
- value = "${_IMPORT_PREFIX}/";
- }
- value += dest;
- value += "/";
-
- if (itgen->IsImportLibrary()) {
- // Construct the property name.
- std::string prop = cmStrCat("IMPORTED_IMPLIB", suffix);
-
- // Append the installed file name.
- value += cmInstallTargetGenerator::GetInstallFilename(
- target, config, cmInstallTargetGenerator::NameImplibReal);
-
- // Store the property.
- properties[prop] = value;
- importedLocations.insert(prop);
- } else if (itgen->GetTarget()->GetType() == cmStateEnums::OBJECT_LIBRARY) {
- // Construct the property name.
- std::string prop = cmStrCat("IMPORTED_OBJECTS", suffix);
-
- // Compute all the object files inside this target and setup
- // IMPORTED_OBJECTS as a list of object files
- std::vector<std::string> objects;
- itgen->GetInstallObjectNames(config, objects);
- for (std::string& obj : objects) {
- obj = cmStrCat(value, obj);
- }
-
- // Store the property.
- properties[prop] = cmList::to_string(objects);
- importedLocations.insert(prop);
- } else {
- if (target->IsFrameworkOnApple() && target->HasImportLibrary(config)) {
- // store as well IMPLIB value
- auto importProp = cmStrCat("IMPORTED_IMPLIB", suffix);
- auto importValue =
- cmStrCat(value,
- cmInstallTargetGenerator::GetInstallFilename(
- target, config, cmInstallTargetGenerator::NameImplibReal));
-
- // Store the property.
- properties[importProp] = importValue;
- importedLocations.insert(importProp);
- }
-
- // Construct the property name.
- std::string prop = cmStrCat("IMPORTED_LOCATION", suffix);
-
- // Append the installed file name.
- if (target->IsAppBundleOnApple()) {
- value += cmInstallTargetGenerator::GetInstallFilename(target, config);
- value += ".app/";
- if (!target->Makefile->PlatformIsAppleEmbedded()) {
- value += "Contents/MacOS/";
- }
- value += cmInstallTargetGenerator::GetInstallFilename(target, config);
- } else {
- value += cmInstallTargetGenerator::GetInstallFilename(
- target, config, cmInstallTargetGenerator::NameReal);
- }
-
- // Store the property.
- properties[prop] = value;
- importedLocations.insert(prop);
- }
-}
-
-cmStateEnums::TargetType
-cmExportInstallCMakeConfigGenerator::GetExportTargetType(
- cmTargetExport const* targetExport) const
-{
- cmStateEnums::TargetType targetType = targetExport->Target->GetType();
- // An OBJECT library installed with no OBJECTS DESTINATION
- // is transformed to an INTERFACE library.
- if (targetType == cmStateEnums::OBJECT_LIBRARY &&
- targetExport->ObjectsGenerator == nullptr) {
- targetType = cmStateEnums::INTERFACE_LIBRARY;
- }
- return targetType;
-}
-
-void cmExportInstallCMakeConfigGenerator::HandleMissingTarget(
- std::string& link_libs, cmGeneratorTarget const* depender,
- cmGeneratorTarget* dependee)
-{
- std::string const name = dependee->GetName();
- cmGlobalGenerator* gg = dependee->GetLocalGenerator()->GetGlobalGenerator();
- auto exportInfo = this->FindNamespaces(gg, name);
- std::vector<std::string> const& exportFiles = exportInfo.first;
- if (exportFiles.size() == 1) {
- std::string missingTarget = exportInfo.second;
-
- missingTarget += dependee->GetExportName();
- link_libs += missingTarget;
- this->MissingTargets.emplace_back(std::move(missingTarget));
- } else {
- // All exported targets should be known here and should be unique.
- // This is probably user-error.
- this->ComplainAboutMissingTarget(depender, dependee, exportFiles);
- }
-}
-
-std::pair<std::vector<std::string>, std::string>
-cmExportInstallCMakeConfigGenerator::FindNamespaces(cmGlobalGenerator* gg,
- std::string const& name)
-{
- std::vector<std::string> exportFiles;
- std::string ns;
- cmExportSetMap const& exportSets = gg->GetExportSets();
-
- for (auto const& expIt : exportSets) {
- cmExportSet const& exportSet = expIt.second;
-
- bool containsTarget = false;
- for (auto const& target : exportSet.GetTargetExports()) {
- if (name == target->TargetName) {
- containsTarget = true;
- break;
- }
- }
-
- if (containsTarget) {
- std::vector<cmInstallExportGenerator const*> const* installs =
- exportSet.GetInstallations();
- for (cmInstallExportGenerator const* install : *installs) {
- exportFiles.push_back(install->GetDestinationFile());
- ns = install->GetNamespace();
- }
- }
- }
-
- return { exportFiles, ns };
-}
-
-void cmExportInstallCMakeConfigGenerator::ComplainAboutMissingTarget(
- cmGeneratorTarget const* depender, cmGeneratorTarget const* dependee,
- std::vector<std::string> const& exportFiles)
-{
- std::ostringstream e;
- e << "install(EXPORT \"" << this->GetExportSet()->GetName() << "\" ...) "
- << "includes target \"" << depender->GetName()
- << "\" which requires target \"" << dependee->GetName() << "\" ";
- if (exportFiles.empty()) {
- e << "that is not in any export set.";
- } else {
- e << "that is not in this export set, but in multiple other export sets: "
- << cmJoin(exportFiles, ", ") << ".\n";
- e << "An exported target cannot depend upon another target which is "
- "exported multiple times. Consider consolidating the exports of the "
- "\""
- << dependee->GetName() << "\" target to a single export.";
- }
- cmSystemTools::Error(e.str());
-}
-
-std::string cmExportInstallCMakeConfigGenerator::InstallNameDir(
- cmGeneratorTarget const* target, std::string const& config)
-{
- std::string install_name_dir;
-
- cmMakefile* mf = target->Target->GetMakefile();
- if (mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) {
- install_name_dir =
- target->GetInstallNameDirForInstallTree(config, "${_IMPORT_PREFIX}");
- }
-
- return install_name_dir;
-}
-
namespace {
bool EntryIsContextSensitive(
std::unique_ptr<cmCompiledGeneratorExpression> const& cge)
@@ -602,7 +314,7 @@ bool EntryIsContextSensitive(
}
std::string cmExportInstallCMakeConfigGenerator::GetFileSetDirectories(
- cmGeneratorTarget* gte, cmFileSet* fileSet, cmTargetExport* te)
+ cmGeneratorTarget* gte, cmFileSet* fileSet, cmTargetExport const* te)
{
std::vector<std::string> resultVector;
@@ -647,7 +359,7 @@ std::string cmExportInstallCMakeConfigGenerator::GetFileSetDirectories(
}
std::string cmExportInstallCMakeConfigGenerator::GetFileSetFiles(
- cmGeneratorTarget* gte, cmFileSet* fileSet, cmTargetExport* te)
+ cmGeneratorTarget* gte, cmFileSet* fileSet, cmTargetExport const* te)
{
std::vector<std::string> resultVector;
@@ -745,11 +457,6 @@ void cmExportInstallCMakeConfigGenerator::GenerateCxxModuleConfigInformation(
/* clang-format on */
}
-std::string cmExportInstallCMakeConfigGenerator::GetCxxModuleFile() const
-{
- return this->GetCxxModuleFile(this->GetExportSet()->GetName());
-}
-
bool cmExportInstallCMakeConfigGenerator::
GenerateImportCxxModuleConfigTargetInclusion(std::string const& name,
std::string const& config)
diff --git a/Source/cmExportInstallCMakeConfigGenerator.h b/Source/cmExportInstallCMakeConfigGenerator.h
index 57d2969..2ef9af0 100644
--- a/Source/cmExportInstallCMakeConfigGenerator.h
+++ b/Source/cmExportInstallCMakeConfigGenerator.h
@@ -5,30 +5,25 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
-#include <map>
-#include <set>
#include <string>
-#include <utility>
-#include <vector>
-#include "cmExportFileGenerator.h"
-#include "cmInstallExportGenerator.h"
-#include "cmStateTypes.h"
+#include "cmExportCMakeConfigGenerator.h"
+#include "cmExportInstallFileGenerator.h"
-class cmExportSet;
class cmFileSet;
class cmGeneratorTarget;
-class cmGlobalGenerator;
-class cmInstallTargetGenerator;
+class cmInstallExportGenerator;
class cmTargetExport;
/** \class cmExportInstallCMakeConfigGenerator
- * \brief Generate a file exporting targets from an install tree.
+ * \brief Generate files exporting targets from an install tree.
*
* cmExportInstallCMakeConfigGenerator generates files exporting targets from
- * install an installation tree. The files are placed in a temporary
- * location for installation by cmInstallExportGenerator. One main
- * file is generated that creates the imported targets and loads
+ * an installation tree. The files are placed in a temporary location for
+ * installation by cmInstallExportGenerator. The file format is CMake's native
+ * package configuration format.
+ *
+ * One main file is generated that creates the imported targets and loads
* per-configuration files. Target locations and settings for each
* configuration are written to these per-configuration files. After
* installation the main file loads the configurations that have been
@@ -36,64 +31,24 @@ class cmTargetExport;
*
* This is used to implement the INSTALL(EXPORT) command.
*/
-class cmExportInstallCMakeConfigGenerator : public cmExportFileGenerator
+class cmExportInstallCMakeConfigGenerator
+ : public cmExportCMakeConfigGenerator
+ , public cmExportInstallFileGenerator
{
public:
/** Construct with the export installer that will install the
files. */
cmExportInstallCMakeConfigGenerator(cmInstallExportGenerator* iegen);
- /** Get the per-config file generated for each configuration. This
- maps from the configuration name to the file temporary location
- for installation. */
- std::map<std::string, std::string> const& GetConfigImportFiles()
- {
- return this->ConfigImportFiles;
- }
-
- /** Get the temporary location of the config-agnostic C++ module file. */
- std::string GetCxxModuleFile() const;
-
- /** Get the per-config C++ module file generated for each configuration.
- This maps from the configuration name to the file temporary location
- for installation. */
- std::map<std::string, std::string> const& GetConfigCxxModuleFiles()
- {
- return this->ConfigCxxModuleFiles;
- }
-
- /** Get the per-config C++ module file generated for each configuration.
- This maps from the configuration name to the file temporary location
- for installation for each target in the export set. */
- std::map<std::string, std::vector<std::string>> const&
- GetConfigCxxModuleTargetFiles()
- {
- return this->ConfigCxxModuleTargetFiles;
- }
-
/** Compute the globbing expression used to load per-config import
files from the main file. */
- std::string GetConfigImportFileGlob();
+ std::string GetConfigImportFileGlob() const override;
protected:
// Implement virtual methods from the superclass.
bool GenerateMainFile(std::ostream& os) override;
void GenerateImportTargetsConfig(std::ostream& os, std::string const& config,
std::string const& suffix) override;
- cmStateEnums::TargetType GetExportTargetType(
- cmTargetExport const* targetExport) const;
- void HandleMissingTarget(std::string& link_libs,
- cmGeneratorTarget const* depender,
- cmGeneratorTarget* dependee) override;
-
- void ReplaceInstallPrefix(std::string& input) override;
-
- void ComplainAboutMissingTarget(cmGeneratorTarget const* depender,
- cmGeneratorTarget const* dependee,
- std::vector<std::string> const& exportFiles);
-
- std::pair<std::vector<std::string>, std::string> FindNamespaces(
- cmGlobalGenerator* gg, std::string const& name);
/** Generate the relative import prefix. */
virtual void GenerateImportPrefix(std::ostream&);
@@ -106,40 +61,14 @@ protected:
/** Generate a per-configuration file for the targets. */
virtual bool GenerateImportFileConfig(std::string const& config);
- /** Fill in properties indicating installed file locations. */
- void SetImportLocationProperty(std::string const& config,
- std::string const& suffix,
- cmInstallTargetGenerator* itgen,
- ImportPropertyMap& properties,
- std::set<std::string>& importedLocations);
-
- std::string InstallNameDir(cmGeneratorTarget const* target,
- std::string const& config) override;
-
std::string GetFileSetDirectories(cmGeneratorTarget* gte, cmFileSet* fileSet,
- cmTargetExport* te) override;
+ cmTargetExport const* te) override;
std::string GetFileSetFiles(cmGeneratorTarget* gte, cmFileSet* fileSet,
- cmTargetExport* te) override;
-
- using cmExportFileGenerator::GetCxxModuleFile;
+ cmTargetExport const* te) override;
std::string GetCxxModulesDirectory() const override;
void GenerateCxxModuleConfigInformation(std::string const&,
std::ostream&) const override;
bool GenerateImportCxxModuleConfigTargetInclusion(std::string const&,
std::string const&);
-
- cmExportSet* GetExportSet() const override
- {
- return this->IEGen->GetExportSet();
- }
-
- cmInstallExportGenerator* IEGen;
-
- // The import file generated for each configuration.
- std::map<std::string, std::string> ConfigImportFiles;
- // The C++ module property file generated for each configuration.
- std::map<std::string, std::string> ConfigCxxModuleFiles;
- // The C++ module property target files generated for each configuration.
- std::map<std::string, std::vector<std::string>> ConfigCxxModuleTargetFiles;
};
diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx
index c71a1f4..374b5ed 100644
--- a/Source/cmExportInstallFileGenerator.cxx
+++ b/Source/cmExportInstallFileGenerator.cxx
@@ -2,30 +2,21 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmExportInstallFileGenerator.h"
-#include <algorithm>
+#include <cassert>
+#include <cstddef>
#include <memory>
+#include <set>
#include <sstream>
-#include <utility>
-
-#include <cm/string_view>
-#include <cmext/string_view>
#include "cmExportSet.h"
-#include "cmFileSet.h"
-#include "cmGeneratedFileStream.h"
-#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
-#include "cmInstallExportGenerator.h"
-#include "cmInstallFileSetGenerator.h"
#include "cmInstallTargetGenerator.h"
#include "cmList.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
-#include "cmOutputConverter.h"
#include "cmPolicies.h"
-#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
@@ -38,369 +29,71 @@ cmExportInstallFileGenerator::cmExportInstallFileGenerator(
{
}
-std::string cmExportInstallFileGenerator::GetConfigImportFileGlob()
+void cmExportInstallFileGenerator::ReplaceInstallPrefix(
+ std::string& input) const
{
- std::string glob = cmStrCat(this->FileBase, "-*", this->FileExt);
- return glob;
+ cmGeneratorExpression::ReplaceInstallPrefix(input, this->GetInstallPrefix());
}
-bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
+void cmExportInstallFileGenerator::PopulateImportProperties(
+ std::string const& config, std::string const& suffix,
+ cmTargetExport const* targetExport, ImportPropertyMap& properties,
+ std::set<std::string>& importedLocations)
{
- std::vector<cmTargetExport*> allTargets;
- {
- std::string expectedTargets;
- std::string sep;
- for (std::unique_ptr<cmTargetExport> const& te :
- this->GetExportSet()->GetTargetExports()) {
- if (te->NamelinkOnly) {
- continue;
- }
- expectedTargets += sep + this->Namespace + te->Target->GetExportName();
- sep = " ";
- if (this->ExportedTargets.insert(te->Target).second) {
- allTargets.push_back(te.get());
- } else {
- std::ostringstream e;
- e << "install(EXPORT \"" << this->GetExportSet()->GetName()
- << "\" ...) "
- << "includes target \"" << te->Target->GetName()
- << "\" more than once in the export set.";
- cmSystemTools::Error(e.str());
- return false;
- }
- }
-
- this->GenerateExpectedTargetsCode(os, expectedTargets);
- }
-
- // Compute the relative import prefix for the file
- this->GenerateImportPrefix(os);
-
- bool requiresConfigFiles = false;
- // Create all the imported targets.
- for (cmTargetExport* te : allTargets) {
- cmGeneratorTarget* gt = te->Target;
- cmStateEnums::TargetType targetType = this->GetExportTargetType(te);
-
- requiresConfigFiles =
- requiresConfigFiles || targetType != cmStateEnums::INTERFACE_LIBRARY;
-
- this->GenerateImportTargetCode(os, gt, targetType);
-
- ImportPropertyMap properties;
-
- std::string includesDestinationDirs;
- this->PopulateIncludeDirectoriesInterface(
- gt, cmGeneratorExpression::InstallInterface, properties, *te,
- includesDestinationDirs);
- this->PopulateSourcesInterface(gt, cmGeneratorExpression::InstallInterface,
- properties);
- this->PopulateInterfaceProperty("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES", gt,
- cmGeneratorExpression::InstallInterface,
- properties);
- this->PopulateInterfaceProperty("INTERFACE_COMPILE_DEFINITIONS", gt,
- cmGeneratorExpression::InstallInterface,
- properties);
- this->PopulateInterfaceProperty("INTERFACE_COMPILE_OPTIONS", gt,
- cmGeneratorExpression::InstallInterface,
- properties);
- this->PopulateInterfaceProperty("INTERFACE_PRECOMPILE_HEADERS", gt,
- cmGeneratorExpression::InstallInterface,
- properties);
- this->PopulateInterfaceProperty("INTERFACE_AUTOUIC_OPTIONS", gt,
- cmGeneratorExpression::InstallInterface,
- properties);
- this->PopulateInterfaceProperty("INTERFACE_AUTOMOC_MACRO_NAMES", gt,
- cmGeneratorExpression::InstallInterface,
- properties);
- this->PopulateInterfaceProperty("INTERFACE_COMPILE_FEATURES", gt,
- cmGeneratorExpression::InstallInterface,
- properties);
- this->PopulateInterfaceProperty("INTERFACE_LINK_OPTIONS", gt,
- cmGeneratorExpression::InstallInterface,
- properties);
- this->PopulateLinkDirectoriesInterface(
- gt, cmGeneratorExpression::InstallInterface, properties);
- this->PopulateLinkDependsInterface(
- gt, cmGeneratorExpression::InstallInterface, properties);
-
- std::string errorMessage;
- if (!this->PopulateCxxModuleExportProperties(
- gt, properties, cmGeneratorExpression::InstallInterface,
- includesDestinationDirs, errorMessage)) {
- cmSystemTools::Error(errorMessage);
- return false;
- }
-
- if (!this->PopulateExportProperties(gt, properties, errorMessage)) {
- cmSystemTools::Error(errorMessage);
- return false;
- }
-
- bool const newCMP0022Behavior =
- gt->GetPolicyStatusCMP0022() != cmPolicies::WARN &&
- gt->GetPolicyStatusCMP0022() != cmPolicies::OLD;
- if (newCMP0022Behavior) {
- if (this->PopulateInterfaceLinkLibrariesProperty(
- gt, cmGeneratorExpression::InstallInterface, properties) &&
- !this->ExportOld) {
- this->SetRequiredCMakeVersion(2, 8, 12);
- }
- }
- if (targetType == cmStateEnums::INTERFACE_LIBRARY) {
- 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.
- this->SetRequiredCMakeVersion(3, 1, 0);
- }
-
- this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE", gt,
- properties);
-
- this->PopulateCompatibleInterfaceProperties(gt, properties);
- this->PopulateCustomTransitiveInterfaceProperties(
- gt, cmGeneratorExpression::InstallInterface, properties);
-
- this->GenerateInterfaceProperties(gt, os, properties);
-
- this->GenerateTargetFileSets(gt, os, te);
- }
-
- this->LoadConfigFiles(os);
-
- bool result = true;
-
- std::string cxx_modules_name = this->GetExportSet()->GetName();
- this->GenerateCxxModuleInformation(cxx_modules_name, os);
- if (requiresConfigFiles) {
- for (std::string const& c : this->Configurations) {
- if (!this->GenerateImportCxxModuleConfigTargetInclusion(cxx_modules_name,
- c)) {
- result = false;
- }
- }
- }
-
- this->CleanupTemporaryVariables(os);
- this->GenerateImportedFileCheckLoop(os);
-
- // Generate an import file for each configuration.
- // Don't do this if we only export INTERFACE_LIBRARY targets.
- if (requiresConfigFiles) {
- for (std::string const& c : this->Configurations) {
- if (!this->GenerateImportFileConfig(c)) {
- result = false;
- }
- }
+ this->SetImportLocationProperty(config, suffix,
+ targetExport->ArchiveGenerator, properties,
+ importedLocations);
+ this->SetImportLocationProperty(config, suffix,
+ targetExport->LibraryGenerator, properties,
+ importedLocations);
+ this->SetImportLocationProperty(config, suffix,
+ targetExport->RuntimeGenerator, properties,
+ importedLocations);
+ this->SetImportLocationProperty(config, suffix,
+ targetExport->ObjectsGenerator, properties,
+ importedLocations);
+ this->SetImportLocationProperty(config, suffix,
+ targetExport->FrameworkGenerator, properties,
+ importedLocations);
+ this->SetImportLocationProperty(config, suffix,
+ targetExport->BundleGenerator, properties,
+ importedLocations);
+
+ // If any file location was set for the target add it to the
+ // import file.
+ if (!properties.empty()) {
+ // Get the rest of the target details.
+ cmGeneratorTarget const* const gtgt = targetExport->Target;
+ this->SetImportDetailProperties(config, suffix, gtgt, properties);
+
+ // TODO: PUBLIC_HEADER_LOCATION
+ // This should wait until the build feature propagation stuff is done.
+ // Then this can be a propagated include directory.
+ // this->GenerateImportProperty(config, te->HeaderGenerator, properties);
}
-
- this->GenerateMissingTargetsCheckCode(os);
-
- return result;
}
-void cmExportInstallFileGenerator::GenerateImportPrefix(std::ostream& os)
+std::string cmExportInstallFileGenerator::GetImportXcFrameworkLocation(
+ std::string const& config, cmTargetExport const* targetExport) const
{
- // Set an _IMPORT_PREFIX variable for import location properties
- // to reference if they are relative to the install prefix.
- std::string installPrefix =
- this->IEGen->GetLocalGenerator()->GetMakefile()->GetSafeDefinition(
- "CMAKE_INSTALL_PREFIX");
- std::string const& expDest = this->IEGen->GetDestination();
- if (cmSystemTools::FileIsFullPath(expDest)) {
- // The export file is being installed to an absolute path so the
- // package is not relocatable. Use the configured install prefix.
- /* clang-format off */
- os <<
- "# The installation prefix configured by this project.\n"
- "set(_IMPORT_PREFIX \"" << installPrefix << "\")\n"
- "\n";
- /* clang-format on */
- } else {
- // Add code to compute the installation prefix relative to the
- // import file location.
- std::string absDest = installPrefix + "/" + expDest;
- std::string absDestS = absDest + "/";
- os << "# Compute the installation prefix relative to this file.\n"
- << "get_filename_component(_IMPORT_PREFIX"
- << " \"${CMAKE_CURRENT_LIST_FILE}\" PATH)\n";
- if (cmHasLiteralPrefix(absDestS, "/lib/") ||
- cmHasLiteralPrefix(absDestS, "/lib64/") ||
- cmHasLiteralPrefix(absDestS, "/libx32/") ||
- cmHasLiteralPrefix(absDestS, "/usr/lib/") ||
- cmHasLiteralPrefix(absDestS, "/usr/lib64/") ||
- cmHasLiteralPrefix(absDestS, "/usr/libx32/")) {
- // Handle "/usr move" symlinks created by some Linux distros.
- /* clang-format off */
- os <<
- "# Use original install prefix when loaded through a\n"
- "# cross-prefix symbolic link such as /lib -> /usr/lib.\n"
- "get_filename_component(_realCurr \"${_IMPORT_PREFIX}\" REALPATH)\n"
- "get_filename_component(_realOrig \"" << absDest << "\" REALPATH)\n"
- "if(_realCurr STREQUAL _realOrig)\n"
- " set(_IMPORT_PREFIX \"" << absDest << "\")\n"
- "endif()\n"
- "unset(_realOrig)\n"
- "unset(_realCurr)\n";
- /* clang-format on */
- }
- std::string dest = expDest;
- while (!dest.empty()) {
- os << "get_filename_component(_IMPORT_PREFIX \"${_IMPORT_PREFIX}\" "
- "PATH)\n";
- dest = cmSystemTools::GetFilenamePath(dest);
+ std::string importedXcFrameworkLocation = targetExport->XcFrameworkLocation;
+ if (!importedXcFrameworkLocation.empty()) {
+ importedXcFrameworkLocation = cmGeneratorExpression::Preprocess(
+ importedXcFrameworkLocation,
+ cmGeneratorExpression::PreprocessContext::InstallInterface, true);
+ importedXcFrameworkLocation = cmGeneratorExpression::Evaluate(
+ importedXcFrameworkLocation, targetExport->Target->GetLocalGenerator(),
+ config, targetExport->Target, nullptr, targetExport->Target);
+ if (!importedXcFrameworkLocation.empty() &&
+ !cmSystemTools::FileIsFullPath(importedXcFrameworkLocation) &&
+ !cmHasPrefix(importedXcFrameworkLocation,
+ this->GetImportPrefixWithSlash())) {
+ return cmStrCat(this->GetImportPrefixWithSlash(),
+ importedXcFrameworkLocation);
}
- os << "if(_IMPORT_PREFIX STREQUAL \"/\")\n"
- << " set(_IMPORT_PREFIX \"\")\n"
- << "endif()\n"
- << "\n";
}
-}
-void cmExportInstallFileGenerator::CleanupTemporaryVariables(std::ostream& os)
-{
- /* clang-format off */
- os << "# Cleanup temporary variables.\n"
- << "set(_IMPORT_PREFIX)\n"
- << "\n";
- /* clang-format on */
-}
-
-void cmExportInstallFileGenerator::LoadConfigFiles(std::ostream& os)
-{
- // Now load per-configuration properties for them.
- /* clang-format off */
- os << "# Load information for each installed configuration.\n"
- << "file(GLOB _cmake_config_files \"${CMAKE_CURRENT_LIST_DIR}/"
- << this->GetConfigImportFileGlob() << "\")\n"
- << "foreach(_cmake_config_file IN LISTS _cmake_config_files)\n"
- << " include(\"${_cmake_config_file}\")\n"
- << "endforeach()\n"
- << "unset(_cmake_config_file)\n"
- << "unset(_cmake_config_files)\n"
- << "\n";
- /* clang-format on */
-}
-
-void cmExportInstallFileGenerator::ReplaceInstallPrefix(std::string& input)
-{
- cmGeneratorExpression::ReplaceInstallPrefix(input, "${_IMPORT_PREFIX}");
-}
-
-bool cmExportInstallFileGenerator::GenerateImportFileConfig(
- std::string const& config)
-{
- // Skip configurations not enabled for this export.
- if (!this->IEGen->InstallsForConfig(config)) {
- return true;
- }
-
- // Construct the name of the file to generate.
- std::string fileName = cmStrCat(this->FileDir, '/', this->FileBase, '-');
- if (!config.empty()) {
- fileName += cmSystemTools::LowerCase(config);
- } else {
- fileName += "noconfig";
- }
- fileName += this->FileExt;
-
- // Open the output file to generate it.
- cmGeneratedFileStream exportFileStream(fileName, true);
- if (!exportFileStream) {
- std::string se = cmSystemTools::GetLastSystemError();
- std::ostringstream e;
- e << "cannot write to file \"" << fileName << "\": " << se;
- cmSystemTools::Error(e.str());
- return false;
- }
- exportFileStream.SetCopyIfDifferent(true);
- std::ostream& os = exportFileStream;
-
- // Start with the import file header.
- this->GenerateImportHeaderCode(os, config);
-
- // Generate the per-config target information.
- this->GenerateImportConfig(os, config);
-
- // End with the import file footer.
- this->GenerateImportFooterCode(os);
-
- // Record this per-config import file.
- this->ConfigImportFiles[config] = fileName;
-
- return true;
-}
-
-void cmExportInstallFileGenerator::GenerateImportTargetsConfig(
- std::ostream& os, std::string const& config, std::string const& suffix)
-{
- // Add each target in the set to the export.
- for (std::unique_ptr<cmTargetExport> const& te :
- this->GetExportSet()->GetTargetExports()) {
- // Collect import properties for this target.
- if (this->GetExportTargetType(te.get()) ==
- cmStateEnums::INTERFACE_LIBRARY) {
- continue;
- }
-
- ImportPropertyMap properties;
- std::set<std::string> importedLocations;
-
- this->SetImportLocationProperty(config, suffix, te->ArchiveGenerator,
- properties, importedLocations);
- this->SetImportLocationProperty(config, suffix, te->LibraryGenerator,
- properties, importedLocations);
- this->SetImportLocationProperty(config, suffix, te->RuntimeGenerator,
- properties, importedLocations);
- this->SetImportLocationProperty(config, suffix, te->ObjectsGenerator,
- properties, importedLocations);
- this->SetImportLocationProperty(config, suffix, te->FrameworkGenerator,
- properties, importedLocations);
- this->SetImportLocationProperty(config, suffix, te->BundleGenerator,
- properties, importedLocations);
-
- // If any file location was set for the target add it to the
- // import file.
- if (!properties.empty()) {
- // Get the rest of the target details.
- cmGeneratorTarget* gtgt = te->Target;
- this->SetImportDetailProperties(config, suffix, gtgt, properties);
-
- this->SetImportLinkInterface(config, suffix,
- cmGeneratorExpression::InstallInterface,
- gtgt, properties);
-
- // TODO: PUBLIC_HEADER_LOCATION
- // This should wait until the build feature propagation stuff
- // is done. Then this can be a propagated include directory.
- // this->GenerateImportProperty(config, te->HeaderGenerator,
- // properties);
-
- // Generate code in the export file.
- std::string importedXcFrameworkLocation = te->XcFrameworkLocation;
- if (!importedXcFrameworkLocation.empty()) {
- importedXcFrameworkLocation = cmGeneratorExpression::Preprocess(
- importedXcFrameworkLocation,
- cmGeneratorExpression::PreprocessContext::InstallInterface, true);
- importedXcFrameworkLocation = cmGeneratorExpression::Evaluate(
- importedXcFrameworkLocation, te->Target->GetLocalGenerator(), config,
- te->Target, nullptr, te->Target);
- if (!importedXcFrameworkLocation.empty() &&
- !cmSystemTools::FileIsFullPath(importedXcFrameworkLocation) &&
- !cmHasLiteralPrefix(importedXcFrameworkLocation,
- "${_IMPORT_PREFIX}/")) {
- importedXcFrameworkLocation =
- cmStrCat("${_IMPORT_PREFIX}/", importedXcFrameworkLocation);
- }
- }
- this->GenerateImportPropertyCode(os, config, suffix, gtgt, properties,
- importedXcFrameworkLocation);
- this->GenerateImportedFileChecksCode(
- os, gtgt, properties, importedLocations, importedXcFrameworkLocation);
- }
- }
+ return importedXcFrameworkLocation;
}
void cmExportInstallFileGenerator::SetImportLocationProperty(
@@ -501,11 +194,16 @@ cmStateEnums::TargetType cmExportInstallFileGenerator::GetExportTargetType(
return targetType;
}
+std::string const& cmExportInstallFileGenerator::GetExportName() const
+{
+ return this->GetExportSet()->GetName();
+}
+
void cmExportInstallFileGenerator::HandleMissingTarget(
std::string& link_libs, cmGeneratorTarget const* depender,
cmGeneratorTarget* dependee)
{
- std::string const name = dependee->GetName();
+ std::string const& name = dependee->GetName();
cmGlobalGenerator* gg = dependee->GetLocalGenerator()->GetGlobalGenerator();
auto exportInfo = this->FindNamespaces(gg, name);
std::vector<std::string> const& exportFiles = exportInfo.first;
@@ -524,7 +222,7 @@ void cmExportInstallFileGenerator::HandleMissingTarget(
std::pair<std::vector<std::string>, std::string>
cmExportInstallFileGenerator::FindNamespaces(cmGlobalGenerator* gg,
- std::string const& name)
+ std::string const& name) const
{
std::vector<std::string> exportFiles;
std::string ns;
@@ -556,10 +254,11 @@ cmExportInstallFileGenerator::FindNamespaces(cmGlobalGenerator* gg,
void cmExportInstallFileGenerator::ComplainAboutMissingTarget(
cmGeneratorTarget const* depender, cmGeneratorTarget const* dependee,
- std::vector<std::string> const& exportFiles)
+ std::vector<std::string> const& exportFiles) const
{
std::ostringstream e;
- e << "install(EXPORT \"" << this->GetExportSet()->GetName() << "\" ...) "
+ e << "install(" << this->IEGen->InstallSubcommand() << " \""
+ << this->GetExportName() << "\" ...) "
<< "includes target \"" << depender->GetName()
<< "\" which requires target \"" << dependee->GetName() << "\" ";
if (exportFiles.empty()) {
@@ -572,7 +271,24 @@ void cmExportInstallFileGenerator::ComplainAboutMissingTarget(
"\""
<< dependee->GetName() << "\" target to a single export.";
}
- cmSystemTools::Error(e.str());
+ this->ReportError(e.str());
+}
+
+void cmExportInstallFileGenerator::ComplainAboutDuplicateTarget(
+ std::string const& targetName) const
+{
+ std::ostringstream e;
+ e << "install(" << this->IEGen->InstallSubcommand() << " \""
+ << this->GetExportName() << "\" ...) "
+ << "includes target \"" << targetName
+ << "\" more than once in the export set.";
+ this->ReportError(e.str());
+}
+
+void cmExportInstallFileGenerator::ReportError(
+ std::string const& errorMessage) const
+{
+ cmSystemTools::Error(errorMessage);
}
std::string cmExportInstallFileGenerator::InstallNameDir(
@@ -582,215 +298,341 @@ std::string cmExportInstallFileGenerator::InstallNameDir(
cmMakefile* mf = target->Target->GetMakefile();
if (mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) {
- install_name_dir =
- target->GetInstallNameDirForInstallTree(config, "${_IMPORT_PREFIX}");
+ auto const& prefix = this->GetInstallPrefix();
+ install_name_dir = target->GetInstallNameDirForInstallTree(config, prefix);
}
return install_name_dir;
}
-namespace {
-bool EntryIsContextSensitive(
- std::unique_ptr<cmCompiledGeneratorExpression> const& cge)
+std::string cmExportInstallFileGenerator::GetCxxModuleFile() const
{
- return cge->GetHadContextSensitiveCondition();
-}
+ return this->GetCxxModuleFile(this->GetExportSet()->GetName());
}
-std::string cmExportInstallFileGenerator::GetFileSetDirectories(
- cmGeneratorTarget* gte, cmFileSet* fileSet, cmTargetExport* te)
+bool cmExportInstallFileGenerator::CollectExports(
+ std::function<void(cmTargetExport const*)> const& visitor)
{
- std::vector<std::string> resultVector;
-
- auto configs =
- gte->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
-
- cmGeneratorExpression ge(*gte->Makefile->GetCMakeInstance());
- auto cge = ge.Parse(te->FileSetGenerators.at(fileSet)->GetDestination());
-
- for (auto const& config : configs) {
- auto unescapedDest = cge->Evaluate(gte->LocalGenerator, config, gte);
- auto dest = cmOutputConverter::EscapeForCMake(
- unescapedDest, cmOutputConverter::WrapQuotes::NoWrap);
- if (!cmSystemTools::FileIsFullPath(unescapedDest)) {
- dest = cmStrCat("${_IMPORT_PREFIX}/", dest);
- }
-
- auto const& type = fileSet->GetType();
- // C++ modules do not support interface file sets which are dependent upon
- // the configuration.
- if (cge->GetHadContextSensitiveCondition() && type == "CXX_MODULES"_s) {
- auto* mf = this->IEGen->GetLocalGenerator()->GetMakefile();
- std::ostringstream e;
- e << "The \"" << gte->GetName() << "\" target's interface file set \""
- << fileSet->GetName() << "\" of type \"" << type
- << "\" contains context-sensitive base file entries which is not "
- "supported.";
- mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
- return std::string{};
+ for (auto const& te : this->GetExportSet()->GetTargetExports()) {
+ if (te->NamelinkOnly) {
+ continue;
}
-
- if (cge->GetHadContextSensitiveCondition() && configs.size() != 1) {
- resultVector.push_back(
- cmStrCat("\"$<$<CONFIG:", config, ">:", dest, ">\""));
+ if (this->ExportedTargets.insert(te->Target).second) {
+ visitor(te.get());
} else {
- resultVector.emplace_back(cmStrCat('"', dest, '"'));
- break;
+ this->ComplainAboutDuplicateTarget(te->Target->GetName());
+ return false;
}
}
+ return true;
+}
- return cmJoin(resultVector, " ");
+bool cmExportInstallFileGenerator::PopulateInterfaceProperties(
+ cmTargetExport const* targetExport, ImportPropertyMap& properties)
+{
+ cmGeneratorTarget const* const gt = targetExport->Target;
+
+ std::string includesDestinationDirs;
+ this->PopulateInterfaceProperty("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES", gt,
+ cmGeneratorExpression::InstallInterface,
+ properties);
+ this->PopulateIncludeDirectoriesInterface(
+ gt, cmGeneratorExpression::InstallInterface, properties, *targetExport,
+ includesDestinationDirs);
+ this->PopulateLinkDirectoriesInterface(
+ gt, cmGeneratorExpression::InstallInterface, properties);
+ this->PopulateLinkDependsInterface(
+ gt, cmGeneratorExpression::InstallInterface, properties);
+ this->PopulateSourcesInterface(gt, cmGeneratorExpression::InstallInterface,
+ properties);
+
+ return this->PopulateInterfaceProperties(
+ gt, includesDestinationDirs, cmGeneratorExpression::InstallInterface,
+ properties);
}
-std::string cmExportInstallFileGenerator::GetFileSetFiles(
- cmGeneratorTarget* gte, cmFileSet* fileSet, cmTargetExport* te)
+namespace {
+bool isSubDirectory(std::string const& a, std::string const& b)
{
- std::vector<std::string> resultVector;
+ return (cmSystemTools::ComparePath(a, b) ||
+ cmSystemTools::IsSubDirectory(a, b));
+}
- auto configs =
- gte->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
+bool checkInterfaceDirs(std::string const& prepro,
+ cmGeneratorTarget const* target,
+ std::string const& prop)
+{
+ std::string const& installDir =
+ target->Makefile->GetSafeDefinition("CMAKE_INSTALL_PREFIX");
+ std::string const& topSourceDir =
+ target->GetLocalGenerator()->GetSourceDirectory();
+ std::string const& topBinaryDir =
+ target->GetLocalGenerator()->GetBinaryDirectory();
- auto fileEntries = fileSet->CompileFileEntries();
- auto directoryEntries = fileSet->CompileDirectoryEntries();
+ std::vector<std::string> parts;
+ cmGeneratorExpression::Split(prepro, parts);
- cmGeneratorExpression destGe(*gte->Makefile->GetCMakeInstance());
- auto destCge =
- destGe.Parse(te->FileSetGenerators.at(fileSet)->GetDestination());
+ bool const inSourceBuild = topSourceDir == topBinaryDir;
- for (auto const& config : configs) {
- auto directories = fileSet->EvaluateDirectoryEntries(
- directoryEntries, gte->LocalGenerator, config, gte);
+ bool hadFatalError = false;
- std::map<std::string, std::vector<std::string>> files;
- for (auto const& entry : fileEntries) {
- fileSet->EvaluateFileEntry(directories, files, entry,
- gte->LocalGenerator, config, gte);
+ for (std::string const& li : parts) {
+ size_t genexPos = cmGeneratorExpression::Find(li);
+ if (genexPos == 0) {
+ continue;
}
- auto unescapedDest = destCge->Evaluate(gte->LocalGenerator, config, gte);
- auto dest =
- cmStrCat(cmOutputConverter::EscapeForCMake(
- unescapedDest, cmOutputConverter::WrapQuotes::NoWrap),
- '/');
- if (!cmSystemTools::FileIsFullPath(unescapedDest)) {
- dest = cmStrCat("${_IMPORT_PREFIX}/", dest);
+ if (cmHasLiteralPrefix(li, "${_IMPORT_PREFIX}")) {
+ continue;
}
-
- bool const contextSensitive = destCge->GetHadContextSensitiveCondition() ||
- std::any_of(directoryEntries.begin(), directoryEntries.end(),
- EntryIsContextSensitive) ||
- std::any_of(fileEntries.begin(), fileEntries.end(),
- EntryIsContextSensitive);
-
- auto const& type = fileSet->GetType();
- // C++ modules do not support interface file sets which are dependent upon
- // the configuration.
- if (contextSensitive && type == "CXX_MODULES"_s) {
- auto* mf = this->IEGen->GetLocalGenerator()->GetMakefile();
- std::ostringstream e;
- e << "The \"" << gte->GetName() << "\" target's interface file set \""
- << fileSet->GetName() << "\" of type \"" << type
- << "\" contains context-sensitive base file entries which is not "
- "supported.";
- mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
- return std::string{};
+ MessageType messageType = MessageType::FATAL_ERROR;
+ std::ostringstream e;
+ if (genexPos != std::string::npos) {
+ if (prop == "INTERFACE_INCLUDE_DIRECTORIES") {
+ switch (target->GetPolicyStatusCMP0041()) {
+ case cmPolicies::WARN:
+ messageType = MessageType::WARNING;
+ e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0041) << "\n";
+ break;
+ case cmPolicies::OLD:
+ continue;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::NEW:
+ hadFatalError = true;
+ break; // Issue fatal message.
+ }
+ } else {
+ hadFatalError = true;
+ }
}
-
- for (auto const& it : files) {
- auto prefix = it.first.empty() ? "" : cmStrCat(it.first, '/');
- for (auto const& filename : it.second) {
- auto relFile =
- cmStrCat(prefix, cmSystemTools::GetFilenameName(filename));
- auto escapedFile =
- cmStrCat(dest,
- cmOutputConverter::EscapeForCMake(
- relFile, cmOutputConverter::WrapQuotes::NoWrap));
- if (contextSensitive && configs.size() != 1) {
- resultVector.push_back(
- cmStrCat("\"$<$<CONFIG:", config, ">:", escapedFile, ">\""));
- } else {
- resultVector.emplace_back(cmStrCat('"', escapedFile, '"'));
+ if (!cmSystemTools::FileIsFullPath(li)) {
+ /* clang-format off */
+ e << "Target \"" << target->GetName() << "\" " << prop <<
+ " property contains relative path:\n"
+ " \"" << li << "\"";
+ /* clang-format on */
+ target->GetLocalGenerator()->IssueMessage(messageType, e.str());
+ }
+ bool inBinary = isSubDirectory(li, topBinaryDir);
+ bool inSource = isSubDirectory(li, topSourceDir);
+ if (isSubDirectory(li, installDir)) {
+ // The include directory is inside the install tree. If the
+ // install tree is not inside the source tree or build tree then
+ // fall through to the checks below that the include directory is not
+ // also inside the source tree or build tree.
+ bool shouldContinue =
+ (!inBinary || isSubDirectory(installDir, topBinaryDir)) &&
+ (!inSource || isSubDirectory(installDir, topSourceDir));
+
+ if (prop == "INTERFACE_INCLUDE_DIRECTORIES") {
+ if (!shouldContinue) {
+ switch (target->GetPolicyStatusCMP0052()) {
+ case cmPolicies::WARN: {
+ std::ostringstream s;
+ s << cmPolicies::GetPolicyWarning(cmPolicies::CMP0052) << "\n";
+ s << "Directory:\n \"" << li
+ << "\"\nin "
+ "INTERFACE_INCLUDE_DIRECTORIES of target \""
+ << target->GetName()
+ << "\" is a subdirectory of the install "
+ "directory:\n \""
+ << installDir
+ << "\"\nhowever it is also "
+ "a subdirectory of the "
+ << (inBinary ? "build" : "source") << " tree:\n \""
+ << (inBinary ? topBinaryDir : topSourceDir) << "\"\n";
+ target->GetLocalGenerator()->IssueMessage(
+ MessageType::AUTHOR_WARNING, s.str());
+ CM_FALLTHROUGH;
+ }
+ case cmPolicies::OLD:
+ shouldContinue = true;
+ break;
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::NEW:
+ break;
+ }
}
}
+ if (shouldContinue) {
+ continue;
+ }
}
-
- if (!(contextSensitive && configs.size() != 1)) {
- break;
+ if (inBinary) {
+ /* clang-format off */
+ e << "Target \"" << target->GetName() << "\" " << prop <<
+ " property contains path:\n"
+ " \"" << li << "\"\nwhich is prefixed in the build directory.";
+ /* clang-format on */
+ target->GetLocalGenerator()->IssueMessage(messageType, e.str());
+ }
+ if (!inSourceBuild) {
+ if (inSource) {
+ e << "Target \"" << target->GetName() << "\" " << prop
+ << " property contains path:\n"
+ " \""
+ << li << "\"\nwhich is prefixed in the source directory.";
+ target->GetLocalGenerator()->IssueMessage(messageType, e.str());
+ }
}
}
-
- return cmJoin(resultVector, " ");
+ return !hadFatalError;
}
-
-std::string cmExportInstallFileGenerator::GetCxxModulesDirectory() const
-{
- return IEGen->GetCxxModuleDirectory();
}
-void cmExportInstallFileGenerator::GenerateCxxModuleConfigInformation(
- std::string const& name, std::ostream& os) const
+void cmExportInstallFileGenerator::PopulateSourcesInterface(
+ cmGeneratorTarget const* gt,
+ cmGeneratorExpression::PreprocessContext preprocessRule,
+ ImportPropertyMap& properties)
{
- // Now load per-configuration properties for them.
- /* clang-format off */
- os << "# Load information for each installed configuration.\n"
- "file(GLOB _cmake_cxx_module_includes \"${CMAKE_CURRENT_LIST_DIR}/cxx-modules-" << name << "-*.cmake\")\n"
- "foreach(_cmake_cxx_module_include IN LISTS _cmake_cxx_module_includes)\n"
- " include(\"${_cmake_cxx_module_include}\")\n"
- "endforeach()\n"
- "unset(_cmake_cxx_module_include)\n"
- "unset(_cmake_cxx_module_includes)\n";
- /* clang-format on */
+ assert(preprocessRule == cmGeneratorExpression::InstallInterface);
+
+ char const* const propName = "INTERFACE_SOURCES";
+ cmValue input = gt->GetProperty(propName);
+
+ if (!input) {
+ return;
+ }
+
+ if (input->empty()) {
+ properties[propName].clear();
+ return;
+ }
+
+ std::string prepro =
+ cmGeneratorExpression::Preprocess(*input, preprocessRule, true);
+ if (!prepro.empty()) {
+ this->ResolveTargetsInGeneratorExpressions(prepro, gt);
+
+ if (!checkInterfaceDirs(prepro, gt, propName)) {
+ return;
+ }
+ properties[propName] = prepro;
+ }
}
-std::string cmExportInstallFileGenerator::GetCxxModuleFile() const
+void cmExportInstallFileGenerator::PopulateIncludeDirectoriesInterface(
+ cmGeneratorTarget const* target,
+ cmGeneratorExpression::PreprocessContext preprocessRule,
+ ImportPropertyMap& properties, cmTargetExport const& te,
+ std::string& includesDestinationDirs)
{
- return this->GetCxxModuleFile(this->GetExportSet()->GetName());
+ assert(preprocessRule == cmGeneratorExpression::InstallInterface);
+
+ includesDestinationDirs.clear();
+
+ char const* const propName = "INTERFACE_INCLUDE_DIRECTORIES";
+ cmValue input = target->GetProperty(propName);
+
+ cmGeneratorExpression ge(*target->Makefile->GetCMakeInstance());
+
+ std::string dirs = cmGeneratorExpression::Preprocess(
+ cmList::to_string(target->Target->GetInstallIncludeDirectoriesEntries(te)),
+ preprocessRule, true);
+ this->ReplaceInstallPrefix(dirs);
+ std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(dirs);
+ std::string exportDirs =
+ cge->Evaluate(target->GetLocalGenerator(), "", target);
+
+ if (cge->GetHadContextSensitiveCondition()) {
+ cmLocalGenerator* lg = target->GetLocalGenerator();
+ std::ostringstream e;
+ e << "Target \"" << target->GetName()
+ << "\" is installed with "
+ "INCLUDES DESTINATION set to a context sensitive path. Paths which "
+ "depend on the configuration, policy values or the link interface "
+ "are "
+ "not supported. Consider using target_include_directories instead.";
+ lg->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ return;
+ }
+
+ if (!input && exportDirs.empty()) {
+ return;
+ }
+ if ((input && input->empty()) && exportDirs.empty()) {
+ // Set to empty
+ properties[propName].clear();
+ return;
+ }
+
+ this->AddImportPrefix(exportDirs);
+ includesDestinationDirs = exportDirs;
+
+ std::string includes = (input ? *input : "");
+ char const* const sep = input ? ";" : "";
+ includes += sep + exportDirs;
+ std::string prepro =
+ cmGeneratorExpression::Preprocess(includes, preprocessRule, true);
+ if (!prepro.empty()) {
+ this->ResolveTargetsInGeneratorExpressions(prepro, target);
+
+ if (!checkInterfaceDirs(prepro, target, propName)) {
+ return;
+ }
+ properties[propName] = prepro;
+ }
}
-bool cmExportInstallFileGenerator::
- GenerateImportCxxModuleConfigTargetInclusion(std::string const& name,
- std::string const& config)
+void cmExportInstallFileGenerator::PopulateLinkDependsInterface(
+ cmGeneratorTarget const* gt,
+ cmGeneratorExpression::PreprocessContext preprocessRule,
+ ImportPropertyMap& properties)
{
- auto cxx_modules_dirname = this->GetCxxModulesDirectory();
- if (cxx_modules_dirname.empty()) {
- return true;
+ assert(preprocessRule == cmGeneratorExpression::InstallInterface);
+
+ char const* const propName = "INTERFACE_LINK_DEPENDS";
+ cmValue input = gt->GetProperty(propName);
+
+ if (!input) {
+ return;
}
- std::string filename_config = config;
- if (filename_config.empty()) {
- filename_config = "noconfig";
+ if (input->empty()) {
+ properties[propName].clear();
+ return;
}
- std::string const dest =
- cmStrCat(this->FileDir, '/', cxx_modules_dirname, '/');
- std::string fileName =
- cmStrCat(dest, "cxx-modules-", name, '-', filename_config, ".cmake");
+ std::string prepro =
+ cmGeneratorExpression::Preprocess(*input, preprocessRule, true);
+ if (!prepro.empty()) {
+ this->ResolveTargetsInGeneratorExpressions(prepro, gt);
- cmGeneratedFileStream os(fileName, true);
- if (!os) {
- std::string se = cmSystemTools::GetLastSystemError();
- std::ostringstream e;
- e << "cannot write to file \"" << fileName << "\": " << se;
- cmSystemTools::Error(e.str());
- return false;
+ if (!checkInterfaceDirs(prepro, gt, propName)) {
+ return;
+ }
+ properties[propName] = prepro;
}
- os.SetCopyIfDifferent(true);
+}
- // Record this per-config import file.
- this->ConfigCxxModuleFiles[config] = fileName;
+void cmExportInstallFileGenerator::PopulateLinkDirectoriesInterface(
+ cmGeneratorTarget const* gt,
+ cmGeneratorExpression::PreprocessContext preprocessRule,
+ ImportPropertyMap& properties)
+{
+ assert(preprocessRule == cmGeneratorExpression::InstallInterface);
- auto& prop_files = this->ConfigCxxModuleTargetFiles[config];
- for (auto const* tgt : this->ExportedTargets) {
- // Only targets with C++ module sources will have a
- // collator-generated install script.
- if (!tgt->HaveCxx20ModuleSources()) {
- continue;
- }
+ char const* const propName = "INTERFACE_LINK_DIRECTORIES";
+ cmValue input = gt->GetProperty(propName);
- auto prop_filename = cmStrCat("target-", tgt->GetFilesystemExportName(),
- '-', filename_config, ".cmake");
- prop_files.emplace_back(cmStrCat(dest, prop_filename));
- os << "include(\"${CMAKE_CURRENT_LIST_DIR}/" << prop_filename << "\")\n";
+ if (!input) {
+ return;
}
- return true;
+ if (input->empty()) {
+ properties[propName].clear();
+ return;
+ }
+
+ std::string prepro =
+ cmGeneratorExpression::Preprocess(*input, preprocessRule, true);
+ if (!prepro.empty()) {
+ this->ResolveTargetsInGeneratorExpressions(prepro, gt);
+
+ if (!checkInterfaceDirs(prepro, gt, propName)) {
+ return;
+ }
+ properties[propName] = prepro;
+ }
}
diff --git a/Source/cmExportInstallFileGenerator.h b/Source/cmExportInstallFileGenerator.h
index 5bcaaca..24cda9d 100644
--- a/Source/cmExportInstallFileGenerator.h
+++ b/Source/cmExportInstallFileGenerator.h
@@ -4,19 +4,21 @@
#include "cmConfigure.h" // IWYU pragma: keep
-#include <iosfwd>
+#include <functional>
#include <map>
#include <set>
#include <string>
#include <utility>
#include <vector>
+#include <cm/string_view>
+
#include "cmExportFileGenerator.h"
+#include "cmGeneratorExpression.h"
#include "cmInstallExportGenerator.h"
#include "cmStateTypes.h"
class cmExportSet;
-class cmFileSet;
class cmGeneratorTarget;
class cmGlobalGenerator;
class cmInstallTargetGenerator;
@@ -25,18 +27,10 @@ class cmTargetExport;
/** \class cmExportInstallFileGenerator
* \brief Generate a file exporting targets from an install tree.
*
- * cmExportInstallFileGenerator generates files exporting targets from
- * install an installation tree. The files are placed in a temporary
- * location for installation by cmInstallExportGenerator. One main
- * file is generated that creates the imported targets and loads
- * per-configuration files. Target locations and settings for each
- * configuration are written to these per-configuration files. After
- * installation the main file loads the configurations that have been
- * installed.
- *
- * This is used to implement the INSTALL(EXPORT) command.
+ * cmExportInstallFileGenerator is the generic interface class for generating
+ * export files for an install tree.
*/
-class cmExportInstallFileGenerator : public cmExportFileGenerator
+class cmExportInstallFileGenerator : virtual public cmExportFileGenerator
{
public:
/** Construct with the export installer that will install the
@@ -73,38 +67,37 @@ public:
/** Compute the globbing expression used to load per-config import
files from the main file. */
- std::string GetConfigImportFileGlob();
+ virtual std::string GetConfigImportFileGlob() const = 0;
protected:
- // Implement virtual methods from the superclass.
- bool GenerateMainFile(std::ostream& os) override;
- void GenerateImportTargetsConfig(std::ostream& os, std::string const& config,
- std::string const& suffix) override;
cmStateEnums::TargetType GetExportTargetType(
cmTargetExport const* targetExport) const;
+
+ virtual std::string const& GetExportName() const;
+
+ std::string GetInstallPrefix() const
+ {
+ cm::string_view const& prefixWithSlash = this->GetImportPrefixWithSlash();
+ return std::string(prefixWithSlash.data(), prefixWithSlash.length() - 1);
+ }
+
void HandleMissingTarget(std::string& link_libs,
cmGeneratorTarget const* depender,
cmGeneratorTarget* dependee) override;
- void ReplaceInstallPrefix(std::string& input) override;
-
- void ComplainAboutMissingTarget(cmGeneratorTarget const* depender,
- cmGeneratorTarget const* dependee,
- std::vector<std::string> const& exportFiles);
+ void ReplaceInstallPrefix(std::string& input) const override;
- std::pair<std::vector<std::string>, std::string> FindNamespaces(
- cmGlobalGenerator* gg, std::string const& name);
-
- /** Generate the relative import prefix. */
- virtual void GenerateImportPrefix(std::ostream&);
+ void ComplainAboutMissingTarget(
+ cmGeneratorTarget const* depender, cmGeneratorTarget const* dependee,
+ std::vector<std::string> const& exportFiles) const;
- /** Generate the relative import prefix. */
- virtual void LoadConfigFiles(std::ostream&);
+ void ComplainAboutDuplicateTarget(
+ std::string const& targetName) const override;
- virtual void CleanupTemporaryVariables(std::ostream&);
+ std::pair<std::vector<std::string>, std::string> FindNamespaces(
+ cmGlobalGenerator* gg, std::string const& name) const;
- /** Generate a per-configuration file for the targets. */
- virtual bool GenerateImportFileConfig(std::string const& config);
+ void ReportError(std::string const& errorMessage) const override;
/** Fill in properties indicating installed file locations. */
void SetImportLocationProperty(std::string const& config,
@@ -116,24 +109,31 @@ protected:
std::string InstallNameDir(cmGeneratorTarget const* target,
std::string const& config) override;
- std::string GetFileSetDirectories(cmGeneratorTarget* gte, cmFileSet* fileSet,
- cmTargetExport* te) override;
- std::string GetFileSetFiles(cmGeneratorTarget* gte, cmFileSet* fileSet,
- cmTargetExport* te) override;
-
using cmExportFileGenerator::GetCxxModuleFile;
- std::string GetCxxModulesDirectory() const override;
- void GenerateCxxModuleConfigInformation(std::string const&,
- std::ostream&) const override;
- bool GenerateImportCxxModuleConfigTargetInclusion(std::string const&,
- std::string const&);
+ /** Walk the list of targets to be exported. Returns true iff no duplicates
+ are found. */
+ bool CollectExports(
+ std::function<void(cmTargetExport const*)> const& visitor);
cmExportSet* GetExportSet() const override
{
return this->IEGen->GetExportSet();
}
+ std::string GetImportXcFrameworkLocation(
+ std::string const& config, cmTargetExport const* targetExport) const;
+
+ using cmExportFileGenerator::PopulateInterfaceProperties;
+ bool PopulateInterfaceProperties(cmTargetExport const* targetExport,
+ ImportPropertyMap& properties);
+
+ void PopulateImportProperties(std::string const& config,
+ std::string const& suffix,
+ cmTargetExport const* targetExport,
+ ImportPropertyMap& properties,
+ std::set<std::string>& importedLocations);
+
cmInstallExportGenerator* IEGen;
// The import file generated for each configuration.
@@ -142,4 +142,29 @@ protected:
std::map<std::string, std::string> ConfigCxxModuleFiles;
// The C++ module property target files generated for each configuration.
std::map<std::string, std::vector<std::string>> ConfigCxxModuleTargetFiles;
+
+private:
+ void PopulateCompatibleInterfaceProperties(cmGeneratorTarget const* target,
+ ImportPropertyMap& properties);
+ void PopulateCustomTransitiveInterfaceProperties(
+ cmGeneratorTarget const* target,
+ cmGeneratorExpression::PreprocessContext preprocessRule,
+ ImportPropertyMap& properties);
+ void PopulateIncludeDirectoriesInterface(
+ cmGeneratorTarget const* target,
+ cmGeneratorExpression::PreprocessContext preprocessRule,
+ ImportPropertyMap& properties, cmTargetExport const& te,
+ std::string& includesDestinationDirs);
+ void PopulateSourcesInterface(
+ cmGeneratorTarget const* target,
+ cmGeneratorExpression::PreprocessContext preprocessRule,
+ ImportPropertyMap& properties);
+ void PopulateLinkDirectoriesInterface(
+ cmGeneratorTarget const* target,
+ cmGeneratorExpression::PreprocessContext preprocessRule,
+ ImportPropertyMap& properties);
+ void PopulateLinkDependsInterface(
+ cmGeneratorTarget const* target,
+ cmGeneratorExpression::PreprocessContext preprocessRule,
+ ImportPropertyMap& properties);
};
diff --git a/Source/cmExportTryCompileFileGenerator.cxx b/Source/cmExportTryCompileFileGenerator.cxx
index 6506822..021e071 100644
--- a/Source/cmExportTryCompileFileGenerator.cxx
+++ b/Source/cmExportTryCompileFileGenerator.cxx
@@ -19,6 +19,7 @@
#include "cmOutputConverter.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmValue.h"
@@ -32,6 +33,12 @@ cmExportTryCompileFileGenerator::cmExportTryCompileFileGenerator(
gg->CreateImportedGenerationObjects(mf, targets, this->Exports);
}
+void cmExportTryCompileFileGenerator::ReportError(
+ std::string const& errorMessage) const
+{
+ cmSystemTools::Error(errorMessage);
+}
+
bool cmExportTryCompileFileGenerator::GenerateMainFile(std::ostream& os)
{
std::set<cmGeneratorTarget const*> emitted;
@@ -153,14 +160,14 @@ std::string cmExportTryCompileFileGenerator::InstallNameDir(
}
std::string cmExportTryCompileFileGenerator::GetFileSetDirectories(
- cmGeneratorTarget* /*gte*/, cmFileSet* fileSet, cmTargetExport* /*te*/)
+ cmGeneratorTarget* /*gte*/, cmFileSet* fileSet, cmTargetExport const* /*te*/)
{
return cmOutputConverter::EscapeForCMake(
cmList::to_string(fileSet->GetDirectoryEntries()));
}
std::string cmExportTryCompileFileGenerator::GetFileSetFiles(
- cmGeneratorTarget* /*gte*/, cmFileSet* fileSet, cmTargetExport* /*te*/)
+ cmGeneratorTarget* /*gte*/, cmFileSet* fileSet, cmTargetExport const* /*te*/)
{
return cmOutputConverter::EscapeForCMake(
cmList::to_string(fileSet->GetFileEntries()));
diff --git a/Source/cmExportTryCompileFileGenerator.h b/Source/cmExportTryCompileFileGenerator.h
index e96d332..4b290e6 100644
--- a/Source/cmExportTryCompileFileGenerator.h
+++ b/Source/cmExportTryCompileFileGenerator.h
@@ -9,7 +9,7 @@
#include <string>
#include <vector>
-#include "cmExportFileGenerator.h"
+#include "cmExportCMakeConfigGenerator.h"
class cmFileSet;
class cmGeneratorTarget;
@@ -17,7 +17,7 @@ class cmGlobalGenerator;
class cmMakefile;
class cmTargetExport;
-class cmExportTryCompileFileGenerator : public cmExportFileGenerator
+class cmExportTryCompileFileGenerator : public cmExportCMakeConfigGenerator
{
public:
cmExportTryCompileFileGenerator(cmGlobalGenerator* gg,
@@ -30,6 +30,10 @@ public:
protected:
// Implement virtual methods from the superclass.
+ void ComplainAboutDuplicateTarget(
+ std::string const& /*targetName*/) const override{};
+ void ReportError(std::string const& errorMessage) const override;
+
bool GenerateMainFile(std::ostream& os) override;
void GenerateImportTargetsConfig(std::ostream&, std::string const&,
@@ -50,10 +54,10 @@ protected:
std::string GetFileSetDirectories(cmGeneratorTarget* target,
cmFileSet* fileSet,
- cmTargetExport* te) override;
+ cmTargetExport const* te) override;
std::string GetFileSetFiles(cmGeneratorTarget* target, cmFileSet* fileSet,
- cmTargetExport* te) override;
+ cmTargetExport const* te) override;
std::string GetCxxModulesDirectory() const override { return {}; }
void GenerateCxxModuleConfigInformation(std::string const&,
diff --git a/Source/cmInstallAndroidMKExportGenerator.cxx b/Source/cmInstallAndroidMKExportGenerator.cxx
index 2c52f56..b038ac1 100644
--- a/Source/cmInstallAndroidMKExportGenerator.cxx
+++ b/Source/cmInstallAndroidMKExportGenerator.cxx
@@ -16,23 +16,15 @@ cmInstallAndroidMKExportGenerator::cmInstallAndroidMKExportGenerator(
cmExportSet* exportSet, std::string destination, std::string filePermissions,
std::vector<std::string> const& configurations, std::string component,
MessageLevel message, bool excludeFromAll, std::string filename,
- std::string targetNamespace, bool exportOld, cmListFileBacktrace backtrace)
+ std::string targetNamespace, cmListFileBacktrace backtrace)
: cmInstallExportGenerator(exportSet, std::move(destination),
std::move(filePermissions), configurations,
std::move(component), message, excludeFromAll,
std::move(filename), std::move(targetNamespace),
std::string{}, std::move(backtrace))
- , ExportOld(exportOld)
{
this->EFGen = cm::make_unique<cmExportInstallAndroidMKGenerator>(this);
}
cmInstallAndroidMKExportGenerator::~cmInstallAndroidMKExportGenerator() =
default;
-
-void cmInstallAndroidMKExportGenerator::GenerateScript(std::ostream& os)
-{
- this->EFGen->SetExportOld(this->ExportOld);
-
- this->cmInstallExportGenerator::GenerateScript(os);
-}
diff --git a/Source/cmInstallAndroidMKExportGenerator.h b/Source/cmInstallAndroidMKExportGenerator.h
index dcff756..4ee80d4 100644
--- a/Source/cmInstallAndroidMKExportGenerator.h
+++ b/Source/cmInstallAndroidMKExportGenerator.h
@@ -2,7 +2,6 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#pragma once
-#include <iosfwd>
#include <string>
#include <vector>
@@ -22,8 +21,7 @@ public:
std::string filePermissions,
std::vector<std::string> const& configurations, std::string component,
MessageLevel message, bool excludeFromAll, std::string filename,
- std::string targetNamespace, bool exportOld,
- cmListFileBacktrace backtrace);
+ std::string targetNamespace, cmListFileBacktrace backtrace);
cmInstallAndroidMKExportGenerator(cmInstallAndroidMKExportGenerator const&) =
delete;
~cmInstallAndroidMKExportGenerator() override;
@@ -31,10 +29,8 @@ public:
cmInstallAndroidMKExportGenerator& operator=(
cmInstallAndroidMKExportGenerator const&) = delete;
-protected:
- char const* InstallSubcommand() const override { return "EXPORT"; }
-
- void GenerateScript(std::ostream& os) override;
-
- bool const ExportOld;
+ char const* InstallSubcommand() const override
+ {
+ return "EXPORT_ANDROID_MK";
+ }
};
diff --git a/Source/cmInstallCMakeConfigExportGenerator.cxx b/Source/cmInstallCMakeConfigExportGenerator.cxx
index bb7a1a0..e247e5b 100644
--- a/Source/cmInstallCMakeConfigExportGenerator.cxx
+++ b/Source/cmInstallCMakeConfigExportGenerator.cxx
@@ -6,6 +6,7 @@
#include <cm/memory>
+#include "cmExportInstallCMakeConfigGenerator.h"
#include "cmExportInstallFileGenerator.h"
#include "cmListFileCache.h"
@@ -25,7 +26,7 @@ cmInstallCMakeConfigExportGenerator::cmInstallCMakeConfigExportGenerator(
, ExportOld(exportOld)
, ExportPackageDependencies(exportPackageDependencies)
{
- this->EFGen = cm::make_unique<cmExportInstallFileGenerator>(this);
+ this->EFGen = cm::make_unique<cmExportInstallCMakeConfigGenerator>(this);
}
cmInstallCMakeConfigExportGenerator::~cmInstallCMakeConfigExportGenerator() =
@@ -33,8 +34,10 @@ cmInstallCMakeConfigExportGenerator::~cmInstallCMakeConfigExportGenerator() =
void cmInstallCMakeConfigExportGenerator::GenerateScript(std::ostream& os)
{
- this->EFGen->SetExportOld(this->ExportOld);
- this->EFGen->SetExportPackageDependencies(this->ExportPackageDependencies);
+ auto* const efgen =
+ static_cast<cmExportInstallCMakeConfigGenerator*>(this->EFGen.get());
+ efgen->SetExportOld(this->ExportOld);
+ efgen->SetExportPackageDependencies(this->ExportPackageDependencies);
this->cmInstallExportGenerator::GenerateScript(os);
}
diff --git a/Source/cmInstallCMakeConfigExportGenerator.h b/Source/cmInstallCMakeConfigExportGenerator.h
index 8f019b1..03296de 100644
--- a/Source/cmInstallCMakeConfigExportGenerator.h
+++ b/Source/cmInstallCMakeConfigExportGenerator.h
@@ -32,9 +32,9 @@ public:
cmInstallCMakeConfigExportGenerator& operator=(
cmInstallCMakeConfigExportGenerator const&) = delete;
-protected:
char const* InstallSubcommand() const override { return "EXPORT"; }
+protected:
void GenerateScript(std::ostream& os) override;
bool const ExportOld;
diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx
index 1dffd43..3160585 100644
--- a/Source/cmInstallCommand.cxx
+++ b/Source/cmInstallCommand.cxx
@@ -2033,7 +2033,7 @@ bool HandleExportAndroidMKMode(std::vector<std::string> const& args,
&exportSet, ica.GetDestination(), ica.GetPermissions(),
ica.GetConfigurations(), ica.GetComponent(), message,
ica.GetExcludeFromAll(), std::move(fname), std::move(name_space),
- exportOld, helper.Makefile->GetBacktrace()));
+ helper.Makefile->GetBacktrace()));
return true;
#else
diff --git a/Source/cmInstallExportGenerator.cxx b/Source/cmInstallExportGenerator.cxx
index b351fbe..9828bf2 100644
--- a/Source/cmInstallExportGenerator.cxx
+++ b/Source/cmInstallExportGenerator.cxx
@@ -136,7 +136,8 @@ void cmInstallExportGenerator::GenerateScriptConfigs(std::ostream& os,
auto const cxxModuleDestination =
cmStrCat(this->Destination, '/', this->CxxModulesDirectory);
auto const cxxModuleInstallFilePath = this->EFGen->GetCxxModuleFile();
- if (!cxxModuleInstallFilePath.empty()) {
+ auto const configImportFilesGlob = this->EFGen->GetConfigImportFileGlob();
+ if (!cxxModuleInstallFilePath.empty() && !configImportFilesGlob.empty()) {
auto const cxxModuleFilename =
cmSystemTools::GetFilenameName(cxxModuleInstallFilePath);
@@ -149,17 +150,20 @@ void cmInstallExportGenerator::GenerateScriptConfigs(std::ostream& os,
Indent indentN = indent.Next();
Indent indentNN = indentN.Next();
Indent indentNNN = indentNN.Next();
- /* clang-format off */
os << indentN << "file(DIFFERENT _cmake_export_file_changed FILES\n"
<< indentN << " \"" << installedFile << "\"\n"
<< indentN << " \"" << cxxModuleInstallFilePath << "\")\n";
os << indentN << "if(_cmake_export_file_changed)\n";
os << indentNN << "file(GLOB _cmake_old_config_files \"" << installedDir
- << this->EFGen->GetConfigImportFileGlob() << "\")\n";
+ << configImportFilesGlob << "\")\n";
os << indentNN << "if(_cmake_old_config_files)\n";
- os << indentNNN << "string(REPLACE \";\" \", \" _cmake_old_config_files_text \"${_cmake_old_config_files}\")\n";
- os << indentNNN << R"(message(STATUS "Old C++ module export file \")" << installedFile
- << "\\\" will be replaced. Removing files [${_cmake_old_config_files_text}].\")\n";
+ os << indentNNN
+ << "string(REPLACE \";\" \", \" _cmake_old_config_files_text "
+ "\"${_cmake_old_config_files}\")\n";
+ os << indentNNN << R"(message(STATUS "Old C++ module export file \")"
+ << installedFile
+ << "\\\" will be replaced. "
+ "Removing files [${_cmake_old_config_files_text}].\")\n";
os << indentNNN << "unset(_cmake_old_config_files_text)\n";
os << indentNNN << "file(REMOVE ${_cmake_old_config_files})\n";
os << indentNN << "endif()\n";
@@ -167,7 +171,6 @@ void cmInstallExportGenerator::GenerateScriptConfigs(std::ostream& os,
os << indentN << "endif()\n";
os << indentN << "unset(_cmake_export_file_changed)\n";
os << indent << "endif()\n";
- /* clang-format on */
// All of these files are siblings; get its location to know where the
// "anchor" file is.
@@ -201,33 +204,37 @@ void cmInstallExportGenerator::GenerateScriptConfigs(std::ostream& os,
void cmInstallExportGenerator::GenerateScriptActions(std::ostream& os,
Indent indent)
{
- // Remove old per-configuration export files if the main changes.
- std::string installedDir = cmStrCat(
- "$ENV{DESTDIR}", ConvertToAbsoluteDestination(this->Destination), '/');
- std::string installedFile = cmStrCat(installedDir, this->FileName);
- os << indent << "if(EXISTS \"" << installedFile << "\")\n";
- Indent indentN = indent.Next();
- Indent indentNN = indentN.Next();
- Indent indentNNN = indentNN.Next();
- /* clang-format off */
- os << indentN << "file(DIFFERENT _cmake_export_file_changed FILES\n"
- << indentN << " \"" << installedFile << "\"\n"
- << indentN << " \"" << this->MainImportFile << "\")\n";
- os << indentN << "if(_cmake_export_file_changed)\n";
- os << indentNN << "file(GLOB _cmake_old_config_files \"" << installedDir
- << this->EFGen->GetConfigImportFileGlob() << "\")\n";
- os << indentNN << "if(_cmake_old_config_files)\n";
- os << indentNNN << "string(REPLACE \";\" \", \" _cmake_old_config_files_text \"${_cmake_old_config_files}\")\n";
- os << indentNNN << R"(message(STATUS "Old export file \")" << installedFile
- << "\\\" will be replaced. Removing files [${_cmake_old_config_files_text}].\")\n";
- os << indentNNN << "unset(_cmake_old_config_files_text)\n";
- os << indentNNN << "file(REMOVE ${_cmake_old_config_files})\n";
- os << indentNN << "endif()\n";
- os << indentNN << "unset(_cmake_old_config_files)\n";
- os << indentN << "endif()\n";
- os << indentN << "unset(_cmake_export_file_changed)\n";
- os << indent << "endif()\n";
- /* clang-format on */
+ auto const configImportFilesGlob = this->EFGen->GetConfigImportFileGlob();
+ if (!configImportFilesGlob.empty()) {
+ // Remove old per-configuration export files if the main changes.
+ std::string installedDir = cmStrCat(
+ "$ENV{DESTDIR}", ConvertToAbsoluteDestination(this->Destination), '/');
+ std::string installedFile = cmStrCat(installedDir, this->FileName);
+ os << indent << "if(EXISTS \"" << installedFile << "\")\n";
+ Indent indentN = indent.Next();
+ Indent indentNN = indentN.Next();
+ Indent indentNNN = indentNN.Next();
+ os << indentN << "file(DIFFERENT _cmake_export_file_changed FILES\n"
+ << indentN << " \"" << installedFile << "\"\n"
+ << indentN << " \"" << this->MainImportFile << "\")\n";
+ os << indentN << "if(_cmake_export_file_changed)\n";
+ os << indentNN << "file(GLOB _cmake_old_config_files \"" << installedDir
+ << configImportFilesGlob << "\")\n";
+ os << indentNN << "if(_cmake_old_config_files)\n";
+ os << indentNNN
+ << "string(REPLACE \";\" \", \" _cmake_old_config_files_text "
+ "\"${_cmake_old_config_files}\")\n";
+ os << indentNNN << R"(message(STATUS "Old export file \")" << installedFile
+ << "\\\" will be replaced. "
+ "Removing files [${_cmake_old_config_files_text}].\")\n";
+ os << indentNNN << "unset(_cmake_old_config_files_text)\n";
+ os << indentNNN << "file(REMOVE ${_cmake_old_config_files})\n";
+ os << indentNN << "endif()\n";
+ os << indentNN << "unset(_cmake_old_config_files)\n";
+ os << indentN << "endif()\n";
+ os << indentN << "unset(_cmake_export_file_changed)\n";
+ os << indent << "endif()\n";
+ }
// Install the main export file.
std::vector<std::string> files;
diff --git a/Source/cmInstallExportGenerator.h b/Source/cmInstallExportGenerator.h
index b2a74ac..6100610 100644
--- a/Source/cmInstallExportGenerator.h
+++ b/Source/cmInstallExportGenerator.h
@@ -36,6 +36,8 @@ public:
cmInstallExportGenerator& operator=(const cmInstallExportGenerator&) =
delete;
+ virtual char const* InstallSubcommand() const = 0;
+
cmExportSet* GetExportSet() { return this->ExportSet; }
bool Compute(cmLocalGenerator* lg) override;
@@ -56,8 +58,6 @@ public:
}
protected:
- virtual char const* InstallSubcommand() const = 0;
-
void GenerateScript(std::ostream& os) override;
void GenerateScriptConfigs(std::ostream& os, Indent indent) override;
void GenerateScriptActions(std::ostream& os, Indent indent) override;
diff --git a/bootstrap b/bootstrap
index 241f44b..682cca0 100755
--- a/bootstrap
+++ b/bootstrap
@@ -345,8 +345,11 @@ CMAKE_CXX_SOURCES="\
cmExecuteProcessCommand \
cmExpandedCommandArgument \
cmExperimental \
+ cmExportBuildCMakeConfigGenerator \
cmExportBuildFileGenerator \
+ cmExportCMakeConfigGenerator \
cmExportFileGenerator \
+ cmExportInstallCMakeConfigGenerator \
cmExportInstallFileGenerator \
cmExportSet \
cmExportTryCompileFileGenerator \