summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorKyle Edwards <kyle.edwards@kitware.com>2021-06-17 21:01:28 (GMT)
committerKyle Edwards <kyle.edwards@kitware.com>2021-10-27 19:17:23 (GMT)
commit9b479124cc4be49a4b2c6e45e733b489f7a26432 (patch)
treec8ca0ce69ed5706d20cfc08a486507c58905233c /Source
parentd8af2d954f8619f0e8bc42252d310085dec94df4 (diff)
downloadCMake-9b479124cc4be49a4b2c6e45e733b489f7a26432.zip
CMake-9b479124cc4be49a4b2c6e45e733b489f7a26432.tar.gz
CMake-9b479124cc4be49a4b2c6e45e733b489f7a26432.tar.bz2
install(TARGETS): Add FILE_SET mode
Diffstat (limited to 'Source')
-rw-r--r--Source/CMakeLists.txt2
-rw-r--r--Source/cmInstallCommand.cxx119
-rw-r--r--Source/cmInstallCommandArguments.cxx19
-rw-r--r--Source/cmInstallCommandArguments.h16
-rw-r--r--Source/cmInstallFileSetGenerator.cxx88
-rw-r--r--Source/cmInstallFileSetGenerator.h52
6 files changed, 289 insertions, 7 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 5e20736..c125378 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -318,6 +318,8 @@ set(SRCS
cmInstallExportGenerator.cxx
cmInstalledFile.h
cmInstalledFile.cxx
+ cmInstallFileSetGenerator.h
+ cmInstallFileSetGenerator.cxx
cmInstallFilesGenerator.h
cmInstallFilesGenerator.cxx
cmInstallImportedRuntimeArtifactsGenerator.h
diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx
index eaf88f6..08c308d 100644
--- a/Source/cmInstallCommand.cxx
+++ b/Source/cmInstallCommand.cxx
@@ -6,11 +6,13 @@
#include <cassert>
#include <cstddef>
#include <iterator>
+#include <map>
#include <set>
#include <sstream>
#include <utility>
#include <cm/memory>
+#include <cm/string_view>
#include <cmext/string_view>
#include "cmsys/Glob.hxx"
@@ -18,11 +20,13 @@
#include "cmArgumentParser.h"
#include "cmExecutionStatus.h"
#include "cmExportSet.h"
+#include "cmFileSet.h"
#include "cmGeneratorExpression.h"
#include "cmGlobalGenerator.h"
#include "cmInstallCommandArguments.h"
#include "cmInstallDirectoryGenerator.h"
#include "cmInstallExportGenerator.h"
+#include "cmInstallFileSetGenerator.h"
#include "cmInstallFilesGenerator.h"
#include "cmInstallGenerator.h"
#include "cmInstallGetRuntimeDependenciesGenerator.h"
@@ -89,6 +93,9 @@ public:
bool MakeFilesFullPath(const char* modeName,
const std::vector<std::string>& relFiles,
std::vector<std::string>& absFiles);
+ bool MakeFilesFullPath(const char* modeName, const std::string& basePath,
+ const std::vector<std::string>& relFiles,
+ std::vector<std::string>& absFiles);
bool CheckCMP0006(bool& failure) const;
std::string GetDestination(const cmInstallCommandArguments* args,
@@ -177,6 +184,19 @@ std::unique_ptr<cmInstallFilesGenerator> CreateInstallFilesGenerator(
args.GetDestination());
}
+std::unique_ptr<cmInstallFileSetGenerator> CreateInstallFileSetGenerator(
+ Helper& helper, cmTarget& target, cmFileSet* fileSet,
+ const std::string& destination, const cmInstallCommandArguments& args)
+{
+ cmInstallGenerator::MessageLevel message =
+ cmInstallGenerator::SelectMessageLevel(helper.Makefile);
+ return cm::make_unique<cmInstallFileSetGenerator>(
+ target.GetName(), fileSet, destination, args.GetPermissions(),
+ args.GetConfigurations(), args.GetComponent(), message,
+ args.GetExcludeFromAll(), args.GetOptional(),
+ helper.Makefile->GetBacktrace());
+}
+
void AddInstallRuntimeDependenciesGenerator(
Helper& helper, cmInstallRuntimeDependencySet* runtimeDependencySet,
const cmInstallCommandArguments& runtimeArgs,
@@ -390,6 +410,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
std::vector<std::string> PrivateHeader;
std::vector<std::string> PublicHeader;
std::vector<std::string> Resource;
+ std::vector<std::vector<std::string>> FileSets;
};
static auto const argHelper =
@@ -403,7 +424,8 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
.Bind("INCLUDES"_s, &ArgVectors::Includes)
.Bind("PRIVATE_HEADER"_s, &ArgVectors::PrivateHeader)
.Bind("PUBLIC_HEADER"_s, &ArgVectors::PublicHeader)
- .Bind("RESOURCE"_s, &ArgVectors::Resource);
+ .Bind("RESOURCE"_s, &ArgVectors::Resource)
+ .Bind("FILE_SET"_s, &ArgVectors::FileSets);
std::vector<std::string> genericArgVector;
ArgVectors const argVectors = argHelper.Parse(args, &genericArgVector);
@@ -442,6 +464,8 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
cmInstallCommandArguments publicHeaderArgs(helper.DefaultComponentName);
cmInstallCommandArguments resourceArgs(helper.DefaultComponentName);
cmInstallCommandIncludesArgument includesArgs;
+ std::vector<cmInstallCommandFileSetArguments> fileSetArgs(
+ argVectors.FileSets.size(), { helper.DefaultComponentName });
// now parse the args for specific parts of the target (e.g. LIBRARY,
// RUNTIME, ARCHIVE etc.
@@ -455,6 +479,15 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
publicHeaderArgs.Parse(argVectors.PublicHeader, &unknownArgs);
resourceArgs.Parse(argVectors.Resource, &unknownArgs);
includesArgs.Parse(&argVectors.Includes, &unknownArgs);
+ for (std::size_t i = 0; i < argVectors.FileSets.size(); i++) {
+ // We have to create a separate object for the parsing because
+ // cmArgumentParser<void>::Bind() binds to a specific address, but the
+ // objects in the vector can move around. So we parse in an object with a
+ // fixed address and then copy the data into the vector.
+ cmInstallCommandFileSetArguments fileSetArg(helper.DefaultComponentName);
+ fileSetArg.Parse(argVectors.FileSets[i], &unknownArgs);
+ fileSetArgs[i] = std::move(fileSetArg);
+ }
if (!unknownArgs.empty()) {
// Unknown argument.
@@ -473,6 +506,9 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
privateHeaderArgs.SetGenericArguments(&genericArgs);
publicHeaderArgs.SetGenericArguments(&genericArgs);
resourceArgs.SetGenericArguments(&genericArgs);
+ for (auto& fileSetArg : fileSetArgs) {
+ fileSetArg.SetGenericArguments(&genericArgs);
+ }
success = success && archiveArgs.Finalize();
success = success && libraryArgs.Finalize();
@@ -483,6 +519,9 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
success = success && privateHeaderArgs.Finalize();
success = success && publicHeaderArgs.Finalize();
success = success && resourceArgs.Finalize();
+ for (auto& fileSetArg : fileSetArgs) {
+ success = success && fileSetArg.Finalize();
+ }
if (!success) {
return false;
@@ -493,7 +532,10 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
if (archiveArgs.GetNamelinkOnly() || runtimeArgs.GetNamelinkOnly() ||
objectArgs.GetNamelinkOnly() || frameworkArgs.GetNamelinkOnly() ||
bundleArgs.GetNamelinkOnly() || privateHeaderArgs.GetNamelinkOnly() ||
- publicHeaderArgs.GetNamelinkOnly() || resourceArgs.GetNamelinkOnly()) {
+ publicHeaderArgs.GetNamelinkOnly() || resourceArgs.GetNamelinkOnly() ||
+ std::any_of(fileSetArgs.begin(), fileSetArgs.end(),
+ [](const cmInstallCommandFileSetArguments& fileSetArg)
+ -> bool { return fileSetArg.GetNamelinkOnly(); })) {
status.SetError(
"TARGETS given NAMELINK_ONLY option not in LIBRARY group. "
"The NAMELINK_ONLY option may be specified only following LIBRARY.");
@@ -502,7 +544,10 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
if (archiveArgs.GetNamelinkSkip() || runtimeArgs.GetNamelinkSkip() ||
objectArgs.GetNamelinkSkip() || frameworkArgs.GetNamelinkSkip() ||
bundleArgs.GetNamelinkSkip() || privateHeaderArgs.GetNamelinkSkip() ||
- publicHeaderArgs.GetNamelinkSkip() || resourceArgs.GetNamelinkSkip()) {
+ publicHeaderArgs.GetNamelinkSkip() || resourceArgs.GetNamelinkSkip() ||
+ std::any_of(fileSetArgs.begin(), fileSetArgs.end(),
+ [](const cmInstallCommandFileSetArguments& fileSetArg)
+ -> bool { return fileSetArg.GetNamelinkSkip(); })) {
status.SetError(
"TARGETS given NAMELINK_SKIP option not in LIBRARY group. "
"The NAMELINK_SKIP option may be specified only following LIBRARY.");
@@ -515,7 +560,10 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
bundleArgs.HasNamelinkComponent() ||
privateHeaderArgs.HasNamelinkComponent() ||
publicHeaderArgs.HasNamelinkComponent() ||
- resourceArgs.HasNamelinkComponent()) {
+ resourceArgs.HasNamelinkComponent() ||
+ std::any_of(fileSetArgs.begin(), fileSetArgs.end(),
+ [](const cmInstallCommandFileSetArguments& fileSetArg)
+ -> bool { return fileSetArg.HasNamelinkComponent(); })) {
status.SetError(
"TARGETS given NAMELINK_COMPONENT option not in LIBRARY group. "
"The NAMELINK_COMPONENT option may be specified only following "
@@ -531,12 +579,21 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
!libraryArgs.GetType().empty() || !runtimeArgs.GetType().empty() ||
!objectArgs.GetType().empty() || !frameworkArgs.GetType().empty() ||
!bundleArgs.GetType().empty() || !privateHeaderArgs.GetType().empty() ||
- !publicHeaderArgs.GetType().empty() || !resourceArgs.GetType().empty()) {
+ !publicHeaderArgs.GetType().empty() || !resourceArgs.GetType().empty() ||
+ std::any_of(fileSetArgs.begin(), fileSetArgs.end(),
+ [](const cmInstallCommandFileSetArguments& fileSetArg)
+ -> bool { return !fileSetArg.GetType().empty(); })) {
status.SetError(
"TARGETS given TYPE option. The TYPE option may only be specified in "
" install(FILES) and install(DIRECTORIES).");
return false;
}
+ if (std::any_of(fileSetArgs.begin(), fileSetArgs.end(),
+ [](const cmInstallCommandFileSetArguments& fileSetArg)
+ -> bool { return fileSetArg.GetFileSet().empty(); })) {
+ status.SetError("TARGETS given FILE_SET option without file set name.");
+ return false;
+ }
cmInstallRuntimeDependencySet* runtimeDependencySet = nullptr;
if (withRuntimeDependencies) {
@@ -647,6 +704,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
bool installsPrivateHeader = false;
bool installsPublicHeader = false;
bool installsResource = false;
+ std::vector<bool> installsFileSet(fileSetArgs.size(), false);
// Generate install script code to install the given targets.
for (cmTarget* ti : targets) {
@@ -662,6 +720,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
std::unique_ptr<cmInstallFilesGenerator> privateHeaderGenerator;
std::unique_ptr<cmInstallFilesGenerator> publicHeaderGenerator;
std::unique_ptr<cmInstallFilesGenerator> resourceGenerator;
+ std::vector<std::unique_ptr<cmInstallFileSetGenerator>> fileSetGenerators;
// Avoid selecting default destinations for PUBLIC_HEADER and
// PRIVATE_HEADER if any artifacts are specified.
@@ -991,6 +1050,35 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
}
}
+ if (!namelinkOnly) {
+ for (std::size_t i = 0; i < fileSetArgs.size(); i++) {
+ auto* fileSet = target.GetFileSet(fileSetArgs[i].GetFileSet());
+ auto interfaceFileSetEntries = cmExpandedList(target.GetSafeProperty(
+ cmTarget::GetInterfaceFileSetsPropertyName(fileSet->GetType())));
+ if (fileSet &&
+ std::find(
+ interfaceFileSetEntries.begin(), interfaceFileSetEntries.end(),
+ fileSetArgs[i].GetFileSet()) != interfaceFileSetEntries.end()) {
+ std::string destination;
+ if (fileSet->GetType() == "HEADERS"_s) {
+ destination = helper.GetIncludeDestination(&fileSetArgs[i]);
+ } else {
+ destination = fileSetArgs[i].GetDestination();
+ if (destination.empty()) {
+ status.SetError(
+ cmStrCat("TARGETS given no FILE_SET DESTINATION for target \"",
+ target.GetName(), "\" file set \"",
+ fileSet->GetName(), "\"."));
+ return false;
+ }
+ }
+ fileSetGenerators.push_back(CreateInstallFileSetGenerator(
+ helper, target, fileSet, destination, fileSetArgs[i]));
+ installsFileSet[i] = true;
+ }
+ }
+ }
+
// Add this install rule to an export if one was specified.
addTargetExport();
@@ -1016,6 +1104,9 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
helper.Makefile->AddInstallGenerator(std::move(privateHeaderGenerator));
helper.Makefile->AddInstallGenerator(std::move(publicHeaderGenerator));
helper.Makefile->AddInstallGenerator(std::move(resourceGenerator));
+ for (auto& gen : fileSetGenerators) {
+ helper.Makefile->AddInstallGenerator(std::move(gen));
+ }
}
if (withRuntimeDependencies && !runtimeDependencySet->Empty()) {
@@ -1067,6 +1158,12 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
resourceArgs.GetComponent());
}
+ for (std::size_t i = 0; i < fileSetArgs.size(); i++) {
+ if (installsFileSet[i]) {
+ helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
+ fileSetArgs[i].GetComponent());
+ }
+ }
return true;
}
@@ -2063,12 +2160,20 @@ bool Helper::MakeFilesFullPath(const char* modeName,
const std::vector<std::string>& relFiles,
std::vector<std::string>& absFiles)
{
+ return this->MakeFilesFullPath(
+ modeName, this->Makefile->GetCurrentSourceDirectory(), relFiles, absFiles);
+}
+
+bool Helper::MakeFilesFullPath(const char* modeName,
+ const std::string& basePath,
+ const std::vector<std::string>& relFiles,
+ std::vector<std::string>& absFiles)
+{
for (std::string const& relFile : relFiles) {
std::string file = relFile;
std::string::size_type gpos = cmGeneratorExpression::Find(file);
if (gpos != 0 && !cmSystemTools::FileIsFullPath(file)) {
- file =
- cmStrCat(this->Makefile->GetCurrentSourceDirectory(), '/', relFile);
+ file = cmStrCat(basePath, '/', relFile);
}
// Make sure the file is not a directory.
diff --git a/Source/cmInstallCommandArguments.cxx b/Source/cmInstallCommandArguments.cxx
index cc3df2a..7309316 100644
--- a/Source/cmInstallCommandArguments.cxx
+++ b/Source/cmInstallCommandArguments.cxx
@@ -152,6 +152,11 @@ const std::string& cmInstallCommandArguments::GetType() const
return this->Type;
}
+const std::string& cmInstallCommandArguments::GetDefaultComponent() const
+{
+ return this->DefaultComponentName;
+}
+
const std::vector<std::string>& cmInstallCommandArguments::GetConfigurations()
const
{
@@ -220,3 +225,17 @@ void cmInstallCommandIncludesArgument::Parse(
this->IncludeDirs.push_back(std::move(dir));
}
}
+
+cmInstallCommandFileSetArguments::cmInstallCommandFileSetArguments(
+ std::string defaultComponent)
+ : cmInstallCommandArguments(std::move(defaultComponent))
+{
+ this->Bind("FILE_SET"_s, this->FileSet);
+}
+
+void cmInstallCommandFileSetArguments::Parse(
+ std::vector<std::string> args, std::vector<std::string>* unconsumedArgs)
+{
+ args.insert(args.begin(), "FILE_SET");
+ this->cmInstallCommandArguments::Parse(args, unconsumedArgs);
+}
diff --git a/Source/cmInstallCommandArguments.h b/Source/cmInstallCommandArguments.h
index f318a1a..79bd945 100644
--- a/Source/cmInstallCommandArguments.h
+++ b/Source/cmInstallCommandArguments.h
@@ -34,6 +34,8 @@ public:
bool HasNamelinkComponent() const;
const std::string& GetType() const;
+ const std::string& GetDefaultComponent() const;
+
static bool CheckPermissions(const std::string& onePerm, std::string& perm);
private:
@@ -71,3 +73,17 @@ public:
private:
std::vector<std::string> IncludeDirs;
};
+
+class cmInstallCommandFileSetArguments : public cmInstallCommandArguments
+{
+public:
+ cmInstallCommandFileSetArguments(std::string defaultComponent);
+
+ void Parse(std::vector<std::string> args,
+ std::vector<std::string>* unconsumedArgs);
+
+ const std::string& GetFileSet() const { return this->FileSet; }
+
+private:
+ std::string FileSet;
+};
diff --git a/Source/cmInstallFileSetGenerator.cxx b/Source/cmInstallFileSetGenerator.cxx
new file mode 100644
index 0000000..7121ea3
--- /dev/null
+++ b/Source/cmInstallFileSetGenerator.cxx
@@ -0,0 +1,88 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmInstallFileSetGenerator.h"
+
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "cmFileSet.h"
+#include "cmGeneratorExpression.h"
+#include "cmGlobalGenerator.h"
+#include "cmInstallType.h"
+#include "cmLocalGenerator.h"
+#include "cmStringAlgorithms.h"
+
+cmInstallFileSetGenerator::cmInstallFileSetGenerator(
+ std::string targetName, cmFileSet* fileSet, std::string const& dest,
+ std::string file_permissions, std::vector<std::string> const& configurations,
+ std::string const& component, MessageLevel message, bool exclude_from_all,
+ bool optional, cmListFileBacktrace backtrace)
+ : cmInstallGenerator(dest, configurations, component, message,
+ exclude_from_all, false, std::move(backtrace))
+ , TargetName(std::move(targetName))
+ , FileSet(fileSet)
+ , FilePermissions(std::move(file_permissions))
+ , Optional(optional)
+{
+ this->ActionsPerConfig = true;
+}
+
+cmInstallFileSetGenerator::~cmInstallFileSetGenerator() = default;
+
+bool cmInstallFileSetGenerator::Compute(cmLocalGenerator* lg)
+{
+ this->LocalGenerator = lg;
+
+ // Lookup this target in the current directory.
+ this->Target = lg->FindLocalNonAliasGeneratorTarget(this->TargetName);
+ if (!this->Target) {
+ // If no local target has been found, find it in the global scope.
+ this->Target =
+ lg->GetGlobalGenerator()->FindGeneratorTarget(this->TargetName);
+ }
+
+ return true;
+}
+
+std::string cmInstallFileSetGenerator::GetDestination(
+ std::string const& config) const
+{
+ return cmGeneratorExpression::Evaluate(this->Destination,
+ this->LocalGenerator, config);
+}
+
+void cmInstallFileSetGenerator::GenerateScriptForConfig(
+ std::ostream& os, const std::string& config, Indent indent)
+{
+ for (auto const& dirEntry : this->CalculateFilesPerDir(config)) {
+ std::string destSub;
+ if (!dirEntry.first.empty()) {
+ destSub = cmStrCat('/', dirEntry.first);
+ }
+ this->AddInstallRule(os, cmStrCat(this->GetDestination(config), destSub),
+ cmInstallType_FILES, dirEntry.second,
+ this->GetOptional(), this->FilePermissions.c_str(),
+ nullptr, nullptr, nullptr, indent);
+ }
+}
+
+std::map<std::string, std::vector<std::string>>
+cmInstallFileSetGenerator::CalculateFilesPerDir(
+ const std::string& config) const
+{
+ std::map<std::string, std::vector<std::string>> result;
+
+ auto dirCges = this->FileSet->CompileDirectoryEntries();
+ auto dirs = this->FileSet->EvaluateDirectoryEntries(
+ dirCges, this->LocalGenerator, config, this->Target);
+
+ auto fileCges = this->FileSet->CompileFileEntries();
+ for (auto const& fileCge : fileCges) {
+ this->FileSet->EvaluateFileEntry(
+ dirs, result, fileCge, this->LocalGenerator, config, this->Target);
+ }
+
+ return result;
+}
diff --git a/Source/cmInstallFileSetGenerator.h b/Source/cmInstallFileSetGenerator.h
new file mode 100644
index 0000000..8d067d9
--- /dev/null
+++ b/Source/cmInstallFileSetGenerator.h
@@ -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 <iosfwd>
+#include <map>
+#include <string>
+#include <vector>
+
+#include "cmInstallGenerator.h"
+#include "cmListFileCache.h"
+#include "cmScriptGenerator.h"
+
+class cmGeneratorTarget;
+class cmFileSet;
+class cmLocalGenerator;
+
+class cmInstallFileSetGenerator : public cmInstallGenerator
+{
+public:
+ cmInstallFileSetGenerator(std::string targetName, cmFileSet* fileSet,
+ std::string const& dest,
+ std::string file_permissions,
+ std::vector<std::string> const& configurations,
+ std::string const& component, MessageLevel message,
+ bool exclude_from_all, bool optional,
+ cmListFileBacktrace backtrace);
+ ~cmInstallFileSetGenerator() override;
+
+ bool Compute(cmLocalGenerator* lg) override;
+
+ std::string GetDestination(std::string const& config) const;
+ std::string GetDestination() const { return this->Destination; }
+ bool GetOptional() const { return this->Optional; }
+ cmFileSet* GetFileSet() const { return this->FileSet; }
+ cmGeneratorTarget* GetTarget() const { return this->Target; }
+
+protected:
+ void GenerateScriptForConfig(std::ostream& os, const std::string& config,
+ Indent indent) override;
+
+private:
+ std::string TargetName;
+ cmLocalGenerator* LocalGenerator;
+ cmFileSet* const FileSet;
+ std::string const FilePermissions;
+ bool const Optional;
+ cmGeneratorTarget* Target;
+
+ std::map<std::string, std::vector<std::string>> CalculateFilesPerDir(
+ const std::string& config) const;
+};