summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2021-06-01 12:42:08 (GMT)
committerKitware Robot <kwrobot@kitware.com>2021-06-01 12:42:16 (GMT)
commit02957bb58906bcb769410b6d4938dbdbfcacb78f (patch)
tree4d82f0744daedfb77cc13952663bc3aefed907da /Source
parent5eb2aa1f57e99f30be5ea145ce9af5fd9652392f (diff)
parentf7ba3a05893279f6704db15358b08fd4ecb28814 (diff)
downloadCMake-02957bb58906bcb769410b6d4938dbdbfcacb78f.zip
CMake-02957bb58906bcb769410b6d4938dbdbfcacb78f.tar.gz
CMake-02957bb58906bcb769410b6d4938dbdbfcacb78f.tar.bz2
Merge topic 'install-imported-runtime-artifacts'
f7ba3a0589 FileAPI: Populate information for IMPORTED_RUNTIME_ARTIFACTS df7040a271 install(): Add IMPORTED_RUNTIME_ARTIFACTS mode 60e752ced8 Refactor: Move common methods into cmInstallGenerator Acked-by: Kitware Robot <kwrobot@kitware.com> Merge-request: !6162
Diffstat (limited to 'Source')
-rw-r--r--Source/CMakeLists.txt2
-rw-r--r--Source/cmFileAPICodemodel.cxx10
-rw-r--r--Source/cmInstallCommand.cxx224
-rw-r--r--Source/cmInstallExportGenerator.cxx5
-rw-r--r--Source/cmInstallGenerator.cxx63
-rw-r--r--Source/cmInstallGenerator.h16
-rw-r--r--Source/cmInstallImportedRuntimeArtifactsGenerator.cxx146
-rw-r--r--Source/cmInstallImportedRuntimeArtifactsGenerator.h44
-rw-r--r--Source/cmInstallTargetGenerator.cxx73
-rw-r--r--Source/cmInstallTargetGenerator.h9
10 files changed, 514 insertions, 78 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index bd9e4c2..844a2ee 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -350,6 +350,8 @@ set(SRCS
cmInstalledFile.cxx
cmInstallFilesGenerator.h
cmInstallFilesGenerator.cxx
+ cmInstallImportedRuntimeArtifactsGenerator.h
+ cmInstallImportedRuntimeArtifactsGenerator.cxx
cmInstallScriptGenerator.h
cmInstallScriptGenerator.cxx
cmInstallSubdirectoryGenerator.h
diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx
index 945b547..ff11f4a 100644
--- a/Source/cmFileAPICodemodel.cxx
+++ b/Source/cmFileAPICodemodel.cxx
@@ -29,6 +29,7 @@
#include "cmInstallExportGenerator.h"
#include "cmInstallFilesGenerator.h"
#include "cmInstallGenerator.h"
+#include "cmInstallImportedRuntimeArtifactsGenerator.h"
#include "cmInstallScriptGenerator.h"
#include "cmInstallSubdirectoryGenerator.h"
#include "cmInstallTargetGenerator.h"
@@ -1009,6 +1010,15 @@ Json::Value DirectoryObject::DumpInstaller(cmInstallGenerator* gen)
installer["scriptFile"] = RelativeIfUnder(
this->TopSource, installScript->GetScript(this->Config));
}
+ } else if (auto* installImportedRuntimeArtifacts =
+ dynamic_cast<cmInstallImportedRuntimeArtifactsGenerator*>(
+ gen)) {
+ installer["type"] = "importedRuntimeArtifacts";
+ installer["destination"] =
+ installImportedRuntimeArtifacts->GetDestination(this->Config);
+ if (installImportedRuntimeArtifacts->GetOptional()) {
+ installer["isOptional"] = true;
+ }
}
// Add fields common to all install generators.
diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx
index e973764..c9bb467 100644
--- a/Source/cmInstallCommand.cxx
+++ b/Source/cmInstallCommand.cxx
@@ -2,6 +2,7 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmInstallCommand.h"
+#include <cassert>
#include <cstddef>
#include <set>
#include <sstream>
@@ -22,6 +23,7 @@
#include "cmInstallExportGenerator.h"
#include "cmInstallFilesGenerator.h"
#include "cmInstallGenerator.h"
+#include "cmInstallImportedRuntimeArtifactsGenerator.h"
#include "cmInstallScriptGenerator.h"
#include "cmInstallTargetGenerator.h"
#include "cmListFileCache.h"
@@ -865,6 +867,227 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
return true;
}
+bool HandleImportedRuntimeArtifactsMode(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ Helper helper(status);
+
+ // This is the IMPORTED_RUNTIME_ARTIFACTS mode.
+ std::vector<cmTarget*> targets;
+
+ struct ArgVectors
+ {
+ std::vector<std::string> Library;
+ std::vector<std::string> Runtime;
+ std::vector<std::string> Framework;
+ std::vector<std::string> Bundle;
+ };
+
+ static auto const argHelper = cmArgumentParser<ArgVectors>{}
+ .Bind("LIBRARY"_s, &ArgVectors::Library)
+ .Bind("RUNTIME"_s, &ArgVectors::Runtime)
+ .Bind("FRAMEWORK"_s, &ArgVectors::Framework)
+ .Bind("BUNDLE"_s, &ArgVectors::Bundle);
+
+ std::vector<std::string> genericArgVector;
+ ArgVectors const argVectors = argHelper.Parse(args, &genericArgVector);
+
+ // now parse the generic args (i.e. the ones not specialized on LIBRARY,
+ // RUNTIME etc. (see above)
+ std::vector<std::string> targetList;
+ std::vector<std::string> unknownArgs;
+ cmInstallCommandArguments genericArgs(helper.DefaultComponentName);
+ genericArgs.Bind("IMPORTED_RUNTIME_ARTIFACTS"_s, targetList);
+ genericArgs.Parse(genericArgVector, &unknownArgs);
+ bool success = genericArgs.Finalize();
+
+ cmInstallCommandArguments libraryArgs(helper.DefaultComponentName);
+ cmInstallCommandArguments runtimeArgs(helper.DefaultComponentName);
+ cmInstallCommandArguments frameworkArgs(helper.DefaultComponentName);
+ cmInstallCommandArguments bundleArgs(helper.DefaultComponentName);
+
+ // now parse the args for specific parts of the target (e.g. LIBRARY,
+ // RUNTIME etc.
+ libraryArgs.Parse(argVectors.Library, &unknownArgs);
+ runtimeArgs.Parse(argVectors.Runtime, &unknownArgs);
+ frameworkArgs.Parse(argVectors.Framework, &unknownArgs);
+ bundleArgs.Parse(argVectors.Bundle, &unknownArgs);
+
+ if (!unknownArgs.empty()) {
+ // Unknown argument.
+ status.SetError(
+ cmStrCat("IMPORTED_RUNTIME_ARTIFACTS given unknown argument \"",
+ unknownArgs[0], "\"."));
+ return false;
+ }
+
+ // apply generic args
+ libraryArgs.SetGenericArguments(&genericArgs);
+ runtimeArgs.SetGenericArguments(&genericArgs);
+ frameworkArgs.SetGenericArguments(&genericArgs);
+ bundleArgs.SetGenericArguments(&genericArgs);
+
+ success = success && libraryArgs.Finalize();
+ success = success && runtimeArgs.Finalize();
+ success = success && frameworkArgs.Finalize();
+ success = success && bundleArgs.Finalize();
+
+ if (!success) {
+ return false;
+ }
+
+ // Check if there is something to do.
+ if (targetList.empty()) {
+ return true;
+ }
+
+ for (std::string const& tgt : targetList) {
+ if (helper.Makefile->IsAlias(tgt)) {
+ status.SetError(cmStrCat("IMPORTED_RUNTIME_ARTIFACTS given target \"",
+ tgt, "\" which is an alias."));
+ return false;
+ }
+ // Lookup this target in the current directory.
+ cmTarget* target = helper.Makefile->FindTargetToUse(tgt);
+ if (!target || !target->IsImported()) {
+ // If no local target has been found, find it in the global scope.
+ cmTarget* const global_target =
+ helper.Makefile->GetGlobalGenerator()->FindTarget(tgt, true);
+ if (global_target && global_target->IsImported()) {
+ target = global_target;
+ }
+ }
+ if (target) {
+ // Found the target. Check its type.
+ if (target->GetType() != cmStateEnums::EXECUTABLE &&
+ target->GetType() != cmStateEnums::SHARED_LIBRARY &&
+ target->GetType() != cmStateEnums::MODULE_LIBRARY) {
+ status.SetError(
+ cmStrCat("IMPORTED_RUNTIME_ARTIFACTS given target \"", tgt,
+ "\" which is not an executable, library, or module."));
+ return false;
+ }
+ // Store the target in the list to be installed.
+ targets.push_back(target);
+ } else {
+ // Did not find the target.
+ status.SetError(cmStrCat("IMPORTED_RUNTIME_ARTIFACTS given target \"",
+ tgt, "\" which does not exist."));
+ return false;
+ }
+ }
+
+ // Keep track of whether we will be performing an installation of
+ // any files of the given type.
+ bool installsLibrary = false;
+ bool installsRuntime = false;
+ bool installsFramework = false;
+ bool installsBundle = false;
+
+ auto const createInstallGenerator =
+ [helper](cmTarget& target, const cmInstallCommandArguments& typeArgs,
+ const std::string& destination)
+ -> std::unique_ptr<cmInstallImportedRuntimeArtifactsGenerator> {
+ return cm::make_unique<cmInstallImportedRuntimeArtifactsGenerator>(
+ target.GetName(), destination, typeArgs.GetPermissions(),
+ typeArgs.GetConfigurations(), typeArgs.GetComponent(),
+ cmInstallGenerator::SelectMessageLevel(helper.Makefile),
+ typeArgs.GetExcludeFromAll(), typeArgs.GetOptional(),
+ helper.Makefile->GetBacktrace());
+ };
+
+ // Generate install script code to install the given targets.
+ for (cmTarget* ti : targets) {
+ // Handle each target type.
+ cmTarget& target = *ti;
+ std::unique_ptr<cmInstallImportedRuntimeArtifactsGenerator>
+ libraryGenerator;
+ std::unique_ptr<cmInstallImportedRuntimeArtifactsGenerator>
+ runtimeGenerator;
+ std::unique_ptr<cmInstallImportedRuntimeArtifactsGenerator>
+ frameworkGenerator;
+ std::unique_ptr<cmInstallImportedRuntimeArtifactsGenerator>
+ bundleGenerator;
+
+ switch (target.GetType()) {
+ case cmStateEnums::SHARED_LIBRARY:
+ if (target.IsDLLPlatform()) {
+ runtimeGenerator = createInstallGenerator(
+ target, runtimeArgs, helper.GetRuntimeDestination(&runtimeArgs));
+ } else if (target.IsFrameworkOnApple()) {
+ if (frameworkArgs.GetDestination().empty()) {
+ status.SetError(cmStrCat("IMPORTED_RUNTIME_ARTIFACTS given no "
+ "FRAMEWORK DESTINATION for shared "
+ "library FRAMEWORK target \"",
+ target.GetName(), "\"."));
+ return false;
+ }
+ frameworkGenerator = createInstallGenerator(
+ target, frameworkArgs, frameworkArgs.GetDestination());
+ } else {
+ libraryGenerator = createInstallGenerator(
+ target, libraryArgs, helper.GetLibraryDestination(&libraryArgs));
+ }
+ break;
+ case cmStateEnums::MODULE_LIBRARY:
+ libraryGenerator = createInstallGenerator(
+ target, libraryArgs, helper.GetLibraryDestination(&libraryArgs));
+ break;
+ case cmStateEnums::EXECUTABLE:
+ if (target.IsAppBundleOnApple()) {
+ if (bundleArgs.GetDestination().empty()) {
+ status.SetError(
+ cmStrCat("IMPORTED_RUNTIME_ARTIFACTS given no BUNDLE "
+ "DESTINATION for MACOSX_BUNDLE executable target \"",
+ target.GetName(), "\"."));
+ return false;
+ }
+ bundleGenerator = createInstallGenerator(
+ target, bundleArgs, bundleArgs.GetDestination());
+ } else {
+ runtimeGenerator = createInstallGenerator(
+ target, runtimeArgs, helper.GetRuntimeDestination(&runtimeArgs));
+ }
+ break;
+ default:
+ assert(false && "This should never happen");
+ break;
+ }
+
+ // Keep track of whether we're installing anything in each category
+ installsLibrary = installsLibrary || libraryGenerator;
+ installsRuntime = installsRuntime || runtimeGenerator;
+ installsFramework = installsFramework || frameworkGenerator;
+ installsBundle = installsBundle || bundleGenerator;
+
+ helper.Makefile->AddInstallGenerator(std::move(libraryGenerator));
+ helper.Makefile->AddInstallGenerator(std::move(runtimeGenerator));
+ helper.Makefile->AddInstallGenerator(std::move(frameworkGenerator));
+ helper.Makefile->AddInstallGenerator(std::move(bundleGenerator));
+ }
+
+ // Tell the global generator about any installation component names
+ // specified
+ if (installsLibrary) {
+ helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
+ libraryArgs.GetComponent());
+ }
+ if (installsRuntime) {
+ helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
+ runtimeArgs.GetComponent());
+ }
+ if (installsFramework) {
+ helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
+ frameworkArgs.GetComponent());
+ }
+ if (installsBundle) {
+ helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
+ bundleArgs.GetComponent());
+ }
+
+ return true;
+}
+
bool HandleFilesMode(std::vector<std::string> const& args,
cmExecutionStatus& status)
{
@@ -1705,6 +1928,7 @@ bool cmInstallCommand(std::vector<std::string> const& args,
{ "SCRIPT"_s, HandleScriptMode },
{ "CODE"_s, HandleScriptMode },
{ "TARGETS"_s, HandleTargetsMode },
+ { "IMPORTED_RUNTIME_ARTIFACTS"_s, HandleImportedRuntimeArtifactsMode },
{ "FILES"_s, HandleFilesMode },
{ "PROGRAMS"_s, HandleFilesMode },
{ "DIRECTORY"_s, HandleDirectoryMode },
diff --git a/Source/cmInstallExportGenerator.cxx b/Source/cmInstallExportGenerator.cxx
index ccefd92..d932fd9 100644
--- a/Source/cmInstallExportGenerator.cxx
+++ b/Source/cmInstallExportGenerator.cxx
@@ -184,9 +184,8 @@ void cmInstallExportGenerator::GenerateScriptActions(std::ostream& os,
Indent indent)
{
// Remove old per-configuration export files if the main changes.
- std::string installedDir =
- cmStrCat("$ENV{DESTDIR}",
- this->ConvertToAbsoluteDestination(this->Destination), '/');
+ 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();
diff --git a/Source/cmInstallGenerator.cxx b/Source/cmInstallGenerator.cxx
index cf5f45e..9f0d119 100644
--- a/Source/cmInstallGenerator.cxx
+++ b/Source/cmInstallGenerator.cxx
@@ -2,10 +2,11 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmInstallGenerator.h"
-#include <ostream>
+#include <sstream>
#include <utility>
#include "cmMakefile.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
cmInstallGenerator::cmInstallGenerator(
@@ -98,7 +99,7 @@ void cmInstallGenerator::AddInstallRule(
<< "${CMAKE_ABSOLUTE_DESTINATION_FILES}\")\n";
os << indent << "endif()\n";
}
- std::string absDest = this->ConvertToAbsoluteDestination(dest);
+ std::string absDest = ConvertToAbsoluteDestination(dest);
os << "file(INSTALL DESTINATION \"" << absDest << "\" TYPE " << stype;
if (optional) {
os << " OPTIONAL";
@@ -183,7 +184,7 @@ bool cmInstallGenerator::InstallsForConfig(const std::string& config)
}
std::string cmInstallGenerator::ConvertToAbsoluteDestination(
- std::string const& dest) const
+ std::string const& dest)
{
std::string result;
if (!dest.empty() && !cmSystemTools::FileIsFullPath(dest)) {
@@ -211,3 +212,59 @@ cmInstallGenerator::MessageLevel cmInstallGenerator::SelectMessageLevel(
}
return MessageDefault;
}
+
+std::string cmInstallGenerator::GetDestDirPath(std::string const& file)
+{
+ // Construct the path of the file on disk after installation on
+ // which tweaks may be performed.
+ std::string toDestDirPath = "$ENV{DESTDIR}";
+ if (file[0] != '/' && file[0] != '$') {
+ toDestDirPath += "/";
+ }
+ toDestDirPath += file;
+ return toDestDirPath;
+}
+
+void cmInstallGenerator::AddTweak(std::ostream& os, Indent indent,
+ const std::string& config,
+ std::string const& file,
+ const TweakMethod& tweak)
+{
+ std::ostringstream tw;
+ tweak(tw, indent.Next(), config, file);
+ std::string tws = tw.str();
+ if (!tws.empty()) {
+ os << indent << "if(EXISTS \"" << file << "\" AND\n"
+ << indent << " NOT IS_SYMLINK \"" << file << "\")\n";
+ os << tws;
+ os << indent << "endif()\n";
+ }
+}
+
+void cmInstallGenerator::AddTweak(std::ostream& os, Indent indent,
+ const std::string& config,
+ std::string const& dir,
+ std::vector<std::string> const& files,
+ const TweakMethod& tweak)
+{
+ if (files.size() == 1) {
+ // Tweak a single file.
+ AddTweak(os, indent, config, GetDestDirPath(cmStrCat(dir, files[0])),
+ tweak);
+ } else {
+ // Generate a foreach loop to tweak multiple files.
+ std::ostringstream tw;
+ AddTweak(tw, indent.Next(), config, "${file}", tweak);
+ std::string tws = tw.str();
+ if (!tws.empty()) {
+ Indent indent2 = indent.Next().Next();
+ os << indent << "foreach(file\n";
+ for (std::string const& f : files) {
+ os << indent2 << "\"" << GetDestDirPath(cmStrCat(dir, f)) << "\"\n";
+ }
+ os << indent2 << ")\n";
+ os << tws;
+ os << indent << "endforeach()\n";
+ }
+ }
+}
diff --git a/Source/cmInstallGenerator.h b/Source/cmInstallGenerator.h
index 0117617..97acb88 100644
--- a/Source/cmInstallGenerator.h
+++ b/Source/cmInstallGenerator.h
@@ -4,6 +4,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <functional>
#include <iosfwd>
#include <string>
#include <vector>
@@ -53,7 +54,7 @@ public:
/** Get the install destination as it should appear in the
installation script. */
- std::string ConvertToAbsoluteDestination(std::string const& dest) const;
+ static std::string ConvertToAbsoluteDestination(std::string const& dest);
/** Test if this generator installs something for a given configuration. */
bool InstallsForConfig(const std::string& config);
@@ -70,12 +71,25 @@ public:
cmListFileBacktrace const& GetBacktrace() const { return this->Backtrace; }
+ static std::string GetDestDirPath(std::string const& file);
+
protected:
void GenerateScript(std::ostream& os) override;
std::string CreateComponentTest(const std::string& component,
bool exclude_from_all);
+ using TweakMethod =
+ std::function<void(std::ostream& os, Indent indent,
+ const std::string& config, const std::string& file)>;
+ static void AddTweak(std::ostream& os, Indent indent,
+ const std::string& config, std::string const& file,
+ const TweakMethod& tweak);
+ static void AddTweak(std::ostream& os, Indent indent,
+ const std::string& config, std::string const& dir,
+ std::vector<std::string> const& files,
+ const TweakMethod& tweak);
+
// Information shared by most generator types.
std::string const Destination;
std::string const Component;
diff --git a/Source/cmInstallImportedRuntimeArtifactsGenerator.cxx b/Source/cmInstallImportedRuntimeArtifactsGenerator.cxx
new file mode 100644
index 0000000..01980ac
--- /dev/null
+++ b/Source/cmInstallImportedRuntimeArtifactsGenerator.cxx
@@ -0,0 +1,146 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmInstallImportedRuntimeArtifactsGenerator.h"
+
+#include <cassert>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "cmsys/RegularExpression.hxx"
+
+#include "cmGeneratorExpression.h"
+#include "cmGeneratorTarget.h"
+#include "cmGlobalGenerator.h"
+#include "cmInstallType.h"
+#include "cmListFileCache.h"
+#include "cmLocalGenerator.h"
+#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
+
+namespace {
+const cmsys::RegularExpression FrameworkRegularExpression(
+ "^(.*/)?([^/]*)\\.framework/(.*)$");
+
+const cmsys::RegularExpression BundleRegularExpression(
+ "^(.*/)?([^/]*)\\.app/(.*)$");
+
+const cmsys::RegularExpression CFBundleRegularExpression(
+ "^(.*/)?([^/]*)\\.bundle/(.*)$");
+}
+
+cmInstallImportedRuntimeArtifactsGenerator::
+ cmInstallImportedRuntimeArtifactsGenerator(
+ std::string targetName, 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))
+ , FilePermissions(std::move(file_permissions))
+ , Optional(optional)
+{
+ this->ActionsPerConfig = true;
+}
+
+bool cmInstallImportedRuntimeArtifactsGenerator::Compute(cmLocalGenerator* lg)
+{
+ // Lookup this target in the current directory.
+ this->Target = lg->FindGeneratorTargetToUse(this->TargetName);
+ if (!this->Target || !this->Target->IsImported()) {
+ // If no local target has been found, find it in the global scope.
+ this->Target =
+ lg->GetGlobalGenerator()->FindGeneratorTarget(this->TargetName);
+ }
+
+ return true;
+}
+
+std::string cmInstallImportedRuntimeArtifactsGenerator::GetDestination(
+ std::string const& config) const
+{
+ return cmGeneratorExpression::Evaluate(
+ this->Destination, this->Target->GetLocalGenerator(), config);
+}
+
+void cmInstallImportedRuntimeArtifactsGenerator::GenerateScriptForConfig(
+ std::ostream& os, const std::string& config, Indent indent)
+{
+ auto location = this->Target->GetFullPath(config);
+
+ switch (this->Target->GetType()) {
+ case cmStateEnums::EXECUTABLE:
+ if (this->Target->IsBundleOnApple()) {
+ cmsys::RegularExpressionMatch match;
+ if (BundleRegularExpression.find(location.c_str(), match)) {
+ auto bundleDir = match.match(1);
+ auto bundleName = match.match(2);
+ auto bundlePath = cmStrCat(bundleDir, bundleName, ".app");
+ this->AddInstallRule(os, this->GetDestination(config),
+ cmInstallType_DIRECTORY, { bundlePath },
+ this->Optional, nullptr,
+ this->FilePermissions.c_str(), nullptr,
+ " USE_SOURCE_PERMISSIONS", indent);
+ }
+ } else {
+ this->AddInstallRule(os, this->GetDestination(config),
+ cmInstallType_EXECUTABLE, { location },
+ this->Optional, this->FilePermissions.c_str(),
+ nullptr, nullptr, nullptr, indent);
+ }
+ break;
+ case cmStateEnums::SHARED_LIBRARY:
+ if (this->Target->IsFrameworkOnApple()) {
+ cmsys::RegularExpressionMatch match;
+ if (FrameworkRegularExpression.find(location.c_str(), match)) {
+ auto frameworkDir = match.match(1);
+ auto frameworkName = match.match(2);
+ auto frameworkPath =
+ cmStrCat(frameworkDir, frameworkName, ".framework");
+ this->AddInstallRule(os, this->GetDestination(config),
+ cmInstallType_DIRECTORY, { frameworkPath },
+ this->Optional, nullptr,
+ this->FilePermissions.c_str(), nullptr,
+ " USE_SOURCE_PERMISSIONS", indent);
+ }
+ } else {
+ std::vector<std::string> files{ location };
+ auto soName = this->Target->GetSOName(config);
+ auto soNameFile =
+ cmStrCat(this->Target->GetDirectory(config), '/', soName);
+ if (!soName.empty() && soNameFile != location) {
+ files.push_back(soNameFile);
+ }
+ this->AddInstallRule(os, this->GetDestination(config),
+ cmInstallType_SHARED_LIBRARY, files,
+ this->Optional, this->FilePermissions.c_str(),
+ nullptr, nullptr, nullptr, indent);
+ }
+ break;
+ case cmStateEnums::MODULE_LIBRARY:
+ if (this->Target->IsCFBundleOnApple()) {
+ cmsys::RegularExpressionMatch match;
+ if (CFBundleRegularExpression.find(location.c_str(), match)) {
+ auto bundleDir = match.match(1);
+ auto bundleName = match.match(2);
+ auto bundlePath = cmStrCat(bundleDir, bundleName, ".bundle");
+ this->AddInstallRule(os, this->GetDestination(config),
+ cmInstallType_DIRECTORY, { bundlePath },
+ this->Optional, nullptr,
+ this->FilePermissions.c_str(), nullptr,
+ " USE_SOURCE_PERMISSIONS", indent);
+ }
+ } else {
+ this->AddInstallRule(os, this->GetDestination(config),
+ cmInstallType_MODULE_LIBRARY, { location },
+ this->Optional, this->FilePermissions.c_str(),
+ nullptr, nullptr, nullptr, indent);
+ }
+ break;
+ default:
+ assert(false && "This should never happen");
+ break;
+ }
+}
diff --git a/Source/cmInstallImportedRuntimeArtifactsGenerator.h b/Source/cmInstallImportedRuntimeArtifactsGenerator.h
new file mode 100644
index 0000000..9e045ee
--- /dev/null
+++ b/Source/cmInstallImportedRuntimeArtifactsGenerator.h
@@ -0,0 +1,44 @@
+/* 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 "cmInstallGenerator.h"
+#include "cmListFileCache.h"
+#include "cmScriptGenerator.h"
+
+class cmGeneratorTarget;
+class cmLocalGenerator;
+
+class cmInstallImportedRuntimeArtifactsGenerator : public cmInstallGenerator
+{
+public:
+ cmInstallImportedRuntimeArtifactsGenerator(
+ std::string targetName, 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 = cmListFileBacktrace());
+ ~cmInstallImportedRuntimeArtifactsGenerator() override = default;
+
+ bool Compute(cmLocalGenerator* lg) override;
+
+ cmGeneratorTarget* GetTarget() const { return this->Target; }
+
+ bool GetOptional() const { return this->Optional; }
+
+ std::string GetDestination(std::string const& config) const;
+
+protected:
+ void GenerateScriptForConfig(std::ostream& os, const std::string& config,
+ Indent indent) override;
+
+private:
+ std::string const TargetName;
+ cmGeneratorTarget* Target;
+ std::string const FilePermissions;
+ bool const Optional;
+};
diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx
index 3e79ad8..35165cf 100644
--- a/Source/cmInstallTargetGenerator.cxx
+++ b/Source/cmInstallTargetGenerator.cxx
@@ -77,12 +77,15 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(
}
// Tweak files located in the destination directory.
- std::string toDir = cmStrCat(this->ConvertToAbsoluteDestination(dest), '/');
+ std::string toDir = cmStrCat(ConvertToAbsoluteDestination(dest), '/');
// Add pre-installation tweaks.
if (!files.NoTweak) {
- this->AddTweak(os, indent, config, toDir, files.To,
- &cmInstallTargetGenerator::PreReplacementTweaks);
+ AddTweak(os, indent, config, toDir, files.To,
+ [this](std::ostream& o, Indent i, const std::string& c,
+ const std::string& f) {
+ this->PreReplacementTweaks(o, i, c, f);
+ });
}
// Write code to install the target file.
@@ -102,8 +105,11 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(
// Add post-installation tweaks.
if (!files.NoTweak) {
- this->AddTweak(os, indent, config, toDir, files.To,
- &cmInstallTargetGenerator::PostReplacementTweaks);
+ AddTweak(os, indent, config, toDir, files.To,
+ [this](std::ostream& o, Indent i, const std::string& c,
+ const std::string& f) {
+ this->PostReplacementTweaks(o, i, c, f);
+ });
}
}
@@ -461,63 +467,6 @@ bool cmInstallTargetGenerator::Compute(cmLocalGenerator* lg)
return true;
}
-void cmInstallTargetGenerator::AddTweak(std::ostream& os, Indent indent,
- const std::string& config,
- std::string const& file,
- TweakMethod tweak)
-{
- std::ostringstream tw;
- (this->*tweak)(tw, indent.Next(), config, file);
- std::string tws = tw.str();
- if (!tws.empty()) {
- os << indent << "if(EXISTS \"" << file << "\" AND\n"
- << indent << " NOT IS_SYMLINK \"" << file << "\")\n";
- os << tws;
- os << indent << "endif()\n";
- }
-}
-
-void cmInstallTargetGenerator::AddTweak(std::ostream& os, Indent indent,
- const std::string& config,
- std::string const& dir,
- std::vector<std::string> const& files,
- TweakMethod tweak)
-{
- if (files.size() == 1) {
- // Tweak a single file.
- this->AddTweak(os, indent, config,
- this->GetDestDirPath(cmStrCat(dir, files[0])), tweak);
- } else {
- // Generate a foreach loop to tweak multiple files.
- std::ostringstream tw;
- this->AddTweak(tw, indent.Next(), config, "${file}", tweak);
- std::string tws = tw.str();
- if (!tws.empty()) {
- Indent indent2 = indent.Next().Next();
- os << indent << "foreach(file\n";
- for (std::string const& f : files) {
- os << indent2 << "\"" << this->GetDestDirPath(cmStrCat(dir, f))
- << "\"\n";
- }
- os << indent2 << ")\n";
- os << tws;
- os << indent << "endforeach()\n";
- }
- }
-}
-
-std::string cmInstallTargetGenerator::GetDestDirPath(std::string const& file)
-{
- // Construct the path of the file on disk after installation on
- // which tweaks may be performed.
- std::string toDestDirPath = "$ENV{DESTDIR}";
- if (file[0] != '/' && file[0] != '$') {
- toDestDirPath += "/";
- }
- toDestDirPath += file;
- return toDestDirPath;
-}
-
void cmInstallTargetGenerator::PreReplacementTweaks(std::ostream& os,
Indent indent,
const std::string& config,
diff --git a/Source/cmInstallTargetGenerator.h b/Source/cmInstallTargetGenerator.h
index 84fce42..6173f2c 100644
--- a/Source/cmInstallTargetGenerator.h
+++ b/Source/cmInstallTargetGenerator.h
@@ -93,15 +93,6 @@ public:
protected:
void GenerateScriptForConfig(std::ostream& os, const std::string& config,
Indent indent) override;
- using TweakMethod = void (cmInstallTargetGenerator::*)(std::ostream&, Indent,
- const std::string&,
- const std::string&);
- void AddTweak(std::ostream& os, Indent indent, const std::string& config,
- std::string const& file, TweakMethod tweak);
- void AddTweak(std::ostream& os, Indent indent, const std::string& config,
- std::string const& dir, std::vector<std::string> const& files,
- TweakMethod tweak);
- std::string GetDestDirPath(std::string const& file);
void PreReplacementTweaks(std::ostream& os, Indent indent,
const std::string& config,
std::string const& file);