Browse Source

Merge topic 'install-minor-refactor'

203cc694dd cmInstallGenerator: Add accessors for settings common to all installers
e32818dd76 cmInstallGenerator: Add backtrace to all install generators
eea61268e6 cmInstallExportGenerator: Add method to get installed file name
1215092507 cmInstallScriptGenerator: Factor out method to get script
2452cfdeab cmInstallDirectoryGenerator: Factor out method to get list of directories
5b23d8a7b1 cmInstallFilesGenerator: Factor out method to get list of files
5990276226 cmInstallTargetGenerator: Factor out method to get list of target files
c9e87e3447 cmInstallTargetGenerator: Avoid duplicating install destination in memory
...

Acked-by: Kitware Robot <[email protected]>
Merge-request: !5746
Brad King 4 years ago
parent
commit
e9875b6164

+ 1 - 0
Source/cmGlobalGenerator.cxx

@@ -1811,6 +1811,7 @@ void cmGlobalGenerator::ClearGeneratorMembers()
 
   this->AliasTargets.clear();
   this->ExportSets.clear();
+  this->InstallComponents.clear();
   this->TargetDependencies.clear();
   this->TargetSearchIndex.clear();
   this->GeneratorTargetSearchIndex.clear();

+ 14 - 8
Source/cmInstallCommand.cxx

@@ -133,7 +133,8 @@ std::unique_ptr<cmInstallFilesGenerator> CreateInstallFilesGenerator(
   return cm::make_unique<cmInstallFilesGenerator>(
     absFiles, destination, programs, args.GetPermissions(),
     args.GetConfigurations(), args.GetComponent(), message,
-    args.GetExcludeFromAll(), args.GetRename(), args.GetOptional());
+    args.GetExcludeFromAll(), args.GetRename(), args.GetOptional(),
+    mf->GetBacktrace());
 }
 
 std::unique_ptr<cmInstallFilesGenerator> CreateInstallFilesGenerator(
@@ -206,14 +207,16 @@ bool HandleScriptMode(std::vector<std::string> const& args,
         return false;
       }
       helper.Makefile->AddInstallGenerator(
-        cm::make_unique<cmInstallScriptGenerator>(script, false, component,
-                                                  exclude_from_all));
+        cm::make_unique<cmInstallScriptGenerator>(
+          script, false, component, exclude_from_all,
+          helper.Makefile->GetBacktrace()));
     } else if (doing_code) {
       doing_code = false;
       std::string const& code = arg;
       helper.Makefile->AddInstallGenerator(
-        cm::make_unique<cmInstallScriptGenerator>(code, true, component,
-                                                  exclude_from_all));
+        cm::make_unique<cmInstallScriptGenerator>(
+          code, true, component, exclude_from_all,
+          helper.Makefile->GetBacktrace()));
     }
   }
 
@@ -1253,7 +1256,8 @@ bool HandleDirectoryMode(std::vector<std::string> const& args,
   helper.Makefile->AddInstallGenerator(
     cm::make_unique<cmInstallDirectoryGenerator>(
       dirs, *destination, permissions_file, permissions_dir, configurations,
-      component, message, exclude_from_all, literal_args, optional));
+      component, message, exclude_from_all, literal_args, optional,
+      helper.Makefile->GetBacktrace()));
 
   // Tell the global generator about any installation component names
   // specified.
@@ -1345,7 +1349,8 @@ bool HandleExportAndroidMKMode(std::vector<std::string> const& args,
     cm::make_unique<cmInstallExportGenerator>(
       &exportSet, ica.GetDestination(), ica.GetPermissions(),
       ica.GetConfigurations(), ica.GetComponent(), message,
-      ica.GetExcludeFromAll(), fname, name_space, exportOld, true));
+      ica.GetExcludeFromAll(), fname, name_space, exportOld, true,
+      helper.Makefile->GetBacktrace()));
 
   return true;
 #else
@@ -1458,7 +1463,8 @@ bool HandleExportMode(std::vector<std::string> const& args,
     cm::make_unique<cmInstallExportGenerator>(
       &exportSet, ica.GetDestination(), ica.GetPermissions(),
       ica.GetConfigurations(), ica.GetComponent(), message,
-      ica.GetExcludeFromAll(), fname, name_space, exportOld, false));
+      ica.GetExcludeFromAll(), fname, name_space, exportOld, false,
+      helper.Makefile->GetBacktrace()));
 
   return true;
 }

+ 19 - 7
Source/cmInstallDirectoryGenerator.cxx

@@ -16,9 +16,9 @@ cmInstallDirectoryGenerator::cmInstallDirectoryGenerator(
   std::string file_permissions, std::string dir_permissions,
   std::vector<std::string> const& configurations, std::string const& component,
   MessageLevel message, bool exclude_from_all, std::string literal_args,
-  bool optional)
+  bool optional, cmListFileBacktrace backtrace)
   : cmInstallGenerator(dest, configurations, component, message,
-                       exclude_from_all)
+                       exclude_from_all, std::move(backtrace))
   , LocalGenerator(nullptr)
   , Directories(dirs)
   , FilePermissions(std::move(file_permissions))
@@ -50,6 +50,22 @@ bool cmInstallDirectoryGenerator::Compute(cmLocalGenerator* lg)
   return true;
 }
 
+std::vector<std::string> cmInstallDirectoryGenerator::GetDirectories(
+  std::string const& config) const
+{
+  std::vector<std::string> directories;
+  if (this->ActionsPerConfig) {
+    for (std::string const& f : this->Directories) {
+      cmExpandList(
+        cmGeneratorExpression::Evaluate(f, this->LocalGenerator, config),
+        directories);
+    }
+  } else {
+    directories = this->Directories;
+  }
+  return directories;
+}
+
 void cmInstallDirectoryGenerator::GenerateScriptActions(std::ostream& os,
                                                         Indent indent)
 {
@@ -63,11 +79,7 @@ void cmInstallDirectoryGenerator::GenerateScriptActions(std::ostream& os,
 void cmInstallDirectoryGenerator::GenerateScriptForConfig(
   std::ostream& os, const std::string& config, Indent indent)
 {
-  std::vector<std::string> dirs;
-  for (std::string const& d : this->Directories) {
-    cmExpandList(
-      cmGeneratorExpression::Evaluate(d, this->LocalGenerator, config), dirs);
-  }
+  std::vector<std::string> dirs = this->GetDirectories(config);
 
   // Make sure all dirs have absolute paths.
   cmMakefile const& mf = *this->LocalGenerator->GetMakefile();

+ 10 - 8
Source/cmInstallDirectoryGenerator.h

@@ -9,6 +9,7 @@
 #include <vector>
 
 #include "cmInstallGenerator.h"
+#include "cmListFileCache.h"
 #include "cmScriptGenerator.h"
 
 class cmLocalGenerator;
@@ -19,19 +20,20 @@ class cmLocalGenerator;
 class cmInstallDirectoryGenerator : public cmInstallGenerator
 {
 public:
-  cmInstallDirectoryGenerator(std::vector<std::string> const& dirs,
-                              std::string const& dest,
-                              std::string file_permissions,
-                              std::string dir_permissions,
-                              std::vector<std::string> const& configurations,
-                              std::string const& component,
-                              MessageLevel message, bool exclude_from_all,
-                              std::string literal_args, bool optional = false);
+  cmInstallDirectoryGenerator(
+    std::vector<std::string> const& dirs, std::string const& dest,
+    std::string file_permissions, std::string dir_permissions,
+    std::vector<std::string> const& configurations,
+    std::string const& component, MessageLevel message, bool exclude_from_all,
+    std::string literal_args, bool optional, cmListFileBacktrace backtrace);
   ~cmInstallDirectoryGenerator() override;
 
   bool Compute(cmLocalGenerator* lg) override;
 
   std::string GetDestination(std::string const& config) const;
+  std::vector<std::string> GetDirectories(std::string const& config) const;
+
+  bool GetOptional() const { return this->Optional; }
 
 protected:
   void GenerateScriptActions(std::ostream& os, Indent indent) override;

+ 3 - 2
Source/cmInstallExportGenerator.cxx

@@ -23,9 +23,10 @@ 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, bool exportOld, bool android)
+  std::string filename, std::string name_space, bool exportOld, bool android,
+  cmListFileBacktrace backtrace)
   : cmInstallGenerator(destination, configurations, component, message,
-                       exclude_from_all)
+                       exclude_from_all, std::move(backtrace))
   , ExportSet(exportSet)
   , FilePermissions(std::move(file_permissions))
   , FileName(std::move(filename))

+ 5 - 1
Source/cmInstallExportGenerator.h

@@ -11,6 +11,7 @@
 #include <vector>
 
 #include "cmInstallGenerator.h"
+#include "cmListFileCache.h"
 #include "cmScriptGenerator.h"
 
 class cmExportInstallFileGenerator;
@@ -29,7 +30,7 @@ public:
                            std::string const& component, MessageLevel message,
                            bool exclude_from_all, std::string filename,
                            std::string name_space, bool exportOld,
-                           bool android);
+                           bool android, cmListFileBacktrace backtrace);
   cmInstallExportGenerator(const cmInstallExportGenerator&) = delete;
   ~cmInstallExportGenerator() override;
 
@@ -44,8 +45,11 @@ public:
 
   const std::string& GetNamespace() const { return this->Namespace; }
 
+  std::string const& GetMainImportFile() const { return this->MainImportFile; }
+
   std::string const& GetDestination() const { return this->Destination; }
   std::string GetDestinationFile() const;
+  std::string GetFileName() const { return this->FileName; }
 
 protected:
   void GenerateScript(std::ostream& os) override;

+ 1 - 1
Source/cmInstallFilesCommand.cxx

@@ -125,7 +125,7 @@ static void CreateInstallGenerator(cmMakefile& makefile,
     cmInstallGenerator::SelectMessageLevel(&makefile);
   makefile.AddInstallGenerator(cm::make_unique<cmInstallFilesGenerator>(
     files, destination, false, no_permissions, no_configurations, no_component,
-    message, no_exclude_from_all, no_rename));
+    message, no_exclude_from_all, no_rename, false, makefile.GetBacktrace()));
 }
 
 /**

+ 19 - 7
Source/cmInstallFilesGenerator.cxx

@@ -15,9 +15,9 @@ cmInstallFilesGenerator::cmInstallFilesGenerator(
   bool programs, std::string file_permissions,
   std::vector<std::string> const& configurations, std::string const& component,
   MessageLevel message, bool exclude_from_all, std::string rename,
-  bool optional)
+  bool optional, cmListFileBacktrace backtrace)
   : cmInstallGenerator(dest, configurations, component, message,
-                       exclude_from_all)
+                       exclude_from_all, std::move(backtrace))
   , LocalGenerator(nullptr)
   , Files(files)
   , FilePermissions(std::move(file_permissions))
@@ -66,6 +66,22 @@ std::string cmInstallFilesGenerator::GetRename(std::string const& config) const
                                          config);
 }
 
+std::vector<std::string> cmInstallFilesGenerator::GetFiles(
+  std::string const& config) const
+{
+  std::vector<std::string> files;
+  if (this->ActionsPerConfig) {
+    for (std::string const& f : this->Files) {
+      cmExpandList(
+        cmGeneratorExpression::Evaluate(f, this->LocalGenerator, config),
+        files);
+    }
+  } else {
+    files = this->Files;
+  }
+  return files;
+}
+
 void cmInstallFilesGenerator::AddFilesInstallRule(
   std::ostream& os, std::string const& config, Indent indent,
   std::vector<std::string> const& files)
@@ -92,10 +108,6 @@ void cmInstallFilesGenerator::GenerateScriptActions(std::ostream& os,
 void cmInstallFilesGenerator::GenerateScriptForConfig(
   std::ostream& os, const std::string& config, Indent indent)
 {
-  std::vector<std::string> files;
-  for (std::string const& f : this->Files) {
-    cmExpandList(
-      cmGeneratorExpression::Evaluate(f, this->LocalGenerator, config), files);
-  }
+  std::vector<std::string> files = this->GetFiles(config);
   this->AddFilesInstallRule(os, config, indent, files);
 }

+ 4 - 1
Source/cmInstallFilesGenerator.h

@@ -9,6 +9,7 @@
 #include <vector>
 
 #include "cmInstallGenerator.h"
+#include "cmListFileCache.h"
 #include "cmScriptGenerator.h"
 
 class cmLocalGenerator;
@@ -25,13 +26,15 @@ public:
                           std::vector<std::string> const& configurations,
                           std::string const& component, MessageLevel message,
                           bool exclude_from_all, std::string rename,
-                          bool optional = false);
+                          bool optional, cmListFileBacktrace backtrace);
   ~cmInstallFilesGenerator() override;
 
   bool Compute(cmLocalGenerator* lg) override;
 
   std::string GetDestination(std::string const& config) const;
   std::string GetRename(std::string const& config) const;
+  std::vector<std::string> GetFiles(std::string const& config) const;
+  bool GetOptional() const { return this->Optional; }
 
 protected:
   void GenerateScriptActions(std::ostream& os, Indent indent) override;

+ 3 - 1
Source/cmInstallGenerator.cxx

@@ -10,12 +10,14 @@
 
 cmInstallGenerator::cmInstallGenerator(
   std::string destination, std::vector<std::string> const& configurations,
-  std::string component, MessageLevel message, bool exclude_from_all)
+  std::string component, MessageLevel message, bool exclude_from_all,
+  cmListFileBacktrace backtrace)
   : cmScriptGenerator("CMAKE_INSTALL_CONFIG_NAME", configurations)
   , Destination(std::move(destination))
   , Component(std::move(component))
   , Message(message)
   , ExcludeFromAll(exclude_from_all)
+  , Backtrace(std::move(backtrace))
 {
 }
 

+ 9 - 1
Source/cmInstallGenerator.h

@@ -9,6 +9,7 @@
 #include <vector>
 
 #include "cmInstallType.h"
+#include "cmListFileCache.h"
 #include "cmScriptGenerator.h"
 
 class cmLocalGenerator;
@@ -32,7 +33,7 @@ public:
   cmInstallGenerator(std::string destination,
                      std::vector<std::string> const& configurations,
                      std::string component, MessageLevel message,
-                     bool exclude_from_all);
+                     bool exclude_from_all, cmListFileBacktrace backtrace);
   ~cmInstallGenerator() override;
 
   cmInstallGenerator(cmInstallGenerator const&) = delete;
@@ -61,6 +62,12 @@ public:
 
   virtual bool Compute(cmLocalGenerator*) { return true; }
 
+  std::string const& GetComponent() const { return this->Component; }
+
+  bool GetExcludeFromAll() const { return this->ExcludeFromAll; }
+
+  cmListFileBacktrace const& GetBacktrace() const { return this->Backtrace; }
+
 protected:
   void GenerateScript(std::ostream& os) override;
 
@@ -72,4 +79,5 @@ protected:
   std::string const Component;
   MessageLevel const Message;
   bool const ExcludeFromAll;
+  cmListFileBacktrace const Backtrace;
 };

+ 1 - 1
Source/cmInstallProgramsCommand.cxx

@@ -99,7 +99,7 @@ static void FinalAction(cmMakefile& makefile, std::string const& dest,
     cmInstallGenerator::SelectMessageLevel(&makefile);
   makefile.AddInstallGenerator(cm::make_unique<cmInstallFilesGenerator>(
     files, destination, true, no_permissions, no_configurations, no_component,
-    message, no_exclude_from_all, no_rename));
+    message, no_exclude_from_all, no_rename, false, makefile.GetBacktrace()));
 }
 
 /**

+ 16 - 9
Source/cmInstallScriptGenerator.cxx

@@ -14,9 +14,9 @@
 
 cmInstallScriptGenerator::cmInstallScriptGenerator(
   std::string script, bool code, std::string const& component,
-  bool exclude_from_all)
+  bool exclude_from_all, cmListFileBacktrace backtrace)
   : cmInstallGenerator("", std::vector<std::string>(), component,
-                       MessageDefault, exclude_from_all)
+                       MessageDefault, exclude_from_all, std::move(backtrace))
   , Script(std::move(script))
   , Code(code)
   , AllowGenex(false)
@@ -53,6 +53,19 @@ bool cmInstallScriptGenerator::Compute(cmLocalGenerator* lg)
   return true;
 }
 
+std::string cmInstallScriptGenerator::GetScript(
+  std::string const& config) const
+{
+  std::string script;
+  if (this->AllowGenex && this->ActionsPerConfig) {
+    script = cmGeneratorExpression::Evaluate(this->Script,
+                                             this->LocalGenerator, config);
+  } else {
+    script = this->Script;
+  }
+  return script;
+}
+
 void cmInstallScriptGenerator::AddScriptInstallRule(
   std::ostream& os, Indent indent, std::string const& script) const
 {
@@ -76,11 +89,5 @@ void cmInstallScriptGenerator::GenerateScriptActions(std::ostream& os,
 void cmInstallScriptGenerator::GenerateScriptForConfig(
   std::ostream& os, const std::string& config, Indent indent)
 {
-  if (this->AllowGenex) {
-    this->AddScriptInstallRule(os, indent,
-                               cmGeneratorExpression::Evaluate(
-                                 this->Script, this->LocalGenerator, config));
-  } else {
-    this->AddScriptInstallRule(os, indent, this->Script);
-  }
+  this->AddScriptInstallRule(os, indent, this->GetScript(config));
 }

+ 9 - 3
Source/cmInstallScriptGenerator.h

@@ -8,6 +8,7 @@
 #include <string>
 
 #include "cmInstallGenerator.h"
+#include "cmListFileCache.h"
 #include "cmScriptGenerator.h"
 
 class cmLocalGenerator;
@@ -18,13 +19,18 @@ class cmLocalGenerator;
 class cmInstallScriptGenerator : public cmInstallGenerator
 {
 public:
-  cmInstallScriptGenerator(std::string script, bool code,
-                           std::string const& component,
-                           bool exclude_from_all);
+  cmInstallScriptGenerator(
+    std::string script, bool code, std::string const& component,
+    bool exclude_from_all,
+    cmListFileBacktrace backtrace = cmListFileBacktrace());
   ~cmInstallScriptGenerator() override;
 
   bool Compute(cmLocalGenerator* lg) override;
 
+  bool IsCode() const { return this->Code; }
+
+  std::string GetScript(std::string const& config) const;
+
 protected:
   void GenerateScriptActions(std::ostream& os, Indent indent) override;
   void GenerateScriptForConfig(std::ostream& os, const std::string& config,

+ 3 - 2
Source/cmInstallSubdirectoryGenerator.cxx

@@ -14,9 +14,10 @@
 #include "cmSystemTools.h"
 
 cmInstallSubdirectoryGenerator::cmInstallSubdirectoryGenerator(
-  cmMakefile* makefile, std::string binaryDirectory, bool excludeFromAll)
+  cmMakefile* makefile, std::string binaryDirectory, bool excludeFromAll,
+  cmListFileBacktrace backtrace)
   : cmInstallGenerator("", std::vector<std::string>(), "", MessageDefault,
-                       excludeFromAll)
+                       excludeFromAll, std::move(backtrace))
   , Makefile(makefile)
   , BinaryDirectory(std::move(binaryDirectory))
 {

+ 3 - 1
Source/cmInstallSubdirectoryGenerator.h

@@ -8,6 +8,7 @@
 #include <string>
 
 #include "cmInstallGenerator.h"
+#include "cmListFileCache.h"
 
 class cmLocalGenerator;
 class cmMakefile;
@@ -20,7 +21,8 @@ class cmInstallSubdirectoryGenerator : public cmInstallGenerator
 public:
   cmInstallSubdirectoryGenerator(cmMakefile* makefile,
                                  std::string binaryDirectory,
-                                 bool excludeFromAll);
+                                 bool excludeFromAll,
+                                 cmListFileBacktrace backtrace);
   ~cmInstallSubdirectoryGenerator() override;
 
   bool HaveInstall() override;

+ 137 - 120
Source/cmInstallTargetGenerator.cxx

@@ -25,19 +25,33 @@
 #include "cmTarget.h"
 #include "cmake.h"
 
+namespace {
+std::string computeInstallObjectDir(cmGeneratorTarget* gt,
+                                    std::string const& config)
+{
+  std::string objectDir = "objects";
+  if (!config.empty()) {
+    objectDir += "-";
+    objectDir += config;
+  }
+  objectDir += "/";
+  objectDir += gt->GetName();
+  return objectDir;
+}
+}
+
 cmInstallTargetGenerator::cmInstallTargetGenerator(
   std::string targetName, std::string const& dest, bool implib,
   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)
+                       exclude_from_all, std::move(backtrace))
   , TargetName(std::move(targetName))
   , Target(nullptr)
   , FilePermissions(std::move(file_permissions))
   , ImportLibrary(implib)
   , Optional(optional)
-  , Backtrace(std::move(backtrace))
 {
   this->ActionsPerConfig = true;
   this->NamelinkMode = NamelinkModeNone;
@@ -48,20 +62,69 @@ cmInstallTargetGenerator::~cmInstallTargetGenerator() = default;
 void cmInstallTargetGenerator::GenerateScriptForConfig(
   std::ostream& os, const std::string& config, Indent indent)
 {
+  // Compute the list of files to install for this target.
+  Files files = this->GetFiles(config);
+
+  // Skip this rule if no files are to be installed for the target.
+  if (files.From.empty()) {
+    return;
+  }
+
+  // Compute the effective install destination.
+  std::string dest = this->GetDestination(config);
+  if (!files.ToDir.empty()) {
+    dest = cmStrCat(dest, '/', files.ToDir);
+  }
+
+  // Tweak files located in the destination directory.
+  std::string toDir = cmStrCat(this->ConvertToAbsoluteDestination(dest), '/');
+
+  // Add pre-installation tweaks.
+  if (!files.NoTweak) {
+    this->AddTweak(os, indent, config, toDir, files.To,
+                   &cmInstallTargetGenerator::PreReplacementTweaks);
+  }
+
+  // Write code to install the target file.
+  const char* no_dir_permissions = nullptr;
+  const char* no_rename = nullptr;
+  bool optional = this->Optional || this->ImportLibrary;
+  std::string literal_args;
+  if (!files.FromDir.empty()) {
+    literal_args += " FILES_FROM_DIR \"" + files.FromDir + "\"";
+  }
+  if (files.UseSourcePermissions) {
+    literal_args += " USE_SOURCE_PERMISSIONS";
+  }
+  this->AddInstallRule(os, dest, files.Type, files.From, optional,
+                       this->FilePermissions.c_str(), no_dir_permissions,
+                       no_rename, literal_args.c_str(), indent);
+
+  // Add post-installation tweaks.
+  if (!files.NoTweak) {
+    this->AddTweak(os, indent, config, toDir, files.To,
+                   &cmInstallTargetGenerator::PostReplacementTweaks);
+  }
+}
+
+cmInstallTargetGenerator::Files cmInstallTargetGenerator::GetFiles(
+  std::string const& config) const
+{
+  Files files;
+
   cmStateEnums::TargetType targetType = this->Target->GetType();
-  cmInstallType type = cmInstallType();
   switch (targetType) {
     case cmStateEnums::EXECUTABLE:
-      type = cmInstallType_EXECUTABLE;
+      files.Type = cmInstallType_EXECUTABLE;
       break;
     case cmStateEnums::STATIC_LIBRARY:
-      type = cmInstallType_STATIC_LIBRARY;
+      files.Type = cmInstallType_STATIC_LIBRARY;
       break;
     case cmStateEnums::SHARED_LIBRARY:
-      type = cmInstallType_SHARED_LIBRARY;
+      files.Type = cmInstallType_SHARED_LIBRARY;
       break;
     case cmStateEnums::MODULE_LIBRARY:
-      type = cmInstallType_MODULE_LIBRARY;
+      files.Type = cmInstallType_MODULE_LIBRARY;
       break;
     case cmStateEnums::INTERFACE_LIBRARY:
       // Not reachable. We never create a cmInstallTargetGenerator for
@@ -70,9 +133,21 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(
              "INTERFACE_LIBRARY targets have no installable outputs.");
       break;
 
-    case cmStateEnums::OBJECT_LIBRARY:
-      this->GenerateScriptForConfigObjectLibrary(os, config, indent);
-      return;
+    case cmStateEnums::OBJECT_LIBRARY: {
+      // Compute all the object files inside this target
+      std::vector<std::string> objects;
+      this->Target->GetTargetObjectNames(config, objects);
+
+      files.Type = cmInstallType_FILES;
+      files.NoTweak = true;
+      files.FromDir = this->Target->GetObjectDirectory(config);
+      files.ToDir = computeInstallObjectDir(this->Target, config);
+      for (std::string& obj : objects) {
+        files.From.emplace_back(obj);
+        files.To.emplace_back(std::move(obj));
+      }
+      return files;
+    }
 
     case cmStateEnums::UTILITY:
     case cmStateEnums::GLOBAL_TARGET:
@@ -80,7 +155,7 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(
       this->Target->GetLocalGenerator()->IssueMessage(
         MessageType::INTERNAL_ERROR,
         "cmInstallTargetGenerator created with non-installable target.");
-      return;
+      return files;
   }
 
   // Compute the build tree directory from which to copy the target.
@@ -97,14 +172,6 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(
       cmStrCat(this->Target->GetDirectory(config, artifact), '/');
   }
 
-  std::string toDir = cmStrCat(
-    this->ConvertToAbsoluteDestination(this->GetDestination(config)), '/');
-
-  // Compute the list of files to install for this target.
-  std::vector<std::string> filesFrom;
-  std::vector<std::string> filesTo;
-  std::string literal_args;
-
   if (targetType == cmStateEnums::EXECUTABLE) {
     // There is a bug in cmInstallCommand if this fails.
     assert(this->NamelinkMode == NamelinkModeNone);
@@ -113,21 +180,21 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(
       this->Target->GetExecutableNames(config);
     if (this->ImportLibrary) {
       std::string from1 = fromDirConfig + targetNames.ImportLibrary;
-      std::string to1 = toDir + targetNames.ImportLibrary;
-      filesFrom.push_back(std::move(from1));
-      filesTo.push_back(std::move(to1));
+      std::string to1 = targetNames.ImportLibrary;
+      files.From.emplace_back(std::move(from1));
+      files.To.emplace_back(std::move(to1));
       std::string targetNameImportLib;
       if (this->Target->GetImplibGNUtoMS(config, targetNames.ImportLibrary,
                                          targetNameImportLib)) {
-        filesFrom.push_back(fromDirConfig + targetNameImportLib);
-        filesTo.push_back(toDir + targetNameImportLib);
+        files.From.emplace_back(fromDirConfig + targetNameImportLib);
+        files.To.emplace_back(targetNameImportLib);
       }
 
       // An import library looks like a static library.
-      type = cmInstallType_STATIC_LIBRARY;
+      files.Type = cmInstallType_STATIC_LIBRARY;
     } else {
       std::string from1 = fromDirConfig + targetNames.Output;
-      std::string to1 = toDir + targetNames.Output;
+      std::string to1 = targetNames.Output;
 
       // Handle OSX Bundles.
       if (this->Target->IsAppBundleOnApple()) {
@@ -142,8 +209,8 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(
         }
 
         // Install the whole app bundle directory.
-        type = cmInstallType_DIRECTORY;
-        literal_args += " USE_SOURCE_PERMISSIONS";
+        files.Type = cmInstallType_DIRECTORY;
+        files.UseSourcePermissions = true;
         from1 += ".";
         from1 += ext;
 
@@ -159,14 +226,14 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(
         // Tweaks apply to the real file, so list it first.
         if (targetNames.Real != targetNames.Output) {
           std::string from2 = fromDirConfig + targetNames.Real;
-          std::string to2 = toDir += targetNames.Real;
-          filesFrom.push_back(std::move(from2));
-          filesTo.push_back(std::move(to2));
+          std::string to2 = targetNames.Real;
+          files.From.emplace_back(std::move(from2));
+          files.To.emplace_back(std::move(to2));
         }
       }
 
-      filesFrom.push_back(std::move(from1));
-      filesTo.push_back(std::move(to1));
+      files.From.emplace_back(std::move(from1));
+      files.To.emplace_back(std::move(to1));
     }
   } else {
     cmGeneratorTarget::Names targetNames =
@@ -176,18 +243,18 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(
       assert(this->NamelinkMode == NamelinkModeNone);
 
       std::string from1 = fromDirConfig + targetNames.ImportLibrary;
-      std::string to1 = toDir + targetNames.ImportLibrary;
-      filesFrom.push_back(std::move(from1));
-      filesTo.push_back(std::move(to1));
+      std::string to1 = targetNames.ImportLibrary;
+      files.From.emplace_back(std::move(from1));
+      files.To.emplace_back(std::move(to1));
       std::string targetNameImportLib;
       if (this->Target->GetImplibGNUtoMS(config, targetNames.ImportLibrary,
                                          targetNameImportLib)) {
-        filesFrom.push_back(fromDirConfig + targetNameImportLib);
-        filesTo.push_back(toDir + targetNameImportLib);
+        files.From.emplace_back(fromDirConfig + targetNameImportLib);
+        files.To.emplace_back(targetNameImportLib);
       }
 
       // An import library looks like a static library.
-      type = cmInstallType_STATIC_LIBRARY;
+      files.Type = cmInstallType_STATIC_LIBRARY;
     } else if (this->Target->IsFrameworkOnApple()) {
       // FIXME: In principle we should be able to
       //   assert(this->NamelinkMode == NamelinkModeNone);
@@ -207,7 +274,7 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(
           break;
         case NamelinkModeOnly:
           // Assume the NamelinkModeSkip instance will warn and install.
-          return;
+          return files;
         case NamelinkModeSkip: {
           std::string e = "Target '" + this->Target->GetName() +
             "' was changed to a FRAMEWORK sometime after install().  "
@@ -219,36 +286,36 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(
       }
 
       // Install the whole framework directory.
-      type = cmInstallType_DIRECTORY;
-      literal_args += " USE_SOURCE_PERMISSIONS";
+      files.Type = cmInstallType_DIRECTORY;
+      files.UseSourcePermissions = true;
 
       std::string from1 = fromDirConfig + targetNames.Output;
       from1 = cmSystemTools::GetFilenamePath(from1);
 
       // Tweaks apply to the binary inside the bundle.
-      std::string to1 = toDir + targetNames.Real;
+      std::string to1 = targetNames.Real;
 
-      filesFrom.push_back(std::move(from1));
-      filesTo.push_back(std::move(to1));
+      files.From.emplace_back(std::move(from1));
+      files.To.emplace_back(std::move(to1));
     } else if (this->Target->IsCFBundleOnApple()) {
       // Install the whole app bundle directory.
-      type = cmInstallType_DIRECTORY;
-      literal_args += " USE_SOURCE_PERMISSIONS";
+      files.Type = cmInstallType_DIRECTORY;
+      files.UseSourcePermissions = true;
 
       std::string targetNameBase =
         targetNames.Output.substr(0, targetNames.Output.find('/'));
 
       std::string from1 = fromDirConfig + targetNameBase;
-      std::string to1 = toDir + targetNames.Output;
+      std::string to1 = targetNames.Output;
 
-      filesFrom.push_back(std::move(from1));
-      filesTo.push_back(std::move(to1));
+      files.From.emplace_back(std::move(from1));
+      files.To.emplace_back(std::move(to1));
     } else {
       bool haveNamelink = false;
 
       // Library link name.
       std::string fromName = fromDirConfig + targetNames.Output;
-      std::string toName = toDir + targetNames.Output;
+      std::string toName = targetNames.Output;
 
       // Library interface name.
       std::string fromSOName;
@@ -256,7 +323,7 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(
       if (targetNames.SharedObject != targetNames.Output) {
         haveNamelink = true;
         fromSOName = fromDirConfig + targetNames.SharedObject;
-        toSOName = toDir + targetNames.SharedObject;
+        toSOName = targetNames.SharedObject;
       }
 
       // Library implementation name.
@@ -266,7 +333,7 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(
           targetNames.Real != targetNames.SharedObject) {
         haveNamelink = true;
         fromRealName = fromDirConfig + targetNames.Real;
-        toRealName = toDir + targetNames.Real;
+        toRealName = targetNames.Real;
       }
 
       // Add the names based on the current namelink mode.
@@ -274,95 +341,42 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(
         // With a namelink we need to check the mode.
         if (this->NamelinkMode == NamelinkModeOnly) {
           // Install the namelink only.
-          filesFrom.push_back(fromName);
-          filesTo.push_back(toName);
+          files.From.emplace_back(fromName);
+          files.To.emplace_back(toName);
         } else {
           // Install the real file if it has its own name.
           if (!fromRealName.empty()) {
-            filesFrom.push_back(fromRealName);
-            filesTo.push_back(toRealName);
+            files.From.emplace_back(fromRealName);
+            files.To.emplace_back(toRealName);
           }
 
           // Install the soname link if it has its own name.
           if (!fromSOName.empty()) {
-            filesFrom.push_back(fromSOName);
-            filesTo.push_back(toSOName);
+            files.From.emplace_back(fromSOName);
+            files.To.emplace_back(toSOName);
           }
 
           // Install the namelink if it is not to be skipped.
           if (this->NamelinkMode != NamelinkModeSkip) {
-            filesFrom.push_back(fromName);
-            filesTo.push_back(toName);
+            files.From.emplace_back(fromName);
+            files.To.emplace_back(toName);
           }
         }
       } else {
         // Without a namelink there will be only one file.  Install it
         // if this is not a namelink-only rule.
         if (this->NamelinkMode != NamelinkModeOnly) {
-          filesFrom.push_back(fromName);
-          filesTo.push_back(toName);
+          files.From.emplace_back(fromName);
+          files.To.emplace_back(toName);
         }
       }
     }
   }
 
   // If this fails the above code is buggy.
-  assert(filesFrom.size() == filesTo.size());
-
-  // Skip this rule if no files are to be installed for the target.
-  if (filesFrom.empty()) {
-    return;
-  }
-
-  // Add pre-installation tweaks.
-  this->AddTweak(os, indent, config, filesTo,
-                 &cmInstallTargetGenerator::PreReplacementTweaks);
-
-  // Write code to install the target file.
-  const char* no_dir_permissions = nullptr;
-  const char* no_rename = nullptr;
-  bool optional = this->Optional || this->ImportLibrary;
-  this->AddInstallRule(os, this->GetDestination(config), type, filesFrom,
-                       optional, this->FilePermissions.c_str(),
-                       no_dir_permissions, no_rename, literal_args.c_str(),
-                       indent);
-
-  // Add post-installation tweaks.
-  this->AddTweak(os, indent, config, filesTo,
-                 &cmInstallTargetGenerator::PostReplacementTweaks);
-}
+  assert(files.From.size() == files.To.size());
 
-static std::string computeInstallObjectDir(cmGeneratorTarget* gt,
-                                           std::string const& config)
-{
-  std::string objectDir = "objects";
-  if (!config.empty()) {
-    objectDir += "-";
-    objectDir += config;
-  }
-  objectDir += "/";
-  objectDir += gt->GetName();
-  return objectDir;
-}
-
-void cmInstallTargetGenerator::GenerateScriptForConfigObjectLibrary(
-  std::ostream& os, const std::string& config, Indent indent)
-{
-  // Compute all the object files inside this target
-  std::vector<std::string> objects;
-  this->Target->GetTargetObjectNames(config, objects);
-
-  std::string const dest = this->GetDestination(config) + "/" +
-    computeInstallObjectDir(this->Target, config);
-
-  std::string const obj_dir = this->Target->GetObjectDirectory(config);
-  std::string const literal_args = " FILES_FROM_DIR \"" + obj_dir + "\"";
-
-  const char* no_dir_permissions = nullptr;
-  const char* no_rename = nullptr;
-  this->AddInstallRule(os, dest, cmInstallType_FILES, objects, this->Optional,
-                       this->FilePermissions.c_str(), no_dir_permissions,
-                       no_rename, literal_args.c_str(), indent);
+  return files;
 }
 
 void cmInstallTargetGenerator::GetInstallObjectNames(
@@ -464,12 +478,14 @@ void cmInstallTargetGenerator::AddTweak(std::ostream& os, Indent indent,
 
 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(files[0]), tweak);
+    this->AddTweak(os, indent, config,
+                   this->GetDestDirPath(cmStrCat(dir, files[0])), tweak);
   } else {
     // Generate a foreach loop to tweak multiple files.
     std::ostringstream tw;
@@ -479,7 +495,8 @@ void cmInstallTargetGenerator::AddTweak(std::ostream& os, Indent indent,
       Indent indent2 = indent.Next().Next();
       os << indent << "foreach(file\n";
       for (std::string const& f : files) {
-        os << indent2 << "\"" << this->GetDestDirPath(f) << "\"\n";
+        os << indent2 << "\"" << this->GetDestDirPath(cmStrCat(dir, f))
+           << "\"\n";
       }
       os << indent2 << ")\n";
       os << tws;

+ 26 - 6
Source/cmInstallTargetGenerator.h

@@ -9,6 +9,7 @@
 #include <vector>
 
 #include "cmInstallGenerator.h"
+#include "cmInstallType.h"
 #include "cmListFileCache.h"
 #include "cmScriptGenerator.h"
 
@@ -65,21 +66,41 @@ public:
 
   std::string GetDestination(std::string const& config) const;
 
-  cmListFileBacktrace const& GetBacktrace() const { return this->Backtrace; }
+  struct Files
+  {
+    // Names or paths of files to be read from the source or build tree.
+    // The paths may be computed as [FromDir/] + From[i].
+    std::vector<std::string> From;
+
+    // Corresponding names of files to be written in the install directory.
+    // The paths may be computed as Destination/ + [ToDir/] + To[i].
+    std::vector<std::string> To;
+
+    // Prefix for all files in From.
+    std::string FromDir;
+
+    // Prefix for all files in To.
+    std::string ToDir;
+
+    bool NoTweak = false;
+    bool UseSourcePermissions = false;
+    cmInstallType Type = cmInstallType();
+  };
+  Files GetFiles(std::string const& config) const;
+
+  bool GetOptional() const { return this->Optional; }
 
 protected:
   void GenerateScriptForConfig(std::ostream& os, const std::string& config,
                                Indent indent) override;
-  void GenerateScriptForConfigObjectLibrary(std::ostream& os,
-                                            const std::string& config,
-                                            Indent indent);
   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::vector<std::string> const& files, TweakMethod tweak);
+                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,
@@ -111,5 +132,4 @@ protected:
   NamelinkModeType NamelinkMode;
   bool const ImportLibrary;
   bool const Optional;
-  cmListFileBacktrace const Backtrace;
 };

+ 1 - 1
Source/cmMakefile.cxx

@@ -1838,7 +1838,7 @@ void cmMakefile::AddSubDirectory(const std::string& srcPath,
   }
 
   this->AddInstallGenerator(cm::make_unique<cmInstallSubdirectoryGenerator>(
-    subMf, binPath, excludeFromAll));
+    subMf, binPath, excludeFromAll, this->GetBacktrace()));
 }
 
 const std::string& cmMakefile::GetCurrentSourceDirectory() const