Browse Source

CPackWIX: refactor and cleanup

Extract addtional classes and functions which are getting unsightly large.
Use some of the coding conventions more consistently.
Nils Gladitz 12 years ago
parent
commit
6fcd835c07

+ 4 - 0
Source/CMakeLists.txt

@@ -562,7 +562,11 @@ if(WIN32)
   set(CPACK_SRCS ${CPACK_SRCS}
     CPack/WiX/cmCPackWIXGenerator.cxx
     CPack/WiX/cmWIXSourceWriter.cxx
+    CPack/WiX/cmWIXDirectoriesSourceWriter.cxx
+    CPack/WiX/cmWIXFeaturesSourceWriter.cxx
+    CPack/WiX/cmWIXFilesSourceWriter.cxx
     CPack/WiX/cmWIXRichTextFormatWriter.cxx
+    CPack/WiX/cmWIXPatch.cxx
     CPack/WiX/cmWIXPatchParser.cxx
   )
 endif()

+ 133 - 444
Source/CPack/WiX/cmCPackWIXGenerator.cxx

@@ -1,6 +1,6 @@
 /*============================================================================
   CMake - Cross Platform Makefile Generator
-  Copyright 2000-2013 Kitware, Inc., Insight Software Consortium
+  Copyright 2000-2014 Kitware, Inc., Insight Software Consortium
 
   Distributed under the OSI-approved BSD License (the "License");
   see accompanying file Copyright.txt for details.
@@ -19,6 +19,9 @@
 #include <CPack/cmCPackComponentGroup.h>
 
 #include "cmWIXSourceWriter.h"
+#include "cmWIXDirectoriesSourceWriter.h"
+#include "cmWIXFeaturesSourceWriter.h"
+#include "cmWIXFilesSourceWriter.h"
 #include "cmWIXRichTextFormatWriter.h"
 
 #include <cmsys/SystemTools.hxx>
@@ -28,11 +31,9 @@
 
 #include <rpc.h> // for GUID generation
 
-#include <sys/types.h>
-#include <sys/stat.h>
-
 cmCPackWIXGenerator::cmCPackWIXGenerator():
-  HasDesktopShortcuts(false)
+  HasDesktopShortcuts(false),
+  Patch(Logger)
 {
 
 }
@@ -44,15 +45,9 @@ int cmCPackWIXGenerator::InitializeInternal()
   return this->Superclass::InitializeInternal();
 }
 
-bool cmCPackWIXGenerator::RunWiXCommand(const std::string& command)
+bool cmCPackWIXGenerator::RunWiXCommand(std::string const& command)
 {
-  std::string cpackTopLevel;
-  if(!RequireOption("CPACK_TOPLEVEL_DIRECTORY", cpackTopLevel))
-    {
-    return false;
-    }
-
-  std::string logFileName = cpackTopLevel + "/wix.log";
+  std::string logFileName = this->CPackTopLevel + "/wix.log";
 
   cmCPackLogger(cmCPackLog::LOG_DEBUG,
     "Running WiX command: " << command << std::endl);
@@ -81,7 +76,7 @@ bool cmCPackWIXGenerator::RunWiXCommand(const std::string& command)
 }
 
 bool cmCPackWIXGenerator::RunCandleCommand(
-  const std::string& sourceFile, const std::string& objectFile)
+  std::string const& sourceFile, std::string const& objectFile)
 {
   std::string executable;
   if(!RequireOption("CPACK_WIX_CANDLE_EXECUTABLE", executable))
@@ -108,7 +103,7 @@ bool cmCPackWIXGenerator::RunCandleCommand(
   return RunWiXCommand(command.str());
 }
 
-bool cmCPackWIXGenerator::RunLightCommand(const std::string& objectFiles)
+bool cmCPackWIXGenerator::RunLightCommand(std::string const& objectFiles)
 {
   std::string executable;
   if(!RequireOption("CPACK_WIX_LIGHT_EXECUTABLE", executable))
@@ -121,8 +116,8 @@ bool cmCPackWIXGenerator::RunLightCommand(const std::string& objectFiles)
   command << " -nologo";
   command << " -out " << QuotePath(packageFileNames.at(0));
 
-  for(extension_set_t::const_iterator i = LightExtensions.begin();
-      i != LightExtensions.end(); ++i)
+  for(extension_set_t::const_iterator i = this->LightExtensions.begin();
+      i != this->LightExtensions.end(); ++i)
     {
     command << " -ext " << QuotePath(*i);
     }
@@ -182,15 +177,14 @@ bool cmCPackWIXGenerator::InitializeWiXConfiguration()
       "you might want to set this explicitly." << std::endl);
     }
 
-  std::string cpackTopLevel;
-  if(!RequireOption("CPACK_TOPLEVEL_DIRECTORY", cpackTopLevel))
+  if(!RequireOption("CPACK_TOPLEVEL_DIRECTORY", this->CPackTopLevel))
     {
     return false;
     }
 
   if(GetOption("CPACK_WIX_LICENSE_RTF") == 0)
     {
-    std::string licenseFilename = cpackTopLevel + "/License.rtf";
+    std::string licenseFilename = this->CPackTopLevel + "/License.rtf";
     SetOption("CPACK_WIX_LICENSE_RTF", licenseFilename.c_str());
 
     if(!CreateLicenseFile())
@@ -213,7 +207,7 @@ bool cmCPackWIXGenerator::InitializeWiXConfiguration()
     {
     std::string defaultRef = "WixUI_InstallDir";
 
-    if(Components.size())
+    if(this->Components.size())
       {
       defaultRef = "WixUI_FeatureTree";
       }
@@ -221,17 +215,17 @@ bool cmCPackWIXGenerator::InitializeWiXConfiguration()
     SetOption("CPACK_WIX_UI_REF", defaultRef.c_str());
     }
 
-  CollectExtensions("CPACK_WIX_EXTENSIONS", CandleExtensions);
-  CollectExtensions("CPACK_WIX_CANDLE_EXTENSIONS", CandleExtensions);
+  CollectExtensions("CPACK_WIX_EXTENSIONS", this->CandleExtensions);
+  CollectExtensions("CPACK_WIX_CANDLE_EXTENSIONS", this->CandleExtensions);
 
-  LightExtensions.insert("WixUIExtension");
-  CollectExtensions("CPACK_WIX_EXTENSIONS", LightExtensions);
-  CollectExtensions("CPACK_WIX_LIGHT_EXTENSIONS", LightExtensions);
+  this->LightExtensions.insert("WixUIExtension");
+  CollectExtensions("CPACK_WIX_EXTENSIONS", this->LightExtensions);
+  CollectExtensions("CPACK_WIX_LIGHT_EXTENSIONS", this->LightExtensions);
 
   const char* patchFilePath = GetOption("CPACK_WIX_PATCH_FILE");
   if(patchFilePath)
     {
-    LoadPatchFragments(patchFilePath);
+    this->Patch.LoadFragments(patchFilePath);
     }
 
   return true;
@@ -244,10 +238,7 @@ bool cmCPackWIXGenerator::PackageFilesImpl()
     return false;
     }
 
-  if(!CreateWiXVariablesIncludeFile())
-    {
-    return false;
-    }
+  CreateWiXVariablesIncludeFile();
 
   if(!CreateWiXSourceFiles())
     {
@@ -257,9 +248,9 @@ bool cmCPackWIXGenerator::PackageFilesImpl()
   AppendUserSuppliedExtraSources();
 
   std::stringstream objectFiles;
-  for(size_t i = 0; i < WixSources.size(); ++i)
+  for(size_t i = 0; i < this->WixSources.size(); ++i)
     {
-    const std::string& sourceFilename = WixSources[i];
+    std::string const& sourceFilename = this->WixSources[i];
 
     std::string objectFilename =
       cmSystemTools::GetFilenameWithoutExtension(sourceFilename) + ".wixobj";
@@ -282,7 +273,7 @@ void cmCPackWIXGenerator::AppendUserSuppliedExtraSources()
   const char *cpackWixExtraSources = GetOption("CPACK_WIX_EXTRA_SOURCES");
   if(!cpackWixExtraSources) return;
 
-  cmSystemTools::ExpandListArgument(cpackWixExtraSources, WixSources);
+  cmSystemTools::ExpandListArgument(cpackWixExtraSources, this->WixSources);
 }
 
 void cmCPackWIXGenerator::AppendUserSuppliedExtraObjects(std::ostream& stream)
@@ -297,22 +288,18 @@ void cmCPackWIXGenerator::AppendUserSuppliedExtraObjects(std::ostream& stream)
 
   for(size_t i = 0; i < expandedExtraObjects.size(); ++i)
     {
-      stream << " " << QuotePath(expandedExtraObjects[i]);
+    stream << " " << QuotePath(expandedExtraObjects[i]);
     }
 }
 
-bool cmCPackWIXGenerator::CreateWiXVariablesIncludeFile()
+void cmCPackWIXGenerator::CreateWiXVariablesIncludeFile()
 {
-  std::string cpackTopLevel;
-  if(!RequireOption("CPACK_TOPLEVEL_DIRECTORY", cpackTopLevel))
-    {
-    return false;
-    }
-
   std::string includeFilename =
-    cpackTopLevel + "/cpack_variables.wxi";
+    this->CPackTopLevel + "/cpack_variables.wxi";
+
+  cmWIXSourceWriter includeFile(
+    this->Logger, includeFilename, true);
 
-  cmWIXSourceWriter includeFile(Logger, includeFilename, true);
   CopyDefinition(includeFile, "CPACK_WIX_PRODUCT_GUID");
   CopyDefinition(includeFile, "CPACK_WIX_UPGRADE_GUID");
   CopyDefinition(includeFile, "CPACK_PACKAGE_VENDOR");
@@ -326,12 +313,10 @@ bool cmCPackWIXGenerator::CreateWiXVariablesIncludeFile()
     GetOption("CPACK_PACKAGE_NAME"));
   CopyDefinition(includeFile, "CPACK_WIX_PROGRAM_MENU_FOLDER");
   CopyDefinition(includeFile, "CPACK_WIX_UI_REF");
-
-  return true;
 }
 
 void cmCPackWIXGenerator::CopyDefinition(
-  cmWIXSourceWriter &source, const std::string &name)
+  cmWIXSourceWriter &source, std::string const& name)
 {
   const char* value = GetOption(name.c_str());
   if(value)
@@ -341,7 +326,7 @@ void cmCPackWIXGenerator::CopyDefinition(
 }
 
 void cmCPackWIXGenerator::AddDefinition(cmWIXSourceWriter& source,
-  const std::string& name, const std::string& value)
+  std::string const& name, std::string const& value)
 {
   std::stringstream tmp;
   tmp << name << "=\"" << value << '"';
@@ -352,81 +337,47 @@ void cmCPackWIXGenerator::AddDefinition(cmWIXSourceWriter& source,
 
 bool cmCPackWIXGenerator::CreateWiXSourceFiles()
 {
-  std::string cpackTopLevel;
-  if(!RequireOption("CPACK_TOPLEVEL_DIRECTORY", cpackTopLevel))
-    {
-    return false;
-    }
-
   std::string directoryDefinitionsFilename =
-    cpackTopLevel + "/directories.wxs";
+    this->CPackTopLevel + "/directories.wxs";
 
-  WixSources.push_back(directoryDefinitionsFilename);
+  this->WixSources.push_back(directoryDefinitionsFilename);
 
-  cmWIXSourceWriter directoryDefinitions(Logger, directoryDefinitionsFilename);
+  cmWIXDirectoriesSourceWriter directoryDefinitions(
+    this->Logger, directoryDefinitionsFilename);
   directoryDefinitions.BeginElement("Fragment");
 
-  directoryDefinitions.BeginElement("Directory");
-  directoryDefinitions.AddAttribute("Id", "TARGETDIR");
-  directoryDefinitions.AddAttribute("Name", "SourceDir");
-
-  directoryDefinitions.BeginElement("Directory");
-  if(GetArchitecture() == "x86")
-    {
-    directoryDefinitions.AddAttribute("Id", "ProgramFilesFolder");
-    }
-  else
-    {
-    directoryDefinitions.AddAttribute("Id", "ProgramFiles64Folder");
-    }
-
-  std::vector<std::string> install_root;
-
-  std::string tmp;
-  if(!RequireOption("CPACK_PACKAGE_INSTALL_DIRECTORY", tmp))
+  std::string installRoot;
+  if(!RequireOption("CPACK_PACKAGE_INSTALL_DIRECTORY", installRoot))
     {
     return false;
     }
 
-  cmSystemTools::SplitPath(tmp.c_str(), install_root);
-
-  if(!install_root.empty() && install_root.back().empty())
-    {
-    install_root.pop_back();
-    }
-
-  for(size_t i = 1; i < install_root.size(); ++i)
-    {
-    directoryDefinitions.BeginElement("Directory");
-
-    if(i == install_root.size() - 1)
-      {
-      directoryDefinitions.AddAttribute("Id", "INSTALL_ROOT");
-      }
-    else
-      {
-      std::stringstream ss;
-      ss << "INSTALL_PREFIX_" << i;
-      directoryDefinitions.AddAttribute("Id", ss.str());
-      }
+  directoryDefinitions.BeginElement("Directory");
+  directoryDefinitions.AddAttribute("Id", "TARGETDIR");
+  directoryDefinitions.AddAttribute("Name", "SourceDir");
 
-    directoryDefinitions.AddAttribute("Name", install_root[i]);
-  }
+  size_t installRootSize =
+    directoryDefinitions.BeginInstallationPrefixDirectory(
+      GetProgramFilesFolderId(), installRoot);
 
   std::string fileDefinitionsFilename =
-    cpackTopLevel + "/files.wxs";
+    this->CPackTopLevel + "/files.wxs";
 
-  WixSources.push_back(fileDefinitionsFilename);
+  this->WixSources.push_back(fileDefinitionsFilename);
+
+  cmWIXFilesSourceWriter fileDefinitions(
+    this->Logger, fileDefinitionsFilename);
 
-  cmWIXSourceWriter fileDefinitions(Logger, fileDefinitionsFilename);
   fileDefinitions.BeginElement("Fragment");
 
   std::string featureDefinitionsFilename =
-      cpackTopLevel +"/features.wxs";
+      this->CPackTopLevel +"/features.wxs";
+
+  this->WixSources.push_back(featureDefinitionsFilename);
 
-  WixSources.push_back(featureDefinitionsFilename);
+  cmWIXFeaturesSourceWriter featureDefinitions(
+    this->Logger, featureDefinitionsFilename);
 
-  cmWIXSourceWriter featureDefinitions(Logger, featureDefinitionsFilename);
   featureDefinitions.BeginElement("Fragment");
 
   featureDefinitions.BeginElement("Feature");
@@ -439,13 +390,15 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles()
     {
     return false;
     }
-  featureDefinitions.AddAttribute("Title", cpackPackageName);
 
+  featureDefinitions.AddAttribute("Title", cpackPackageName);
   featureDefinitions.AddAttribute("Level", "1");
 
-  if(!CreateCMakePackageRegistryEntry(featureDefinitions))
+  const char* package = GetOption("CPACK_WIX_CMAKE_PACKAGE_REGISTRY");
+  if(package)
     {
-    return false;
+    featureDefinitions.CreateCMakePackageRegistryEntry(
+        package, GetOption("CPACK_WIX_UPGRADE_GUID"));
     }
 
   if(!CreateFeatureHierarchy(featureDefinitions))
@@ -471,7 +424,7 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles()
   else
     {
     for(std::map<std::string, cmCPackComponent>::const_iterator
-      i = Components.begin(); i != Components.end(); ++i)
+      i = this->Components.begin(); i != this->Components.end(); ++i)
       {
       cmCPackComponent const& component = i->second;
 
@@ -513,31 +466,51 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles()
   featureDefinitions.EndElement("Fragment");
   fileDefinitions.EndElement("Fragment");
 
-  for(size_t i = 1; i < install_root.size(); ++i)
-    {
-    directoryDefinitions.EndElement("Directory");
-    }
-
-  directoryDefinitions.EndElement("Directory");
+  directoryDefinitions.EndInstallationPrefixDirectory(
+    installRootSize);
 
   if(hasShortcuts)
     {
-    CreateStartMenuFolder(directoryDefinitions);
+    directoryDefinitions.EmitStartMenuFolder(
+      GetOption("CPACK_WIX_PROGRAM_MENU_FOLDER"));
     }
 
   if(this->HasDesktopShortcuts)
     {
-    CreateDesktopFolder(directoryDefinitions);
+    directoryDefinitions.EmitDesktopFolder();
     }
 
   directoryDefinitions.EndElement("Directory");
   directoryDefinitions.EndElement("Fragment");
 
+  if(!GenerateMainSourceFileFromTemplate())
+    {
+    return false;
+    }
+
+  return this->Patch.CheckForUnappliedFragments();
+}
+
+std::string cmCPackWIXGenerator::GetProgramFilesFolderId() const
+{
+  if(GetArchitecture() == "x86")
+    {
+    return "ProgramFilesFolder";
+    }
+  else
+    {
+    return "ProgramFiles64Folder";
+    }
+}
+
+bool cmCPackWIXGenerator::GenerateMainSourceFileFromTemplate()
+{
   std::string wixTemplate = FindTemplate("WIX.template.in");
   if(GetOption("CPACK_WIX_TEMPLATE") != 0)
     {
     wixTemplate = GetOption("CPACK_WIX_TEMPLATE");
     }
+
   if(wixTemplate.empty())
     {
     cmCPackLogger(cmCPackLog::LOG_ERROR,
@@ -545,7 +518,7 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles()
     return false;
     }
 
-  std::string mainSourceFilePath = cpackTopLevel + "/main.wxs";
+  std::string mainSourceFilePath = this->CPackTopLevel + "/main.wxs";
 
   if(!ConfigureFile(wixTemplate.c_str(), mainSourceFilePath .c_str()))
     {
@@ -556,68 +529,13 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles()
     return false;
     }
 
-  WixSources.push_back(mainSourceFilePath);
-
-  std::string fragmentList;
-  for(cmWIXPatchParser::fragment_map_t::const_iterator
-    i = Fragments.begin(); i != Fragments.end(); ++i)
-    {
-    if(!fragmentList.empty())
-      {
-      fragmentList += ", ";
-      }
-
-    fragmentList += "'";
-    fragmentList += i->first;
-    fragmentList += "'";
-    }
-
-  if(fragmentList.size())
-    {
-      cmCPackLogger(cmCPackLog::LOG_ERROR,
-        "Some XML patch fragments did not have matching IDs: " <<
-        fragmentList << std::endl);
-      return false;
-    }
-
-  return true;
-}
-
-bool cmCPackWIXGenerator::CreateCMakePackageRegistryEntry(
-  cmWIXSourceWriter& featureDefinitions)
-{
-  const char* package = GetOption("CPACK_WIX_CMAKE_PACKAGE_REGISTRY");
-  if(!package)
-    {
-    return true;
-    }
-
-  featureDefinitions.BeginElement("Component");
-  featureDefinitions.AddAttribute("Id", "CM_PACKAGE_REGISTRY");
-  featureDefinitions.AddAttribute("Directory", "TARGETDIR");
-  featureDefinitions.AddAttribute("Guid", "*");
-
-  std::string registryKey =
-      std::string("Software\\Kitware\\CMake\\Packages\\") + package;
-
-  std::string upgradeGuid = GetOption("CPACK_WIX_UPGRADE_GUID");
-
-  featureDefinitions.BeginElement("RegistryValue");
-  featureDefinitions.AddAttribute("Root", "HKLM");
-  featureDefinitions.AddAttribute("Key", registryKey);
-  featureDefinitions.AddAttribute("Name", upgradeGuid);
-  featureDefinitions.AddAttribute("Type", "string");
-  featureDefinitions.AddAttribute("Value", "[INSTALL_ROOT]");
-  featureDefinitions.AddAttribute("KeyPath", "yes");
-  featureDefinitions.EndElement("RegistryValue");
-
-  featureDefinitions.EndElement("Component");
+  this->WixSources.push_back(mainSourceFilePath);
 
   return true;
 }
 
 bool cmCPackWIXGenerator::CreateFeatureHierarchy(
-  cmWIXSourceWriter& featureDefinitions)
+  cmWIXFeaturesSourceWriter& featureDefinitions)
 {
   for(std::map<std::string, cmCPackComponentGroup>::const_iterator
     i = ComponentGroups.begin(); i != ComponentGroups.end(); ++i)
@@ -625,105 +543,30 @@ bool cmCPackWIXGenerator::CreateFeatureHierarchy(
     cmCPackComponentGroup const& group = i->second;
     if(group.ParentGroup == 0)
       {
-      if(!EmitFeatureForComponentGroup(featureDefinitions, group))
-        {
-        return false;
-        }
+      featureDefinitions.EmitFeatureForComponentGroup(group);
       }
     }
 
   for(std::map<std::string, cmCPackComponent>::const_iterator
-    i = Components.begin(); i != Components.end(); ++i)
+    i = this->Components.begin(); i != this->Components.end(); ++i)
     {
     cmCPackComponent const& component = i->second;
 
     if(!component.Group)
       {
-      if(!EmitFeatureForComponent(featureDefinitions, component))
-        {
-        return false;
-        }
+      featureDefinitions.EmitFeatureForComponent(component);
       }
     }
 
   return true;
 }
 
-bool cmCPackWIXGenerator::EmitFeatureForComponentGroup(
-  cmWIXSourceWriter& featureDefinitions,
-  cmCPackComponentGroup const& group)
-{
-  featureDefinitions.BeginElement("Feature");
-  featureDefinitions.AddAttribute("Id", "CM_G_" + group.Name);
-
-  if(group.IsExpandedByDefault)
-    {
-    featureDefinitions.AddAttribute("Display", "expand");
-    }
-
-  featureDefinitions.AddAttributeUnlessEmpty(
-    "Title", group.DisplayName);
-
-  featureDefinitions.AddAttributeUnlessEmpty(
-    "Description", group.Description);
-
-  for(std::vector<cmCPackComponentGroup*>::const_iterator
-    i = group.Subgroups.begin(); i != group.Subgroups.end(); ++i)
-    {
-    if(!EmitFeatureForComponentGroup(featureDefinitions, **i))
-      {
-      return false;
-      }
-    }
-
-  for(std::vector<cmCPackComponent*>::const_iterator
-    i = group.Components.begin(); i != group.Components.end(); ++i)
-    {
-    if(!EmitFeatureForComponent(featureDefinitions, **i))
-      {
-      return false;
-      }
-    }
-
-  featureDefinitions.EndElement("Feature");
-
-  return true;
-}
-
-bool cmCPackWIXGenerator::EmitFeatureForComponent(
-  cmWIXSourceWriter& featureDefinitions,
-  cmCPackComponent const& component)
-{
-  featureDefinitions.BeginElement("Feature");
-  featureDefinitions.AddAttribute("Id", "CM_C_" + component.Name);
-
-  featureDefinitions.AddAttributeUnlessEmpty(
-    "Title", component.DisplayName);
-
-  featureDefinitions.AddAttributeUnlessEmpty(
-    "Description", component.Description);
-
-  if(component.IsRequired)
-    {
-    featureDefinitions.AddAttribute("Absent", "disallow");
-    }
-
-  if(component.IsHidden)
-    {
-    featureDefinitions.AddAttribute("Display", "hidden");
-    }
-
-  featureDefinitions.EndElement("Feature");
-
-  return true;
-}
-
 bool cmCPackWIXGenerator::AddComponentsToFeature(
   std::string const& rootPath,
   std::string const& featureId,
-  cmWIXSourceWriter& directoryDefinitions,
-  cmWIXSourceWriter& fileDefinitions,
-  cmWIXSourceWriter& featureDefinitions,
+  cmWIXDirectoriesSourceWriter& directoryDefinitions,
+  cmWIXFilesSourceWriter& fileDefinitions,
+  cmWIXFeaturesSourceWriter& featureDefinitions,
   shortcut_map_t& shortcutMap)
 {
   featureDefinitions.BeginElement("FeatureRef");
@@ -768,8 +611,8 @@ bool cmCPackWIXGenerator::CreateStartMenuShortcuts(
   std::string const& cpackComponentName,
   std::string const& featureId,
   shortcut_map_t& shortcutMap,
-  cmWIXSourceWriter& fileDefinitions,
-  cmWIXSourceWriter& featureDefinitions)
+  cmWIXFilesSourceWriter& fileDefinitions,
+  cmWIXFeaturesSourceWriter& featureDefinitions)
 {
   bool thisHasDesktopShortcuts = false;
 
@@ -799,6 +642,7 @@ bool cmCPackWIXGenerator::CreateStartMenuShortcuts(
 
   fileDefinitions.BeginElement("DirectoryRef");
   fileDefinitions.AddAttribute("Id", "PROGRAM_MENU_FOLDER");
+
   fileDefinitions.BeginElement("Component");
   fileDefinitions.AddAttribute("Id", componentId);
   fileDefinitions.AddAttribute("Guid", "*");
@@ -809,63 +653,34 @@ bool cmCPackWIXGenerator::CreateStartMenuShortcuts(
     std::string const& id = i->first;
     cmWIXShortcut const& shortcut = i->second;
 
-    std::string shortcutId = std::string("CM_S") + id;
-    std::string fileId = std::string("CM_F") + id;
-
-    fileDefinitions.BeginElement("Shortcut");
-    fileDefinitions.AddAttribute("Id", shortcutId);
-    fileDefinitions.AddAttribute("Name", shortcut.textLabel);
-    std::string target = "[#" + fileId + "]";
-    fileDefinitions.AddAttribute("Target", target);
-    fileDefinitions.AddAttribute("WorkingDirectory",
-      shortcut.workingDirectoryId);
-    fileDefinitions.EndElement("Shortcut");
+    fileDefinitions.EmitShortcut(id, shortcut, false);
 
-    if (shortcut.desktop)
+    if(shortcut.desktop)
       {
-        thisHasDesktopShortcuts = true;
+      thisHasDesktopShortcuts = true;
       }
     }
 
   if(cpackComponentName.empty())
     {
-    CreateUninstallShortcut(cpackPackageName, fileDefinitions);
+    fileDefinitions.EmitUninstallShortcut(cpackPackageName);
     }
 
-  fileDefinitions.BeginElement("RemoveFolder");
-  fileDefinitions.AddAttribute("Id",
+  fileDefinitions.EmitRemoveFolder(
     "CM_REMOVE_PROGRAM_MENU_FOLDER" + idSuffix);
-  fileDefinitions.AddAttribute("On", "uninstall");
-  fileDefinitions.EndElement("RemoveFolder");
 
   std::string registryKey =
     std::string("Software\\") + cpackVendor + "\\" + cpackPackageName;
 
-  fileDefinitions.BeginElement("RegistryValue");
-  fileDefinitions.AddAttribute("Root", "HKCU");
-  fileDefinitions.AddAttribute("Key", registryKey);
-
-  std::string valueName;
-  if(!cpackComponentName.empty())
-    {
-      valueName = cpackComponentName + "_";
-    }
-  valueName += "installed";
-
-  fileDefinitions.AddAttribute("Name", valueName);
-  fileDefinitions.AddAttribute("Type", "integer");
-  fileDefinitions.AddAttribute("Value", "1");
-  fileDefinitions.AddAttribute("KeyPath", "yes");
-  fileDefinitions.EndElement("RegistryValue");
+  fileDefinitions.EmitStartMenuShortcutRegistryValue(
+    registryKey, cpackComponentName);
 
   fileDefinitions.EndElement("Component");
   fileDefinitions.EndElement("DirectoryRef");
 
-  featureDefinitions.BeginElement("ComponentRef");
-  featureDefinitions.AddAttribute("Id", componentId);
-  featureDefinitions.EndElement("ComponentRef");
+  featureDefinitions.EmitComponentRef(componentId);
 
-  if (thisHasDesktopShortcuts)
+  if(thisHasDesktopShortcuts)
     {
     this->HasDesktopShortcuts = true;
     componentId = "CM_DESKTOP_SHORTCUT" + idSuffix;
@@ -876,7 +691,7 @@ bool cmCPackWIXGenerator::CreateStartMenuShortcuts(
     fileDefinitions.AddAttribute("Id", componentId);
     fileDefinitions.AddAttribute("Guid", "*");
 
-    for (shortcut_map_t::const_iterator
+    for(shortcut_map_t::const_iterator
       i = shortcutMap.begin(); i != shortcutMap.end(); ++i)
       {
       std::string const& id = i->first;
@@ -885,34 +700,16 @@ bool cmCPackWIXGenerator::CreateStartMenuShortcuts(
       if (!shortcut.desktop)
         continue;
 
-      std::string shortcutId = std::string("CM_DS") + id;
-      std::string fileId = std::string("CM_F") + id;
-
-      fileDefinitions.BeginElement("Shortcut");
-      fileDefinitions.AddAttribute("Id", shortcutId);
-      fileDefinitions.AddAttribute("Name", shortcut.textLabel);
-      std::string target = "[#" + fileId + "]";
-      fileDefinitions.AddAttribute("Target", target);
-      fileDefinitions.AddAttribute("WorkingDirectory",
-        shortcut.workingDirectoryId);
-      fileDefinitions.EndElement("Shortcut");
+      fileDefinitions.EmitShortcut(id, shortcut, true);
       }
 
-    fileDefinitions.BeginElement("RegistryValue");
-    fileDefinitions.AddAttribute("Root", "HKCU");
-    fileDefinitions.AddAttribute("Key", registryKey);
-    fileDefinitions.AddAttribute("Name", valueName + "_desktop");
-    fileDefinitions.AddAttribute("Type", "integer");
-    fileDefinitions.AddAttribute("Value", "1");
-    fileDefinitions.AddAttribute("KeyPath", "yes");
-    fileDefinitions.EndElement("RegistryValue");
+    fileDefinitions.EmitDesktopShortcutRegistryValue(
+      registryKey, cpackComponentName);
 
     fileDefinitions.EndElement("Component");
     fileDefinitions.EndElement("DirectoryRef");
 
-    featureDefinitions.BeginElement("ComponentRef");
-    featureDefinitions.AddAttribute("Id", componentId);
-    featureDefinitions.EndElement("ComponentRef");
+    featureDefinitions.EmitComponentRef(componentId);
     }
 
   featureDefinitions.EndElement("FeatureRef");
@@ -920,19 +717,6 @@ bool cmCPackWIXGenerator::CreateStartMenuShortcuts(
   return true;
 }
 
-void cmCPackWIXGenerator::CreateUninstallShortcut(
-  std::string const& packageName,
-  cmWIXSourceWriter& fileDefinitions)
-{
-  fileDefinitions.BeginElement("Shortcut");
-  fileDefinitions.AddAttribute("Id", "UNINSTALL");
-  fileDefinitions.AddAttribute("Name", "Uninstall " + packageName);
-  fileDefinitions.AddAttribute("Description", "Uninstalls " + packageName);
-  fileDefinitions.AddAttribute("Target", "[SystemFolder]msiexec.exe");
-  fileDefinitions.AddAttribute("Arguments", "/x [ProductCode]");
-  fileDefinitions.EndElement("Shortcut");
-}
-
 bool cmCPackWIXGenerator::CreateLicenseFile()
 {
   std::string licenseSourceFilename;
@@ -981,11 +765,11 @@ bool cmCPackWIXGenerator::CreateLicenseFile()
 }
 
 void cmCPackWIXGenerator::AddDirectoryAndFileDefinitons(
-  const std::string& topdir,
-  const std::string& directoryId,
-  cmWIXSourceWriter& directoryDefinitions,
-  cmWIXSourceWriter& fileDefinitions,
-  cmWIXSourceWriter& featureDefinitions,
+  std::string const& topdir,
+  std::string const& directoryId,
+  cmWIXDirectoriesSourceWriter& directoryDefinitions,
+  cmWIXFilesSourceWriter& fileDefinitions,
+  cmWIXFeaturesSourceWriter& featureDefinitions,
   const std::vector<std::string>& packageExecutables,
   const std::vector<std::string>& desktopExecutables,
   shortcut_map_t& shortcutMap)
@@ -1026,44 +810,15 @@ void cmCPackWIXGenerator::AddDirectoryAndFileDefinitons(
         desktopExecutables,
         shortcutMap);
 
-      ApplyPatchFragment(subDirectoryId, directoryDefinitions);
+      this->Patch.ApplyFragment(subDirectoryId, directoryDefinitions);
       directoryDefinitions.EndElement("Directory");
       }
     else
       {
-      std::string componentId = std::string("CM_C") + id;
-      std::string fileId = std::string("CM_F") + id;
-
-      fileDefinitions.BeginElement("DirectoryRef");
-      fileDefinitions.AddAttribute("Id", directoryId);
-
-      fileDefinitions.BeginElement("Component");
-      fileDefinitions.AddAttribute("Id", componentId);
-      fileDefinitions.AddAttribute("Guid", "*");
+      std::string componentId = fileDefinitions.EmitComponentFile(
+        directoryId, id, fullPath, this->Patch);
 
-      fileDefinitions.BeginElement("File");
-      fileDefinitions.AddAttribute("Id", fileId);
-      fileDefinitions.AddAttribute("Source", fullPath);
-      fileDefinitions.AddAttribute("KeyPath", "yes");
-
-      mode_t fileMode = 0;
-      cmSystemTools::GetPermissions(fullPath.c_str(), fileMode);
-
-      if(!(fileMode & S_IWRITE))
-        {
-        fileDefinitions.AddAttribute("ReadOnly", "yes");
-        }
-
-      ApplyPatchFragment(fileId, fileDefinitions);
-      fileDefinitions.EndElement("File");
-
-      ApplyPatchFragment(componentId, fileDefinitions);
-      fileDefinitions.EndElement("Component");
-      fileDefinitions.EndElement("DirectoryRef");
-
-      featureDefinitions.BeginElement("ComponentRef");
-      featureDefinitions.AddAttribute("Id", componentId);
-      featureDefinitions.EndElement("ComponentRef");
+      featureDefinitions.EmitComponentRef(componentId);
 
       for(size_t j = 0; j < packageExecutables.size(); ++j)
         {
@@ -1092,7 +847,7 @@ void cmCPackWIXGenerator::AddDirectoryAndFileDefinitons(
 }
 
 bool cmCPackWIXGenerator::RequireOption(
-  const std::string& name, std::string &value) const
+  std::string const& name, std::string &value) const
 {
   const char* tmp = GetOption(name.c_str());
   if(tmp)
@@ -1140,13 +895,13 @@ std::string cmCPackWIXGenerator::GenerateGUID()
   return cmSystemTools::UpperCase(result);
 }
 
-std::string cmCPackWIXGenerator::QuotePath(const std::string& path)
+std::string cmCPackWIXGenerator::QuotePath(std::string const& path)
 {
   return std::string("\"") + path + '"';
 }
 
 std::string cmCPackWIXGenerator::GetRightmostExtension(
-  const std::string& filename)
+  std::string const& filename)
 {
   std::string extension;
 
@@ -1159,7 +914,7 @@ std::string cmCPackWIXGenerator::GetRightmostExtension(
   return cmSystemTools::LowerCase(extension);
 }
 
-std::string cmCPackWIXGenerator::PathToId(const std::string& path)
+std::string cmCPackWIXGenerator::PathToId(std::string const& path)
 {
   id_map_t::const_iterator i = PathToIdMap.find(path);
   if(i != PathToIdMap.end()) return i->second;
@@ -1168,7 +923,7 @@ std::string cmCPackWIXGenerator::PathToId(const std::string& path)
   return id;
 }
 
-std::string cmCPackWIXGenerator::CreateNewIdForPath(const std::string& path)
+std::string cmCPackWIXGenerator::CreateNewIdForPath(std::string const& path)
 {
   std::vector<std::string> components;
   cmSystemTools::SplitPath(path.c_str(), components, false);
@@ -1222,7 +977,7 @@ std::string cmCPackWIXGenerator::CreateNewIdForPath(const std::string& path)
 }
 
 std::string cmCPackWIXGenerator::CreateHashedId(
-  const std::string& path, const std::string& normalizedFilename)
+  std::string const& path, std::string const& normalizedFilename)
 {
   cmsys::auto_ptr<cmCryptoHash> sha1 = cmCryptoHash::New("SHA1");
   std::string hash = sha1->HashString(path.c_str());
@@ -1245,7 +1000,7 @@ std::string cmCPackWIXGenerator::CreateHashedId(
 }
 
 std::string cmCPackWIXGenerator::NormalizeComponentForId(
-  const std::string& component, size_t& replacementCount)
+  std::string const& component, size_t& replacementCount)
 {
   std::string result;
   result.resize(component.size());
@@ -1276,7 +1031,7 @@ bool cmCPackWIXGenerator::IsLegalIdCharacter(char c)
 }
 
 void cmCPackWIXGenerator::CollectExtensions(
-     const std::string& variableName, extension_set_t& extensions)
+     std::string const& variableName, extension_set_t& extensions)
 {
   const char *variableContent = GetOption(variableName.c_str());
   if(!variableContent) return;
@@ -1292,7 +1047,7 @@ void cmCPackWIXGenerator::CollectExtensions(
 }
 
 void cmCPackWIXGenerator::AddCustomFlags(
-  const std::string& variableName, std::ostream& stream)
+  std::string const& variableName, std::ostream& stream)
 {
   const char *variableContent = GetOption(variableName.c_str());
   if(!variableContent) return;
@@ -1306,69 +1061,3 @@ void cmCPackWIXGenerator::AddCustomFlags(
       stream << " " << QuotePath(*i);
     }
 }
-
-void cmCPackWIXGenerator::CreateStartMenuFolder(
-    cmWIXSourceWriter& directoryDefinitions)
-{
-  directoryDefinitions.BeginElement("Directory");
-  directoryDefinitions.AddAttribute("Id", "ProgramMenuFolder");
-
-  directoryDefinitions.BeginElement("Directory");
-  directoryDefinitions.AddAttribute("Id", "PROGRAM_MENU_FOLDER");
-  const char *startMenuFolder = GetOption("CPACK_WIX_PROGRAM_MENU_FOLDER");
-  directoryDefinitions.AddAttribute("Name", startMenuFolder);
-  directoryDefinitions.EndElement("Directory");
-
-  directoryDefinitions.EndElement("Directory");
-}
-
-void cmCPackWIXGenerator::CreateDesktopFolder(
-    cmWIXSourceWriter& directoryDefinitions)
-{
-    directoryDefinitions.BeginElement("Directory");
-    directoryDefinitions.AddAttribute("Id", "DesktopFolder");
-    directoryDefinitions.AddAttribute("Name", "Desktop");
-    directoryDefinitions.EndElement("Directory");
-}
-
-void cmCPackWIXGenerator::LoadPatchFragments(const std::string& patchFilePath)
-{
-  cmWIXPatchParser parser(Fragments, Logger);
-  parser.ParseFile(patchFilePath.c_str());
-}
-
-void cmCPackWIXGenerator::ApplyPatchFragment(
-  const std::string& id, cmWIXSourceWriter& writer)
-{
-  cmWIXPatchParser::fragment_map_t::iterator i = Fragments.find(id);
-  if(i == Fragments.end()) return;
-
-  const cmWIXPatchElement& fragment = i->second;
-  for(cmWIXPatchElement::child_list_t::const_iterator
-    j = fragment.children.begin(); j != fragment.children.end(); ++j)
-    {
-    ApplyPatchElement(**j, writer);
-    }
-
-  Fragments.erase(i);
-}
-
-void cmCPackWIXGenerator::ApplyPatchElement(
-  const cmWIXPatchElement& element, cmWIXSourceWriter& writer)
-{
-  writer.BeginElement(element.name);
-
-  for(cmWIXPatchElement::attributes_t::const_iterator
-    i = element.attributes.begin(); i != element.attributes.end(); ++i)
-    {
-    writer.AddAttribute(i->first, i->second);
-    }
-
-  for(cmWIXPatchElement::child_list_t::const_iterator
-    i = element.children.begin(); i != element.children.end(); ++i)
-    {
-    ApplyPatchElement(**i, writer);
-    }
-
-  writer.EndElement(element.name);
-}

+ 38 - 65
Source/CPack/WiX/cmCPackWIXGenerator.h

@@ -13,25 +13,18 @@
 #ifndef cmCPackWIXGenerator_h
 #define cmCPackWIXGenerator_h
 
-#include "cmWIXPatchParser.h"
+#include "cmWIXPatch.h"
+#include "cmWIXShortcut.h"
 
 #include <CPack/cmCPackGenerator.h>
 
 #include <string>
 #include <map>
 
-struct cmWIXShortcut
-{
-  cmWIXShortcut()
-    :desktop(false)
-    {}
-
-  std::string textLabel;
-  std::string workingDirectoryId;
-  bool desktop;
-};
-
 class cmWIXSourceWriter;
+class cmWIXDirectoriesSourceWriter;
+class cmWIXFilesSourceWriter;
+class cmWIXFeaturesSourceWriter;
 
 /** \class cmCPackWIXGenerator
  * \brief A generator for WIX files
@@ -78,48 +71,37 @@ private:
 
   bool PackageFilesImpl();
 
-  bool CreateWiXVariablesIncludeFile();
+  void CreateWiXVariablesIncludeFile();
 
   void CopyDefinition(
-    cmWIXSourceWriter &source, const std::string &name);
+    cmWIXSourceWriter &source, std::string const& name);
 
   void AddDefinition(cmWIXSourceWriter& source,
-    const std::string& name, const std::string& value);
+    std::string const& name, std::string const& value);
 
   bool CreateWiXSourceFiles();
 
-  bool CreateCMakePackageRegistryEntry(
-    cmWIXSourceWriter& featureDefinitions);
+  std::string GetProgramFilesFolderId() const;
 
-  bool CreateFeatureHierarchy(
-    cmWIXSourceWriter& featureDefinitions);
-
-  bool EmitFeatureForComponentGroup(
-    cmWIXSourceWriter& featureDefinitions,
-    cmCPackComponentGroup const& group);
+  bool GenerateMainSourceFileFromTemplate();
 
-  bool EmitFeatureForComponent(
-    cmWIXSourceWriter& featureDefinitions,
-    cmCPackComponent const& component);
+  bool CreateFeatureHierarchy(
+    cmWIXFeaturesSourceWriter& featureDefinitions);
 
   bool AddComponentsToFeature(
     std::string const& rootPath,
     std::string const& featureId,
-    cmWIXSourceWriter& directoryDefinitions,
-    cmWIXSourceWriter& fileDefinitions,
-    cmWIXSourceWriter& featureDefinitions,
+    cmWIXDirectoriesSourceWriter& directoryDefinitions,
+    cmWIXFilesSourceWriter& fileDefinitions,
+    cmWIXFeaturesSourceWriter& featureDefinitions,
     shortcut_map_t& shortcutMap);
 
   bool CreateStartMenuShortcuts(
     std::string const& cpackComponentName,
     std::string const& featureId,
     shortcut_map_t& shortcutMap,
-    cmWIXSourceWriter& fileDefinitions,
-    cmWIXSourceWriter& featureDefinitions);
-
-  void CreateUninstallShortcut(
-    std::string const& packageName,
-    cmWIXSourceWriter& fileDefinitions);
+    cmWIXFilesSourceWriter& fileDefinitions,
+    cmWIXFeaturesSourceWriter& featureDefinitions);
 
   void AppendUserSuppliedExtraSources();
 
@@ -127,60 +109,49 @@ private:
 
   bool CreateLicenseFile();
 
-  bool RunWiXCommand(const std::string& command);
+  bool RunWiXCommand(std::string const& command);
 
   bool RunCandleCommand(
-    const std::string& sourceFile, const std::string& objectFile);
+    std::string const& sourceFile, std::string const& objectFile);
 
-  bool RunLightCommand(const std::string& objectFiles);
+  bool RunLightCommand(std::string const& objectFiles);
 
-  void AddDirectoryAndFileDefinitons(const std::string& topdir,
-    const std::string& directoryId,
-    cmWIXSourceWriter& directoryDefinitions,
-    cmWIXSourceWriter& fileDefinitions,
-    cmWIXSourceWriter& featureDefinitions,
+  void AddDirectoryAndFileDefinitons(std::string const& topdir,
+    std::string const& directoryId,
+    cmWIXDirectoriesSourceWriter& directoryDefinitions,
+    cmWIXFilesSourceWriter& fileDefinitions,
+    cmWIXFeaturesSourceWriter& featureDefinitions,
     const std::vector<std::string>& pkgExecutables,
     const std::vector<std::string>& desktopExecutables,
     shortcut_map_t& shortcutMap);
 
-  bool RequireOption(const std::string& name, std::string& value) const;
+  bool RequireOption(std::string const& name, std::string& value) const;
 
   std::string GetArchitecture() const;
 
   static std::string GenerateGUID();
 
-  static std::string QuotePath(const std::string& path);
+  static std::string QuotePath(std::string const& path);
 
-  static std::string GetRightmostExtension(const std::string& filename);
+  static std::string GetRightmostExtension(std::string const& filename);
 
-  std::string PathToId(const std::string& path);
+  std::string PathToId(std::string const& path);
 
-  std::string CreateNewIdForPath(const std::string& path);
+  std::string CreateNewIdForPath(std::string const& path);
 
   static std::string CreateHashedId(
-    const std::string& path, const std::string& normalizedFilename);
+    std::string const& path, std::string const& normalizedFilename);
 
   std::string NormalizeComponentForId(
-    const std::string& component, size_t& replacementCount);
+    std::string const& component, size_t& replacementCount);
 
   static bool IsLegalIdCharacter(char c);
 
   void CollectExtensions(
-       const std::string& variableName, extension_set_t& extensions);
+       std::string const& variableName, extension_set_t& extensions);
 
   void AddCustomFlags(
-    const std::string& variableName, std::ostream& stream);
-
-  void CreateStartMenuFolder(cmWIXSourceWriter& directoryDefinitions);
-
-  void CreateDesktopFolder(cmWIXSourceWriter& directoryDefinitions);
-
-  void LoadPatchFragments(const std::string& patchFilePath);
-
-  void ApplyPatchFragment(const std::string& id, cmWIXSourceWriter& writer);
-
-  void ApplyPatchElement(const cmWIXPatchElement& element,
-    cmWIXSourceWriter& writer);
+    std::string const& variableName, std::ostream& stream);
 
   std::vector<std::string> WixSources;
   id_map_t PathToIdMap;
@@ -189,9 +160,11 @@ private:
   extension_set_t CandleExtensions;
   extension_set_t LightExtensions;
 
-  cmWIXPatchParser::fragment_map_t Fragments;
-
   bool HasDesktopShortcuts;
+
+  std::string CPackTopLevel;
+
+  cmWIXPatch Patch;
 };
 
 #endif

+ 87 - 0
Source/CPack/WiX/cmWIXDirectoriesSourceWriter.cxx

@@ -0,0 +1,87 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2014 Kitware, Inc.
+
+  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 "cmWIXDirectoriesSourceWriter.h"
+
+cmWIXDirectoriesSourceWriter::cmWIXDirectoriesSourceWriter(cmCPackLog* logger,
+  std::string const& filename):
+    cmWIXSourceWriter(logger, filename)
+{
+
+}
+
+void cmWIXDirectoriesSourceWriter::EmitStartMenuFolder(
+  std::string const& startMenuFolder)
+{
+  BeginElement("Directory");
+  AddAttribute("Id", "ProgramMenuFolder");
+
+  BeginElement("Directory");
+  AddAttribute("Id", "PROGRAM_MENU_FOLDER");
+  AddAttribute("Name", startMenuFolder);
+  EndElement("Directory");
+
+  EndElement("Directory");
+}
+
+void cmWIXDirectoriesSourceWriter::EmitDesktopFolder()
+{
+  BeginElement("Directory");
+  AddAttribute("Id", "DesktopFolder");
+  AddAttribute("Name", "Desktop");
+  EndElement("Directory");
+}
+
+size_t cmWIXDirectoriesSourceWriter::BeginInstallationPrefixDirectory(
+  std::string const& programFilesFolderId,
+  std::string const& installRootString)
+{
+  BeginElement("Directory");
+  AddAttribute("Id", programFilesFolderId);
+
+  std::vector<std::string> installRoot;
+
+  cmSystemTools::SplitPath(installRootString.c_str(), installRoot);
+
+  if(!installRoot.empty() && installRoot.back().empty())
+    {
+    installRoot.pop_back();
+    }
+
+  for(size_t i = 1; i < installRoot.size(); ++i)
+    {
+    BeginElement("Directory");
+
+    if(i == installRoot.size() - 1)
+      {
+      AddAttribute("Id", "INSTALL_ROOT");
+      }
+    else
+      {
+      std::stringstream tmp;
+      tmp << "INSTALL_PREFIX_" << i;
+      AddAttribute("Id", tmp.str());
+      }
+
+    AddAttribute("Name", installRoot[i]);
+  }
+
+  return installRoot.size();
+}
+
+void cmWIXDirectoriesSourceWriter::EndInstallationPrefixDirectory(size_t size)
+{
+  for(size_t i = 0; i < size; ++i)
+    {
+    EndElement("Directory");
+    }
+}

+ 42 - 0
Source/CPack/WiX/cmWIXDirectoriesSourceWriter.h

@@ -0,0 +1,42 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2014 Kitware, Inc.
+
+  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 cmWIXDirectoriesSourceWriter_h
+#define cmWIXDirectoriesSourceWriter_h
+
+#include "cmWIXSourceWriter.h"
+
+#include <CPack/cmCPackGenerator.h>
+
+#include <string>
+
+/** \class cmWIXDirectoriesSourceWriter
+ * \brief Helper class to generate directories.wxs
+ */
+class cmWIXDirectoriesSourceWriter : public cmWIXSourceWriter
+{
+public:
+  cmWIXDirectoriesSourceWriter(cmCPackLog* logger,
+    std::string const& filename);
+
+  void EmitStartMenuFolder(std::string const& startMenuFolder);
+
+  void EmitDesktopFolder();
+
+  size_t BeginInstallationPrefixDirectory(
+      std::string const& programFilesFolderId,
+      std::string const& installRootString);
+
+  void EndInstallationPrefixDirectory(size_t size);
+};
+
+#endif

+ 102 - 0
Source/CPack/WiX/cmWIXFeaturesSourceWriter.cxx

@@ -0,0 +1,102 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2014 Kitware, Inc.
+
+  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 "cmWIXFeaturesSourceWriter.h"
+
+cmWIXFeaturesSourceWriter::cmWIXFeaturesSourceWriter(cmCPackLog* logger,
+  std::string const& filename):
+    cmWIXSourceWriter(logger, filename)
+{
+
+}
+
+void cmWIXFeaturesSourceWriter::CreateCMakePackageRegistryEntry(
+    std::string const& package,
+    std::string const& upgradeGuid)
+{
+  BeginElement("Component");
+  AddAttribute("Id", "CM_PACKAGE_REGISTRY");
+  AddAttribute("Directory", "TARGETDIR");
+  AddAttribute("Guid", "*");
+
+  std::string registryKey =
+      std::string("Software\\Kitware\\CMake\\Packages\\") + package;
+
+  BeginElement("RegistryValue");
+  AddAttribute("Root", "HKLM");
+  AddAttribute("Key", registryKey);
+  AddAttribute("Name", upgradeGuid);
+  AddAttribute("Type", "string");
+  AddAttribute("Value", "[INSTALL_ROOT]");
+  AddAttribute("KeyPath", "yes");
+  EndElement("RegistryValue");
+
+  EndElement("Component");
+}
+
+void cmWIXFeaturesSourceWriter::EmitFeatureForComponentGroup(
+  cmCPackComponentGroup const& group)
+{
+  BeginElement("Feature");
+  AddAttribute("Id", "CM_G_" + group.Name);
+
+  if(group.IsExpandedByDefault)
+    {
+    AddAttribute("Display", "expand");
+    }
+
+  AddAttributeUnlessEmpty("Title", group.DisplayName);
+  AddAttributeUnlessEmpty("Description", group.Description);
+
+  for(std::vector<cmCPackComponentGroup*>::const_iterator
+    i = group.Subgroups.begin(); i != group.Subgroups.end(); ++i)
+    {
+    EmitFeatureForComponentGroup(**i);
+    }
+
+  for(std::vector<cmCPackComponent*>::const_iterator
+    i = group.Components.begin(); i != group.Components.end(); ++i)
+    {
+    EmitFeatureForComponent(**i);
+    }
+
+  EndElement("Feature");
+}
+
+void cmWIXFeaturesSourceWriter::EmitFeatureForComponent(
+  cmCPackComponent const& component)
+{
+  BeginElement("Feature");
+  AddAttribute("Id", "CM_C_" + component.Name);
+
+  AddAttributeUnlessEmpty("Title", component.DisplayName);
+  AddAttributeUnlessEmpty("Description", component.Description);
+
+  if(component.IsRequired)
+    {
+    AddAttribute("Absent", "disallow");
+    }
+
+  if(component.IsHidden)
+    {
+    AddAttribute("Display", "hidden");
+    }
+
+  EndElement("Feature");
+}
+
+void cmWIXFeaturesSourceWriter::EmitComponentRef(std::string const& id)
+{
+  BeginElement("ComponentRef");
+  AddAttribute("Id", id);
+  EndElement("ComponentRef");
+}

+ 39 - 0
Source/CPack/WiX/cmWIXFeaturesSourceWriter.h

@@ -0,0 +1,39 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2014 Kitware, Inc.
+
+  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 cmWIXFeaturesSourceWriter_h
+#define cmWIXFeaturesSourceWriter_h
+
+#include "cmWIXSourceWriter.h"
+#include <CPack/cmCPackGenerator.h>
+
+/** \class cmWIXFeaturesSourceWriter
+ * \brief Helper class to generate features.wxs
+ */
+class cmWIXFeaturesSourceWriter : public cmWIXSourceWriter
+{
+public:
+  cmWIXFeaturesSourceWriter(cmCPackLog* logger,
+    std::string const& filename);
+
+  void CreateCMakePackageRegistryEntry(
+    std::string const& package,
+    std::string const& upgradeGuid);
+
+  void EmitFeatureForComponentGroup(const cmCPackComponentGroup& group);
+
+  void EmitFeatureForComponent(const cmCPackComponent& component);
+
+  void EmitComponentRef(std::string const& id);
+};
+
+#endif

+ 149 - 0
Source/CPack/WiX/cmWIXFilesSourceWriter.cxx

@@ -0,0 +1,149 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2014 Kitware, Inc.
+
+  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 "cmWIXFilesSourceWriter.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+cmWIXFilesSourceWriter::cmWIXFilesSourceWriter(cmCPackLog* logger,
+  std::string const& filename):
+    cmWIXSourceWriter(logger, filename)
+{
+
+}
+
+void cmWIXFilesSourceWriter::EmitShortcut(
+  std::string const& id,
+  cmWIXShortcut const& shortcut,
+  bool desktop)
+{
+  std::string shortcutId;
+
+  if(desktop)
+    {
+    shortcutId = "CM_DS";
+    }
+  else
+    {
+    shortcutId = "CM_S";
+    }
+
+  shortcutId += id;
+
+  std::string fileId = std::string("CM_F") + id;
+
+  BeginElement("Shortcut");
+  AddAttribute("Id", shortcutId);
+  AddAttribute("Name", shortcut.textLabel);
+  std::string target = "[#" + fileId + "]";
+  AddAttribute("Target", target);
+  AddAttribute("WorkingDirectory", shortcut.workingDirectoryId);
+  EndElement("Shortcut");
+}
+
+void cmWIXFilesSourceWriter::EmitRemoveFolder(std::string const& id)
+{
+  BeginElement("RemoveFolder");
+  AddAttribute("Id", id);
+  AddAttribute("On", "uninstall");
+  EndElement("RemoveFolder");
+}
+
+void cmWIXFilesSourceWriter::EmitStartMenuShortcutRegistryValue(
+  std::string const& registryKey,
+  std::string const& cpackComponentName)
+{
+  EmitInstallRegistryValue(registryKey, cpackComponentName, std::string());
+}
+
+void cmWIXFilesSourceWriter::EmitDesktopShortcutRegistryValue(
+  std::string const& registryKey,
+  std::string const& cpackComponentName)
+{
+  EmitInstallRegistryValue(registryKey, cpackComponentName, "_desktop");
+}
+
+void cmWIXFilesSourceWriter::EmitInstallRegistryValue(
+  std::string const& registryKey,
+  std::string const& cpackComponentName,
+  std::string const& suffix)
+{
+  std::string valueName;
+  if(!cpackComponentName.empty())
+    {
+      valueName = cpackComponentName + "_";
+    }
+
+  valueName += "installed";
+  valueName += suffix;
+
+  BeginElement("RegistryValue");
+  AddAttribute("Root", "HKCU");
+  AddAttribute("Key", registryKey);
+  AddAttribute("Name", valueName);
+  AddAttribute("Type", "integer");
+  AddAttribute("Value", "1");
+  AddAttribute("KeyPath", "yes");
+  EndElement("RegistryValue");
+}
+
+void cmWIXFilesSourceWriter::EmitUninstallShortcut(
+  std::string const& packageName)
+{
+  BeginElement("Shortcut");
+  AddAttribute("Id", "UNINSTALL");
+  AddAttribute("Name", "Uninstall " + packageName);
+  AddAttribute("Description", "Uninstalls " + packageName);
+  AddAttribute("Target", "[SystemFolder]msiexec.exe");
+  AddAttribute("Arguments", "/x [ProductCode]");
+  EndElement("Shortcut");
+}
+
+std::string cmWIXFilesSourceWriter::EmitComponentFile(
+  std::string const& directoryId,
+  std::string const& id,
+  std::string const& filePath,
+  cmWIXPatch &patch)
+{
+  std::string componentId = std::string("CM_C") + id;
+  std::string fileId = std::string("CM_F") + id;
+
+  BeginElement("DirectoryRef");
+  AddAttribute("Id", directoryId);
+
+  BeginElement("Component");
+  AddAttribute("Id", componentId);
+  AddAttribute("Guid", "*");
+
+  BeginElement("File");
+  AddAttribute("Id", fileId);
+  AddAttribute("Source", filePath);
+  AddAttribute("KeyPath", "yes");
+
+  mode_t fileMode = 0;
+  cmSystemTools::GetPermissions(filePath.c_str(), fileMode);
+
+  if(!(fileMode & S_IWRITE))
+    {
+    AddAttribute("ReadOnly", "yes");
+    }
+
+  patch.ApplyFragment(fileId, *this);
+  EndElement("File");
+
+  patch.ApplyFragment(componentId, *this);
+  EndElement("Component");
+  EndElement("DirectoryRef");
+
+  return componentId;
+}

+ 62 - 0
Source/CPack/WiX/cmWIXFilesSourceWriter.h

@@ -0,0 +1,62 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2014 Kitware, Inc.
+
+  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 cmWIXFilesSourceWriter_h
+#define cmWIXFilesSourceWriter_h
+
+#include "cmWIXSourceWriter.h"
+#include "cmWIXShortcut.h"
+#include "cmWIXPatch.h"
+
+#include <CPack/cmCPackGenerator.h>
+
+/** \class cmWIXFilesSourceWriter
+ * \brief Helper class to generate files.wxs
+ */
+class cmWIXFilesSourceWriter : public cmWIXSourceWriter
+{
+public:
+  cmWIXFilesSourceWriter(cmCPackLog* logger,
+    std::string const& filename);
+
+  void EmitShortcut(
+      std::string const& id,
+      cmWIXShortcut const& shortcut,
+      bool desktop);
+
+  void EmitRemoveFolder(std::string const& id);
+
+  void EmitStartMenuShortcutRegistryValue(
+    std::string const& registryKey,
+    std::string const& cpackComponentName);
+
+  void EmitDesktopShortcutRegistryValue(
+    std::string const& registryKey,
+    std::string const& cpackComponentName);
+
+  void EmitUninstallShortcut(std::string const& packageName);
+
+  std::string EmitComponentFile(
+    std::string const& directoryId,
+    std::string const& id,
+    std::string const& filePath,
+    cmWIXPatch &patch);
+
+private:
+  void EmitInstallRegistryValue(
+    std::string const& registryKey,
+    std::string const& cpackComponentName,
+    std::string const& suffix);
+};
+
+
+#endif

+ 91 - 0
Source/CPack/WiX/cmWIXPatch.cxx

@@ -0,0 +1,91 @@
+/*============================================================================
+  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 "cmWIXPatch.h"
+
+#include <CPack/cmCPackGenerator.h>
+
+cmWIXPatch::cmWIXPatch(cmCPackLog* logger):
+  Logger(logger)
+{
+
+}
+
+void cmWIXPatch::LoadFragments(std::string const& patchFilePath)
+{
+  cmWIXPatchParser parser(Fragments, Logger);
+  parser.ParseFile(patchFilePath.c_str());
+}
+
+void cmWIXPatch::ApplyFragment(
+  std::string const& id, cmWIXSourceWriter& writer)
+{
+  cmWIXPatchParser::fragment_map_t::iterator i = Fragments.find(id);
+  if(i == Fragments.end()) return;
+
+  const cmWIXPatchElement& fragment = i->second;
+  for(cmWIXPatchElement::child_list_t::const_iterator
+    j = fragment.children.begin(); j != fragment.children.end(); ++j)
+    {
+    ApplyElement(**j, writer);
+    }
+
+  Fragments.erase(i);
+}
+
+void cmWIXPatch::ApplyElement(
+  const cmWIXPatchElement& element, cmWIXSourceWriter& writer)
+{
+  writer.BeginElement(element.name);
+
+  for(cmWIXPatchElement::attributes_t::const_iterator
+    i = element.attributes.begin(); i != element.attributes.end(); ++i)
+    {
+    writer.AddAttribute(i->first, i->second);
+    }
+
+  for(cmWIXPatchElement::child_list_t::const_iterator
+    i = element.children.begin(); i != element.children.end(); ++i)
+    {
+    ApplyElement(**i, writer);
+    }
+
+  writer.EndElement(element.name);
+}
+
+
+bool cmWIXPatch::CheckForUnappliedFragments()
+{
+  std::string fragmentList;
+  for(cmWIXPatchParser::fragment_map_t::const_iterator
+    i = Fragments.begin(); i != Fragments.end(); ++i)
+    {
+    if(!fragmentList.empty())
+      {
+      fragmentList += ", ";
+      }
+
+    fragmentList += "'";
+    fragmentList += i->first;
+    fragmentList += "'";
+    }
+
+  if(fragmentList.size())
+    {
+      cmCPackLogger(cmCPackLog::LOG_ERROR,
+        "Some XML patch fragments did not have matching IDs: " <<
+        fragmentList << std::endl);
+      return false;
+    }
+
+  return true;
+}

+ 45 - 0
Source/CPack/WiX/cmWIXPatch.h

@@ -0,0 +1,45 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2014 Kitware, Inc.
+
+  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 cmWIXPatch_h
+#define cmWIXPatch_h
+
+#include "cmWIXSourceWriter.h"
+#include "cmWIXPatchParser.h"
+
+#include <string>
+
+/** \class cmWIXPatch
+ * \brief Class that maintains and applies patch fragments
+ */
+class cmWIXPatch
+{
+public:
+  cmWIXPatch(cmCPackLog* logger);
+
+  void LoadFragments(std::string const& patchFilePath);
+
+  void ApplyFragment(std::string const& id, cmWIXSourceWriter& writer);
+
+  bool CheckForUnappliedFragments();
+
+private:
+  void ApplyElement(const cmWIXPatchElement& element,
+    cmWIXSourceWriter& writer);
+
+  cmCPackLog* Logger;
+
+  cmWIXPatchParser::fragment_map_t Fragments;
+};
+
+
+#endif

+ 1 - 1
Source/CPack/WiX/cmWIXPatchParser.cxx

@@ -132,7 +132,7 @@ void cmWIXPatchParser::ReportError(int line, int column, const char* msg)
   Valid = false;
 }
 
-void cmWIXPatchParser::ReportValidationError(const std::string& message)
+void cmWIXPatchParser::ReportValidationError(std::string const& message)
 {
   ReportError(XML_GetCurrentLineNumber(Parser),
     XML_GetCurrentColumnNumber(Parser),

+ 1 - 1
Source/CPack/WiX/cmWIXPatchParser.h

@@ -50,7 +50,7 @@ private:
   virtual void EndElement(const char *name);
   virtual void ReportError(int line, int column, const char* msg);
 
-  void ReportValidationError(const std::string& message);
+  void ReportValidationError(std::string const& message);
 
   bool IsValid() const;
 

+ 4 - 4
Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx

@@ -15,7 +15,7 @@
 #include <cmVersion.h>
 
 cmWIXRichTextFormatWriter::cmWIXRichTextFormatWriter(
-  const std::string& filename):
+  std::string const& filename):
     File(filename.c_str(), std::ios::binary)
 {
   StartGroup();
@@ -33,7 +33,7 @@ cmWIXRichTextFormatWriter::~cmWIXRichTextFormatWriter()
   File.put(0);
 }
 
-void cmWIXRichTextFormatWriter::AddText(const std::string& text)
+void cmWIXRichTextFormatWriter::AddText(std::string const& text)
 {
   typedef unsigned char rtf_byte_t;
 
@@ -167,12 +167,12 @@ void cmWIXRichTextFormatWriter::WriteDocumentPrefix()
   ControlWord("fs20");
 }
 
-void cmWIXRichTextFormatWriter::ControlWord(const std::string& keyword)
+void cmWIXRichTextFormatWriter::ControlWord(std::string const& keyword)
 {
   File << "\\" << keyword;
 }
 
-void cmWIXRichTextFormatWriter::NewControlWord(const std::string& keyword)
+void cmWIXRichTextFormatWriter::NewControlWord(std::string const& keyword)
 {
   File << "\\*\\" << keyword;
 }

+ 4 - 4
Source/CPack/WiX/cmWIXRichTextFormatWriter.h

@@ -22,10 +22,10 @@
 class cmWIXRichTextFormatWriter
 {
 public:
-  cmWIXRichTextFormatWriter(const std::string& filename);
+  cmWIXRichTextFormatWriter(std::string const& filename);
   ~cmWIXRichTextFormatWriter();
 
-  void AddText(const std::string& text);
+  void AddText(std::string const& text);
 
 private:
   void WriteHeader();
@@ -35,8 +35,8 @@ private:
 
   void WriteDocumentPrefix();
 
-  void ControlWord(const std::string& keyword);
-  void NewControlWord(const std::string& keyword);
+  void ControlWord(std::string const& keyword);
+  void NewControlWord(std::string const& keyword);
 
   void StartGroup();
   void EndGroup();

+ 29 - 0
Source/CPack/WiX/cmWIXShortcut.h

@@ -0,0 +1,29 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2014 Kitware, Inc.
+
+  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 cmWIXFilesShortcut_h
+#define cmWIXFilesShortcut_h
+
+#include <string>
+
+struct cmWIXShortcut
+{
+  cmWIXShortcut()
+    :desktop(false)
+    {}
+
+  std::string textLabel;
+  std::string workingDirectoryId;
+  bool desktop;
+};
+
+#endif

+ 7 - 7
Source/CPack/WiX/cmWIXSourceWriter.cxx

@@ -17,7 +17,7 @@
 #include <windows.h>
 
 cmWIXSourceWriter::cmWIXSourceWriter(cmCPackLog* logger,
-  const std::string& filename,
+  std::string const& filename,
   bool isIncludeFile):
     Logger(logger),
     File(filename.c_str()),
@@ -51,7 +51,7 @@ cmWIXSourceWriter::~cmWIXSourceWriter()
   EndElement(Elements.back());
 }
 
-void cmWIXSourceWriter::BeginElement(const std::string& name)
+void cmWIXSourceWriter::BeginElement(std::string const& name)
 {
   if(State == BEGIN)
     {
@@ -101,7 +101,7 @@ void cmWIXSourceWriter::EndElement(std::string const& name)
 }
 
 void cmWIXSourceWriter::AddProcessingInstruction(
-  const std::string& target, const std::string& content)
+  std::string const& target, std::string const& content)
 {
   if(State == BEGIN)
     {
@@ -116,7 +116,7 @@ void cmWIXSourceWriter::AddProcessingInstruction(
 }
 
 void cmWIXSourceWriter::AddAttribute(
-  const std::string& key, const std::string& value)
+  std::string const& key, std::string const& value)
 {
   std::string utf8 = WindowsCodepageToUtf8(value);
 
@@ -124,7 +124,7 @@ void cmWIXSourceWriter::AddAttribute(
 }
 
 void cmWIXSourceWriter::AddAttributeUnlessEmpty(
-    const std::string& key, const std::string& value)
+    std::string const& key, std::string const& value)
 {
   if(value.size())
     {
@@ -132,7 +132,7 @@ void cmWIXSourceWriter::AddAttributeUnlessEmpty(
     }
 }
 
-std::string cmWIXSourceWriter::WindowsCodepageToUtf8(const std::string& value)
+std::string cmWIXSourceWriter::WindowsCodepageToUtf8(std::string const& value)
 {
   if(value.empty())
     {
@@ -184,7 +184,7 @@ void cmWIXSourceWriter::Indent(size_t count)
 }
 
 std::string cmWIXSourceWriter::EscapeAttributeValue(
-  const std::string& value)
+  std::string const& value)
 {
   std::string result;
   result.reserve(value.size());

+ 8 - 8
Source/CPack/WiX/cmWIXSourceWriter.h

@@ -26,24 +26,24 @@ class cmWIXSourceWriter
 {
 public:
   cmWIXSourceWriter(cmCPackLog* logger,
-    const std::string& filename, bool isIncludeFile = false);
+    std::string const& filename, bool isIncludeFile = false);
 
   ~cmWIXSourceWriter();
 
-  void BeginElement(const std::string& name);
+  void BeginElement(std::string const& name);
 
-  void EndElement(const std::string& name);
+  void EndElement(std::string const& name);
 
   void AddProcessingInstruction(
-    const std::string& target, const std::string& content);
+    std::string const& target, std::string const& content);
 
   void AddAttribute(
-    const std::string& key, const std::string& value);
+    std::string const& key, std::string const& value);
 
   void AddAttributeUnlessEmpty(
-    const std::string& key, const std::string& value);
+    std::string const& key, std::string const& value);
 
-  static std::string WindowsCodepageToUtf8(const std::string& value);
+  static std::string WindowsCodepageToUtf8(std::string const& value);
 
 private:
   enum State
@@ -56,7 +56,7 @@ private:
 
   void Indent(size_t count);
 
-  static std::string EscapeAttributeValue(const std::string& value);
+  static std::string EscapeAttributeValue(std::string const& value);
 
   cmCPackLog* Logger;