Browse Source

Add an "installed file" property scope

Teach set_property and get_property an "INSTALL" property type to be
associated with install-tree file paths.  Make the properties available
to CPack for use during packaging.  Add a "prop_inst" Sphinx domain
object type for documentation of such properties.
Nils Gladitz 11 năm trước cách đây
mục cha
commit
15a8af21e8
42 tập tin đã thay đổi với 612 bổ sung12 xóa
  1. 4 4
      Help/manual/cmake-developer.7.rst
  2. 6 0
      Help/manual/cmake-properties.7.rst
  3. 4 0
      Source/CMakeLists.txt
  4. 8 0
      Source/CPack/cmCPackGenerator.cxx
  5. 3 0
      Source/CPack/cmCPackGenerator.h
  6. 5 4
      Source/CPack/cpack.cxx
  7. 45 0
      Source/cmCPackPropertiesGenerator.cxx
  8. 38 0
      Source/cmCPackPropertiesGenerator.h
  9. 36 1
      Source/cmGetPropertyCommand.cxx
  10. 1 0
      Source/cmGetPropertyCommand.h
  11. 44 0
      Source/cmGlobalGenerator.cxx
  12. 2 0
      Source/cmGlobalGenerator.h
  13. 115 0
      Source/cmInstalledFile.cxx
  14. 83 0
      Source/cmInstalledFile.h
  15. 1 1
      Source/cmProperty.h
  16. 2 1
      Source/cmRST.cxx
  17. 58 1
      Source/cmSetPropertyCommand.cxx
  18. 2 0
      Source/cmSetPropertyCommand.h
  19. 35 0
      Source/cmake.cxx
  20. 12 0
      Source/cmake.h
  21. 8 0
      Templates/CPackConfig.cmake.in
  22. 1 0
      Tests/RunCMake/CMakeLists.txt
  23. 3 0
      Tests/RunCMake/CPackInstallProperties/Append-check.cmake
  24. 2 0
      Tests/RunCMake/CPackInstallProperties/Append.cmake
  25. 6 0
      Tests/RunCMake/CPackInstallProperties/CMakeLists.txt
  26. 3 0
      Tests/RunCMake/CPackInstallProperties/FilenameGenex-check.cmake
  27. 7 0
      Tests/RunCMake/CPackInstallProperties/FilenameGenex.cmake
  28. 3 0
      Tests/RunCMake/CPackInstallProperties/MultipleValues-check.cmake
  29. 1 0
      Tests/RunCMake/CPackInstallProperties/MultipleValues.cmake
  30. 13 0
      Tests/RunCMake/CPackInstallProperties/PerConfigValue-check.cmake
  31. 14 0
      Tests/RunCMake/CPackInstallProperties/PerConfigValue.cmake
  32. 3 0
      Tests/RunCMake/CPackInstallProperties/Replace-check.cmake
  33. 2 0
      Tests/RunCMake/CPackInstallProperties/Replace.cmake
  34. 9 0
      Tests/RunCMake/CPackInstallProperties/RunCMakeTest.cmake
  35. 3 0
      Tests/RunCMake/CPackInstallProperties/Simple-check.cmake
  36. 1 0
      Tests/RunCMake/CPackInstallProperties/Simple.cmake
  37. 3 0
      Tests/RunCMake/CPackInstallProperties/ValueGenex-check.cmake
  38. 7 0
      Tests/RunCMake/CPackInstallProperties/ValueGenex.cmake
  39. 12 0
      Tests/RunCMake/CPackInstallProperties/check.cmake
  40. 1 0
      Tests/RunCMake/CPackInstallProperties/test.cpp
  41. 4 0
      Utilities/Sphinx/cmake.py
  42. 2 0
      bootstrap

+ 4 - 4
Help/manual/cmake-developer.7.rst

@@ -331,10 +331,10 @@ documentation:
  See the :manual:`cmake-policies(7)` manual
  and the :command:`cmake_policy` command.
 
-``prop_cache, prop_dir, prop_gbl, prop_sf, prop_test, prop_tgt``
- A CMake cache, directory, global, source file, test, or target
- property, respectively.  See the :manual:`cmake-properties(7)` manual
- and the :command:`set_property` command.
+``prop_cache, prop_dir, prop_gbl, prop_sf, prop_inst, prop_test, prop_tgt``
+ A CMake cache, directory, global, source file, installed file, test,
+ or target property, respectively.  See the :manual:`cmake-properties(7)`
+ manual and the :command:`set_property` command.
 
 ``variable``
  A CMake language variable.

+ 6 - 0
Help/manual/cmake-properties.7.rst

@@ -302,3 +302,9 @@ Properties on Cache Entries
    /prop_cache/STRINGS
    /prop_cache/TYPE
    /prop_cache/VALUE
+
+Properties on Installed Files
+=============================
+
+.. toctree::
+   :maxdepth: 1

+ 4 - 0
Source/CMakeLists.txt

@@ -163,6 +163,8 @@ set(SRCS
   cmComputeLinkInformation.h
   cmComputeTargetDepends.h
   cmComputeTargetDepends.cxx
+  cmCPackPropertiesGenerator.h
+  cmCPackPropertiesGenerator.cxx
   cmCryptoHash.cxx
   cmCryptoHash.h
   cmCustomCommand.cxx
@@ -243,6 +245,8 @@ set(SRCS
   cmInstallGenerator.h
   cmInstallGenerator.cxx
   cmInstallExportGenerator.cxx
+  cmInstalledFile.h
+  cmInstalledFile.cxx
   cmInstallFilesGenerator.h
   cmInstallFilesGenerator.cxx
   cmInstallScriptGenerator.h

+ 8 - 0
Source/CPack/cmCPackGenerator.cxx

@@ -1313,6 +1313,14 @@ int cmCPackGenerator::CleanTemporaryDirectory()
   return 1;
 }
 
+//----------------------------------------------------------------------
+cmInstalledFile const* cmCPackGenerator::GetInstalledFile(
+  std::string const& name) const
+{
+  cmake const* cm = this->MakefileMap->GetCMakeInstance();
+  return cm->GetInstalledFile(name);
+}
+
 //----------------------------------------------------------------------
 int cmCPackGenerator::PrepareGroupingKind()
 {

+ 3 - 0
Source/CPack/cmCPackGenerator.h

@@ -47,6 +47,7 @@
 
 class cmMakefile;
 class cmCPackLog;
+class cmInstalledFile;
 
 /** \class cmCPackGenerator
  * \brief A superclass of all CPack Generators
@@ -129,6 +130,8 @@ protected:
 
   int CleanTemporaryDirectory();
 
+  cmInstalledFile const* GetInstalledFile(std::string const& name) const;
+
   virtual const char* GetOutputExtension() { return ".cpack"; }
   virtual const char* GetOutputPostfix() { return 0; }
 

+ 5 - 4
Source/CPack/cpack.cxx

@@ -257,6 +257,11 @@ int main (int argc, char const* const* argv)
       return 1;
       }
 
+    if ( !cpackBuildConfig.empty() )
+      {
+      globalMF->AddDefinition("CPACK_BUILD_CONFIG", cpackBuildConfig.c_str());
+      }
+
     if ( cmSystemTools::FileExists(cpackConfigFile.c_str()) )
       {
       cpackConfigFile =
@@ -317,10 +322,6 @@ int main (int argc, char const* const* argv)
                                 cpackProjectDirectory.c_str());
         }
       }
-    if ( !cpackBuildConfig.empty() )
-      {
-      globalMF->AddDefinition("CPACK_BUILD_CONFIG", cpackBuildConfig.c_str());
-      }
     cpackDefinitions::MapType::iterator cdit;
     for ( cdit = definitions.Map.begin();
       cdit != definitions.Map.end();

+ 45 - 0
Source/cmCPackPropertiesGenerator.cxx

@@ -0,0 +1,45 @@
+#include "cmCPackPropertiesGenerator.h"
+
+#include "cmLocalGenerator.h"
+
+cmCPackPropertiesGenerator::cmCPackPropertiesGenerator(
+  cmMakefile* mf,
+  cmInstalledFile const& installedFile,
+  std::vector<std::string> const& configurations):
+    cmScriptGenerator("CPACK_BUILD_CONFIG", configurations),
+    Makefile(mf),
+    InstalledFile(installedFile)
+{
+  this->ActionsPerConfig = true;
+}
+
+void cmCPackPropertiesGenerator::GenerateScriptForConfig(std::ostream& os,
+  const std::string& config, Indent const& indent)
+{
+  std::string const& expandedFileName =
+      this->InstalledFile.GetNameExpression().Evaluate(this->Makefile, config);
+
+  cmInstalledFile::PropertyMapType const& properties =
+    this->InstalledFile.GetProperties();
+
+  for(cmInstalledFile::PropertyMapType::const_iterator i = properties.begin();
+    i != properties.end(); ++i)
+    {
+    std::string const& name = i->first;
+    cmInstalledFile::Property const& property = i->second;
+
+    os << indent << "set_property(INSTALL " <<
+      cmLocalGenerator::EscapeForCMake(expandedFileName) << " PROPERTY " <<
+      cmLocalGenerator::EscapeForCMake(name);
+
+    for(cmInstalledFile::ExpressionVectorType::const_iterator
+      j = property.ValueExpressions.begin();
+      j != property.ValueExpressions.end(); ++j)
+      {
+      std::string value = (*j)->Evaluate(this->Makefile, config);
+      os << " " << cmLocalGenerator::EscapeForCMake(value);
+      }
+
+    os << ")\n";
+    }
+}

+ 38 - 0
Source/cmCPackPropertiesGenerator.h

@@ -0,0 +1,38 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2014 Kitware, Inc., Insight Software Consortium
+
+  Distributed under the OSI-approved BSD License (the "License");
+  see accompanying file Copyright.txt for details.
+
+  This software is distributed WITHOUT ANY WARRANTY; without even the
+  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the License for more information.
+============================================================================*/
+#ifndef cmCPackPropertiesGenerator_h
+#define cmCPackPropertiesGenerator_h
+
+#include "cmScriptGenerator.h"
+#include "cmInstalledFile.h"
+
+/** \class cmCPackPropertiesGenerator
+ * \brief Support class for generating CPackProperties.cmake.
+ *
+ */
+class cmCPackPropertiesGenerator: public cmScriptGenerator
+{
+public:
+  cmCPackPropertiesGenerator(
+     cmMakefile* mf,
+     cmInstalledFile const& installedFile,
+     std::vector<std::string> const& configurations);
+
+protected:
+  virtual void GenerateScriptForConfig(std::ostream& os,
+    const std::string& config, Indent const& indent);
+
+  cmMakefile* Makefile;
+  cmInstalledFile const& InstalledFile;
+};
+
+#endif

+ 36 - 1
Source/cmGetPropertyCommand.cxx

@@ -67,12 +67,16 @@ bool cmGetPropertyCommand
     {
     scope = cmProperty::CACHE;
     }
+  else if(args[1] == "INSTALL")
+    {
+    scope = cmProperty::INSTALL;
+    }
   else
     {
     cmOStringStream e;
     e << "given invalid scope " << args[1] << ".  "
       << "Valid scopes are "
-      << "GLOBAL, DIRECTORY, TARGET, SOURCE, TEST, VARIABLE, CACHE.";
+      << "GLOBAL, DIRECTORY, TARGET, SOURCE, TEST, VARIABLE, CACHE, INSTALL.";
     this->SetError(e.str());
     return false;
     }
@@ -190,6 +194,7 @@ bool cmGetPropertyCommand
       case cmProperty::TEST:        return this->HandleTestMode();
       case cmProperty::VARIABLE:    return this->HandleVariableMode();
       case cmProperty::CACHE:       return this->HandleCacheMode();
+      case cmProperty::INSTALL:       return this->HandleInstallMode();
 
       case cmProperty::CACHED_VARIABLE:
         break; // should never happen
@@ -395,3 +400,33 @@ bool cmGetPropertyCommand::HandleCacheMode()
   this->StoreResult(value);
   return true;
 }
+
+//----------------------------------------------------------------------------
+bool cmGetPropertyCommand::HandleInstallMode()
+{
+  if(this->Name.empty())
+    {
+    this->SetError("not given name for INSTALL scope.");
+    return false;
+    }
+
+  // Get the installed file.
+  cmake* cm = this->Makefile->GetCMakeInstance();
+
+  if(cmInstalledFile* file = cm->GetOrCreateInstalledFile(
+    this->Makefile, this->Name))
+    {
+    std::string value;
+    bool isSet = file->GetProperty(this->PropertyName, value);
+
+    return this->StoreResult(isSet ? value.c_str() : 0);
+    }
+  else
+    {
+    cmOStringStream e;
+    e << "given INSTALL name that could not be found or created: "
+      << this->Name;
+    this->SetError(e.str());
+    return false;
+    }
+}

+ 1 - 0
Source/cmGetPropertyCommand.h

@@ -60,6 +60,7 @@ private:
   bool HandleTestMode();
   bool HandleVariableMode();
   bool HandleCacheMode();
+  bool HandleInstallMode();
 };
 
 #endif

+ 44 - 0
Source/cmGlobalGenerator.cxx

@@ -28,6 +28,7 @@
 #include "cmGeneratorExpression.h"
 #include "cmGeneratorExpressionEvaluationFile.h"
 #include "cmExportBuildFileGenerator.h"
+#include "cmCPackPropertiesGenerator.h"
 
 #include <cmsys/Directory.hxx>
 #include <cmsys/FStream.hxx>
@@ -1269,6 +1270,13 @@ void cmGlobalGenerator::Generate()
     }
   this->SetCurrentLocalGenerator(0);
 
+  if(!this->GenerateCPackPropertiesFile())
+    {
+    this->GetCMakeInstance()->IssueMessage(
+      cmake::FATAL_ERROR, "Could not write CPack properties file.",
+      cmListFileBacktrace());
+    }
+
   for (std::map<std::string, cmExportBuildFileGenerator*>::iterator
       it = this->BuildExportSets.begin(); it != this->BuildExportSets.end();
       ++it)
@@ -3014,3 +3022,39 @@ std::string cmGlobalGenerator::ExpandCFGIntDir(const std::string& str,
 {
   return str;
 }
+
+//----------------------------------------------------------------------------
+bool cmGlobalGenerator::GenerateCPackPropertiesFile()
+{
+  cmake::InstalledFilesMap const& installedFiles =
+    this->CMakeInstance->GetInstalledFiles();
+
+  cmMakefile* mf = this->LocalGenerators[0]->GetMakefile();
+
+  std::vector<std::string> configs;
+  std::string config = mf->GetConfigurations(configs, false);
+
+  std::string path = this->CMakeInstance->GetStartOutputDirectory();
+  path += "/CPackProperties.cmake";
+
+  if(!cmSystemTools::FileExists(path.c_str()) && installedFiles.empty())
+    {
+      return true;
+    }
+
+  cmGeneratedFileStream file(path.c_str());
+  file << "# CPack properties\n";
+
+  for(cmake::InstalledFilesMap::const_iterator i = installedFiles.begin();
+    i != installedFiles.end(); ++i)
+    {
+    cmInstalledFile const& installedFile = i->second;
+
+    cmCPackPropertiesGenerator cpackPropertiesGenerator(
+      mf, installedFile, configs);
+
+    cpackPropertiesGenerator.Generate(file, config, configs);
+    }
+
+  return true;
+}

+ 2 - 0
Source/cmGlobalGenerator.h

@@ -329,6 +329,8 @@ public:
 
   virtual void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const;
 
+  bool GenerateCPackPropertiesFile();
+
 protected:
   typedef std::vector<cmLocalGenerator*> GeneratorVector;
   // for a project collect all its targets by following depend

+ 115 - 0
Source/cmInstalledFile.cxx

@@ -0,0 +1,115 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2014 Kitware, Inc., Insight Software Consortium
+
+  Distributed under the OSI-approved BSD License (the "License");
+  see accompanying file Copyright.txt for details.
+
+  This software is distributed WITHOUT ANY WARRANTY; without even the
+  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the License for more information.
+============================================================================*/
+#include "cmInstalledFile.h"
+#include "cmSystemTools.h"
+#include "cmMakefile.h"
+
+//----------------------------------------------------------------------------
+cmInstalledFile::cmInstalledFile():
+  NameExpression(0)
+{
+
+}
+
+//----------------------------------------------------------------------------
+cmInstalledFile::~cmInstalledFile()
+{
+  if(NameExpression)
+    {
+    delete NameExpression;
+    }
+}
+
+//----------------------------------------------------------------------------
+void cmInstalledFile::SetName(cmMakefile* mf, const std::string& name)
+{
+  cmListFileBacktrace backtrace;
+  mf->GetBacktrace(backtrace);
+  cmGeneratorExpression ge(backtrace);
+
+  this->Name = name;
+  this->NameExpression = ge.Parse(name).release();
+}
+
+//----------------------------------------------------------------------------
+std::string const& cmInstalledFile::GetName() const
+{
+  return this->Name;
+}
+
+//----------------------------------------------------------------------------
+cmCompiledGeneratorExpression const& cmInstalledFile::GetNameExpression() const
+{
+  return *(this->NameExpression);
+}
+
+//----------------------------------------------------------------------------
+void cmInstalledFile::RemoveProperty(const std::string& prop)
+{
+  this->Properties.erase(prop);
+}
+
+//----------------------------------------------------------------------------
+void cmInstalledFile::SetProperty(cmMakefile const* mf,
+  const std::string& prop, const char* value)
+{
+  this->RemoveProperty(prop);
+  this->AppendProperty(mf, prop, value);
+}
+
+//----------------------------------------------------------------------------
+void cmInstalledFile::AppendProperty(cmMakefile const* mf,
+  const std::string& prop, const char* value, bool /*asString*/)
+{
+  cmListFileBacktrace backtrace;
+  mf->GetBacktrace(backtrace);
+  cmGeneratorExpression ge(backtrace);
+
+  Property& property = this->Properties[prop];
+  property.ValueExpressions.push_back(ge.Parse(value).release());
+}
+
+//----------------------------------------------------------------------------
+bool cmInstalledFile::GetProperty(
+  const std::string& prop, std::string& value) const
+{
+  PropertyMapType::const_iterator i = this->Properties.find(prop);
+  if(i == this->Properties.end())
+    {
+    return false;
+    }
+
+  Property const& property = i->second;
+
+  std::string output;
+  std::string separator;
+
+  for(ExpressionVectorType::const_iterator
+    j = property.ValueExpressions.begin();
+    j != property.ValueExpressions.end(); ++j)
+    {
+    output += separator;
+    output += (*j)->GetInput();
+    separator = ";";
+    }
+
+  value = output;
+  return true;
+}
+
+//----------------------------------------------------------------------------
+bool cmInstalledFile::GetPropertyAsBool(const std::string& prop) const
+{
+  std::string value;
+  bool isSet = this->GetProperty(prop, value);
+  return isSet && cmSystemTools::IsOn(value.c_str());
+}

+ 83 - 0
Source/cmInstalledFile.h

@@ -0,0 +1,83 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2014 Kitware, Inc., Insight Software Consortium
+
+  Distributed under the OSI-approved BSD License (the "License");
+  see accompanying file Copyright.txt for details.
+
+  This software is distributed WITHOUT ANY WARRANTY; without even the
+  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the License for more information.
+============================================================================*/
+#ifndef cmInstalledFile_h
+#define cmInstalledFile_h
+
+#include "cmGeneratorExpression.h"
+
+/** \class cmInstalledFile
+ * \brief Represents a file intended for installation.
+ *
+ * cmInstalledFile represents a file intended for installation.
+ */
+class cmInstalledFile
+{
+public:
+
+  typedef cmsys::auto_ptr<cmCompiledGeneratorExpression>
+    CompiledGeneratorExpressionPtrType;
+
+  typedef std::vector<cmCompiledGeneratorExpression*>
+    ExpressionVectorType;
+
+  struct Property
+  {
+    Property()
+    {
+
+    }
+
+    ~Property()
+    {
+      for(ExpressionVectorType::iterator i = ValueExpressions.begin();
+        i != ValueExpressions.end(); ++i)
+        {
+        delete *i;
+        }
+    }
+
+    ExpressionVectorType ValueExpressions;
+  };
+
+  typedef std::map<std::string, Property> PropertyMapType;
+
+  cmInstalledFile();
+
+  ~cmInstalledFile();
+
+  void RemoveProperty(const std::string& prop);
+
+  void SetProperty(cmMakefile const* mf,
+    const std::string& prop, const char *value);
+
+  void AppendProperty(cmMakefile const* mf,
+    const std::string& prop, const char* value,bool asString=false);
+
+  bool GetProperty(const std::string& prop, std::string& value) const;
+
+  bool GetPropertyAsBool(const std::string& prop) const;
+
+  void SetName(cmMakefile* mf, const std::string& name);
+
+  std::string const& GetName() const;
+
+  cmCompiledGeneratorExpression const& GetNameExpression() const;
+
+  PropertyMapType const& GetProperties() const { return this->Properties; }
+
+private:
+  std::string Name;
+  cmCompiledGeneratorExpression* NameExpression;
+  PropertyMapType Properties;
+};
+
+#endif

+ 1 - 1
Source/cmProperty.h

@@ -18,7 +18,7 @@ class cmProperty
 {
 public:
   enum ScopeType { TARGET, SOURCE_FILE, DIRECTORY, GLOBAL, CACHE,
-                   TEST, VARIABLE, CACHED_VARIABLE };
+                   TEST, VARIABLE, CACHED_VARIABLE, INSTALL };
 
   // set this property
   void Set(const std::string& name, const char *value);

+ 2 - 1
Source/cmRST.cxx

@@ -39,7 +39,8 @@ cmRST::cmRST(std::ostream& os, std::string const& docroot):
   ModuleRST("^#\\[(=*)\\[\\.rst:$"),
   CMakeRole("(:cmake)?:("
             "command|generator|variable|module|policy|"
-            "prop_cache|prop_dir|prop_gbl|prop_sf|prop_test|prop_tgt|"
+            "prop_cache|prop_dir|prop_gbl|prop_inst|prop_sf|"
+            "prop_test|prop_tgt|"
             "manual"
             "):`(<*([^`<]|[^` \t]<)*)([ \t]+<[^`]*>)?`"),
   Substitution("(^|[^A-Za-z0-9_])"

+ 58 - 1
Source/cmSetPropertyCommand.cxx

@@ -61,11 +61,16 @@ bool cmSetPropertyCommand
     {
     scope = cmProperty::CACHE;
     }
+  else if(*arg == "INSTALL")
+    {
+    scope = cmProperty::INSTALL;
+    }
   else
     {
     cmOStringStream e;
     e << "given invalid scope " << *arg << ".  "
-      << "Valid scopes are GLOBAL, DIRECTORY, TARGET, SOURCE, TEST, CACHE.";
+      << "Valid scopes are GLOBAL, DIRECTORY, "
+        "TARGET, SOURCE, TEST, CACHE, INSTALL.";
     this->SetError(e.str());
     return false;
     }
@@ -135,6 +140,7 @@ bool cmSetPropertyCommand
     case cmProperty::SOURCE_FILE: return this->HandleSourceMode();
     case cmProperty::TEST:        return this->HandleTestMode();
     case cmProperty::CACHE:       return this->HandleCacheMode();
+    case cmProperty::INSTALL:     return this->HandleInstallMode();
 
     case cmProperty::VARIABLE:
     case cmProperty::CACHED_VARIABLE:
@@ -488,3 +494,54 @@ bool cmSetPropertyCommand::HandleCacheEntry(cmCacheManager::CacheIterator& it)
 
   return true;
 }
+
+//----------------------------------------------------------------------------
+bool cmSetPropertyCommand::HandleInstallMode()
+{
+  cmake* cm = this->Makefile->GetCMakeInstance();
+
+  for(std::set<std::string>::const_iterator i = this->Names.begin();
+      i != this->Names.end(); ++i)
+    {
+    if(cmInstalledFile* file = cm->GetOrCreateInstalledFile(
+      this->Makefile, *i))
+      {
+      if(!this->HandleInstall(file))
+        {
+        return false;
+        }
+      }
+    else
+      {
+      cmOStringStream e;
+      e << "given INSTALL name that could not be found or created: " << *i;
+      this->SetError(e.str());
+      return false;
+      }
+    }
+  return true;
+}
+
+//----------------------------------------------------------------------------
+bool cmSetPropertyCommand::HandleInstall(cmInstalledFile* file)
+{
+  // Set or append the property.
+  std::string const& name = this->PropertyName;
+
+  cmMakefile* mf = this->Makefile;
+
+  const char *value = this->PropertyValue.c_str();
+  if (this->Remove)
+    {
+    file->RemoveProperty(name);
+    }
+  else if(this->AppendMode)
+    {
+    file->AppendProperty(mf, name, value, this->AppendAsString);
+    }
+  else
+    {
+    file->SetProperty(mf, name, value);
+    }
+  return true;
+}

+ 2 - 0
Source/cmSetPropertyCommand.h

@@ -62,6 +62,8 @@ private:
   bool HandleTest(cmTest* test);
   bool HandleCacheMode();
   bool HandleCacheEntry(cmCacheManager::CacheIterator&);
+  bool HandleInstallMode();
+  bool HandleInstall(cmInstalledFile* file);
 };
 
 

+ 35 - 0
Source/cmake.cxx

@@ -2287,6 +2287,41 @@ bool cmake::GetPropertyAsBool(const std::string& prop)
   return cmSystemTools::IsOn(this->GetProperty(prop));
 }
 
+cmInstalledFile *cmake::GetOrCreateInstalledFile(
+  cmMakefile* mf, const std::string& name)
+{
+  std::map<std::string, cmInstalledFile>::iterator i =
+    this->InstalledFiles.find(name);
+
+  if(i != this->InstalledFiles.end())
+    {
+    cmInstalledFile &file = i->second;
+    return &file;
+    }
+  else
+    {
+    cmInstalledFile &file = this->InstalledFiles[name];
+    file.SetName(mf, name);
+    return &file;
+    }
+}
+
+cmInstalledFile const* cmake::GetInstalledFile(const std::string& name) const
+{
+  std::map<std::string, cmInstalledFile>::const_iterator i =
+    this->InstalledFiles.find(name);
+
+  if(i != this->InstalledFiles.end())
+    {
+    cmInstalledFile const& file = i->second;
+    return &file;
+    }
+  else
+    {
+    return 0;
+    }
+}
+
 int cmake::GetSystemInformation(std::vector<std::string>& args)
 {
   // so create the directory

+ 12 - 0
Source/cmake.h

@@ -16,6 +16,7 @@
 #include "cmSystemTools.h"
 #include "cmPropertyDefinitionMap.h"
 #include "cmPropertyMap.h"
+#include "cmInstalledFile.h"
 
 class cmGlobalGeneratorFactory;
 class cmGlobalGenerator;
@@ -92,6 +93,7 @@ class cmake
     FIND_PACKAGE_MODE
   };
   typedef std::map<std::string, cmCommand*> RegisteredCommandsMap;
+  typedef std::map<std::string, cmInstalledFile> InstalledFilesMap;
 
   /// Default constructor
   cmake();
@@ -280,6 +282,15 @@ class cmake
   // Get the properties
   cmPropertyMap &GetProperties() { return this->Properties; }
 
+  ///! Get or create an cmInstalledFile instance and return a pointer to it
+  cmInstalledFile *GetOrCreateInstalledFile(
+    cmMakefile* mf, const std::string& name);
+
+  cmInstalledFile const* GetInstalledFile(const std::string& name) const;
+
+  InstalledFilesMap const& GetInstalledFiles() const
+    { return this->InstalledFiles; }
+
   ///! Do all the checks before running configure
   int DoPreConfigureChecks();
 
@@ -445,6 +456,7 @@ private:
   cmFileTimeComparison* FileComparison;
   std::string GraphVizFile;
   std::vector<std::string> DebugConfigs;
+  InstalledFilesMap InstalledFiles;
 
   void UpdateConversionPathTable();
 };

+ 8 - 0
Templates/CPackConfig.cmake.in

@@ -10,3 +10,11 @@
 # usually begin with CPACK_<GENNAME>_xxxx.
 
 @_CPACK_OTHER_VARIABLES_@
+
+if(NOT CPACK_PROPERTIES_FILE)
+  set(CPACK_PROPERTIES_FILE "@CMAKE_BINARY_DIR@/CPackProperties.cmake")
+endif()
+
+if(EXISTS ${CPACK_PROPERTIES_FILE})
+  include(${CPACK_PROPERTIES_FILE})
+endif()

+ 1 - 0
Tests/RunCMake/CMakeLists.txt

@@ -132,3 +132,4 @@ add_RunCMake_test(CheckModules)
 add_RunCMake_test(CommandLine)
 
 add_RunCMake_test(install)
+add_RunCMake_test(CPackInstallProperties)

+ 3 - 0
Tests/RunCMake/CPackInstallProperties/Append-check.cmake

@@ -0,0 +1,3 @@
+include(${RunCMake_SOURCE_DIR}/check.cmake)
+
+test_property("append.txt" CPACK_TEST_PROP "value1;value2;value3")

+ 2 - 0
Tests/RunCMake/CPackInstallProperties/Append.cmake

@@ -0,0 +1,2 @@
+set_property(INSTALL append.txt PROPERTY CPACK_TEST_PROP value1)
+set_property(INSTALL append.txt PROPERTY CPACK_TEST_PROP value2 value3 APPEND)

+ 6 - 0
Tests/RunCMake/CPackInstallProperties/CMakeLists.txt

@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 3.0)
+
+project(${RunCMake_TEST} CXX)
+include(${RunCMake_TEST}.cmake)
+
+include(CPack)

+ 3 - 0
Tests/RunCMake/CPackInstallProperties/FilenameGenex-check.cmake

@@ -0,0 +1,3 @@
+include(${RunCMake_SOURCE_DIR}/check.cmake)
+
+test_property(${EXPECTED_MYTEST_NAME} CPACK_TEST_PROP2 PROP_VALUE2)

+ 7 - 0
Tests/RunCMake/CPackInstallProperties/FilenameGenex.cmake

@@ -0,0 +1,7 @@
+add_executable(mytest test.cpp)
+
+file(GENERATE OUTPUT runtest_info.cmake CONTENT [[
+set(EXPECTED_MYTEST_NAME "$<TARGET_FILE_NAME:mytest>")
+]])
+
+set_property(INSTALL $<TARGET_FILE_NAME:mytest> PROPERTY CPACK_TEST_PROP2 PROP_VALUE2)

+ 3 - 0
Tests/RunCMake/CPackInstallProperties/MultipleValues-check.cmake

@@ -0,0 +1,3 @@
+include(${RunCMake_SOURCE_DIR}/check.cmake)
+
+test_property("multiple_values.txt" CPACK_TEST_PROP "value1;value2;value3")

+ 1 - 0
Tests/RunCMake/CPackInstallProperties/MultipleValues.cmake

@@ -0,0 +1 @@
+set_property(INSTALL multiple_values.txt PROPERTY CPACK_TEST_PROP value1 value2 value3)

+ 13 - 0
Tests/RunCMake/CPackInstallProperties/PerConfigValue-check.cmake

@@ -0,0 +1,13 @@
+include(${RunCMake_SOURCE_DIR}/check.cmake)
+
+file(GLOB INFO_FILES ${RunCMake_TEST_BINARY_DIR}/runtest_info_*.cmake)
+
+if(NOT INFO_FILES)
+  message(FATAL_ERROR "missing expected info files")
+endif()
+
+foreach(INFO_FILE IN LISTS INFO_FILES)
+  include(${INFO_FILE})
+  include(${RunCMake_TEST_BINARY_DIR}/CPackProperties.cmake)
+  test_property("config.cpp" FOO ${EXPECTED_MYTEST_NAME})
+endforeach()

+ 14 - 0
Tests/RunCMake/CPackInstallProperties/PerConfigValue.cmake

@@ -0,0 +1,14 @@
+add_executable(mytest test.cpp)
+
+foreach(CONFIG IN LISTS CMAKE_CONFIGURATION_TYPES)
+  string(TOUPPER ${CONFIG} UPPER_CONFIG)
+  set_property(TARGET mytest PROPERTY
+    OUTPUT_NAME_${UPPER_CONFIG} bar_${CONFIG})
+endforeach()
+
+file(GENERATE OUTPUT runtest_info_$<CONFIG>.cmake CONTENT [[
+set(CPACK_BUILD_CONFIG "$<CONFIG>")
+set(EXPECTED_MYTEST_NAME "$<TARGET_FILE_NAME:mytest>")
+]])
+
+set_property(INSTALL config.cpp PROPERTY FOO $<TARGET_FILE_NAME:mytest>)

+ 3 - 0
Tests/RunCMake/CPackInstallProperties/Replace-check.cmake

@@ -0,0 +1,3 @@
+include(${RunCMake_SOURCE_DIR}/check.cmake)
+
+test_property("replace.txt" CPACK_TEST_PROP "value2")

+ 2 - 0
Tests/RunCMake/CPackInstallProperties/Replace.cmake

@@ -0,0 +1,2 @@
+set_property(INSTALL replace.txt PROPERTY CPACK_TEST_PROP value1)
+set_property(INSTALL replace.txt PROPERTY CPACK_TEST_PROP value2)

+ 9 - 0
Tests/RunCMake/CPackInstallProperties/RunCMakeTest.cmake

@@ -0,0 +1,9 @@
+include(RunCMake)
+
+run_cmake(Simple)
+run_cmake(FilenameGenex)
+run_cmake(ValueGenex)
+run_cmake(MultipleValues)
+run_cmake(Append)
+run_cmake(Replace)
+run_cmake(PerConfigValue)

+ 3 - 0
Tests/RunCMake/CPackInstallProperties/Simple-check.cmake

@@ -0,0 +1,3 @@
+include(${RunCMake_SOURCE_DIR}/check.cmake)
+
+test_property("foo/test.cpp" CPACK_TEST_PROP PROP_VALUE)

+ 1 - 0
Tests/RunCMake/CPackInstallProperties/Simple.cmake

@@ -0,0 +1 @@
+set_property(INSTALL foo/test.cpp PROPERTY CPACK_TEST_PROP PROP_VALUE)

+ 3 - 0
Tests/RunCMake/CPackInstallProperties/ValueGenex-check.cmake

@@ -0,0 +1,3 @@
+include(${RunCMake_SOURCE_DIR}/check.cmake)
+
+test_property("bar/test.cpp" CPACK_TEST_PROP ${EXPECTED_MYTEST_NAME})

+ 7 - 0
Tests/RunCMake/CPackInstallProperties/ValueGenex.cmake

@@ -0,0 +1,7 @@
+add_executable(mytest test.cpp)
+
+file(GENERATE OUTPUT runtest_info.cmake CONTENT [[
+set(EXPECTED_MYTEST_NAME "$<TARGET_FILE_NAME:mytest>")
+]])
+
+set_property(INSTALL bar/test.cpp PROPERTY CPACK_TEST_PROP $<TARGET_FILE_NAME:mytest>)

+ 12 - 0
Tests/RunCMake/CPackInstallProperties/check.cmake

@@ -0,0 +1,12 @@
+function(test_property FILE NAME EXPECTED_VALUE)
+  get_property(ACTUAL_VALUE INSTALL "${FILE}" PROPERTY "${NAME}")
+
+  if(NOT "${ACTUAL_VALUE}" STREQUAL "${EXPECTED_VALUE}")
+    message(FATAL_ERROR "${NAME}@${FILE}: property mismatch expected [${EXPECTED_VALUE}] actual [${ACTUAL_VALUE}] (Config:${CPACK_BUILD_CONFIG})")
+  endif()
+endfunction()
+
+set(CPACK_BUILD_CONFIG Debug)
+include(${RunCMake_TEST_BINARY_DIR}/CPackProperties.cmake)
+
+include(${RunCMake_TEST_BINARY_DIR}/runtest_info.cmake OPTIONAL)

+ 1 - 0
Tests/RunCMake/CPackInstallProperties/test.cpp

@@ -0,0 +1 @@
+int main() {}

+ 4 - 0
Utilities/Sphinx/cmake.py

@@ -142,6 +142,7 @@ _cmake_index_objs = {
     'prop_cache': _cmake_index_entry('cache property'),
     'prop_dir':   _cmake_index_entry('directory property'),
     'prop_gbl':   _cmake_index_entry('global property'),
+    'prop_inst':  _cmake_index_entry('installed file property'),
     'prop_sf':    _cmake_index_entry('source file property'),
     'prop_test':  _cmake_index_entry('test property'),
     'prop_tgt':   _cmake_index_entry('target property'),
@@ -269,6 +270,7 @@ class CMakeDomain(Domain):
         'prop_cache': ObjType('prop_cache', 'prop_cache'),
         'prop_dir':   ObjType('prop_dir',   'prop_dir'),
         'prop_gbl':   ObjType('prop_gbl',   'prop_gbl'),
+        'prop_inst':  ObjType('prop_inst',  'prop_inst'),
         'prop_sf':    ObjType('prop_sf',    'prop_sf'),
         'prop_test':  ObjType('prop_test',  'prop_test'),
         'prop_tgt':   ObjType('prop_tgt',   'prop_tgt'),
@@ -284,6 +286,7 @@ class CMakeDomain(Domain):
         # 'prop_cache': CMakeObject,
         # 'prop_dir':   CMakeObject,
         # 'prop_gbl':   CMakeObject,
+        # 'prop_inst':  CMakeObject,
         # 'prop_sf':    CMakeObject,
         # 'prop_test':  CMakeObject,
         # 'prop_tgt':   CMakeObject,
@@ -298,6 +301,7 @@ class CMakeDomain(Domain):
         'prop_cache': CMakeXRefRole(),
         'prop_dir':   CMakeXRefRole(),
         'prop_gbl':   CMakeXRefRole(),
+        'prop_inst':  CMakeXRefRole(),
         'prop_sf':    CMakeXRefRole(),
         'prop_test':  CMakeXRefRole(),
         'prop_tgt':   CMakeXRefRole(),

+ 2 - 0
bootstrap

@@ -232,6 +232,7 @@ CMAKE_CXX_SOURCES="\
   cmCommandArgumentLexer \
   cmCommandArgumentParser \
   cmCommandArgumentParserHelper \
+  cmCPackPropertiesGenerator \
   cmDefinitions \
   cmDepends \
   cmDependsC \
@@ -258,6 +259,7 @@ CMAKE_CXX_SOURCES="\
   cmGeneratorExpression \
   cmGlobalGenerator \
   cmLocalGenerator \
+  cmInstalledFile \
   cmInstallGenerator \
   cmInstallExportGenerator \
   cmInstallFilesGenerator \