From 73bfe4af26ef4cd8f48b724a982822fde0b9d5c1 Mon Sep 17 00:00:00 2001
From: Robert Goulet <robert.goulet@autodesk.com>
Date: Wed, 23 Sep 2015 13:40:27 -0400
Subject: [PATCH] Add support for genex for install(FILES) DESTINATION option

---
 Help/command/install.rst                           |  4 ++++
 .../dev/INSTALL_FILES_DESTINATION-genex.rst        |  5 +++++
 Source/cmInstallFilesGenerator.cxx                 | 25 ++++++++++++++++++----
 Source/cmInstallFilesGenerator.h                   |  6 +++++-
 Tests/ExportImport/Export/CMakeLists.txt           |  3 +++
 Tests/ExportImport/Import/A/CMakeLists.txt         |  4 ++++
 Tests/ExportImport/Import/A/testExe5.c             |  6 ++++++
 7 files changed, 48 insertions(+), 5 deletions(-)
 create mode 100644 Help/release/dev/INSTALL_FILES_DESTINATION-genex.rst
 create mode 100644 Tests/ExportImport/Import/A/testExe5.c

diff --git a/Help/command/install.rst b/Help/command/install.rst
index c99ed73..9c17bba 100644
--- a/Help/command/install.rst
+++ b/Help/command/install.rst
@@ -192,6 +192,10 @@ The list of ``files...`` given to ``FILES`` or ``PROGRAMS`` may use
 However, if any item begins in a generator expression it must evaluate
 to a full path.
 
+The install destination given to the files install ``DESTINATION`` may
+use "generator expressions" with the syntax ``$<...>``.  See the
+:manual:`cmake-generator-expressions(7)` manual for available expressions.
+
 Installing Directories
 ^^^^^^^^^^^^^^^^^^^^^^
 
diff --git a/Help/release/dev/INSTALL_FILES_DESTINATION-genex.rst b/Help/release/dev/INSTALL_FILES_DESTINATION-genex.rst
new file mode 100644
index 0000000..ddac8a5
--- /dev/null
+++ b/Help/release/dev/INSTALL_FILES_DESTINATION-genex.rst
@@ -0,0 +1,5 @@
+INSTALL_FILES_DESTINATION-genex
+-------------------------------
+
+* The :command:`install` ``FILES`` command ``DESTINATION`` option learned to
+  support :manual:`generator expressions <cmake-generator-expressions(7)>`.
diff --git a/Source/cmInstallFilesGenerator.cxx b/Source/cmInstallFilesGenerator.cxx
index c18b174..094894d 100644
--- a/Source/cmInstallFilesGenerator.cxx
+++ b/Source/cmInstallFilesGenerator.cxx
@@ -34,6 +34,12 @@ cmInstallFilesGenerator
   Programs(programs),
   Optional(optional)
 {
+  // We need per-config actions if destination have generator expressions.
+  if(cmGeneratorExpression::Find(Destination) != std::string::npos)
+    {
+    this->ActionsPerConfig = true;
+    }
+
   // We need per-config actions if any files have generator expressions.
   for(std::vector<std::string>::const_iterator i = files.begin();
       !this->ActionsPerConfig && i != files.end(); ++i)
@@ -57,14 +63,25 @@ void cmInstallFilesGenerator::Compute(cmLocalGenerator* lg)
 }
 
 //----------------------------------------------------------------------------
+std::string
+cmInstallFilesGenerator::GetDestination(std::string const& config) const
+{
+  cmGeneratorExpression ge;
+  return ge.Parse(this->Destination)
+    ->Evaluate(this->LocalGenerator->GetMakefile(), config);
+}
+
+//----------------------------------------------------------------------------
 void cmInstallFilesGenerator::AddFilesInstallRule(
-  std::ostream& os, Indent const& indent,
+  std::ostream& os,
+  const std::string config,
+  Indent const& indent,
   std::vector<std::string> const& files)
 {
   // Write code to install the files.
   const char* no_dir_permissions = 0;
   this->AddInstallRule(os,
-                       this->Destination,
+                       this->GetDestination(config),
                        (this->Programs
                         ? cmInstallType_PROGRAMS
                         : cmInstallType_FILES),
@@ -84,7 +101,7 @@ void cmInstallFilesGenerator::GenerateScriptActions(std::ostream& os,
     }
   else
     {
-    this->AddFilesInstallRule(os, indent, this->Files);
+    this->AddFilesInstallRule(os, "", indent, this->Files);
     }
 }
 
@@ -102,5 +119,5 @@ void cmInstallFilesGenerator::GenerateScriptForConfig(std::ostream& os,
     cmSystemTools::ExpandListArgument(cge->Evaluate(
         this->LocalGenerator->GetMakefile(), config), files);
     }
-  this->AddFilesInstallRule(os, indent, files);
+  this->AddFilesInstallRule(os, config, indent, files);
 }
diff --git a/Source/cmInstallFilesGenerator.h b/Source/cmInstallFilesGenerator.h
index 00b3a79..bfe4039 100644
--- a/Source/cmInstallFilesGenerator.h
+++ b/Source/cmInstallFilesGenerator.h
@@ -32,12 +32,16 @@ public:
 
   void Compute(cmLocalGenerator* lg);
 
+  std::string GetDestination(std::string const& config) const;
+
 protected:
   virtual void GenerateScriptActions(std::ostream& os, Indent const& indent);
   virtual void GenerateScriptForConfig(std::ostream& os,
                                        const std::string& config,
                                        Indent const& indent);
-  void AddFilesInstallRule(std::ostream& os, Indent const& indent,
+  void AddFilesInstallRule(std::ostream& os,
+                           const std::string config,
+                           Indent const& indent,
                            std::vector<std::string> const& files);
 
   cmLocalGenerator* LocalGenerator;
diff --git a/Tests/ExportImport/Export/CMakeLists.txt b/Tests/ExportImport/Export/CMakeLists.txt
index 2b9e844..2541987 100644
--- a/Tests/ExportImport/Export/CMakeLists.txt
+++ b/Tests/ExportImport/Export/CMakeLists.txt
@@ -79,6 +79,9 @@ set_property(TARGET testLib7 PROPERTY OUTPUT_NAME_DEBUG testLib7D-$<CONFIG>)
 set_property(TARGET testLib7 PROPERTY OUTPUT_NAME_RELEASE testLib7R-$<CONFIG>)
 set_property(TARGET testLib7 PROPERTY OUTPUT_NAME testLib7-$<CONFIG>)
 
+# Test install(FILES) destination with generator expressions
+install(FILES $<TARGET_FILE:testLib7> DESTINATION lib-$<CONFIG>)
+
 # Work-around: Visual Studio 6 does not support per-target object files.
 set(VS6)
 if("${CMAKE_GENERATOR}" MATCHES "Visual Studio 6")
diff --git a/Tests/ExportImport/Import/A/CMakeLists.txt b/Tests/ExportImport/Import/A/CMakeLists.txt
index 5ce9628..a646a7d 100644
--- a/Tests/ExportImport/Import/A/CMakeLists.txt
+++ b/Tests/ExportImport/Import/A/CMakeLists.txt
@@ -90,6 +90,10 @@ add_custom_target(check_testLib1_genex ALL
           -P ${CMAKE_CURRENT_SOURCE_DIR}/check_testLib1_genex.cmake
   )
 
+# Try linking to a library installed from install(FILES) DESTINATION with generator expressions
+add_executable(testExe5 ${CMAKE_CURRENT_SOURCE_DIR}/testExe5.c)
+target_link_libraries(testExe5 ${CMAKE_INSTALL_PREFIX}/lib-$<CONFIG>/$<TARGET_FILE_NAME:exp_testLib7>)
+
 if(CMAKE_SHARED_LIBRARY_SONAME_C_FLAG AND
     "${CMAKE_C_CREATE_SHARED_MODULE}" MATCHES "SONAME_FLAG")
   foreach(ns exp bld)
diff --git a/Tests/ExportImport/Import/A/testExe5.c b/Tests/ExportImport/Import/A/testExe5.c
new file mode 100644
index 0000000..413d49a
--- /dev/null
+++ b/Tests/ExportImport/Import/A/testExe5.c
@@ -0,0 +1,6 @@
+extern int testLib7();
+
+int main()
+{
+  return testLib7();
+}
-- 
1.9.5.msysgit.1

