summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKyle Edwards <kyle.edwards@kitware.com>2021-06-18 18:44:46 (GMT)
committerKyle Edwards <kyle.edwards@kitware.com>2021-10-27 19:17:23 (GMT)
commit2a78d47b16c8b7a3b599f1862cbab0de58575d84 (patch)
tree736a0d889a4c0cdf7d64779b1a3bce50feb9bb4b
parent9b479124cc4be49a4b2c6e45e733b489f7a26432 (diff)
downloadCMake-2a78d47b16c8b7a3b599f1862cbab0de58575d84.zip
CMake-2a78d47b16c8b7a3b599f1862cbab0de58575d84.tar.gz
CMake-2a78d47b16c8b7a3b599f1862cbab0de58575d84.tar.bz2
install(EXPORT): Install file sets
-rw-r--r--Source/cmExportBuildFileGenerator.cxx19
-rw-r--r--Source/cmExportBuildFileGenerator.h7
-rw-r--r--Source/cmExportFileGenerator.cxx37
-rw-r--r--Source/cmExportFileGenerator.h12
-rw-r--r--Source/cmExportInstallFileGenerator.cxx105
-rw-r--r--Source/cmExportInstallFileGenerator.h6
-rw-r--r--Source/cmExportTryCompileFileGenerator.cxx19
-rw-r--r--Source/cmExportTryCompileFileGenerator.h9
-rw-r--r--Source/cmInstallCommand.cxx37
-rw-r--r--Source/cmTargetExport.h3
10 files changed, 249 insertions, 5 deletions
diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx
index aa968dc..a47f1e5 100644
--- a/Source/cmExportBuildFileGenerator.cxx
+++ b/Source/cmExportBuildFileGenerator.cxx
@@ -11,12 +11,15 @@
#include <cmext/algorithm>
#include "cmExportSet.h"
+#include "cmFileSet.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
+#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
+#include "cmOutputConverter.h"
#include "cmPolicies.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
@@ -135,6 +138,8 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
this->PopulateCompatibleInterfaceProperties(gte, properties);
this->GenerateInterfaceProperties(gte, os, properties);
+
+ this->GenerateTargetFileSets(gte, os);
}
// Generate import file content for each configuration.
@@ -356,3 +361,17 @@ std::string cmExportBuildFileGenerator::InstallNameDir(
return install_name_dir;
}
+
+std::string cmExportBuildFileGenerator::GetFileSetDirectories(
+ cmGeneratorTarget* /*gte*/, cmFileSet* fileSet, cmTargetExport* /*te*/)
+{
+ return cmOutputConverter::EscapeForCMake(
+ cmJoin(fileSet->GetDirectoryEntries(), ";"));
+}
+
+std::string cmExportBuildFileGenerator::GetFileSetFiles(
+ cmGeneratorTarget* /*gte*/, cmFileSet* fileSet, cmTargetExport* /*te*/)
+{
+ return cmOutputConverter::EscapeForCMake(
+ cmJoin(fileSet->GetFileEntries(), ";"));
+}
diff --git a/Source/cmExportBuildFileGenerator.h b/Source/cmExportBuildFileGenerator.h
index 244f526..a7985c7 100644
--- a/Source/cmExportBuildFileGenerator.h
+++ b/Source/cmExportBuildFileGenerator.h
@@ -15,9 +15,11 @@
#include "cmStateTypes.h"
class cmExportSet;
+class cmFileSet;
class cmGeneratorTarget;
class cmGlobalGenerator;
class cmLocalGenerator;
+class cmTargetExport;
/** \class cmExportBuildFileGenerator
* \brief Generate a file exporting targets from a build tree.
@@ -76,6 +78,11 @@ protected:
std::string InstallNameDir(cmGeneratorTarget const* target,
const std::string& config) override;
+ std::string GetFileSetDirectories(cmGeneratorTarget* gte, cmFileSet* fileSet,
+ cmTargetExport* te) override;
+ std::string GetFileSetFiles(cmGeneratorTarget* gte, cmFileSet* fileSet,
+ cmTargetExport* te) override;
+
std::pair<std::vector<std::string>, std::string> FindBuildExportInfo(
cmGlobalGenerator* gg, const std::string& name);
diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx
index 9f38c12..896240c 100644
--- a/Source/cmExportFileGenerator.cxx
+++ b/Source/cmExportFileGenerator.cxx
@@ -12,6 +12,7 @@
#include "cmsys/FStream.hxx"
#include "cmComputeLinkInformation.h"
+#include "cmFileSet.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
@@ -1256,3 +1257,39 @@ bool cmExportFileGenerator::PopulateExportProperties(
}
return true;
}
+
+void cmExportFileGenerator::GenerateTargetFileSets(cmGeneratorTarget* gte,
+ std::ostream& os,
+ cmTargetExport* te)
+{
+ auto interfaceFileSets = gte->Target->GetAllInterfaceFileSets();
+ if (!interfaceFileSets.empty()) {
+ std::string targetName = cmStrCat(this->Namespace, gte->GetExportName());
+ os << "if(NOT CMAKE_VERSION VERSION_LESS \"" << DEVEL_CMAKE_VERSION(3, 23)
+ << "\")\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 << " )\nendif()\n\n";
+ }
+}
diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h
index 24e048b..5875247 100644
--- a/Source/cmExportFileGenerator.h
+++ b/Source/cmExportFileGenerator.h
@@ -15,7 +15,9 @@
#include "cmVersion.h"
#include "cmVersionConfig.h"
+class cmFileSet;
class cmGeneratorTarget;
+class cmTargetExport;
#define STRINGIFY_HELPER(X) #X
#define STRINGIFY(X) STRINGIFY_HELPER(X)
@@ -184,6 +186,16 @@ protected:
ImportPropertyMap& properties,
std::string& errorMessage);
+ void GenerateTargetFileSets(cmGeneratorTarget* gte, std::ostream& os,
+ cmTargetExport* te = nullptr);
+
+ virtual std::string GetFileSetDirectories(cmGeneratorTarget* gte,
+ cmFileSet* fileSet,
+ cmTargetExport* te) = 0;
+ virtual std::string GetFileSetFiles(cmGeneratorTarget* gte,
+ cmFileSet* fileSet,
+ cmTargetExport* te) = 0;
+
// The namespace in which the exports are placed in the generated file.
std::string Namespace;
diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx
index e9ac875..2dd8b8f 100644
--- a/Source/cmExportInstallFileGenerator.cxx
+++ b/Source/cmExportInstallFileGenerator.cxx
@@ -2,19 +2,23 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmExportInstallFileGenerator.h"
+#include <algorithm>
#include <memory>
#include <sstream>
#include <utility>
#include "cmExportSet.h"
+#include "cmFileSet.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmInstallExportGenerator.h"
+#include "cmInstallFileSetGenerator.h"
#include "cmInstallTargetGenerator.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
+#include "cmOutputConverter.h"
#include "cmPolicies.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
@@ -147,6 +151,8 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
this->PopulateCompatibleInterfaceProperties(gt, properties);
this->GenerateInterfaceProperties(gt, os, properties);
+
+ this->GenerateTargetFileSets(gt, os, te);
}
if (require3_1_0) {
@@ -534,3 +540,102 @@ std::string cmExportInstallFileGenerator::InstallNameDir(
return install_name_dir;
}
+
+namespace {
+bool EntryIsContextSensitive(
+ const std::unique_ptr<cmCompiledGeneratorExpression>& cge)
+{
+ return cge->GetHadContextSensitiveCondition();
+}
+}
+
+std::string cmExportInstallFileGenerator::GetFileSetDirectories(
+ cmGeneratorTarget* gte, cmFileSet* fileSet, cmTargetExport* te)
+{
+ std::vector<std::string> resultVector;
+
+ auto configs =
+ gte->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
+
+ cmGeneratorExpression ge;
+ auto cge = ge.Parse(te->FileSetGenerators.at(fileSet)->GetDestination());
+
+ for (auto const& config : configs) {
+ auto dest = cmStrCat("${_IMPORT_PREFIX}/",
+ cmOutputConverter::EscapeForCMake(
+ cge->Evaluate(gte->LocalGenerator, config, gte),
+ cmOutputConverter::WrapQuotes::NoWrap));
+
+ if (cge->GetHadContextSensitiveCondition() && configs.size() != 1) {
+ resultVector.push_back(
+ cmStrCat("\"$<$<CONFIG:", config, ">:", dest, ">\""));
+ } else {
+ resultVector.push_back(cmStrCat('"', dest, '"'));
+ break;
+ }
+ }
+
+ return cmJoin(resultVector, " ");
+}
+
+std::string cmExportInstallFileGenerator::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();
+
+ cmGeneratorExpression destGe;
+ 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 dest = cmStrCat("${_IMPORT_PREFIX}/",
+ cmOutputConverter::EscapeForCMake(
+ destCge->Evaluate(gte->LocalGenerator, config, gte),
+ cmOutputConverter::WrapQuotes::NoWrap),
+ '/');
+
+ bool const contextSensitive = destCge->GetHadContextSensitiveCondition() ||
+ std::any_of(directoryEntries.begin(), directoryEntries.end(),
+ EntryIsContextSensitive) ||
+ std::any_of(fileEntries.begin(), fileEntries.end(),
+ EntryIsContextSensitive);
+
+ 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.push_back(cmStrCat('"', escapedFile, '"'));
+ }
+ }
+ }
+
+ if (!(contextSensitive && configs.size() != 1)) {
+ break;
+ }
+ }
+
+ return cmJoin(resultVector, " ");
+}
diff --git a/Source/cmExportInstallFileGenerator.h b/Source/cmExportInstallFileGenerator.h
index 5cec2e0..9374c6b 100644
--- a/Source/cmExportInstallFileGenerator.h
+++ b/Source/cmExportInstallFileGenerator.h
@@ -14,6 +14,7 @@
#include "cmExportFileGenerator.h"
#include "cmStateTypes.h"
+class cmFileSet;
class cmGeneratorTarget;
class cmGlobalGenerator;
class cmInstallExportGenerator;
@@ -97,6 +98,11 @@ protected:
std::string InstallNameDir(cmGeneratorTarget const* target,
const std::string& config) override;
+ std::string GetFileSetDirectories(cmGeneratorTarget* gte, cmFileSet* fileSet,
+ cmTargetExport* te) override;
+ std::string GetFileSetFiles(cmGeneratorTarget* gte, cmFileSet* fileSet,
+ cmTargetExport* te) override;
+
cmInstallExportGenerator* IEGen;
// The import file generated for each configuration.
diff --git a/Source/cmExportTryCompileFileGenerator.cxx b/Source/cmExportTryCompileFileGenerator.cxx
index cbe3c4d..4fe92c6 100644
--- a/Source/cmExportTryCompileFileGenerator.cxx
+++ b/Source/cmExportTryCompileFileGenerator.cxx
@@ -7,17 +7,22 @@
#include <cm/memory>
+#include "cmFileSet.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorExpressionDAGChecker.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
+#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
+#include "cmOutputConverter.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmTarget.h"
#include "cmValue.h"
+class cmTargetExport;
+
cmExportTryCompileFileGenerator::cmExportTryCompileFileGenerator(
cmGlobalGenerator* gg, const std::vector<std::string>& targets,
cmMakefile* mf, std::set<std::string> const& langs)
@@ -137,3 +142,17 @@ std::string cmExportTryCompileFileGenerator::InstallNameDir(
return install_name_dir;
}
+
+std::string cmExportTryCompileFileGenerator::GetFileSetDirectories(
+ cmGeneratorTarget* /*gte*/, cmFileSet* fileSet, cmTargetExport* /*te*/)
+{
+ return cmOutputConverter::EscapeForCMake(
+ cmJoin(fileSet->GetDirectoryEntries(), ";"));
+}
+
+std::string cmExportTryCompileFileGenerator::GetFileSetFiles(
+ cmGeneratorTarget* /*gte*/, cmFileSet* fileSet, cmTargetExport* /*te*/)
+{
+ return cmOutputConverter::EscapeForCMake(
+ cmJoin(fileSet->GetFileEntries(), ";"));
+}
diff --git a/Source/cmExportTryCompileFileGenerator.h b/Source/cmExportTryCompileFileGenerator.h
index 127b8df..8a1fd7e 100644
--- a/Source/cmExportTryCompileFileGenerator.h
+++ b/Source/cmExportTryCompileFileGenerator.h
@@ -11,9 +11,11 @@
#include "cmExportFileGenerator.h"
+class cmFileSet;
class cmGeneratorTarget;
class cmGlobalGenerator;
class cmMakefile;
+class cmTargetExport;
class cmExportTryCompileFileGenerator : public cmExportFileGenerator
{
@@ -48,6 +50,13 @@ protected:
std::string InstallNameDir(cmGeneratorTarget const* target,
const std::string& config) override;
+ std::string GetFileSetDirectories(cmGeneratorTarget* target,
+ cmFileSet* fileSet,
+ cmTargetExport* te) override;
+
+ std::string GetFileSetFiles(cmGeneratorTarget* target, cmFileSet* fileSet,
+ cmTargetExport* te) override;
+
private:
std::string FindTargets(const std::string& prop,
const cmGeneratorTarget* tgt,
diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx
index 08c308d..18f2f7f 100644
--- a/Source/cmInstallCommand.cxx
+++ b/Source/cmInstallCommand.cxx
@@ -729,9 +729,24 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
// Track whether this is a namelink-only rule.
bool namelinkOnly = false;
- auto addTargetExport = [&]() {
+ auto addTargetExport = [&]() -> bool {
// Add this install rule to an export if one was specified.
if (!exports.empty()) {
+ auto interfaceFileSets = target.GetAllInterfaceFileSets();
+ if (std::any_of(
+ interfaceFileSets.begin(), interfaceFileSets.end(),
+ [=](const std::string& name) -> bool {
+ return !std::any_of(
+ fileSetArgs.begin(), fileSetArgs.end(),
+ [=](const cmInstallCommandFileSetArguments& fileSetArg)
+ -> bool { return fileSetArg.GetFileSet() == name; });
+ })) {
+ status.SetError(cmStrCat(
+ "TARGETS target ", target.GetName(),
+ " is exported but not all of its file sets are installed"));
+ return false;
+ }
+
auto te = cm::make_unique<cmTargetExport>();
te->TargetName = target.GetName();
te->ArchiveGenerator = archiveGenerator.get();
@@ -741,6 +756,9 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
te->LibraryGenerator = libraryGenerator.get();
te->RuntimeGenerator = runtimeGenerator.get();
te->ObjectsGenerator = objectGenerator.get();
+ for (auto const& gen : fileSetGenerators) {
+ te->FileSetGenerators[gen->GetFileSet()] = gen.get();
+ }
target.AddInstallIncludeDirectories(
cmMakeRange(includesArgs.GetIncludeDirs()));
te->NamelinkOnly = namelinkOnly;
@@ -748,6 +766,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
->GetExportSets()[exports]
.AddTargetExport(std::move(te));
}
+ return true;
};
switch (target.GetType()) {
@@ -759,7 +778,9 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
// When in namelink only mode skip all libraries on Windows.
if (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly) {
namelinkOnly = true;
- addTargetExport();
+ if (!addTargetExport()) {
+ return false;
+ }
continue;
}
@@ -795,7 +816,9 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
// When in namelink only mode skip frameworks.
if (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly) {
namelinkOnly = true;
- addTargetExport();
+ if (!addTargetExport()) {
+ return false;
+ }
continue;
}
@@ -844,7 +867,9 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
// When in namelink only mode skip frameworks.
if (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly) {
namelinkOnly = true;
- addTargetExport();
+ if (!addTargetExport()) {
+ return false;
+ }
continue;
}
@@ -1080,7 +1105,9 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
}
// Add this install rule to an export if one was specified.
- addTargetExport();
+ if (!addTargetExport()) {
+ return false;
+ }
// Keep track of whether we're installing anything in each category
installsArchive = installsArchive || archiveGenerator;
diff --git a/Source/cmTargetExport.h b/Source/cmTargetExport.h
index 19fc931..885ac74 100644
--- a/Source/cmTargetExport.h
+++ b/Source/cmTargetExport.h
@@ -6,7 +6,9 @@
#include <string>
+class cmFileSet;
class cmGeneratorTarget;
+class cmInstallFileSetGenerator;
class cmInstallFilesGenerator;
class cmInstallTargetGenerator;
@@ -29,6 +31,7 @@ public:
cmInstallTargetGenerator* FrameworkGenerator;
cmInstallTargetGenerator* BundleGenerator;
cmInstallFilesGenerator* HeaderGenerator;
+ std::map<cmFileSet*, cmInstallFileSetGenerator*> FileSetGenerators;
///@}
bool NamelinkOnly = false;