mirror of
https://github.com/Kitware/CMake.git
synced 2026-02-25 10:18:34 -06:00
Merge topic 'export-refactor-for-cps'
ff24058e46export: Use std::all_of to collect exports20fa4ce8d8export: Factor out CMake-specific export generation (2/2)6c66340a64export: Fix const placement1bceab3520export: Factor out CMake-specific export generation (*/2)a6cc595772export: Factor out CMake-specific export generation (1/2)0352376e44export: Immediately report actual version required Acked-by: Kitware Robot <kwrobot@kitware.com> Acked-by: buildbot <buildbot@kitware.com> Merge-request: !9646
This commit is contained in:
@@ -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
|
||||
@@ -311,6 +319,10 @@ add_library(
|
||||
cmGraphVizWriter.h
|
||||
cmImportedCxxModuleInfo.cxx
|
||||
cmImportedCxxModuleInfo.h
|
||||
cmInstallAndroidMKExportGenerator.cxx
|
||||
cmInstallAndroidMKExportGenerator.h
|
||||
cmInstallCMakeConfigExportGenerator.cxx
|
||||
cmInstallCMakeConfigExportGenerator.h
|
||||
cmInstallGenerator.h
|
||||
cmInstallGenerator.cxx
|
||||
cmInstallGetRuntimeDependenciesGenerator.h
|
||||
|
||||
165
Source/cmExportAndroidMKGenerator.cxx
Normal file
165
Source/cmExportAndroidMKGenerator.cxx
Normal file
@@ -0,0 +1,165 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
#include "cmExportAndroidMKGenerator.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <cmext/algorithm>
|
||||
#include <cmext/string_view>
|
||||
|
||||
#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"
|
||||
|
||||
cmExportAndroidMKGenerator::cmExportAndroidMKGenerator() = default;
|
||||
|
||||
cm::string_view cmExportAndroidMKGenerator::GetImportPrefixWithSlash() const
|
||||
{
|
||||
return "$(_IMPORT_PREFIX)/"_s;
|
||||
}
|
||||
|
||||
bool cmExportAndroidMKGenerator::GenerateImportFile(std::ostream& os)
|
||||
{
|
||||
if (!this->AppendMode) {
|
||||
// Start with the import file header.
|
||||
this->GenerateImportHeaderCode(os);
|
||||
}
|
||||
|
||||
// Create all the imported targets.
|
||||
std::stringstream mainFileBuffer;
|
||||
bool result = this->GenerateMainFile(mainFileBuffer);
|
||||
|
||||
// Write cached import code.
|
||||
os << mainFileBuffer.rdbuf();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void cmExportAndroidMKGenerator::GenerateInterfaceProperties(
|
||||
cmGeneratorTarget const* target, std::ostream& os,
|
||||
ImportPropertyMap const& properties)
|
||||
{
|
||||
std::string const config =
|
||||
(this->Configurations.empty() ? std::string{} : this->Configurations[0]);
|
||||
GenerateType const type = this->GetGenerateType();
|
||||
|
||||
bool const newCMP0022Behavior =
|
||||
target->GetPolicyStatusCMP0022() != cmPolicies::WARN &&
|
||||
target->GetPolicyStatusCMP0022() != cmPolicies::OLD;
|
||||
if (!newCMP0022Behavior) {
|
||||
std::ostringstream w;
|
||||
if (type == 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 == 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";
|
||||
}
|
||||
73
Source/cmExportAndroidMKGenerator.h
Normal file
73
Source/cmExportAndroidMKGenerator.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
#pragma once
|
||||
|
||||
#include "cmConfigure.h" // IWYU pragma: keep
|
||||
|
||||
#include <iosfwd>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include <cm/string_view>
|
||||
|
||||
#include "cmExportFileGenerator.h"
|
||||
#include "cmStateTypes.h"
|
||||
|
||||
class cmGeneratorTarget;
|
||||
|
||||
/** \class cmExportAndroidMKGenerator
|
||||
* \brief Generate CMake configuration files exporting targets from a build or
|
||||
* install tree.
|
||||
*
|
||||
* cmExportAndroidMKGenerator is the superclass for
|
||||
* cmExportBuildAndroidMKGenerator and cmExportInstallAndroidMKGenerator.
|
||||
* It contains common code generation routines for the two kinds of export
|
||||
* implementations.
|
||||
*/
|
||||
class cmExportAndroidMKGenerator : virtual public cmExportFileGenerator
|
||||
{
|
||||
public:
|
||||
cmExportAndroidMKGenerator();
|
||||
|
||||
using cmExportFileGenerator::GenerateImportFile;
|
||||
|
||||
protected:
|
||||
enum GenerateType
|
||||
{
|
||||
BUILD,
|
||||
INSTALL
|
||||
};
|
||||
virtual GenerateType GetGenerateType() const = 0;
|
||||
|
||||
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) = 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
|
||||
{
|
||||
}
|
||||
};
|
||||
@@ -2,45 +2,58 @@
|
||||
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(
|
||||
std::ostream& os, const std::string&)
|
||||
std::ostream& os, std::string const&)
|
||||
{
|
||||
os << "LOCAL_PATH := $(call my-dir)\n\n";
|
||||
}
|
||||
|
||||
void cmExportBuildAndroidMKGenerator::GenerateImportFooterCode(std::ostream&)
|
||||
{
|
||||
}
|
||||
|
||||
void cmExportBuildAndroidMKGenerator::GenerateExpectedTargetsCode(
|
||||
std::ostream&, const std::string&)
|
||||
{
|
||||
}
|
||||
|
||||
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&, const std::string&, const std::string&,
|
||||
cmGeneratorTarget const*, ImportPropertyMap const&, const std::string&)
|
||||
{
|
||||
}
|
||||
|
||||
void cmExportBuildAndroidMKGenerator::GenerateMissingTargetsCheckCode(
|
||||
std::ostream&)
|
||||
{
|
||||
}
|
||||
|
||||
void cmExportBuildAndroidMKGenerator::GenerateInterfaceProperties(
|
||||
const cmGeneratorTarget* target, std::ostream& os,
|
||||
const ImportPropertyMap& properties)
|
||||
{
|
||||
std::string config;
|
||||
if (!this->Configurations.empty()) {
|
||||
config = this->Configurations[0];
|
||||
}
|
||||
cmExportBuildAndroidMKGenerator::GenerateInterfaceProperties(
|
||||
target, os, properties, cmExportBuildAndroidMKGenerator::BUILD, config);
|
||||
}
|
||||
|
||||
void cmExportBuildAndroidMKGenerator::GenerateInterfaceProperties(
|
||||
const cmGeneratorTarget* target, std::ostream& os,
|
||||
const ImportPropertyMap& properties, GenerateType type,
|
||||
std::string const& config)
|
||||
{
|
||||
const bool 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";
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
const ImportPropertyMap& 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,
|
||||
const std::string& config = "") override;
|
||||
void GenerateImportFooterCode(std::ostream& os) override;
|
||||
std::string const& config = "") override;
|
||||
void GenerateImportTargetCode(
|
||||
std::ostream& os, cmGeneratorTarget const* target,
|
||||
cmStateEnums::TargetType /*targetType*/) override;
|
||||
void GenerateExpectedTargetsCode(
|
||||
std::ostream& os, const std::string& expectedTargets) override;
|
||||
void GenerateImportPropertyCode(
|
||||
std::ostream& os, const std::string& config, const std::string& suffix,
|
||||
cmGeneratorTarget const* target, ImportPropertyMap const& properties,
|
||||
const std::string& importedXcFrameworkLocation) override;
|
||||
void GenerateMissingTargetsCheckCode(std::ostream& os) override;
|
||||
void GenerateFindDependencyCalls(std::ostream&) override {}
|
||||
void GenerateInterfaceProperties(
|
||||
cmGeneratorTarget const* target, std::ostream& os,
|
||||
const ImportPropertyMap& properties) override;
|
||||
|
||||
std::string GetCxxModulesDirectory() const override { return {}; }
|
||||
};
|
||||
|
||||
343
Source/cmExportBuildCMakeConfigGenerator.cxx
Normal file
343
Source/cmExportBuildCMakeConfigGenerator.cxx
Normal file
@@ -0,0 +1,343 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
#include "cmExportBuildCMakeConfigGenerator.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#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 "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"
|
||||
|
||||
cmExportBuildCMakeConfigGenerator::cmExportBuildCMakeConfigGenerator()
|
||||
{
|
||||
this->LG = nullptr;
|
||||
this->ExportSet = nullptr;
|
||||
}
|
||||
|
||||
bool cmExportBuildCMakeConfigGenerator::GenerateMainFile(std::ostream& os)
|
||||
{
|
||||
{
|
||||
std::string expectedTargets;
|
||||
std::string sep;
|
||||
bool generatedInterfaceRequired = false;
|
||||
auto visitor = [&](cmGeneratorTarget const* te) {
|
||||
expectedTargets += sep + this->Namespace + te->GetExportName();
|
||||
sep = " ";
|
||||
|
||||
generatedInterfaceRequired |=
|
||||
this->GetExportTargetType(te) == cmStateEnums::INTERFACE_LIBRARY;
|
||||
};
|
||||
|
||||
if (!this->CollectExports(visitor)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
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;
|
||||
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);
|
||||
|
||||
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 cmExportBuildCMakeConfigGenerator::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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
bool EntryIsContextSensitive(
|
||||
std::unique_ptr<cmCompiledGeneratorExpression> const& cge)
|
||||
{
|
||||
return cge->GetHadContextSensitiveCondition();
|
||||
}
|
||||
}
|
||||
|
||||
std::string cmExportBuildCMakeConfigGenerator::GetFileSetDirectories(
|
||||
cmGeneratorTarget* gte, cmFileSet* fileSet, cmTargetExport const* /*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 cmExportBuildCMakeConfigGenerator::GetFileSetFiles(
|
||||
cmGeneratorTarget* gte, cmFileSet* fileSet, cmTargetExport const* /*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, " ");
|
||||
}
|
||||
|
||||
void cmExportBuildCMakeConfigGenerator::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 cmExportBuildCMakeConfigGenerator::
|
||||
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;
|
||||
}
|
||||
52
Source/cmExportBuildCMakeConfigGenerator.h
Normal file
52
Source/cmExportBuildCMakeConfigGenerator.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
#pragma once
|
||||
|
||||
#include "cmConfigure.h" // IWYU pragma: keep
|
||||
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
|
||||
#include "cmExportBuildFileGenerator.h"
|
||||
#include "cmExportCMakeConfigGenerator.h"
|
||||
|
||||
class cmFileSet;
|
||||
class cmGeneratorTarget;
|
||||
class cmTargetExport;
|
||||
|
||||
/** \class cmExportBuildCMakeConfigGenerator
|
||||
* \brief Generate a file exporting targets from a build tree.
|
||||
*
|
||||
* cmExportBuildCMakeConfigGenerator generates a file exporting targets from
|
||||
* 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 cmExportCMakeConfigGenerator
|
||||
, public cmExportBuildFileGenerator
|
||||
{
|
||||
public:
|
||||
cmExportBuildCMakeConfigGenerator();
|
||||
|
||||
/** Set whether to append generated code to the output file. */
|
||||
void SetAppendMode(bool append) { this->AppendMode = append; }
|
||||
|
||||
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;
|
||||
|
||||
std::string GetFileSetDirectories(cmGeneratorTarget* gte, cmFileSet* fileSet,
|
||||
cmTargetExport const* te) override;
|
||||
std::string GetFileSetFiles(cmGeneratorTarget* gte, cmFileSet* fileSet,
|
||||
cmTargetExport const* te) override;
|
||||
|
||||
void GenerateCxxModuleConfigInformation(std::string const&,
|
||||
std::ostream&) const override;
|
||||
bool GenerateImportCxxModuleConfigTargetInclusion(std::string const&,
|
||||
std::string) const;
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
const bool 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, const std::string& 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
|
||||
{
|
||||
@@ -260,7 +61,7 @@ void cmExportBuildFileGenerator::SetExportSet(cmExportSet* exportSet)
|
||||
}
|
||||
|
||||
void cmExportBuildFileGenerator::SetImportLocationProperty(
|
||||
const std::string& config, std::string const& suffix,
|
||||
std::string const& config, std::string const& suffix,
|
||||
cmGeneratorTarget* target, ImportPropertyMap& properties)
|
||||
{
|
||||
// Get the makefile in which to lookup target information.
|
||||
@@ -276,7 +77,7 @@ void cmExportBuildFileGenerator::SetImportLocationProperty(
|
||||
std::string const obj_dir = target->GetObjectDirectory(config);
|
||||
std::vector<std::string> objects;
|
||||
for (cmSourceFile const* sf : objectSources) {
|
||||
const std::string& obj = target->GetObjectName(sf);
|
||||
std::string const& obj = target->GetObjectName(sf);
|
||||
objects.push_back(obj_dir + obj);
|
||||
}
|
||||
|
||||
@@ -311,13 +112,33 @@ void cmExportBuildFileGenerator::SetImportLocationProperty(
|
||||
}
|
||||
}
|
||||
|
||||
bool cmExportBuildFileGenerator::CollectExports(
|
||||
std::function<void(cmGeneratorTarget const*)> visitor)
|
||||
{
|
||||
auto pred = [&](cmExportBuildFileGenerator::TargetExport& tei) -> bool {
|
||||
cmGeneratorTarget* te = this->LG->FindGeneratorTargetToUse(tei.Name);
|
||||
if (this->ExportedTargets.insert(te).second) {
|
||||
this->Exports.emplace_back(te, tei.XcFrameworkLocation);
|
||||
visitor(te);
|
||||
return true;
|
||||
}
|
||||
|
||||
this->ComplainAboutDuplicateTarget(te->GetName());
|
||||
return false;
|
||||
};
|
||||
|
||||
std::vector<TargetExport> targets;
|
||||
this->GetTargets(targets);
|
||||
return std::all_of(targets.begin(), targets.end(), pred);
|
||||
}
|
||||
|
||||
void cmExportBuildFileGenerator::HandleMissingTarget(
|
||||
std::string& link_libs, cmGeneratorTarget const* depender,
|
||||
cmGeneratorTarget* dependee)
|
||||
{
|
||||
// The target is not in the export.
|
||||
if (!this->AppendMode) {
|
||||
const std::string name = dependee->GetName();
|
||||
std::string const& name = dependee->GetName();
|
||||
cmGlobalGenerator* gg =
|
||||
dependee->GetLocalGenerator()->GetGlobalGenerator();
|
||||
auto exportInfo = this->FindBuildExportInfo(gg, name);
|
||||
@@ -359,7 +180,7 @@ void cmExportBuildFileGenerator::GetTargets(
|
||||
|
||||
std::pair<std::vector<std::string>, std::string>
|
||||
cmExportBuildFileGenerator::FindBuildExportInfo(cmGlobalGenerator* gg,
|
||||
const std::string& name)
|
||||
std::string const& name)
|
||||
{
|
||||
std::vector<std::string> exportFiles;
|
||||
std::string ns;
|
||||
@@ -367,12 +188,12 @@ cmExportBuildFileGenerator::FindBuildExportInfo(cmGlobalGenerator* gg,
|
||||
auto& exportSets = gg->GetBuildExportSets();
|
||||
|
||||
for (auto const& exp : exportSets) {
|
||||
const auto& exportSet = exp.second;
|
||||
auto const& exportSet = exp.second;
|
||||
std::vector<TargetExport> targets;
|
||||
exportSet->GetTargets(targets);
|
||||
if (std::any_of(
|
||||
targets.begin(), targets.end(),
|
||||
[&name](const TargetExport& te) { return te.Name == name; })) {
|
||||
[&name](TargetExport const& te) { return te.Name == name; })) {
|
||||
exportFiles.push_back(exp.first);
|
||||
ns = exportSet->GetNamespace();
|
||||
}
|
||||
@@ -383,7 +204,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,13 +220,27 @@ 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());
|
||||
}
|
||||
|
||||
std::string cmExportBuildFileGenerator::InstallNameDir(
|
||||
cmGeneratorTarget const* target, const std::string& config)
|
||||
cmGeneratorTarget const* target, std::string const& config)
|
||||
{
|
||||
std::string install_name_dir;
|
||||
|
||||
@@ -417,185 +252,22 @@ std::string cmExportBuildFileGenerator::InstallNameDir(
|
||||
return install_name_dir;
|
||||
}
|
||||
|
||||
namespace {
|
||||
bool EntryIsContextSensitive(
|
||||
const std::unique_ptr<cmCompiledGeneratorExpression>& 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
|
||||
{
|
||||
const char* 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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -64,54 +61,56 @@ public:
|
||||
{
|
||||
this->CxxModulesDirectory = std::move(cxx_module_dir);
|
||||
}
|
||||
const std::string& GetCxxModuleDirectory() const
|
||||
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, const std::string& 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(const std::string& config,
|
||||
void SetImportLocationProperty(std::string const& config,
|
||||
std::string const& suffix,
|
||||
cmGeneratorTarget* target,
|
||||
ImportPropertyMap& properties);
|
||||
|
||||
std::string InstallNameDir(cmGeneratorTarget const* target,
|
||||
const std::string& config) override;
|
||||
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, const std::string& name);
|
||||
cmGlobalGenerator* gg, std::string const& name);
|
||||
|
||||
using cmExportFileGenerator::PopulateInterfaceProperties;
|
||||
bool PopulateInterfaceProperties(cmGeneratorTarget const* target,
|
||||
ImportPropertyMap& properties);
|
||||
|
||||
struct TargetExportPrivate
|
||||
{
|
||||
|
||||
686
Source/cmExportCMakeConfigGenerator.cxx
Normal file
686
Source/cmExportCMakeConfigGenerator.cxx
Normal file
@@ -0,0 +1,686 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
#include "cmExportCMakeConfigGenerator.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <cm/optional>
|
||||
#include <cm/string_view>
|
||||
#include <cmext/string_view>
|
||||
|
||||
#include "cmExportSet.h"
|
||||
#include "cmFileSet.h"
|
||||
#include "cmFindPackageStack.h"
|
||||
#include "cmGeneratedFileStream.h"
|
||||
#include "cmGeneratorTarget.h"
|
||||
#include "cmLinkItem.h"
|
||||
#include "cmLocalGenerator.h"
|
||||
#include "cmMakefile.h"
|
||||
#include "cmMessageType.h"
|
||||
#include "cmOutputConverter.h"
|
||||
#include "cmPolicies.h"
|
||||
#include "cmStateTypes.h"
|
||||
#include "cmStringAlgorithms.h"
|
||||
#include "cmSystemTools.h"
|
||||
#include "cmTarget.h"
|
||||
#include "cmValue.h"
|
||||
#include "cmVersion.h"
|
||||
|
||||
static std::string cmExportFileGeneratorEscape(std::string const& str)
|
||||
{
|
||||
// Escape a property value for writing into a .cmake file.
|
||||
std::string result = cmOutputConverter::EscapeForCMake(str);
|
||||
// Un-escape variable references generated by our own export code.
|
||||
cmSystemTools::ReplaceString(result, "\\${_IMPORT_PREFIX}",
|
||||
"${_IMPORT_PREFIX}");
|
||||
cmSystemTools::ReplaceString(result, "\\${CMAKE_IMPORT_LIBRARY_SUFFIX}",
|
||||
"${CMAKE_IMPORT_LIBRARY_SUFFIX}");
|
||||
return result;
|
||||
}
|
||||
|
||||
cmExportCMakeConfigGenerator::cmExportCMakeConfigGenerator() = default;
|
||||
|
||||
cm::string_view cmExportCMakeConfigGenerator::GetImportPrefixWithSlash() const
|
||||
{
|
||||
return "${_IMPORT_PREFIX}/"_s;
|
||||
}
|
||||
|
||||
bool cmExportCMakeConfigGenerator::GenerateImportFile(std::ostream& os)
|
||||
{
|
||||
std::stringstream mainFileWithHeadersAndFootersBuffer;
|
||||
|
||||
// Start with the import file header.
|
||||
this->GenerateImportHeaderCode(mainFileWithHeadersAndFootersBuffer);
|
||||
|
||||
// Create all the imported targets.
|
||||
std::stringstream mainFileBuffer;
|
||||
bool result = this->GenerateMainFile(mainFileBuffer);
|
||||
|
||||
// Export find_dependency() calls. Must be done after GenerateMainFile(),
|
||||
// because that's when target dependencies are gathered, which we need for
|
||||
// the find_dependency() calls.
|
||||
if (!this->AppendMode && this->GetExportSet() &&
|
||||
this->ExportPackageDependencies) {
|
||||
this->SetRequiredCMakeVersion(3, 9, 0);
|
||||
this->GenerateFindDependencyCalls(mainFileWithHeadersAndFootersBuffer);
|
||||
}
|
||||
|
||||
// Write cached import code.
|
||||
mainFileWithHeadersAndFootersBuffer << mainFileBuffer.rdbuf();
|
||||
|
||||
// End with the import file footer.
|
||||
this->GenerateImportFooterCode(mainFileWithHeadersAndFootersBuffer);
|
||||
this->GeneratePolicyFooterCode(mainFileWithHeadersAndFootersBuffer);
|
||||
|
||||
// This has to be done last, after the minimum CMake version has been
|
||||
// determined.
|
||||
this->GeneratePolicyHeaderCode(os);
|
||||
os << mainFileWithHeadersAndFootersBuffer.rdbuf();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void cmExportCMakeConfigGenerator::GenerateInterfaceProperties(
|
||||
cmGeneratorTarget const* target, std::ostream& os,
|
||||
ImportPropertyMap const& properties)
|
||||
{
|
||||
if (!properties.empty()) {
|
||||
std::string targetName =
|
||||
cmStrCat(this->Namespace, target->GetExportName());
|
||||
os << "set_target_properties(" << targetName << " PROPERTIES\n";
|
||||
for (auto const& property : properties) {
|
||||
os << " " << property.first << " "
|
||||
<< cmExportFileGeneratorEscape(property.second) << "\n";
|
||||
}
|
||||
os << ")\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
void cmExportCMakeConfigGenerator::SetImportLinkInterface(
|
||||
std::string const& config, std::string const& suffix,
|
||||
cmGeneratorExpression::PreprocessContext preprocessRule,
|
||||
cmGeneratorTarget const* target, ImportPropertyMap& properties)
|
||||
{
|
||||
// Add the transitive link dependencies for this configuration.
|
||||
cmLinkInterface const* iface = target->GetLinkInterface(config, target);
|
||||
if (!iface) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (iface->ImplementationIsInterface) {
|
||||
// Policy CMP0022 must not be NEW.
|
||||
this->SetImportLinkProperty(
|
||||
suffix, target, "IMPORTED_LINK_INTERFACE_LIBRARIES", iface->Libraries,
|
||||
properties, ImportLinkPropertyTargetNames::Yes);
|
||||
return;
|
||||
}
|
||||
|
||||
cmValue propContent;
|
||||
|
||||
if (cmValue prop_suffixed =
|
||||
target->GetProperty("LINK_INTERFACE_LIBRARIES" + suffix)) {
|
||||
propContent = prop_suffixed;
|
||||
} else if (cmValue prop = target->GetProperty("LINK_INTERFACE_LIBRARIES")) {
|
||||
propContent = prop;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
bool const newCMP0022Behavior =
|
||||
target->GetPolicyStatusCMP0022() != cmPolicies::WARN &&
|
||||
target->GetPolicyStatusCMP0022() != cmPolicies::OLD;
|
||||
|
||||
if (newCMP0022Behavior && !this->ExportOld) {
|
||||
cmLocalGenerator* lg = target->GetLocalGenerator();
|
||||
std::ostringstream e;
|
||||
e << "Target \"" << target->GetName()
|
||||
<< "\" has policy CMP0022 enabled, "
|
||||
"but also has old-style LINK_INTERFACE_LIBRARIES properties "
|
||||
"populated, but it was exported without the "
|
||||
"EXPORT_LINK_INTERFACE_LIBRARIES to export the old-style properties";
|
||||
lg->IssueMessage(MessageType::FATAL_ERROR, e.str());
|
||||
return;
|
||||
}
|
||||
|
||||
if (propContent->empty()) {
|
||||
properties["IMPORTED_LINK_INTERFACE_LIBRARIES" + suffix].clear();
|
||||
return;
|
||||
}
|
||||
|
||||
std::string prepro =
|
||||
cmGeneratorExpression::Preprocess(*propContent, preprocessRule);
|
||||
if (!prepro.empty()) {
|
||||
this->ResolveTargetsInGeneratorExpressions(prepro, target,
|
||||
ReplaceFreeTargets);
|
||||
properties["IMPORTED_LINK_INTERFACE_LIBRARIES" + suffix] = prepro;
|
||||
}
|
||||
}
|
||||
|
||||
void cmExportCMakeConfigGenerator::GeneratePolicyHeaderCode(std::ostream& os)
|
||||
{
|
||||
// Protect that file against use with older CMake versions.
|
||||
/* clang-format off */
|
||||
os << "# Generated by CMake\n\n";
|
||||
os << "if(\"${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}\" LESS 2.8)\n"
|
||||
<< " message(FATAL_ERROR \"CMake >= "
|
||||
<< this->RequiredCMakeVersionMajor << '.'
|
||||
<< this->RequiredCMakeVersionMinor << '.'
|
||||
<< this->RequiredCMakeVersionPatch << " required\")\n"
|
||||
<< "endif()\n"
|
||||
<< "if(CMAKE_VERSION VERSION_LESS \""
|
||||
<< this->RequiredCMakeVersionMajor << '.'
|
||||
<< this->RequiredCMakeVersionMinor << '.'
|
||||
<< this->RequiredCMakeVersionPatch << "\")\n"
|
||||
<< " message(FATAL_ERROR \"CMake >= "
|
||||
<< this->RequiredCMakeVersionMajor << '.'
|
||||
<< this->RequiredCMakeVersionMinor << '.'
|
||||
<< this->RequiredCMakeVersionPatch << " required\")\n"
|
||||
<< "endif()\n";
|
||||
/* clang-format on */
|
||||
|
||||
// Isolate the file policy level.
|
||||
// Support CMake versions as far back as the
|
||||
// RequiredCMakeVersion{Major,Minor,Patch}, but also support using NEW
|
||||
// policy settings for up to CMake 3.29 (this upper limit may be reviewed
|
||||
// and increased from time to time). This reduces the opportunity for CMake
|
||||
// warnings when an older export file is later used with newer CMake
|
||||
// versions.
|
||||
/* clang-format off */
|
||||
os << "cmake_policy(PUSH)\n"
|
||||
<< "cmake_policy(VERSION "
|
||||
<< this->RequiredCMakeVersionMajor << '.'
|
||||
<< this->RequiredCMakeVersionMinor << '.'
|
||||
<< this->RequiredCMakeVersionPatch << "...3.29)\n";
|
||||
/* clang-format on */
|
||||
}
|
||||
|
||||
void cmExportCMakeConfigGenerator::GeneratePolicyFooterCode(std::ostream& os)
|
||||
{
|
||||
os << "cmake_policy(POP)\n";
|
||||
}
|
||||
|
||||
void cmExportCMakeConfigGenerator::GenerateImportHeaderCode(
|
||||
std::ostream& os, std::string const& config)
|
||||
{
|
||||
os << "#----------------------------------------------------------------\n"
|
||||
<< "# Generated CMake target import file";
|
||||
if (!config.empty()) {
|
||||
os << " for configuration \"" << config << "\".\n";
|
||||
} else {
|
||||
os << ".\n";
|
||||
}
|
||||
os << "#----------------------------------------------------------------\n"
|
||||
<< "\n";
|
||||
this->GenerateImportVersionCode(os);
|
||||
}
|
||||
|
||||
void cmExportCMakeConfigGenerator::GenerateImportFooterCode(std::ostream& os)
|
||||
{
|
||||
os << "# Commands beyond this point should not need to know the version.\n"
|
||||
<< "set(CMAKE_IMPORT_FILE_VERSION)\n";
|
||||
}
|
||||
|
||||
void cmExportCMakeConfigGenerator::GenerateImportVersionCode(std::ostream& os)
|
||||
{
|
||||
// Store an import file format version. This will let us change the
|
||||
// format later while still allowing old import files to work.
|
||||
/* clang-format off */
|
||||
os << "# Commands may need to know the format version.\n"
|
||||
<< "set(CMAKE_IMPORT_FILE_VERSION 1)\n"
|
||||
<< "\n";
|
||||
/* clang-format on */
|
||||
}
|
||||
|
||||
void cmExportCMakeConfigGenerator::GenerateExpectedTargetsCode(
|
||||
std::ostream& os, std::string const& expectedTargets)
|
||||
{
|
||||
/* clang-format off */
|
||||
os << "# Protect against multiple inclusion, which would fail when already "
|
||||
"imported targets are added once more.\n"
|
||||
"set(_cmake_targets_defined \"\")\n"
|
||||
"set(_cmake_targets_not_defined \"\")\n"
|
||||
"set(_cmake_expected_targets \"\")\n"
|
||||
"foreach(_cmake_expected_target IN ITEMS " << expectedTargets << ")\n"
|
||||
" list(APPEND _cmake_expected_targets \"${_cmake_expected_target}\")\n"
|
||||
" if(TARGET \"${_cmake_expected_target}\")\n"
|
||||
" list(APPEND _cmake_targets_defined \"${_cmake_expected_target}\")\n"
|
||||
" else()\n"
|
||||
" list(APPEND _cmake_targets_not_defined \"${_cmake_expected_target}\")\n"
|
||||
" endif()\n"
|
||||
"endforeach()\n"
|
||||
"unset(_cmake_expected_target)\n"
|
||||
"if(_cmake_targets_defined STREQUAL _cmake_expected_targets)\n"
|
||||
" unset(_cmake_targets_defined)\n"
|
||||
" unset(_cmake_targets_not_defined)\n"
|
||||
" unset(_cmake_expected_targets)\n"
|
||||
" unset(CMAKE_IMPORT_FILE_VERSION)\n"
|
||||
" cmake_policy(POP)\n"
|
||||
" return()\n"
|
||||
"endif()\n"
|
||||
"if(NOT _cmake_targets_defined STREQUAL \"\")\n"
|
||||
" string(REPLACE \";\" \", \" _cmake_targets_defined_text \"${_cmake_targets_defined}\")\n"
|
||||
" string(REPLACE \";\" \", \" _cmake_targets_not_defined_text \"${_cmake_targets_not_defined}\")\n"
|
||||
" message(FATAL_ERROR \"Some (but not all) targets in this export "
|
||||
"set were already defined.\\nTargets Defined: ${_cmake_targets_defined_text}\\n"
|
||||
"Targets not yet defined: ${_cmake_targets_not_defined_text}\\n\")\n"
|
||||
"endif()\n"
|
||||
"unset(_cmake_targets_defined)\n"
|
||||
"unset(_cmake_targets_not_defined)\n"
|
||||
"unset(_cmake_expected_targets)\n"
|
||||
"\n\n";
|
||||
/* clang-format on */
|
||||
}
|
||||
|
||||
void cmExportCMakeConfigGenerator::GenerateImportTargetCode(
|
||||
std::ostream& os, cmGeneratorTarget const* target,
|
||||
cmStateEnums::TargetType targetType)
|
||||
{
|
||||
// Construct the imported target name.
|
||||
std::string targetName = this->Namespace;
|
||||
|
||||
targetName += target->GetExportName();
|
||||
|
||||
// Create the imported target.
|
||||
os << "# Create imported target " << targetName << "\n";
|
||||
switch (targetType) {
|
||||
case cmStateEnums::EXECUTABLE:
|
||||
os << "add_executable(" << targetName << " IMPORTED)\n";
|
||||
break;
|
||||
case cmStateEnums::STATIC_LIBRARY:
|
||||
os << "add_library(" << targetName << " STATIC IMPORTED)\n";
|
||||
break;
|
||||
case cmStateEnums::SHARED_LIBRARY:
|
||||
os << "add_library(" << targetName << " SHARED IMPORTED)\n";
|
||||
break;
|
||||
case cmStateEnums::MODULE_LIBRARY:
|
||||
os << "add_library(" << targetName << " MODULE IMPORTED)\n";
|
||||
break;
|
||||
case cmStateEnums::UNKNOWN_LIBRARY:
|
||||
os << "add_library(" << targetName << " UNKNOWN IMPORTED)\n";
|
||||
break;
|
||||
case cmStateEnums::OBJECT_LIBRARY:
|
||||
os << "add_library(" << targetName << " OBJECT IMPORTED)\n";
|
||||
break;
|
||||
case cmStateEnums::INTERFACE_LIBRARY:
|
||||
os << "add_library(" << targetName << " INTERFACE IMPORTED)\n";
|
||||
break;
|
||||
default: // should never happen
|
||||
break;
|
||||
}
|
||||
|
||||
// Mark the imported executable if it has exports.
|
||||
if (target->IsExecutableWithExports() ||
|
||||
(target->IsSharedLibraryWithExports() && target->HasImportLibrary(""))) {
|
||||
os << "set_property(TARGET " << targetName
|
||||
<< " PROPERTY ENABLE_EXPORTS 1)\n";
|
||||
}
|
||||
|
||||
// Mark the imported library if it is a framework.
|
||||
if (target->IsFrameworkOnApple()) {
|
||||
os << "set_property(TARGET " << targetName << " PROPERTY FRAMEWORK 1)\n";
|
||||
}
|
||||
|
||||
// Mark the imported executable if it is an application bundle.
|
||||
if (target->IsAppBundleOnApple()) {
|
||||
os << "set_property(TARGET " << targetName
|
||||
<< " PROPERTY MACOSX_BUNDLE 1)\n";
|
||||
}
|
||||
|
||||
if (target->IsCFBundleOnApple()) {
|
||||
os << "set_property(TARGET " << targetName << " PROPERTY BUNDLE 1)\n";
|
||||
}
|
||||
|
||||
// generate DEPRECATION
|
||||
if (target->IsDeprecated()) {
|
||||
os << "set_property(TARGET " << targetName << " PROPERTY DEPRECATION "
|
||||
<< cmExportFileGeneratorEscape(target->GetDeprecation()) << ")\n";
|
||||
}
|
||||
|
||||
if (target->GetPropertyAsBool("IMPORTED_NO_SYSTEM")) {
|
||||
os << "set_property(TARGET " << targetName
|
||||
<< " PROPERTY IMPORTED_NO_SYSTEM 1)\n";
|
||||
}
|
||||
|
||||
if (target->GetPropertyAsBool("EXPORT_NO_SYSTEM")) {
|
||||
os << "set_property(TARGET " << targetName << " PROPERTY SYSTEM 0)\n";
|
||||
}
|
||||
|
||||
os << "\n";
|
||||
}
|
||||
|
||||
void cmExportCMakeConfigGenerator::GenerateImportPropertyCode(
|
||||
std::ostream& os, std::string const& config, std::string const& suffix,
|
||||
cmGeneratorTarget const* target, ImportPropertyMap const& properties,
|
||||
std::string const& importedXcFrameworkLocation)
|
||||
{
|
||||
// Construct the imported target name.
|
||||
std::string targetName = this->Namespace;
|
||||
|
||||
targetName += target->GetExportName();
|
||||
|
||||
// Set the import properties.
|
||||
os << "# Import target \"" << targetName << "\" for configuration \""
|
||||
<< config << "\"\n";
|
||||
os << "set_property(TARGET " << targetName
|
||||
<< " APPEND PROPERTY IMPORTED_CONFIGURATIONS ";
|
||||
if (!config.empty()) {
|
||||
os << cmSystemTools::UpperCase(config);
|
||||
} else {
|
||||
os << "NOCONFIG";
|
||||
}
|
||||
os << ")\n";
|
||||
os << "set_target_properties(" << targetName << " PROPERTIES\n";
|
||||
std::string importedLocationProp = cmStrCat("IMPORTED_LOCATION", suffix);
|
||||
for (auto const& property : properties) {
|
||||
if (importedXcFrameworkLocation.empty() ||
|
||||
property.first != importedLocationProp) {
|
||||
os << " " << property.first << " "
|
||||
<< cmExportFileGeneratorEscape(property.second) << "\n";
|
||||
}
|
||||
}
|
||||
os << " )\n";
|
||||
if (!importedXcFrameworkLocation.empty()) {
|
||||
auto importedLocationIt = properties.find(importedLocationProp);
|
||||
if (importedLocationIt != properties.end()) {
|
||||
os << "if(NOT CMAKE_VERSION VERSION_LESS \"3.28\" AND IS_DIRECTORY "
|
||||
<< cmExportFileGeneratorEscape(importedXcFrameworkLocation)
|
||||
<< ")\n"
|
||||
" set_property(TARGET "
|
||||
<< targetName << " PROPERTY " << importedLocationProp << " "
|
||||
<< cmExportFileGeneratorEscape(importedXcFrameworkLocation)
|
||||
<< ")\nelse()\n set_property(TARGET " << targetName << " PROPERTY "
|
||||
<< importedLocationProp << " "
|
||||
<< cmExportFileGeneratorEscape(importedLocationIt->second)
|
||||
<< ")\nendif()\n";
|
||||
}
|
||||
}
|
||||
os << "\n";
|
||||
}
|
||||
|
||||
void cmExportCMakeConfigGenerator::GenerateFindDependencyCalls(
|
||||
std::ostream& os)
|
||||
{
|
||||
os << "include(CMakeFindDependencyMacro)\n";
|
||||
std::map<std::string, cmExportSet::PackageDependency> packageDependencies;
|
||||
auto* exportSet = this->GetExportSet();
|
||||
if (exportSet) {
|
||||
packageDependencies = exportSet->GetPackageDependencies();
|
||||
}
|
||||
|
||||
for (cmGeneratorTarget const* gt : this->ExternalTargets) {
|
||||
std::string findPackageName;
|
||||
auto exportFindPackageName = gt->GetProperty("EXPORT_FIND_PACKAGE_NAME");
|
||||
cmFindPackageStack pkgStack = gt->Target->GetFindPackageStack();
|
||||
if (!exportFindPackageName.IsEmpty()) {
|
||||
findPackageName = *exportFindPackageName;
|
||||
} else {
|
||||
if (!pkgStack.Empty()) {
|
||||
cmFindPackageCall const& fpc = pkgStack.Top();
|
||||
findPackageName = fpc.Name;
|
||||
}
|
||||
}
|
||||
if (!findPackageName.empty()) {
|
||||
auto& dep = packageDependencies[findPackageName];
|
||||
if (!pkgStack.Empty()) {
|
||||
dep.FindPackageIndex = pkgStack.Top().Index;
|
||||
}
|
||||
if (dep.Enabled == cmExportSet::PackageDependencyExportEnabled::Auto) {
|
||||
dep.Enabled = cmExportSet::PackageDependencyExportEnabled::On;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::pair<std::string, cmExportSet::PackageDependency>>
|
||||
packageDependenciesSorted(packageDependencies.begin(),
|
||||
packageDependencies.end());
|
||||
std::sort(
|
||||
packageDependenciesSorted.begin(), packageDependenciesSorted.end(),
|
||||
[](std::pair<std::string, cmExportSet::PackageDependency> const& lhs,
|
||||
std::pair<std::string, cmExportSet::PackageDependency> const& rhs)
|
||||
-> bool {
|
||||
if (lhs.second.SpecifiedIndex) {
|
||||
if (rhs.second.SpecifiedIndex) {
|
||||
return lhs.second.SpecifiedIndex < rhs.second.SpecifiedIndex;
|
||||
}
|
||||
assert(rhs.second.FindPackageIndex);
|
||||
return true;
|
||||
}
|
||||
assert(lhs.second.FindPackageIndex);
|
||||
if (rhs.second.SpecifiedIndex) {
|
||||
return false;
|
||||
}
|
||||
assert(rhs.second.FindPackageIndex);
|
||||
return lhs.second.FindPackageIndex < rhs.second.FindPackageIndex;
|
||||
});
|
||||
|
||||
for (auto const& it : packageDependenciesSorted) {
|
||||
if (it.second.Enabled == cmExportSet::PackageDependencyExportEnabled::On) {
|
||||
os << "find_dependency(" << it.first;
|
||||
for (auto const& arg : it.second.ExtraArguments) {
|
||||
os << " " << cmOutputConverter::EscapeForCMake(arg);
|
||||
}
|
||||
os << ")\n";
|
||||
}
|
||||
}
|
||||
os << "\n\n";
|
||||
}
|
||||
|
||||
void cmExportCMakeConfigGenerator::GenerateMissingTargetsCheckCode(
|
||||
std::ostream& os)
|
||||
{
|
||||
if (this->MissingTargets.empty()) {
|
||||
/* clang-format off */
|
||||
os << "# This file does not depend on other imported targets which have\n"
|
||||
"# been exported from the same project but in a separate "
|
||||
"export set.\n\n";
|
||||
/* clang-format on */
|
||||
return;
|
||||
}
|
||||
/* clang-format off */
|
||||
os << "# Make sure the targets which have been exported in some other\n"
|
||||
"# export set exist.\n"
|
||||
"unset(${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets)\n"
|
||||
"foreach(_target ";
|
||||
/* clang-format on */
|
||||
std::set<std::string> emitted;
|
||||
for (std::string const& missingTarget : this->MissingTargets) {
|
||||
if (emitted.insert(missingTarget).second) {
|
||||
os << "\"" << missingTarget << "\" ";
|
||||
}
|
||||
}
|
||||
/* clang-format off */
|
||||
os << ")\n"
|
||||
" if(NOT TARGET \"${_target}\" )\n"
|
||||
" set(${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets \""
|
||||
"${${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets} ${_target}\")"
|
||||
"\n"
|
||||
" endif()\n"
|
||||
"endforeach()\n"
|
||||
"\n"
|
||||
"if(DEFINED ${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets)\n"
|
||||
" if(CMAKE_FIND_PACKAGE_NAME)\n"
|
||||
" set( ${CMAKE_FIND_PACKAGE_NAME}_FOUND FALSE)\n"
|
||||
" set( ${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE "
|
||||
"\"The following imported targets are "
|
||||
"referenced, but are missing: "
|
||||
"${${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets}\")\n"
|
||||
" else()\n"
|
||||
" message(FATAL_ERROR \"The following imported targets are "
|
||||
"referenced, but are missing: "
|
||||
"${${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets}\")\n"
|
||||
" endif()\n"
|
||||
"endif()\n"
|
||||
"unset(${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets)\n"
|
||||
"\n";
|
||||
/* clang-format on */
|
||||
}
|
||||
|
||||
void cmExportCMakeConfigGenerator::GenerateImportedFileCheckLoop(
|
||||
std::ostream& os)
|
||||
{
|
||||
// Add code which verifies at cmake time that the file which is being
|
||||
// imported actually exists on disk. This should in theory always be theory
|
||||
// case, but still when packages are split into normal and development
|
||||
// packages this might get broken (e.g. the Config.cmake could be part of
|
||||
// the non-development package, something similar happened to me without
|
||||
// on SUSE with a mysql pkg-config file, which claimed everything is fine,
|
||||
// but the development package was not installed.).
|
||||
/* clang-format off */
|
||||
os << "# Loop over all imported files and verify that they actually exist\n"
|
||||
"foreach(_cmake_target IN LISTS _cmake_import_check_targets)\n"
|
||||
" if(CMAKE_VERSION VERSION_LESS \"3.28\"\n"
|
||||
" OR NOT DEFINED "
|
||||
"_cmake_import_check_xcframework_for_${_cmake_target}\n"
|
||||
" OR NOT IS_DIRECTORY "
|
||||
"\"${_cmake_import_check_xcframework_for_${_cmake_target}}\")\n"
|
||||
" foreach(_cmake_file IN LISTS "
|
||||
"\"_cmake_import_check_files_for_${_cmake_target}\")\n"
|
||||
" if(NOT EXISTS \"${_cmake_file}\")\n"
|
||||
" message(FATAL_ERROR \"The imported target "
|
||||
"\\\"${_cmake_target}\\\" references the file\n"
|
||||
" \\\"${_cmake_file}\\\"\n"
|
||||
"but this file does not exist. Possible reasons include:\n"
|
||||
"* The file was deleted, renamed, or moved to another location.\n"
|
||||
"* An install or uninstall procedure did not complete successfully.\n"
|
||||
"* The installation package was faulty and contained\n"
|
||||
" \\\"${CMAKE_CURRENT_LIST_FILE}\\\"\n"
|
||||
"but not all the files it references.\n"
|
||||
"\")\n"
|
||||
" endif()\n"
|
||||
" endforeach()\n"
|
||||
" endif()\n"
|
||||
" unset(_cmake_file)\n"
|
||||
" unset(\"_cmake_import_check_files_for_${_cmake_target}\")\n"
|
||||
"endforeach()\n"
|
||||
"unset(_cmake_target)\n"
|
||||
"unset(_cmake_import_check_targets)\n"
|
||||
"\n";
|
||||
/* clang-format on */
|
||||
}
|
||||
|
||||
void cmExportCMakeConfigGenerator::GenerateImportedFileChecksCode(
|
||||
std::ostream& os, cmGeneratorTarget const* target,
|
||||
ImportPropertyMap const& properties,
|
||||
std::set<std::string> const& importedLocations,
|
||||
std::string const& importedXcFrameworkLocation)
|
||||
{
|
||||
// Construct the imported target name.
|
||||
std::string targetName = cmStrCat(this->Namespace, target->GetExportName());
|
||||
|
||||
os << "list(APPEND _cmake_import_check_targets " << targetName << " )\n";
|
||||
if (!importedXcFrameworkLocation.empty()) {
|
||||
os << "set(_cmake_import_check_xcframework_for_" << targetName << ' '
|
||||
<< cmExportFileGeneratorEscape(importedXcFrameworkLocation) << ")\n";
|
||||
}
|
||||
os << "list(APPEND _cmake_import_check_files_for_" << targetName << " ";
|
||||
|
||||
for (std::string const& li : importedLocations) {
|
||||
auto pi = properties.find(li);
|
||||
if (pi != properties.end()) {
|
||||
os << cmExportFileGeneratorEscape(pi->second) << " ";
|
||||
}
|
||||
}
|
||||
|
||||
os << ")\n\n";
|
||||
}
|
||||
|
||||
void cmExportCMakeConfigGenerator::GenerateTargetFileSets(
|
||||
cmGeneratorTarget* gte, std::ostream& os, cmTargetExport const* te)
|
||||
{
|
||||
auto interfaceFileSets = gte->Target->GetAllInterfaceFileSets();
|
||||
if (!interfaceFileSets.empty()) {
|
||||
std::string targetName = cmStrCat(this->Namespace, gte->GetExportName());
|
||||
os << "if(NOT CMAKE_VERSION VERSION_LESS \"3.23.0\")\n"
|
||||
" target_sources("
|
||||
<< targetName << "\n";
|
||||
|
||||
for (auto const& name : interfaceFileSets) {
|
||||
auto* fileSet = gte->Target->GetFileSet(name);
|
||||
if (!fileSet) {
|
||||
gte->Makefile->IssueMessage(
|
||||
MessageType::FATAL_ERROR,
|
||||
cmStrCat("File set \"", name,
|
||||
"\" is listed in interface file sets of ", gte->GetName(),
|
||||
" but has not been created"));
|
||||
return;
|
||||
}
|
||||
|
||||
os << " INTERFACE"
|
||||
<< "\n FILE_SET " << cmOutputConverter::EscapeForCMake(name)
|
||||
<< "\n TYPE "
|
||||
<< cmOutputConverter::EscapeForCMake(fileSet->GetType())
|
||||
<< "\n BASE_DIRS "
|
||||
<< this->GetFileSetDirectories(gte, fileSet, te) << "\n FILES "
|
||||
<< this->GetFileSetFiles(gte, fileSet, te) << "\n";
|
||||
}
|
||||
|
||||
os << " )\nelse()\n set_property(TARGET " << targetName
|
||||
<< "\n APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES";
|
||||
for (auto const& name : interfaceFileSets) {
|
||||
auto* fileSet = gte->Target->GetFileSet(name);
|
||||
if (!fileSet) {
|
||||
gte->Makefile->IssueMessage(
|
||||
MessageType::FATAL_ERROR,
|
||||
cmStrCat("File set \"", name,
|
||||
"\" is listed in interface file sets of ", gte->GetName(),
|
||||
" but has not been created"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (fileSet->GetType() == "HEADERS"_s) {
|
||||
os << "\n " << this->GetFileSetDirectories(gte, fileSet, te);
|
||||
}
|
||||
}
|
||||
os << "\n )\nendif()\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
std::string cmExportCMakeConfigGenerator::GetCxxModuleFile(
|
||||
std::string const& name) const
|
||||
{
|
||||
auto const& cxxModuleDirname = this->GetCxxModulesDirectory();
|
||||
if (cxxModuleDirname.empty()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return cmStrCat(cmSystemTools::GetFilenamePath(this->MainImportFile), '/',
|
||||
cxxModuleDirname, "/cxx-modules-", name, ".cmake");
|
||||
}
|
||||
|
||||
void cmExportCMakeConfigGenerator::GenerateCxxModuleInformation(
|
||||
std::string const& name, std::ostream& os)
|
||||
{
|
||||
auto const cxx_module_dirname = this->GetCxxModulesDirectory();
|
||||
if (cxx_module_dirname.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Write the include.
|
||||
os << "# Include C++ module properties\n"
|
||||
<< "include(\"${CMAKE_CURRENT_LIST_DIR}/" << cxx_module_dirname
|
||||
<< "/cxx-modules-" << name << ".cmake\")\n\n";
|
||||
|
||||
// Include all configuration-specific include files.
|
||||
cmGeneratedFileStream ap(this->GetCxxModuleFile(name), true);
|
||||
ap.SetCopyIfDifferent(true);
|
||||
|
||||
this->GenerateCxxModuleConfigInformation(name, ap);
|
||||
}
|
||||
|
||||
void cmExportCMakeConfigGenerator::SetRequiredCMakeVersion(unsigned int major,
|
||||
unsigned int minor,
|
||||
unsigned int patch)
|
||||
{
|
||||
if (CMake_VERSION_ENCODE(major, minor, patch) >
|
||||
CMake_VERSION_ENCODE(this->RequiredCMakeVersionMajor,
|
||||
this->RequiredCMakeVersionMinor,
|
||||
this->RequiredCMakeVersionPatch)) {
|
||||
this->RequiredCMakeVersionMajor = major;
|
||||
this->RequiredCMakeVersionMinor = minor;
|
||||
this->RequiredCMakeVersionPatch = patch;
|
||||
}
|
||||
}
|
||||
109
Source/cmExportCMakeConfigGenerator.h
Normal file
109
Source/cmExportCMakeConfigGenerator.h
Normal file
@@ -0,0 +1,109 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
#pragma once
|
||||
|
||||
#include "cmConfigure.h" // IWYU pragma: keep
|
||||
|
||||
#include <iosfwd>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
#include <cm/string_view>
|
||||
|
||||
#include "cmExportFileGenerator.h"
|
||||
#include "cmGeneratorExpression.h"
|
||||
#include "cmStateTypes.h"
|
||||
|
||||
class cmFileSet;
|
||||
class cmGeneratorTarget;
|
||||
class cmTargetExport;
|
||||
|
||||
/** \class cmExportCMakeConfigGenerator
|
||||
* \brief Generate CMake configuration files exporting targets from a build or
|
||||
* install tree.
|
||||
*
|
||||
* cmExportCMakeConfigGenerator is the superclass for
|
||||
* cmExportBuildCMakeConfigGenerator and cmExportInstallCMakeConfigGenerator.
|
||||
* It contains common code generation routines for the two kinds of export
|
||||
* implementations.
|
||||
*/
|
||||
class cmExportCMakeConfigGenerator : virtual public cmExportFileGenerator
|
||||
{
|
||||
public:
|
||||
cmExportCMakeConfigGenerator();
|
||||
|
||||
void SetExportOld(bool exportOld) { this->ExportOld = exportOld; }
|
||||
|
||||
void SetExportPackageDependencies(bool exportPackageDependencies)
|
||||
{
|
||||
this->ExportPackageDependencies = exportPackageDependencies;
|
||||
}
|
||||
|
||||
using cmExportFileGenerator::GenerateImportFile;
|
||||
|
||||
protected:
|
||||
using ImportPropertyMap = std::map<std::string, std::string>;
|
||||
|
||||
// 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,
|
||||
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 const* 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);
|
||||
|
||||
cm::string_view GetImportPrefixWithSlash() const override;
|
||||
|
||||
virtual void GenerateInterfaceProperties(
|
||||
cmGeneratorTarget const* target, std::ostream& os,
|
||||
ImportPropertyMap const& properties);
|
||||
|
||||
void SetImportLinkInterface(
|
||||
std::string const& config, std::string const& suffix,
|
||||
cmGeneratorExpression::PreprocessContext preprocessRule,
|
||||
cmGeneratorTarget const* target, ImportPropertyMap& properties);
|
||||
|
||||
void GenerateTargetFileSets(cmGeneratorTarget* gte, std::ostream& os,
|
||||
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 const* te) = 0;
|
||||
virtual std::string GetFileSetFiles(cmGeneratorTarget* gte,
|
||||
cmFileSet* fileSet,
|
||||
cmTargetExport const* te) = 0;
|
||||
|
||||
void SetRequiredCMakeVersion(unsigned int major, unsigned int minor,
|
||||
unsigned int patch);
|
||||
|
||||
bool ExportOld = false;
|
||||
bool ExportPackageDependencies = false;
|
||||
|
||||
unsigned int RequiredCMakeVersionMajor = 2;
|
||||
unsigned int RequiredCMakeVersionMinor = 8;
|
||||
unsigned int RequiredCMakeVersionPatch = 3;
|
||||
};
|
||||
@@ -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
@@ -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
|
||||
{
|
||||
@@ -46,65 +40,28 @@ public:
|
||||
virtual ~cmExportFileGenerator() = default;
|
||||
|
||||
/** Set the full path to the export file to generate. */
|
||||
void SetExportFile(const char* mainFile);
|
||||
const std::string& GetMainExportFileName() const;
|
||||
void SetExportFile(char const* mainFile);
|
||||
std::string const& GetMainExportFileName() const;
|
||||
|
||||
/** Set the namespace in which to place exported target names. */
|
||||
void SetNamespace(const std::string& ns) { this->Namespace = ns; }
|
||||
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(const std::string& config);
|
||||
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, const std::string& 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,
|
||||
const std::string& 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, const std::string& config, const std::string& suffix,
|
||||
cmGeneratorTarget const* target, ImportPropertyMap const& properties,
|
||||
const std::string& importedXcFrameworkLocation);
|
||||
virtual void GenerateImportedFileChecksCode(
|
||||
std::ostream& os, cmGeneratorTarget* target,
|
||||
ImportPropertyMap const& properties,
|
||||
const std::set<std::string>& importedLocations,
|
||||
const std::string& 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,
|
||||
const std::string& expectedTargets);
|
||||
|
||||
// Collect properties with detailed information about targets beyond
|
||||
// their location on disk.
|
||||
void SetImportDetailProperties(const std::string& config,
|
||||
void SetImportDetailProperties(std::string const& config,
|
||||
std::string const& suffix,
|
||||
cmGeneratorTarget* target,
|
||||
cmGeneratorTarget const* target,
|
||||
ImportPropertyMap& properties);
|
||||
|
||||
enum class ImportLinkPropertyTargetNames
|
||||
@@ -115,17 +72,25 @@ protected:
|
||||
template <typename T>
|
||||
void SetImportLinkProperty(std::string const& suffix,
|
||||
cmGeneratorTarget const* target,
|
||||
const std::string& propName,
|
||||
std::string const& propName,
|
||||
std::vector<T> const& entries,
|
||||
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,
|
||||
const std::string& config,
|
||||
std::string const& config,
|
||||
std::string const& suffix) = 0;
|
||||
|
||||
/** Each subclass knows how to deal with a target that is missing from an
|
||||
@@ -133,47 +98,33 @@ protected:
|
||||
virtual void HandleMissingTarget(std::string& link_libs,
|
||||
cmGeneratorTarget const* depender,
|
||||
cmGeneratorTarget* dependee) = 0;
|
||||
void PopulateInterfaceProperty(const std::string&,
|
||||
|
||||
/** 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(const std::string& 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,
|
||||
const 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(
|
||||
|
||||
bool PopulateInterfaceProperties(
|
||||
cmGeneratorTarget const* target,
|
||||
std::string const& includesDestinationDirs,
|
||||
cmGeneratorExpression::PreprocessContext preprocessRule,
|
||||
ImportPropertyMap& properties);
|
||||
|
||||
void SetImportLinkInterface(
|
||||
const std::string& 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,36 +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; }
|
||||
|
||||
void SetRequiredCMakeVersion(unsigned int major, unsigned int minor,
|
||||
unsigned int patch);
|
||||
virtual void ReplaceInstallPrefix(std::string& input) const;
|
||||
|
||||
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;
|
||||
|
||||
@@ -223,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(const std::string&, const std::string&,
|
||||
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,
|
||||
const std::string& 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);
|
||||
|
||||
@@ -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,8 +25,55 @@ 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, const std::string&)
|
||||
std::ostream& os, std::string const&)
|
||||
{
|
||||
std::string installDir = this->IEGen->GetDestination();
|
||||
os << "LOCAL_PATH := $(call my-dir)\n";
|
||||
@@ -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&, const std::string&)
|
||||
{
|
||||
}
|
||||
|
||||
void cmExportInstallAndroidMKGenerator::GenerateImportPropertyCode(
|
||||
std::ostream&, const std::string&, const std::string&,
|
||||
cmGeneratorTarget const*, ImportPropertyMap const&, const std::string&)
|
||||
{
|
||||
}
|
||||
|
||||
void cmExportInstallAndroidMKGenerator::GenerateMissingTargetsCheckCode(
|
||||
std::ostream&)
|
||||
{
|
||||
}
|
||||
|
||||
void cmExportInstallAndroidMKGenerator::GenerateInterfaceProperties(
|
||||
cmGeneratorTarget const* target, std::ostream& os,
|
||||
const ImportPropertyMap& 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&,
|
||||
const std::set<std::string>&, const std::string&)
|
||||
{
|
||||
}
|
||||
|
||||
bool cmExportInstallAndroidMKGenerator::GenerateImportFileConfig(
|
||||
const std::string&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
const std::string& config = "") override;
|
||||
void GenerateImportFooterCode(std::ostream& os) override;
|
||||
std::string const& config = "") override;
|
||||
void GenerateImportTargetCode(
|
||||
std::ostream& os, cmGeneratorTarget const* target,
|
||||
cmStateEnums::TargetType /*targetType*/) override;
|
||||
void GenerateExpectedTargetsCode(
|
||||
std::ostream& os, const std::string& expectedTargets) override;
|
||||
void GenerateImportPropertyCode(
|
||||
std::ostream& os, const std::string& config, const std::string& suffix,
|
||||
cmGeneratorTarget const* target, ImportPropertyMap const& properties,
|
||||
const std::string& importedXcFrameworkLocation) override;
|
||||
void GenerateMissingTargetsCheckCode(std::ostream& os) override;
|
||||
void GenerateFindDependencyCalls(std::ostream&) override {}
|
||||
void GenerateInterfaceProperties(
|
||||
cmGeneratorTarget const* target, std::ostream& os,
|
||||
const ImportPropertyMap& properties) override;
|
||||
void GenerateImportPrefix(std::ostream& os) override;
|
||||
void LoadConfigFiles(std::ostream&) override;
|
||||
void CleanupTemporaryVariables(std::ostream&) override;
|
||||
void GenerateImportedFileCheckLoop(std::ostream& os) override;
|
||||
void GenerateImportedFileChecksCode(
|
||||
std::ostream& os, cmGeneratorTarget* target,
|
||||
ImportPropertyMap const& properties,
|
||||
const std::set<std::string>& importedLocations,
|
||||
const std::string& importedXcFrameworkLocation) override;
|
||||
bool GenerateImportFileConfig(const std::string& 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 {}; }
|
||||
};
|
||||
|
||||
507
Source/cmExportInstallCMakeConfigGenerator.cxx
Normal file
507
Source/cmExportInstallCMakeConfigGenerator.cxx
Normal file
@@ -0,0 +1,507 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
#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>
|
||||
|
||||
#include "cmExportSet.h"
|
||||
#include "cmFileSet.h"
|
||||
#include "cmGeneratedFileStream.h"
|
||||
#include "cmGeneratorExpression.h"
|
||||
#include "cmGeneratorTarget.h"
|
||||
#include "cmInstallExportGenerator.h"
|
||||
#include "cmInstallFileSetGenerator.h"
|
||||
#include "cmLocalGenerator.h"
|
||||
#include "cmMakefile.h"
|
||||
#include "cmMessageType.h"
|
||||
#include "cmOutputConverter.h"
|
||||
#include "cmPolicies.h"
|
||||
#include "cmStateTypes.h"
|
||||
#include "cmStringAlgorithms.h"
|
||||
#include "cmSystemTools.h"
|
||||
#include "cmTargetExport.h"
|
||||
#include "cmValue.h"
|
||||
|
||||
cmExportInstallCMakeConfigGenerator::cmExportInstallCMakeConfigGenerator(
|
||||
cmInstallExportGenerator* iegen)
|
||||
: cmExportInstallFileGenerator(iegen)
|
||||
{
|
||||
}
|
||||
|
||||
std::string cmExportInstallCMakeConfigGenerator::GetConfigImportFileGlob()
|
||||
const
|
||||
{
|
||||
std::string glob = cmStrCat(this->FileBase, "-*", this->FileExt);
|
||||
return glob;
|
||||
}
|
||||
|
||||
bool cmExportInstallCMakeConfigGenerator::GenerateMainFile(std::ostream& os)
|
||||
{
|
||||
std::vector<cmTargetExport const*> allTargets;
|
||||
{
|
||||
std::string expectedTargets;
|
||||
std::string sep;
|
||||
auto visitor = [&](cmTargetExport const* te) {
|
||||
allTargets.push_back(te);
|
||||
expectedTargets += sep + this->Namespace + te->Target->GetExportName();
|
||||
sep = " ";
|
||||
};
|
||||
|
||||
if (!this->CollectExports(visitor)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this->GenerateExpectedTargetsCode(os, expectedTargets);
|
||||
}
|
||||
|
||||
// Compute the relative import prefix for the file
|
||||
this->GenerateImportPrefix(os);
|
||||
|
||||
bool requiresConfigFiles = false;
|
||||
// Create all the imported targets.
|
||||
for (cmTargetExport const* te : allTargets) {
|
||||
cmGeneratorTarget* gt = te->Target;
|
||||
cmStateEnums::TargetType targetType = this->GetExportTargetType(te);
|
||||
|
||||
requiresConfigFiles =
|
||||
requiresConfigFiles || targetType != cmStateEnums::INTERFACE_LIBRARY;
|
||||
|
||||
this->GenerateImportTargetCode(os, gt, targetType);
|
||||
|
||||
ImportPropertyMap properties;
|
||||
if (!this->PopulateInterfaceProperties(te, properties)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool const newCMP0022Behavior =
|
||||
gt->GetPolicyStatusCMP0022() != cmPolicies::WARN &&
|
||||
gt->GetPolicyStatusCMP0022() != cmPolicies::OLD;
|
||||
if (newCMP0022Behavior) {
|
||||
if (this->PopulateInterfaceLinkLibrariesProperty(
|
||||
gt, cmGeneratorExpression::InstallInterface, properties) &&
|
||||
!this->ExportOld) {
|
||||
this->SetRequiredCMakeVersion(2, 8, 12);
|
||||
}
|
||||
}
|
||||
if (targetType == cmStateEnums::INTERFACE_LIBRARY) {
|
||||
this->SetRequiredCMakeVersion(3, 0, 0);
|
||||
}
|
||||
if (gt->GetProperty("INTERFACE_SOURCES")) {
|
||||
// We can only generate INTERFACE_SOURCES in CMake 3.3, but CMake 3.1
|
||||
// can consume them.
|
||||
this->SetRequiredCMakeVersion(3, 1, 0);
|
||||
}
|
||||
|
||||
this->GenerateInterfaceProperties(gt, os, properties);
|
||||
|
||||
this->GenerateTargetFileSets(gt, os, te);
|
||||
}
|
||||
|
||||
this->LoadConfigFiles(os);
|
||||
|
||||
bool result = true;
|
||||
|
||||
std::string cxx_modules_name = this->GetExportSet()->GetName();
|
||||
this->GenerateCxxModuleInformation(cxx_modules_name, os);
|
||||
if (requiresConfigFiles) {
|
||||
for (std::string const& c : this->Configurations) {
|
||||
if (!this->GenerateImportCxxModuleConfigTargetInclusion(cxx_modules_name,
|
||||
c)) {
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this->CleanupTemporaryVariables(os);
|
||||
this->GenerateImportedFileCheckLoop(os);
|
||||
|
||||
// Generate an import file for each configuration.
|
||||
// Don't do this if we only export INTERFACE_LIBRARY targets.
|
||||
if (requiresConfigFiles) {
|
||||
for (std::string const& c : this->Configurations) {
|
||||
if (!this->GenerateImportFileConfig(c)) {
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this->GenerateMissingTargetsCheckCode(os);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void cmExportInstallCMakeConfigGenerator::GenerateImportPrefix(
|
||||
std::ostream& os)
|
||||
{
|
||||
// Set an _IMPORT_PREFIX variable for import location properties
|
||||
// to reference if they are relative to the install prefix.
|
||||
std::string installPrefix =
|
||||
this->IEGen->GetLocalGenerator()->GetMakefile()->GetSafeDefinition(
|
||||
"CMAKE_INSTALL_PREFIX");
|
||||
std::string const& expDest = this->IEGen->GetDestination();
|
||||
if (cmSystemTools::FileIsFullPath(expDest)) {
|
||||
// The export file is being installed to an absolute path so the
|
||||
// package is not relocatable. Use the configured install prefix.
|
||||
/* clang-format off */
|
||||
os <<
|
||||
"# The installation prefix configured by this project.\n"
|
||||
"set(_IMPORT_PREFIX \"" << installPrefix << "\")\n"
|
||||
"\n";
|
||||
/* clang-format on */
|
||||
} else {
|
||||
// Add code to compute the installation prefix relative to the
|
||||
// import file location.
|
||||
std::string absDest = installPrefix + "/" + expDest;
|
||||
std::string absDestS = absDest + "/";
|
||||
os << "# Compute the installation prefix relative to this file.\n"
|
||||
<< "get_filename_component(_IMPORT_PREFIX"
|
||||
<< " \"${CMAKE_CURRENT_LIST_FILE}\" PATH)\n";
|
||||
if (cmHasLiteralPrefix(absDestS, "/lib/") ||
|
||||
cmHasLiteralPrefix(absDestS, "/lib64/") ||
|
||||
cmHasLiteralPrefix(absDestS, "/libx32/") ||
|
||||
cmHasLiteralPrefix(absDestS, "/usr/lib/") ||
|
||||
cmHasLiteralPrefix(absDestS, "/usr/lib64/") ||
|
||||
cmHasLiteralPrefix(absDestS, "/usr/libx32/")) {
|
||||
// Handle "/usr move" symlinks created by some Linux distros.
|
||||
/* clang-format off */
|
||||
os <<
|
||||
"# Use original install prefix when loaded through a\n"
|
||||
"# cross-prefix symbolic link such as /lib -> /usr/lib.\n"
|
||||
"get_filename_component(_realCurr \"${_IMPORT_PREFIX}\" REALPATH)\n"
|
||||
"get_filename_component(_realOrig \"" << absDest << "\" REALPATH)\n"
|
||||
"if(_realCurr STREQUAL _realOrig)\n"
|
||||
" set(_IMPORT_PREFIX \"" << absDest << "\")\n"
|
||||
"endif()\n"
|
||||
"unset(_realOrig)\n"
|
||||
"unset(_realCurr)\n";
|
||||
/* clang-format on */
|
||||
}
|
||||
std::string dest = expDest;
|
||||
while (!dest.empty()) {
|
||||
os << "get_filename_component(_IMPORT_PREFIX \"${_IMPORT_PREFIX}\" "
|
||||
"PATH)\n";
|
||||
dest = cmSystemTools::GetFilenamePath(dest);
|
||||
}
|
||||
os << "if(_IMPORT_PREFIX STREQUAL \"/\")\n"
|
||||
<< " set(_IMPORT_PREFIX \"\")\n"
|
||||
<< "endif()\n"
|
||||
<< "\n";
|
||||
}
|
||||
}
|
||||
|
||||
void cmExportInstallCMakeConfigGenerator::CleanupTemporaryVariables(
|
||||
std::ostream& os)
|
||||
{
|
||||
/* clang-format off */
|
||||
os << "# Cleanup temporary variables.\n"
|
||||
<< "set(_IMPORT_PREFIX)\n"
|
||||
<< "\n";
|
||||
/* clang-format on */
|
||||
}
|
||||
|
||||
void cmExportInstallCMakeConfigGenerator::LoadConfigFiles(std::ostream& os)
|
||||
{
|
||||
// Now load per-configuration properties for them.
|
||||
/* clang-format off */
|
||||
os << "# Load information for each installed configuration.\n"
|
||||
<< "file(GLOB _cmake_config_files \"${CMAKE_CURRENT_LIST_DIR}/"
|
||||
<< this->GetConfigImportFileGlob() << "\")\n"
|
||||
<< "foreach(_cmake_config_file IN LISTS _cmake_config_files)\n"
|
||||
<< " include(\"${_cmake_config_file}\")\n"
|
||||
<< "endforeach()\n"
|
||||
<< "unset(_cmake_config_file)\n"
|
||||
<< "unset(_cmake_config_files)\n"
|
||||
<< "\n";
|
||||
/* clang-format on */
|
||||
}
|
||||
|
||||
bool cmExportInstallCMakeConfigGenerator::GenerateImportFileConfig(
|
||||
std::string const& config)
|
||||
{
|
||||
// Skip configurations not enabled for this export.
|
||||
if (!this->IEGen->InstallsForConfig(config)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Construct the name of the file to generate.
|
||||
std::string fileName = cmStrCat(this->FileDir, '/', this->FileBase, '-');
|
||||
if (!config.empty()) {
|
||||
fileName += cmSystemTools::LowerCase(config);
|
||||
} else {
|
||||
fileName += "noconfig";
|
||||
}
|
||||
fileName += this->FileExt;
|
||||
|
||||
// Open the output file to generate it.
|
||||
cmGeneratedFileStream exportFileStream(fileName, true);
|
||||
if (!exportFileStream) {
|
||||
std::string se = cmSystemTools::GetLastSystemError();
|
||||
std::ostringstream e;
|
||||
e << "cannot write to file \"" << fileName << "\": " << se;
|
||||
cmSystemTools::Error(e.str());
|
||||
return false;
|
||||
}
|
||||
exportFileStream.SetCopyIfDifferent(true);
|
||||
std::ostream& os = exportFileStream;
|
||||
|
||||
// Start with the import file header.
|
||||
this->GenerateImportHeaderCode(os, config);
|
||||
|
||||
// Generate the per-config target information.
|
||||
this->GenerateImportConfig(os, config);
|
||||
|
||||
// End with the import file footer.
|
||||
this->GenerateImportFooterCode(os);
|
||||
|
||||
// Record this per-config import file.
|
||||
this->ConfigImportFiles[config] = fileName;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void cmExportInstallCMakeConfigGenerator::GenerateImportTargetsConfig(
|
||||
std::ostream& os, std::string const& config, std::string const& suffix)
|
||||
{
|
||||
// Add each target in the set to the export.
|
||||
for (std::unique_ptr<cmTargetExport> const& te :
|
||||
this->GetExportSet()->GetTargetExports()) {
|
||||
// Collect import properties for this target.
|
||||
if (this->GetExportTargetType(te.get()) ==
|
||||
cmStateEnums::INTERFACE_LIBRARY) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ImportPropertyMap properties;
|
||||
std::set<std::string> importedLocations;
|
||||
|
||||
this->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()) {
|
||||
cmGeneratorTarget const* const gtgt = te->Target;
|
||||
std::string const importedXcFrameworkLocation =
|
||||
this->GetImportXcFrameworkLocation(config, te.get());
|
||||
|
||||
this->SetImportLinkInterface(config, suffix,
|
||||
cmGeneratorExpression::InstallInterface,
|
||||
gtgt, properties);
|
||||
|
||||
this->GenerateImportPropertyCode(os, config, suffix, gtgt, properties,
|
||||
importedXcFrameworkLocation);
|
||||
this->GenerateImportedFileChecksCode(
|
||||
os, gtgt, properties, importedLocations, importedXcFrameworkLocation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
bool EntryIsContextSensitive(
|
||||
std::unique_ptr<cmCompiledGeneratorExpression> const& cge)
|
||||
{
|
||||
return cge->GetHadContextSensitiveCondition();
|
||||
}
|
||||
}
|
||||
|
||||
std::string cmExportInstallCMakeConfigGenerator::GetFileSetDirectories(
|
||||
cmGeneratorTarget* gte, cmFileSet* fileSet, cmTargetExport const* te)
|
||||
{
|
||||
std::vector<std::string> resultVector;
|
||||
|
||||
auto configs =
|
||||
gte->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
|
||||
|
||||
cmGeneratorExpression ge(*gte->Makefile->GetCMakeInstance());
|
||||
auto cge = ge.Parse(te->FileSetGenerators.at(fileSet)->GetDestination());
|
||||
|
||||
for (auto const& config : configs) {
|
||||
auto unescapedDest = cge->Evaluate(gte->LocalGenerator, config, gte);
|
||||
auto dest = cmOutputConverter::EscapeForCMake(
|
||||
unescapedDest, cmOutputConverter::WrapQuotes::NoWrap);
|
||||
if (!cmSystemTools::FileIsFullPath(unescapedDest)) {
|
||||
dest = cmStrCat("${_IMPORT_PREFIX}/", dest);
|
||||
}
|
||||
|
||||
auto const& type = fileSet->GetType();
|
||||
// C++ modules do not support interface file sets which are dependent upon
|
||||
// the configuration.
|
||||
if (cge->GetHadContextSensitiveCondition() && type == "CXX_MODULES"_s) {
|
||||
auto* mf = this->IEGen->GetLocalGenerator()->GetMakefile();
|
||||
std::ostringstream e;
|
||||
e << "The \"" << gte->GetName() << "\" target's interface file set \""
|
||||
<< fileSet->GetName() << "\" of type \"" << type
|
||||
<< "\" contains context-sensitive base file entries which is not "
|
||||
"supported.";
|
||||
mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
|
||||
return std::string{};
|
||||
}
|
||||
|
||||
if (cge->GetHadContextSensitiveCondition() && configs.size() != 1) {
|
||||
resultVector.push_back(
|
||||
cmStrCat("\"$<$<CONFIG:", config, ">:", dest, ">\""));
|
||||
} else {
|
||||
resultVector.emplace_back(cmStrCat('"', dest, '"'));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return cmJoin(resultVector, " ");
|
||||
}
|
||||
|
||||
std::string cmExportInstallCMakeConfigGenerator::GetFileSetFiles(
|
||||
cmGeneratorTarget* gte, cmFileSet* fileSet, cmTargetExport const* te)
|
||||
{
|
||||
std::vector<std::string> resultVector;
|
||||
|
||||
auto configs =
|
||||
gte->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
|
||||
|
||||
auto fileEntries = fileSet->CompileFileEntries();
|
||||
auto directoryEntries = fileSet->CompileDirectoryEntries();
|
||||
|
||||
cmGeneratorExpression destGe(*gte->Makefile->GetCMakeInstance());
|
||||
auto destCge =
|
||||
destGe.Parse(te->FileSetGenerators.at(fileSet)->GetDestination());
|
||||
|
||||
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);
|
||||
}
|
||||
auto unescapedDest = destCge->Evaluate(gte->LocalGenerator, config, gte);
|
||||
auto dest =
|
||||
cmStrCat(cmOutputConverter::EscapeForCMake(
|
||||
unescapedDest, cmOutputConverter::WrapQuotes::NoWrap),
|
||||
'/');
|
||||
if (!cmSystemTools::FileIsFullPath(unescapedDest)) {
|
||||
dest = cmStrCat("${_IMPORT_PREFIX}/", dest);
|
||||
}
|
||||
|
||||
bool const contextSensitive = destCge->GetHadContextSensitiveCondition() ||
|
||||
std::any_of(directoryEntries.begin(), directoryEntries.end(),
|
||||
EntryIsContextSensitive) ||
|
||||
std::any_of(fileEntries.begin(), fileEntries.end(),
|
||||
EntryIsContextSensitive);
|
||||
|
||||
auto const& type = fileSet->GetType();
|
||||
// C++ modules do not support interface file sets which are dependent upon
|
||||
// the configuration.
|
||||
if (contextSensitive && type == "CXX_MODULES"_s) {
|
||||
auto* mf = this->IEGen->GetLocalGenerator()->GetMakefile();
|
||||
std::ostringstream e;
|
||||
e << "The \"" << gte->GetName() << "\" target's interface file set \""
|
||||
<< fileSet->GetName() << "\" of type \"" << type
|
||||
<< "\" contains context-sensitive base file entries which is not "
|
||||
"supported.";
|
||||
mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
|
||||
return std::string{};
|
||||
}
|
||||
|
||||
for (auto const& it : files) {
|
||||
auto prefix = it.first.empty() ? "" : cmStrCat(it.first, '/');
|
||||
for (auto const& filename : it.second) {
|
||||
auto relFile =
|
||||
cmStrCat(prefix, cmSystemTools::GetFilenameName(filename));
|
||||
auto escapedFile =
|
||||
cmStrCat(dest,
|
||||
cmOutputConverter::EscapeForCMake(
|
||||
relFile, cmOutputConverter::WrapQuotes::NoWrap));
|
||||
if (contextSensitive && configs.size() != 1) {
|
||||
resultVector.push_back(
|
||||
cmStrCat("\"$<$<CONFIG:", config, ">:", escapedFile, ">\""));
|
||||
} else {
|
||||
resultVector.emplace_back(cmStrCat('"', escapedFile, '"'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!(contextSensitive && configs.size() != 1)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return cmJoin(resultVector, " ");
|
||||
}
|
||||
|
||||
std::string cmExportInstallCMakeConfigGenerator::GetCxxModulesDirectory() const
|
||||
{
|
||||
return IEGen->GetCxxModuleDirectory();
|
||||
}
|
||||
|
||||
void cmExportInstallCMakeConfigGenerator::GenerateCxxModuleConfigInformation(
|
||||
std::string const& name, std::ostream& os) const
|
||||
{
|
||||
// Now load per-configuration properties for them.
|
||||
/* clang-format off */
|
||||
os << "# Load information for each installed configuration.\n"
|
||||
"file(GLOB _cmake_cxx_module_includes \"${CMAKE_CURRENT_LIST_DIR}/cxx-modules-" << name << "-*.cmake\")\n"
|
||||
"foreach(_cmake_cxx_module_include IN LISTS _cmake_cxx_module_includes)\n"
|
||||
" include(\"${_cmake_cxx_module_include}\")\n"
|
||||
"endforeach()\n"
|
||||
"unset(_cmake_cxx_module_include)\n"
|
||||
"unset(_cmake_cxx_module_includes)\n";
|
||||
/* clang-format on */
|
||||
}
|
||||
|
||||
bool cmExportInstallCMakeConfigGenerator::
|
||||
GenerateImportCxxModuleConfigTargetInclusion(std::string const& name,
|
||||
std::string const& config)
|
||||
{
|
||||
auto cxx_modules_dirname = this->GetCxxModulesDirectory();
|
||||
if (cxx_modules_dirname.empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string filename_config = config;
|
||||
if (filename_config.empty()) {
|
||||
filename_config = "noconfig";
|
||||
}
|
||||
|
||||
std::string const dest =
|
||||
cmStrCat(this->FileDir, '/', cxx_modules_dirname, '/');
|
||||
std::string fileName =
|
||||
cmStrCat(dest, "cxx-modules-", name, '-', filename_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);
|
||||
|
||||
// Record this per-config import file.
|
||||
this->ConfigCxxModuleFiles[config] = fileName;
|
||||
|
||||
auto& prop_files = this->ConfigCxxModuleTargetFiles[config];
|
||||
for (auto const* tgt : this->ExportedTargets) {
|
||||
// Only targets with C++ module sources will have a
|
||||
// collator-generated install script.
|
||||
if (!tgt->HaveCxx20ModuleSources()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto prop_filename = cmStrCat("target-", tgt->GetFilesystemExportName(),
|
||||
'-', filename_config, ".cmake");
|
||||
prop_files.emplace_back(cmStrCat(dest, prop_filename));
|
||||
os << "include(\"${CMAKE_CURRENT_LIST_DIR}/" << prop_filename << "\")\n";
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
74
Source/cmExportInstallCMakeConfigGenerator.h
Normal file
74
Source/cmExportInstallCMakeConfigGenerator.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
#pragma once
|
||||
|
||||
#include "cmConfigure.h" // IWYU pragma: keep
|
||||
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
|
||||
#include "cmExportCMakeConfigGenerator.h"
|
||||
#include "cmExportInstallFileGenerator.h"
|
||||
|
||||
class cmFileSet;
|
||||
class cmGeneratorTarget;
|
||||
class cmInstallExportGenerator;
|
||||
class cmTargetExport;
|
||||
|
||||
/** \class cmExportInstallCMakeConfigGenerator
|
||||
* \brief Generate files exporting targets from an install tree.
|
||||
*
|
||||
* cmExportInstallCMakeConfigGenerator generates files exporting targets from
|
||||
* 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
|
||||
* installed.
|
||||
*
|
||||
* This is used to implement the INSTALL(EXPORT) command.
|
||||
*/
|
||||
class cmExportInstallCMakeConfigGenerator
|
||||
: public cmExportCMakeConfigGenerator
|
||||
, public cmExportInstallFileGenerator
|
||||
{
|
||||
public:
|
||||
/** Construct with the export installer that will install the
|
||||
files. */
|
||||
cmExportInstallCMakeConfigGenerator(cmInstallExportGenerator* iegen);
|
||||
|
||||
/** Compute the globbing expression used to load per-config import
|
||||
files from the main file. */
|
||||
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;
|
||||
|
||||
/** 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);
|
||||
|
||||
std::string GetFileSetDirectories(cmGeneratorTarget* gte, cmFileSet* fileSet,
|
||||
cmTargetExport const* te) override;
|
||||
std::string GetFileSetFiles(cmGeneratorTarget* gte, cmFileSet* fileSet,
|
||||
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&);
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
@@ -51,6 +45,9 @@ public:
|
||||
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. */
|
||||
@@ -70,65 +67,73 @@ 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, const std::string& 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, const std::string& 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(const std::string& config);
|
||||
void ReportError(std::string const& errorMessage) const override;
|
||||
|
||||
/** Fill in properties indicating installed file locations. */
|
||||
void SetImportLocationProperty(const std::string& config,
|
||||
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,
|
||||
const std::string& config) override;
|
||||
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.
|
||||
@@ -137,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);
|
||||
};
|
||||
|
||||
@@ -19,19 +19,26 @@
|
||||
#include "cmOutputConverter.h"
|
||||
#include "cmStateTypes.h"
|
||||
#include "cmStringAlgorithms.h"
|
||||
#include "cmSystemTools.h"
|
||||
#include "cmTarget.h"
|
||||
#include "cmValue.h"
|
||||
|
||||
class cmTargetExport;
|
||||
|
||||
cmExportTryCompileFileGenerator::cmExportTryCompileFileGenerator(
|
||||
cmGlobalGenerator* gg, const std::vector<std::string>& targets,
|
||||
cmGlobalGenerator* gg, std::vector<std::string> const& targets,
|
||||
cmMakefile* mf, std::set<std::string> const& langs)
|
||||
: Languages(langs.begin(), langs.end())
|
||||
{
|
||||
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;
|
||||
@@ -61,7 +68,7 @@ bool cmExportTryCompileFileGenerator::GenerateMainFile(std::ostream& os)
|
||||
}
|
||||
|
||||
std::string cmExportTryCompileFileGenerator::FindTargets(
|
||||
const std::string& propName, cmGeneratorTarget const* tgt,
|
||||
std::string const& propName, cmGeneratorTarget const* tgt,
|
||||
std::string const& language, std::set<cmGeneratorTarget const*>& emitted)
|
||||
{
|
||||
cmValue prop = tgt->GetProperty(propName);
|
||||
@@ -94,7 +101,7 @@ std::string cmExportTryCompileFileGenerator::FindTargets(
|
||||
std::string result = cge->Evaluate(tgt->GetLocalGenerator(), this->Config,
|
||||
&gDummyHead, &dagChecker, tgt, language);
|
||||
|
||||
const std::set<cmGeneratorTarget const*>& allTargets =
|
||||
std::set<cmGeneratorTarget const*> const& allTargets =
|
||||
cge->GetAllTargetsSeen();
|
||||
for (cmGeneratorTarget const* target : allTargets) {
|
||||
if (emitted.insert(target).second) {
|
||||
@@ -105,7 +112,7 @@ std::string cmExportTryCompileFileGenerator::FindTargets(
|
||||
}
|
||||
|
||||
void cmExportTryCompileFileGenerator::PopulateProperties(
|
||||
const cmGeneratorTarget* target, ImportPropertyMap& properties,
|
||||
cmGeneratorTarget const* target, ImportPropertyMap& properties,
|
||||
std::set<cmGeneratorTarget const*>& emitted)
|
||||
{
|
||||
// Look through all non-special properties.
|
||||
@@ -140,7 +147,7 @@ void cmExportTryCompileFileGenerator::PopulateProperties(
|
||||
}
|
||||
|
||||
std::string cmExportTryCompileFileGenerator::InstallNameDir(
|
||||
cmGeneratorTarget const* target, const std::string& config)
|
||||
cmGeneratorTarget const* target, std::string const& config)
|
||||
{
|
||||
std::string install_name_dir;
|
||||
|
||||
@@ -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()));
|
||||
|
||||
@@ -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,
|
||||
@@ -26,13 +26,17 @@ public:
|
||||
std::set<std::string> const& langs);
|
||||
|
||||
/** Set the list of targets to export. */
|
||||
void SetConfig(const std::string& config) { this->Config = config; }
|
||||
void SetConfig(std::string const& config) { this->Config = config; }
|
||||
|
||||
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&, const std::string&,
|
||||
void GenerateImportTargetsConfig(std::ostream&, std::string const&,
|
||||
std::string const&) override
|
||||
{
|
||||
}
|
||||
@@ -43,17 +47,17 @@ protected:
|
||||
|
||||
void PopulateProperties(cmGeneratorTarget const* target,
|
||||
ImportPropertyMap& properties,
|
||||
std::set<const cmGeneratorTarget*>& emitted);
|
||||
std::set<cmGeneratorTarget const*>& emitted);
|
||||
|
||||
std::string InstallNameDir(cmGeneratorTarget const* target,
|
||||
const std::string& config) override;
|
||||
std::string const& config) override;
|
||||
|
||||
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&,
|
||||
@@ -62,10 +66,10 @@ protected:
|
||||
}
|
||||
|
||||
private:
|
||||
std::string FindTargets(const std::string& prop,
|
||||
const cmGeneratorTarget* tgt,
|
||||
std::string FindTargets(std::string const& prop,
|
||||
cmGeneratorTarget const* tgt,
|
||||
std::string const& language,
|
||||
std::set<const cmGeneratorTarget*>& emitted);
|
||||
std::set<cmGeneratorTarget const*>& emitted);
|
||||
|
||||
std::vector<cmGeneratorTarget const*> Exports;
|
||||
std::string Config;
|
||||
|
||||
30
Source/cmInstallAndroidMKExportGenerator.cxx
Normal file
30
Source/cmInstallAndroidMKExportGenerator.cxx
Normal file
@@ -0,0 +1,30 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
#include "cmInstallAndroidMKExportGenerator.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include <cm/memory>
|
||||
|
||||
#include "cmExportInstallAndroidMKGenerator.h"
|
||||
#include "cmExportInstallFileGenerator.h"
|
||||
#include "cmListFileCache.h"
|
||||
|
||||
class cmExportSet;
|
||||
|
||||
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, 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))
|
||||
{
|
||||
this->EFGen = cm::make_unique<cmExportInstallAndroidMKGenerator>(this);
|
||||
}
|
||||
|
||||
cmInstallAndroidMKExportGenerator::~cmInstallAndroidMKExportGenerator() =
|
||||
default;
|
||||
36
Source/cmInstallAndroidMKExportGenerator.h
Normal file
36
Source/cmInstallAndroidMKExportGenerator.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "cmInstallExportGenerator.h"
|
||||
|
||||
class cmExportSet;
|
||||
class cmListFileBacktrace;
|
||||
|
||||
/** \class cmInstallAndroidMKExportGenerator
|
||||
* \brief Generate rules for creating Android .mk export files.
|
||||
*/
|
||||
class cmInstallAndroidMKExportGenerator : public cmInstallExportGenerator
|
||||
{
|
||||
public:
|
||||
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, cmListFileBacktrace backtrace);
|
||||
cmInstallAndroidMKExportGenerator(cmInstallAndroidMKExportGenerator const&) =
|
||||
delete;
|
||||
~cmInstallAndroidMKExportGenerator() override;
|
||||
|
||||
cmInstallAndroidMKExportGenerator& operator=(
|
||||
cmInstallAndroidMKExportGenerator const&) = delete;
|
||||
|
||||
char const* InstallSubcommand() const override
|
||||
{
|
||||
return "EXPORT_ANDROID_MK";
|
||||
}
|
||||
};
|
||||
43
Source/cmInstallCMakeConfigExportGenerator.cxx
Normal file
43
Source/cmInstallCMakeConfigExportGenerator.cxx
Normal file
@@ -0,0 +1,43 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
#include "cmInstallCMakeConfigExportGenerator.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include <cm/memory>
|
||||
|
||||
#include "cmExportInstallCMakeConfigGenerator.h"
|
||||
#include "cmExportInstallFileGenerator.h"
|
||||
#include "cmListFileCache.h"
|
||||
|
||||
class cmExportSet;
|
||||
|
||||
cmInstallCMakeConfigExportGenerator::cmInstallCMakeConfigExportGenerator(
|
||||
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, std::string cxxModulesDirectory, bool exportOld,
|
||||
bool exportPackageDependencies, cmListFileBacktrace backtrace)
|
||||
: cmInstallExportGenerator(
|
||||
exportSet, std::move(destination), std::move(filePermissions),
|
||||
configurations, std::move(component), message, excludeFromAll,
|
||||
std::move(filename), std::move(targetNamespace),
|
||||
std::move(cxxModulesDirectory), std::move(backtrace))
|
||||
, ExportOld(exportOld)
|
||||
, ExportPackageDependencies(exportPackageDependencies)
|
||||
{
|
||||
this->EFGen = cm::make_unique<cmExportInstallCMakeConfigGenerator>(this);
|
||||
}
|
||||
|
||||
cmInstallCMakeConfigExportGenerator::~cmInstallCMakeConfigExportGenerator() =
|
||||
default;
|
||||
|
||||
void cmInstallCMakeConfigExportGenerator::GenerateScript(std::ostream& os)
|
||||
{
|
||||
auto* const efgen =
|
||||
static_cast<cmExportInstallCMakeConfigGenerator*>(this->EFGen.get());
|
||||
efgen->SetExportOld(this->ExportOld);
|
||||
efgen->SetExportPackageDependencies(this->ExportPackageDependencies);
|
||||
|
||||
this->cmInstallExportGenerator::GenerateScript(os);
|
||||
}
|
||||
42
Source/cmInstallCMakeConfigExportGenerator.h
Normal file
42
Source/cmInstallCMakeConfigExportGenerator.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
#pragma once
|
||||
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "cmInstallExportGenerator.h"
|
||||
|
||||
class cmExportSet;
|
||||
class cmListFileBacktrace;
|
||||
|
||||
/** \class cmInstallCMakeConfigExportGenerator
|
||||
* \brief Generate rules for creating CMake export files.
|
||||
*/
|
||||
class cmInstallCMakeConfigExportGenerator : public cmInstallExportGenerator
|
||||
{
|
||||
public:
|
||||
cmInstallCMakeConfigExportGenerator(
|
||||
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, std::string cxxModulesDirectory,
|
||||
bool exportOld, bool exportPackageDependencies,
|
||||
cmListFileBacktrace backtrace);
|
||||
cmInstallCMakeConfigExportGenerator(
|
||||
cmInstallCMakeConfigExportGenerator const&) = delete;
|
||||
~cmInstallCMakeConfigExportGenerator() override;
|
||||
|
||||
cmInstallCMakeConfigExportGenerator& operator=(
|
||||
cmInstallCMakeConfigExportGenerator const&) = delete;
|
||||
|
||||
char const* InstallSubcommand() const override { return "EXPORT"; }
|
||||
|
||||
protected:
|
||||
void GenerateScript(std::ostream& os) override;
|
||||
|
||||
bool const ExportOld;
|
||||
bool const ExportPackageDependencies;
|
||||
};
|
||||
@@ -26,10 +26,11 @@
|
||||
#include "cmFileSet.h"
|
||||
#include "cmGeneratorExpression.h"
|
||||
#include "cmGlobalGenerator.h"
|
||||
#include "cmInstallAndroidMKExportGenerator.h"
|
||||
#include "cmInstallCMakeConfigExportGenerator.h"
|
||||
#include "cmInstallCommandArguments.h"
|
||||
#include "cmInstallCxxModuleBmiGenerator.h"
|
||||
#include "cmInstallDirectoryGenerator.h"
|
||||
#include "cmInstallExportGenerator.h"
|
||||
#include "cmInstallFileSetGenerator.h"
|
||||
#include "cmInstallFilesGenerator.h"
|
||||
#include "cmInstallGenerator.h"
|
||||
@@ -2028,10 +2029,10 @@ bool HandleExportAndroidMKMode(std::vector<std::string> const& args,
|
||||
|
||||
// Create the export install generator.
|
||||
helper.Makefile->AddInstallGenerator(
|
||||
cm::make_unique<cmInstallExportGenerator>(
|
||||
cm::make_unique<cmInstallAndroidMKExportGenerator>(
|
||||
&exportSet, ica.GetDestination(), ica.GetPermissions(),
|
||||
ica.GetConfigurations(), ica.GetComponent(), message,
|
||||
ica.GetExcludeFromAll(), fname, name_space, "", exportOld, true, false,
|
||||
ica.GetExcludeFromAll(), std::move(fname), std::move(name_space),
|
||||
helper.Makefile->GetBacktrace()));
|
||||
|
||||
return true;
|
||||
@@ -2151,11 +2152,11 @@ bool HandleExportMode(std::vector<std::string> const& args,
|
||||
|
||||
// Create the export install generator.
|
||||
helper.Makefile->AddInstallGenerator(
|
||||
cm::make_unique<cmInstallExportGenerator>(
|
||||
cm::make_unique<cmInstallCMakeConfigExportGenerator>(
|
||||
&exportSet, ica.GetDestination(), ica.GetPermissions(),
|
||||
ica.GetConfigurations(), ica.GetComponent(), message,
|
||||
ica.GetExcludeFromAll(), fname, name_space, cxx_modules_directory,
|
||||
exportOld, false, exportPackageDependencies,
|
||||
ica.GetExcludeFromAll(), std::move(fname), std::move(name_space),
|
||||
std::move(cxx_modules_directory), exportOld, exportPackageDependencies,
|
||||
helper.Makefile->GetBacktrace()));
|
||||
|
||||
return true;
|
||||
|
||||
@@ -6,12 +6,7 @@
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
|
||||
#include <cm/memory>
|
||||
|
||||
#include "cmCryptoHash.h"
|
||||
#ifndef CMAKE_BOOTSTRAP
|
||||
# include "cmExportInstallAndroidMKGenerator.h"
|
||||
#endif
|
||||
#include "cmExportInstallFileGenerator.h"
|
||||
#include "cmExportSet.h"
|
||||
#include "cmInstallType.h"
|
||||
@@ -22,29 +17,20 @@
|
||||
#include "cmSystemTools.h"
|
||||
|
||||
cmInstallExportGenerator::cmInstallExportGenerator(
|
||||
cmExportSet* exportSet, std::string const& destination,
|
||||
std::string file_permissions, std::vector<std::string> const& configurations,
|
||||
std::string const& component, MessageLevel message, bool exclude_from_all,
|
||||
std::string filename, std::string name_space,
|
||||
std::string cxx_modules_directory, bool exportOld, bool android,
|
||||
bool exportPackageDependencies, cmListFileBacktrace backtrace)
|
||||
: cmInstallGenerator(destination, configurations, component, message,
|
||||
exclude_from_all, false, std::move(backtrace))
|
||||
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, std::string cxxModulesDirectory,
|
||||
cmListFileBacktrace backtrace)
|
||||
: cmInstallGenerator(std::move(destination), configurations,
|
||||
std::move(component), message, excludeFromAll, false,
|
||||
std::move(backtrace))
|
||||
, ExportSet(exportSet)
|
||||
, FilePermissions(std::move(file_permissions))
|
||||
, FilePermissions(std::move(filePermissions))
|
||||
, FileName(std::move(filename))
|
||||
, Namespace(std::move(name_space))
|
||||
, CxxModulesDirectory(std::move(cxx_modules_directory))
|
||||
, ExportOld(exportOld)
|
||||
, ExportPackageDependencies(exportPackageDependencies)
|
||||
, Namespace(std::move(targetNamespace))
|
||||
, CxxModulesDirectory(std::move(cxxModulesDirectory))
|
||||
{
|
||||
if (android) {
|
||||
#ifndef CMAKE_BOOTSTRAP
|
||||
this->EFGen = cm::make_unique<cmExportInstallAndroidMKGenerator>(this);
|
||||
#endif
|
||||
} else {
|
||||
this->EFGen = cm::make_unique<cmExportInstallFileGenerator>(this);
|
||||
}
|
||||
exportSet->AddInstallation(this);
|
||||
}
|
||||
|
||||
@@ -92,7 +78,7 @@ void cmInstallExportGenerator::GenerateScript(std::ostream& os)
|
||||
// Skip empty sets.
|
||||
if (this->ExportSet->GetTargetExports().empty()) {
|
||||
std::ostringstream e;
|
||||
e << "INSTALL(EXPORT) given unknown export \""
|
||||
e << "INSTALL(" << this->InstallSubcommand() << ") given unknown export \""
|
||||
<< this->ExportSet->GetName() << "\"";
|
||||
cmSystemTools::Error(e.str());
|
||||
return;
|
||||
@@ -108,7 +94,6 @@ void cmInstallExportGenerator::GenerateScript(std::ostream& os)
|
||||
// Generate the import file for this export set.
|
||||
this->EFGen->SetExportFile(this->MainImportFile.c_str());
|
||||
this->EFGen->SetNamespace(this->Namespace);
|
||||
this->EFGen->SetExportOld(this->ExportOld);
|
||||
if (this->ConfigurationTypes->empty()) {
|
||||
if (!this->ConfigurationName.empty()) {
|
||||
this->EFGen->AddConfiguration(this->ConfigurationName);
|
||||
@@ -120,7 +105,6 @@ void cmInstallExportGenerator::GenerateScript(std::ostream& os)
|
||||
this->EFGen->AddConfiguration(c);
|
||||
}
|
||||
}
|
||||
this->EFGen->SetExportPackageDependencies(this->ExportPackageDependencies);
|
||||
this->EFGen->GenerateImportFile();
|
||||
|
||||
// Perform the main install script generation.
|
||||
@@ -149,37 +133,37 @@ void cmInstallExportGenerator::GenerateScriptConfigs(std::ostream& os,
|
||||
|
||||
// Now create a configuration-specific install rule for the C++ module import
|
||||
// property file of each configuration.
|
||||
auto cxx_module_dest =
|
||||
auto const cxxModuleDestination =
|
||||
cmStrCat(this->Destination, '/', this->CxxModulesDirectory);
|
||||
std::string config_file_example;
|
||||
for (auto const& i : this->EFGen->GetConfigCxxModuleFiles()) {
|
||||
config_file_example = i.second;
|
||||
break;
|
||||
}
|
||||
if (!config_file_example.empty()) {
|
||||
auto const cxxModuleInstallFilePath = this->EFGen->GetCxxModuleFile();
|
||||
auto const configImportFilesGlob = this->EFGen->GetConfigImportFileGlob();
|
||||
if (!cxxModuleInstallFilePath.empty() && !configImportFilesGlob.empty()) {
|
||||
auto const cxxModuleFilename =
|
||||
cmSystemTools::GetFilenameName(cxxModuleInstallFilePath);
|
||||
|
||||
// Remove old per-configuration export files if the main changes.
|
||||
std::string installedDir = cmStrCat(
|
||||
"$ENV{DESTDIR}", ConvertToAbsoluteDestination(cxx_module_dest), '/');
|
||||
std::string installedFile = cmStrCat(installedDir, "/cxx-modules-",
|
||||
this->ExportSet->GetName(), ".cmake");
|
||||
std::string toInstallFile =
|
||||
cmStrCat(cmSystemTools::GetFilenamePath(config_file_example),
|
||||
"/cxx-modules-", this->ExportSet->GetName(), ".cmake");
|
||||
std::string installedDir =
|
||||
cmStrCat("$ENV{DESTDIR}",
|
||||
ConvertToAbsoluteDestination(cxxModuleDestination), '/');
|
||||
std::string installedFile = cmStrCat(installedDir, cxxModuleFilename);
|
||||
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 << " \"" << toInstallFile << "\")\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";
|
||||
@@ -187,12 +171,11 @@ 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.
|
||||
files.push_back(toInstallFile);
|
||||
this->AddInstallRule(os, cxx_module_dest, cmInstallType_FILES, files,
|
||||
files.push_back(cxxModuleInstallFilePath);
|
||||
this->AddInstallRule(os, cxxModuleDestination, cmInstallType_FILES, files,
|
||||
false, this->FilePermissions.c_str(), nullptr,
|
||||
nullptr, nullptr, indent);
|
||||
files.clear();
|
||||
@@ -201,7 +184,7 @@ void cmInstallExportGenerator::GenerateScriptConfigs(std::ostream& os,
|
||||
files.push_back(i.second);
|
||||
std::string config_test = this->CreateConfigTest(i.first);
|
||||
os << indent << "if(" << config_test << ")\n";
|
||||
this->AddInstallRule(os, cxx_module_dest, cmInstallType_FILES, files,
|
||||
this->AddInstallRule(os, cxxModuleDestination, cmInstallType_FILES, files,
|
||||
false, this->FilePermissions.c_str(), nullptr,
|
||||
nullptr, nullptr, indent.Next());
|
||||
os << indent << "endif()\n";
|
||||
@@ -210,9 +193,9 @@ void cmInstallExportGenerator::GenerateScriptConfigs(std::ostream& os,
|
||||
for (auto const& i : this->EFGen->GetConfigCxxModuleTargetFiles()) {
|
||||
std::string config_test = this->CreateConfigTest(i.first);
|
||||
os << indent << "if(" << config_test << ")\n";
|
||||
this->AddInstallRule(os, cxx_module_dest, cmInstallType_FILES, i.second,
|
||||
false, this->FilePermissions.c_str(), nullptr,
|
||||
nullptr, nullptr, indent.Next());
|
||||
this->AddInstallRule(os, cxxModuleDestination, cmInstallType_FILES,
|
||||
i.second, false, this->FilePermissions.c_str(),
|
||||
nullptr, nullptr, nullptr, indent.Next());
|
||||
os << indent << "endif()\n";
|
||||
files.clear();
|
||||
}
|
||||
@@ -221,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;
|
||||
|
||||
@@ -17,19 +17,18 @@ class cmListFileBacktrace;
|
||||
class cmLocalGenerator;
|
||||
|
||||
/** \class cmInstallExportGenerator
|
||||
* \brief Generate rules for creating an export files.
|
||||
* \brief Support class for generating rules for creating export files.
|
||||
*/
|
||||
class cmInstallExportGenerator : public cmInstallGenerator
|
||||
{
|
||||
public:
|
||||
cmInstallExportGenerator(cmExportSet* exportSet, std::string const& dest,
|
||||
std::string file_permissions,
|
||||
const std::vector<std::string>& configurations,
|
||||
std::string const& component, MessageLevel message,
|
||||
bool exclude_from_all, std::string filename,
|
||||
std::string name_space,
|
||||
std::string cxx_modules_directory, bool exportOld,
|
||||
bool android, bool exportPackageDependencies,
|
||||
cmInstallExportGenerator(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,
|
||||
std::string cxxModulesDirectory,
|
||||
cmListFileBacktrace backtrace);
|
||||
cmInstallExportGenerator(const cmInstallExportGenerator&) = delete;
|
||||
~cmInstallExportGenerator() override;
|
||||
@@ -37,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;
|
||||
@@ -60,8 +61,6 @@ protected:
|
||||
void GenerateScript(std::ostream& os) override;
|
||||
void GenerateScriptConfigs(std::ostream& os, Indent indent) override;
|
||||
void GenerateScriptActions(std::ostream& os, Indent indent) override;
|
||||
void GenerateImportFile(cmExportSet const* exportSet);
|
||||
void GenerateImportFile(const char* config, cmExportSet const* exportSet);
|
||||
std::string TempDirCalculate() const;
|
||||
void ComputeTempDir();
|
||||
|
||||
@@ -70,8 +69,6 @@ protected:
|
||||
std::string const FileName;
|
||||
std::string const Namespace;
|
||||
std::string const CxxModulesDirectory;
|
||||
bool const ExportOld;
|
||||
bool const ExportPackageDependencies;
|
||||
cmLocalGenerator* LocalGenerator = nullptr;
|
||||
|
||||
std::string TempDir;
|
||||
|
||||
@@ -345,8 +345,11 @@ CMAKE_CXX_SOURCES="\
|
||||
cmExecuteProcessCommand \
|
||||
cmExpandedCommandArgument \
|
||||
cmExperimental \
|
||||
cmExportBuildCMakeConfigGenerator \
|
||||
cmExportBuildFileGenerator \
|
||||
cmExportCMakeConfigGenerator \
|
||||
cmExportFileGenerator \
|
||||
cmExportInstallCMakeConfigGenerator \
|
||||
cmExportInstallFileGenerator \
|
||||
cmExportSet \
|
||||
cmExportTryCompileFileGenerator \
|
||||
@@ -408,6 +411,7 @@ CMAKE_CXX_SOURCES="\
|
||||
cmIncludeGuardCommand \
|
||||
cmIncludeDirectoryCommand \
|
||||
cmIncludeRegularExpressionCommand \
|
||||
cmInstallCMakeConfigExportGenerator \
|
||||
cmInstallCommand \
|
||||
cmInstallCommandArguments \
|
||||
cmInstallCxxModuleBmiGenerator \
|
||||
|
||||
Reference in New Issue
Block a user