1
0
mirror of https://github.com/Kitware/CMake.git synced 2025-10-14 02:08:27 +08:00

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.
This commit is contained in:
Matthew Woehlke
2024-07-18 12:07:26 -04:00
parent 6c66340a64
commit 20fa4ce8d8
30 changed files with 1106 additions and 4517 deletions

View File

@@ -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

View File

@@ -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()
cmExportAndroidMKGenerator::cmExportAndroidMKGenerator() = default;
cm::string_view cmExportAndroidMKGenerator::GetImportPrefixWithSlash() const
{
this->LG = nullptr;
this->ExportSet = nullptr;
return "$(_IMPORT_PREFIX)/"_s;
}
void cmExportAndroidMKGenerator::GenerateImportHeaderCode(std::ostream& os,
std::string const&)
bool cmExportAndroidMKGenerator::GenerateImportFile(std::ostream& os)
{
os << "LOCAL_PATH := $(call my-dir)\n\n";
}
if (!this->AppendMode) {
// Start with the import file header.
this->GenerateImportHeaderCode(os);
}
void cmExportAndroidMKGenerator::GenerateImportFooterCode(std::ostream&)
{
}
// Create all the imported targets.
std::stringstream mainFileBuffer;
bool result = this->GenerateMainFile(mainFileBuffer);
void cmExportAndroidMKGenerator::GenerateExpectedTargetsCode(
std::ostream&, std::string const&)
{
}
// Write cached import code.
os << mainFileBuffer.rdbuf();
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";
}
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

View File

@@ -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.
* \brief Generate CMake configuration files exporting targets from a build or
* install 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.
*
* 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
{
}
};

View File

@@ -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";
}

View File

@@ -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 {}; }
};

View File

@@ -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
{

View File

@@ -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;
};

View File

@@ -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)
bool cmExportBuildFileGenerator::PopulateInterfaceProperties(
cmGeneratorTarget const* target, ImportPropertyMap& properties)
{
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
{
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);
}

View File

@@ -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,

File diff suppressed because it is too large Load Diff

View File

@@ -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);
cm::string_view GetImportPrefixWithSlash() const override;
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;
/** 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;
};

View File

@@ -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 =

File diff suppressed because it is too large Load Diff

View File

@@ -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);
void GenerateCxxModuleInformation(std::string const& name, std::ostream& os);
virtual std::string GetFileSetDirectories(cmGeneratorTarget* gte,
cmFileSet* fileSet,
cmTargetExport* 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;
virtual void ReplaceInstallPrefix(std::string& input) const;
void SetRequiredCMakeVersion(unsigned int major, unsigned int minor,
unsigned int patch);
virtual std::string InstallNameDir(cmGeneratorTarget const* target,
std::string const& config) = 0;
/** Get the temporary location of the config-agnostic C++ module file. */
virtual std::string GetCxxModuleFile(std::string const& name) const = 0;
virtual std::string GetCxxModulesDirectory() const = 0;
virtual void GenerateCxxModuleConfigInformation(std::string const&,
std::ostream& os) const = 0;
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;
virtual std::string GetCxxModulesDirectory() const = 0;
virtual void GenerateCxxModuleConfigInformation(std::string const&,
std::ostream& os) const = 0;
};
extern template void cmExportFileGenerator::SetImportLinkProperty<std::string>(
std::string const&, cmGeneratorTarget const*, std::string const&,
std::vector<std::string> const&, ImportPropertyMap& properties,
ImportLinkPropertyTargetNames);
extern template void cmExportFileGenerator::SetImportLinkProperty<cmLinkItem>(
std::string const&, cmGeneratorTarget const*, std::string const&,
std::vector<cmLinkItem> const&, ImportPropertyMap& properties,
ImportLinkPropertyTargetNames);

View File

@@ -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;
}

View File

@@ -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 {}; }
};

View File

@@ -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)

View File

@@ -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;
};

File diff suppressed because it is too large Load Diff

View File

@@ -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 ReplaceInstallPrefix(std::string& input) const override;
void ComplainAboutMissingTarget(cmGeneratorTarget const* depender,
cmGeneratorTarget const* dependee,
std::vector<std::string> const& exportFiles);
void ComplainAboutMissingTarget(
cmGeneratorTarget const* depender, cmGeneratorTarget const* dependee,
std::vector<std::string> const& exportFiles) const;
void ComplainAboutDuplicateTarget(
std::string const& targetName) const override;
std::pair<std::vector<std::string>, std::string> FindNamespaces(
cmGlobalGenerator* gg, std::string const& name);
cmGlobalGenerator* gg, std::string const& name) const;
/** Generate the relative import prefix. */
virtual void GenerateImportPrefix(std::ostream&);
/** Generate the relative import prefix. */
virtual void LoadConfigFiles(std::ostream&);
virtual void CleanupTemporaryVariables(std::ostream&);
/** 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);
};

View File

@@ -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()));

View File

@@ -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&,

View File

@@ -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);
}

View File

@@ -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";
}
};

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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;

View File

@@ -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;

View File

@@ -345,8 +345,11 @@ CMAKE_CXX_SOURCES="\
cmExecuteProcessCommand \
cmExpandedCommandArgument \
cmExperimental \
cmExportBuildCMakeConfigGenerator \
cmExportBuildFileGenerator \
cmExportCMakeConfigGenerator \
cmExportFileGenerator \
cmExportInstallCMakeConfigGenerator \
cmExportInstallFileGenerator \
cmExportSet \
cmExportTryCompileFileGenerator \