From 9a0ba4d24ae73cf225a07dff2cf4fc2096fb9751 Mon Sep 17 00:00:00 2001
From: Konstantin Podsvirov <konstantin@podsvirov.pro>
Date: Mon, 27 Apr 2015 17:02:49 +0300
Subject: CPackIFW: Add QtIFW 2.0 support

Add variables:

- CPACK_IFW_FRAMEWORK_VERSION
- CPACK_IFW_PACKAGE_ALLOW_NON_ASCII_CHARACTERS
- CPACK_IFW_PACKAGE_ALLOW_SPACE_IN_PATH
- CPACK_IFW_PACKAGE_CONTROL_SCRIPT
- CPACK_IFW_PACKAGE_MAINTENANCE_TOOL_INI_FILE
- CPACK_IFW_PACKAGE_MAINTENANCE_TOOL_NAME
- CPACK_IFW_PACKAGE_START_MENU_DIRECTORY
- CPACK_IFW_VERBOSE
---
 Help/release/dev/cpack-ifw-updates.rst   |   5 +
 Modules/CPackIFW.cmake                   | 115 +++++++++++++++++++++--
 Source/CPack/IFW/cmCPackIFWGenerator.cxx |  79 +++++++++++++++-
 Source/CPack/IFW/cmCPackIFWGenerator.h   |  20 ++++
 Source/CPack/IFW/cmCPackIFWInstaller.cxx | 151 +++++++++++++++++++++++++++++--
 Source/CPack/IFW/cmCPackIFWInstaller.h   |  26 ++++++
 Source/CPack/IFW/cmCPackIFWPackage.cxx   |  26 ++++++
 Source/CPack/IFW/cmCPackIFWPackage.h     |   8 ++
 8 files changed, 410 insertions(+), 20 deletions(-)
 create mode 100644 Help/release/dev/cpack-ifw-updates.rst

diff --git a/Help/release/dev/cpack-ifw-updates.rst b/Help/release/dev/cpack-ifw-updates.rst
new file mode 100644
index 0000000..c01f04b
--- /dev/null
+++ b/Help/release/dev/cpack-ifw-updates.rst
@@ -0,0 +1,5 @@
+cpack-ifw-updates
+-----------------
+
+* The :manual:`cpack(1)` ``IFW`` generator and the :module:`CPackIFW`
+  module learned to support Qt Framework Installer 2.0 tools.
diff --git a/Modules/CPackIFW.cmake b/Modules/CPackIFW.cmake
index e5b7601..6649933 100644
--- a/Modules/CPackIFW.cmake
+++ b/Modules/CPackIFW.cmake
@@ -2,7 +2,7 @@
 # CPackIFW
 # --------
 #
-# .. _QtIFW: http://qt-project.org/doc/qtinstallerframework/index.html
+# .. _QtIFW: http://doc.qt.io/qtinstallerframework/index.html
 #
 # This module looks for the location of the command line utilities supplied with
 # the Qt Installer Framework (QtIFW_).
@@ -33,18 +33,26 @@
 #
 # You can use the following variables to change behavior of CPack ``IFW`` generator.
 #
+# Debug
+# """"""
+#
+# .. variable:: CPACK_IFW_VERBOSE
+#
+#  Set to ``ON`` to enable addition debug output.
+#  By default is ``OFF``.
+#
 # Package
 # """""""
 #
 # .. variable:: CPACK_IFW_PACKAGE_TITLE
 #
 #  Name of the installer as displayed on the title bar.
-#  By default used :variable:`CPACK_PACKAGE_DESCRIPTION_SUMMARY`
+#  By default used :variable:`CPACK_PACKAGE_DESCRIPTION_SUMMARY`.
 #
 # .. variable:: CPACK_IFW_PACKAGE_PUBLISHER
 #
 #  Publisher of the software (as shown in the Windows Control Panel).
-#  By default used :variable:`CPACK_PACKAGE_VENDOR`
+#  By default used :variable:`CPACK_PACKAGE_VENDOR`.
 #
 # .. variable:: CPACK_IFW_PRODUCT_URL
 #
@@ -63,6 +71,12 @@
 #
 #  Filename for a logo is used as QWizard::LogoPixmap.
 #
+# .. variable:: CPACK_IFW_PACKAGE_START_MENU_DIRECTORY
+#
+#  Name of the default program group for the product in the Windows Start menu.
+#
+#  By default used :variable:`CPACK_IFW_PACKAGE_NAME`.
+#
 # .. variable:: CPACK_IFW_TARGET_DIRECTORY
 #
 #  Default target directory for installation.
@@ -85,6 +99,35 @@
 #  The root package name, which will be used if configuration group is not
 #  specified
 #
+# .. variable:: CPACK_IFW_PACKAGE_MAINTENANCE_TOOL_NAME
+#
+#  Filename of the generated maintenance tool.
+#  The platform-specific executable file extension is appended.
+#
+#  By default used QtIFW_ defaults (``maintenancetool``).
+#
+# .. variable:: CPACK_IFW_PACKAGE_MAINTENANCE_TOOL_INI_FILE
+#
+#  Filename for the configuration of the generated maintenance tool.
+#
+#  By default used QtIFW_ defaults (``maintenancetool.ini``).
+#
+# .. variable:: CPACK_IFW_PACKAGE_ALLOW_NON_ASCII_CHARACTERS
+#
+#  Set to ``ON`` if the installation path can contain non-ASCII characters.
+#
+#  Is ``ON`` for QtIFW_ less 2.0 tools.
+#
+# .. variable:: CPACK_IFW_PACKAGE_ALLOW_SPACE_IN_PATH
+#
+#  Set to ``OFF`` if the installation path cannot contain space characters.
+#
+#  Is ``ON`` for QtIFW_ less 2.0 tools.
+#
+# .. variable:: CPACK_IFW_PACKAGE_CONTROL_SCRIPT
+#
+#  Filename for a custom installer control script.
+#
 # .. variable:: CPACK_IFW_REPOSITORIES_ALL
 #
 #  The list of remote repositories.
@@ -113,6 +156,10 @@
 # Tools
 # """"""""
 #
+# .. variable:: CPACK_IFW_FRAMEWORK_VERSION
+#
+#  The version of used QtIFW_ tools.
+#
 # .. variable:: CPACK_IFW_BINARYCREATOR_EXECUTABLE
 #
 #  The path to "binarycreator" command line client.
@@ -276,16 +323,16 @@
 # Qt Installer Framework Manual:
 #
 #  Index page
-#   http://qt-project.org/doc/qtinstallerframework/index.html
+#   http://doc.qt.io/qtinstallerframework/index.html
 #
 #  Component Scripting
-#   http://qt-project.org/doc/qtinstallerframework/scripting.html
+#   http://doc.qt.io/qtinstallerframework/scripting.html
 #
 #  Predefined Variables
-#   http://qt-project.org/doc/qtinstallerframework/scripting.html#predefined-variables
+#   http://doc.qt.io/qtinstallerframework/scripting.html#predefined-variables
 #
-# Download Qt Installer Framework for you platform from Qt Project site:
-#  http://download.qt-project.org/official_releases/qt-installer-framework/
+# Download Qt Installer Framework for you platform from Qt site:
+#  http://download.qt.io/official_releases/qt-installer-framework
 #
 
 #=============================================================================
@@ -324,8 +371,14 @@ else()
 endif()
 
 set(_CPACK_IFW_SUFFIXES
+# Common
   "bin"
-  "QtIFW-1.7.0/bin"
+# Second branch
+  "QtIFW2.3.0/bin"
+  "QtIFW2.2.0/bin"
+  "QtIFW2.1.0/bin"
+  "QtIFW2.0.0/bin"
+# First branch
   "QtIFW-1.6.0/bin"
   "QtIFW-1.5.0/bin"
   "QtIFW-1.4.0/bin"
@@ -351,6 +404,26 @@ find_program(CPACK_IFW_REPOGEN_EXECUTABLE
   )
 mark_as_advanced(CPACK_IFW_REPOGEN_EXECUTABLE)
 
+# Look for 'installerbase'
+
+find_program(CPACK_IFW_INSTALLERBASE_EXECUTABLE
+  NAMES installerbase
+  PATHS ${_CPACK_IFW_PATHS}
+  PATH_SUFFIXES ${_CPACK_IFW_SUFFIXES}
+  DOC "QtIFW installer executable base"
+  )
+mark_as_advanced(CPACK_IFW_INSTALLERBASE_EXECUTABLE)
+
+# Look for 'devtool' (appeared in the second branch)
+
+find_program(CPACK_IFW_DEVTOOL_EXECUTABLE
+  NAMES devtool
+  PATHS ${_CPACK_IFW_PATHS}
+  PATH_SUFFIXES ${_CPACK_IFW_SUFFIXES}
+  DOC "QtIFW devtool command line client"
+  )
+mark_as_advanced(CPACK_IFW_DEVTOOL_EXECUTABLE)
+
 #
 ## Next code is included only once
 #
@@ -359,6 +432,27 @@ if(NOT CPackIFW_CMake_INCLUDED)
 set(CPackIFW_CMake_INCLUDED 1)
 
 #=============================================================================
+# Framework version
+#=============================================================================
+
+if(CPACK_IFW_INSTALLERBASE_EXECUTABLE AND CPACK_IFW_DEVTOOL_EXECUTABLE)
+  execute_process(COMMAND
+    "${CPACK_IFW_INSTALLERBASE_EXECUTABLE}" --framework-version
+    OUTPUT_VARIABLE CPACK_IFW_FRAMEWORK_VERSION)
+  if(CPACK_IFW_FRAMEWORK_VERSION)
+    string(REPLACE " " ""
+      CPACK_IFW_FRAMEWORK_VERSION "${CPACK_IFW_FRAMEWORK_VERSION}")
+    string(REPLACE "\t" ""
+      CPACK_IFW_FRAMEWORK_VERSION "${CPACK_IFW_FRAMEWORK_VERSION}")
+    string(REPLACE "\n" ""
+      CPACK_IFW_FRAMEWORK_VERSION "${CPACK_IFW_FRAMEWORK_VERSION}")
+    if(CPACK_IFW_VERBOSE)
+      message(STATUS "Found QtIFW ${CPACK_IFW_FRAMEWORK_VERSION} version")
+    endif()
+  endif()
+endif()
+
+#=============================================================================
 # Macro definition
 #=============================================================================
 
@@ -514,4 +608,7 @@ macro(cpack_ifw_add_repository reponame)
 
 endmacro()
 
+# Resolve package control script
+_cpack_ifw_resolve_script(CPACK_IFW_PACKAGE_CONTROL_SCRIPT)
+
 endif() # NOT CPackIFW_CMake_INCLUDED
diff --git a/Source/CPack/IFW/cmCPackIFWGenerator.cxx b/Source/CPack/IFW/cmCPackIFWGenerator.cxx
index 0439ff6..80ba068 100644
--- a/Source/CPack/IFW/cmCPackIFWGenerator.cxx
+++ b/Source/CPack/IFW/cmCPackIFWGenerator.cxx
@@ -29,6 +29,8 @@
 #include <cmMakefile.h>
 #include <cmGeneratedFileStream.h>
 #include <cmXMLSafe.h>
+#include <cmVersionConfig.h>
+#include <cmTimestamp.h>
 
 //----------------------------------------------------------------------------
 cmCPackIFWGenerator::cmCPackIFWGenerator()
@@ -41,6 +43,27 @@ cmCPackIFWGenerator::~cmCPackIFWGenerator()
 }
 
 //----------------------------------------------------------------------------
+bool cmCPackIFWGenerator::IsVersionLess(const char *version)
+{
+  return cmSystemTools::VersionCompare(cmSystemTools::OP_LESS,
+    FrameworkVersion.data(), version);
+}
+
+//----------------------------------------------------------------------------
+bool cmCPackIFWGenerator::IsVersionGreater(const char *version)
+{
+  return cmSystemTools::VersionCompare(cmSystemTools::OP_GREATER,
+    FrameworkVersion.data(), version);
+}
+
+//----------------------------------------------------------------------------
+bool cmCPackIFWGenerator::IsVersionEqual(const char *version)
+{
+  return cmSystemTools::VersionCompare(cmSystemTools::OP_EQUAL,
+    FrameworkVersion.data(), version);
+}
+
+//----------------------------------------------------------------------------
 int cmCPackIFWGenerator::PackageFiles()
 {
   cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Configuration" << std::endl);
@@ -59,7 +82,12 @@ int cmCPackIFWGenerator::PackageFiles()
   if (!Installer.Repositories.empty())
     {
     std::string ifwCmd = RepoGen;
-    ifwCmd += " -c " + this->toplevel + "/config/config.xml";
+
+    if(IsVersionLess("2.0.0"))
+      {
+      ifwCmd += " -c " + this->toplevel + "/config/config.xml";
+      }
+
     ifwCmd += " -p " + this->toplevel + "/packages";
 
     if(!PkgsDirsVector.empty())
@@ -216,8 +244,7 @@ const char *cmCPackIFWGenerator::GetPackagingInstallPrefix()
 //----------------------------------------------------------------------------
 const char *cmCPackIFWGenerator::GetOutputExtension()
 {
-  const char *suffix = this->GetOption("CMAKE_EXECUTABLE_SUFFIX");
-  return suffix ? suffix : cmCPackGenerator::GetOutputExtension();
+  return ExecutableSuffix.c_str();
 }
 
 //----------------------------------------------------------------------------
@@ -267,6 +294,17 @@ int cmCPackIFWGenerator::InitializeInternal()
     RepoGen = RepoGenStr;
     }
 
+  // Framework version
+  if(const char* FrameworkVersionSrt =
+      this->GetOption("CPACK_IFW_FRAMEWORK_VERSION"))
+    {
+    FrameworkVersion = FrameworkVersionSrt;
+    }
+  else
+    {
+    FrameworkVersion = "1.9.9";
+    }
+
   // Variables that Change Behavior
 
   // Resolve duplicate names
@@ -307,6 +345,24 @@ int cmCPackIFWGenerator::InitializeInternal()
   return 0;
   }
 
+  // Executable suffix
+  if(const char *optExeSuffix = this->GetOption("CMAKE_EXECUTABLE_SUFFIX"))
+    {
+    ExecutableSuffix = optExeSuffix;
+    if(ExecutableSuffix.empty())
+      {
+      std::string sysName(this->GetOption("CMAKE_SYSTEM_NAME"));
+      if(sysName == "Linux")
+        {
+        ExecutableSuffix = ".run";
+        }
+      }
+    }
+  else
+    {
+    ExecutableSuffix = cmCPackGenerator::GetOutputExtension();
+    }
+
   return this->Superclass::InitializeInternal();
 }
 
@@ -552,3 +608,20 @@ cmCPackIFWPackage* cmCPackIFWGenerator::GetComponentPackage(
     = ComponentPackages.find(component);
   return pit != ComponentPackages.end() ? pit->second : 0;
 }
+
+//----------------------------------------------------------------------------
+void cmCPackIFWGenerator::WriteGeneratedByToStrim(cmGeneratedFileStream &xout)
+{
+  xout << "<!-- Generated by CPack " << CMake_VERSION << " IFW generator "
+       << "for QtIFW ";
+  if(IsVersionLess("2.0"))
+    {
+    xout << "less 2.0";
+    }
+  else
+    {
+    xout << FrameworkVersion;
+    }
+  xout << " tools at " << cmTimestamp().CurrentTime("", true) << " -->"
+       << std::endl;
+}
diff --git a/Source/CPack/IFW/cmCPackIFWGenerator.h b/Source/CPack/IFW/cmCPackIFWGenerator.h
index 1d4d67b..3246861 100644
--- a/Source/CPack/IFW/cmCPackIFWGenerator.h
+++ b/Source/CPack/IFW/cmCPackIFWGenerator.h
@@ -13,6 +13,7 @@
 #ifndef cmCPackIFWGenerator_h
 #define cmCPackIFWGenerator_h
 
+#include <cmGeneratedFileStream.h>
 #include <CPack/cmCPackGenerator.h>
 
 #include "cmCPackIFWPackage.h"
@@ -44,6 +45,21 @@ public:
    */
   virtual ~cmCPackIFWGenerator();
 
+  /**
+   * Compare \a version with QtIFW framework version
+   */
+  bool IsVersionLess(const char *version);
+
+  /**
+   * Compare \a version with QtIFW framework version
+   */
+  bool IsVersionGreater(const char *version);
+
+  /**
+   * Compare \a version with QtIFW framework version
+   */
+  bool IsVersionEqual(const char *version);
+
 protected: // cmCPackGenerator reimplementation
 
   /**
@@ -105,6 +121,8 @@ protected: // Methods
   cmCPackIFWPackage* GetGroupPackage(cmCPackComponentGroup *group) const;
   cmCPackIFWPackage* GetComponentPackage(cmCPackComponent *component) const;
 
+  void WriteGeneratedByToStrim(cmGeneratedFileStream& xout);
+
 protected: // Data
 
   friend class cmCPackIFWPackage;
@@ -126,6 +144,8 @@ protected: // Data
 private:
   std::string RepoGen;
   std::string BinCreator;
+  std::string FrameworkVersion;
+  std::string ExecutableSuffix;
 
   bool OnlineOnly;
   bool ResolveDuplicateNames;
diff --git a/Source/CPack/IFW/cmCPackIFWInstaller.cxx b/Source/CPack/IFW/cmCPackIFWInstaller.cxx
index 4a99e50..8c77a2c 100644
--- a/Source/CPack/IFW/cmCPackIFWInstaller.cxx
+++ b/Source/CPack/IFW/cmCPackIFWInstaller.cxx
@@ -51,6 +51,25 @@ bool cmCPackIFWInstaller::IsOn(const std::string &op) const
 }
 
 //----------------------------------------------------------------------------
+bool cmCPackIFWInstaller::IsVersionLess(const char *version)
+{
+  return Generator ? Generator->IsVersionLess(version) : false;
+}
+
+//----------------------------------------------------------------------------
+bool cmCPackIFWInstaller::IsVersionGreater(const char *version)
+{
+  return Generator ? Generator->IsVersionGreater(version) : false;
+}
+
+//----------------------------------------------------------------------------
+bool cmCPackIFWInstaller::IsVersionEqual(const char *version)
+{
+  return Generator ? Generator->IsVersionEqual(version) : false;
+}
+
+
+//----------------------------------------------------------------------------
 void cmCPackIFWInstaller::ConfigureFromOptions()
 {
   // Name;
@@ -151,6 +170,17 @@ void cmCPackIFWInstaller::ConfigureFromOptions()
       }
     }
 
+  // Start menu
+  if (const char* optIFW_START_MENU_DIR =
+      this->GetOption("CPACK_IFW_PACKAGE_START_MENU_DIRECTORY"))
+    {
+    StartMenuDir = optIFW_START_MENU_DIR;
+    }
+  else
+    {
+    StartMenuDir = Name;
+    }
+
   // Default target directory for installation
   if (const char* optIFW_TARGET_DIRECTORY =
       GetOption("CPACK_IFW_TARGET_DIRECTORY"))
@@ -177,7 +207,7 @@ void cmCPackIFWInstaller::ConfigureFromOptions()
   // Repositories
   Repositories.clear();
   RepositoryStruct Repo;
-  if (const char *site = this->GetOption("CPACK_DOWNLOAD_SITE"))
+  if(const char *site = this->GetOption("CPACK_DOWNLOAD_SITE"))
     {
     Repo.Url = site;
     Repositories.push_back(Repo);
@@ -245,6 +275,53 @@ void cmCPackIFWInstaller::ConfigureFromOptions()
           }
       }
     }
+
+  // Maintenance tool
+  if(const char* optIFW_MAINTENANCE_TOOL =
+      this->GetOption("CPACK_IFW_PACKAGE_MAINTENANCE_TOOL_NAME"))
+    {
+    MaintenanceToolName = optIFW_MAINTENANCE_TOOL;
+    }
+
+  // Maintenance tool ini file
+  if(const char* optIFW_MAINTENANCE_TOOL_INI =
+      this->GetOption("CPACK_IFW_PACKAGE_MAINTENANCE_TOOL_INI_FILE"))
+    {
+    MaintenanceToolIniFile = optIFW_MAINTENANCE_TOOL_INI;
+    }
+
+  // Allow non-ASCII characters
+  if(this->GetOption("CPACK_IFW_PACKAGE_ALLOW_NON_ASCII_CHARACTERS"))
+    {
+    if(IsOn("CPACK_IFW_PACKAGE_ALLOW_NON_ASCII_CHARACTERS"))
+      {
+      AllowNonAsciiCharacters = "true";
+      }
+    else
+      {
+      AllowNonAsciiCharacters = "false";
+      }
+    }
+
+  // Space in path
+  if(this->GetOption("CPACK_IFW_PACKAGE_ALLOW_SPACE_IN_PATH"))
+    {
+    if(IsOn("CPACK_IFW_PACKAGE_ALLOW_SPACE_IN_PATH"))
+      {
+      AllowSpaceInPath = "true";
+      }
+    else
+      {
+      AllowSpaceInPath = "false";
+      }
+    }
+
+  // Control script
+  if(const char* optIFW_CONTROL_SCRIPT =
+      this->GetOption("CPACK_IFW_PACKAGE_CONTROL_SCRIPT"))
+    {
+    ControlScript = optIFW_CONTROL_SCRIPT;
+    }
 }
 
 //----------------------------------------------------------------------------
@@ -259,7 +336,10 @@ void cmCPackIFWInstaller::GenerateInstallerFile()
   // Output stream
   cmGeneratedFileStream xout((Directory + "/config/config.xml").data());
 
-  xout << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
+  xout << "<?xml version=\"1.0\"?>" << std::endl;
+
+  WriteGeneratedByToStrim(xout);
+
   xout << "<Installer>" << std::endl;
 
   xout << "    <Name>" << cmXMLSafe(Name).str() << "</Name>" << std::endl;
@@ -313,11 +393,20 @@ void cmCPackIFWInstaller::GenerateInstallerFile()
     xout << "    <Logo>" << name << "</Logo>" << std::endl;
     }
 
+  // Start menu
+  if(!IsVersionLess("2.0"))
+    {
+    xout << "    <StartMenuDir>" << StartMenuDir
+         << "</StartMenuDir>" << std::endl;
+    }
+
+  // Target dir
   if(!TargetDir.empty())
     {
     xout << "    <TargetDir>" << TargetDir << "</TargetDir>" << std::endl;
     }
 
+  // Admin target dir
   if(!AdminTargetDir.empty())
     {
     xout << "    <AdminTargetDir>" << AdminTargetDir
@@ -364,11 +453,52 @@ void cmCPackIFWInstaller::GenerateInstallerFile()
     xout << "    </RemoteRepositories>" << std::endl;
     }
 
-  // CPack IFW default policy
-  xout << "    <!-- CPack IFW default policy -->" << std::endl;
-  xout << "    <AllowNonAsciiCharacters>true</AllowNonAsciiCharacters>"
-       << std::endl;
-  xout << "    <AllowSpaceInPath>true</AllowSpaceInPath>" << std::endl;
+  // Maintenance tool
+  if(!IsVersionLess("2.0") && !MaintenanceToolName.empty())
+    {
+    xout << "    <MaintenanceToolName>" << MaintenanceToolName
+         << "</MaintenanceToolName>" << std::endl;
+    }
+
+  // Maintenance tool ini file
+  if(!IsVersionLess("2.0") && !MaintenanceToolIniFile.empty())
+    {
+    xout << "    <MaintenanceToolIniFile>" << MaintenanceToolIniFile
+         << "</MaintenanceToolIniFile>" << std::endl;
+    }
+
+  // Different allows
+  if(IsVersionLess("2.0"))
+    {
+    // CPack IFW default policy
+    xout << "    <!-- CPack IFW default policy for QtIFW less 2.0 -->"
+         << std::endl;
+    xout << "    <AllowNonAsciiCharacters>true</AllowNonAsciiCharacters>"
+         << std::endl;
+    xout << "    <AllowSpaceInPath>true</AllowSpaceInPath>" << std::endl;
+    }
+  else
+    {
+      if(!AllowNonAsciiCharacters.empty())
+        {
+        xout << "    <AllowNonAsciiCharacters>" << AllowNonAsciiCharacters
+             << "</AllowNonAsciiCharacters>" << std::endl;
+        }
+      if(!AllowSpaceInPath.empty())
+        {
+        xout << "    <AllowAllowSpaceInPath>" << AllowSpaceInPath
+             << "</AllowSpaceInPath>" << std::endl;
+        }
+    }
+
+  // Control script (copy to config dir)
+  if(!IsVersionLess("2.0") && !ControlScript.empty())
+    {
+    std::string name = cmSystemTools::GetFilenameName(ControlScript);
+    std::string path = Directory + "/config/" + name;
+    cmsys::SystemTools::CopyFileIfDifferent(ControlScript.data(), path.data());
+    xout << "    <ControlScript>" << name << "</ControlScript>" << std::endl;
+    }
 
   xout << "</Installer>" << std::endl;
 }
@@ -402,5 +532,10 @@ void cmCPackIFWInstaller::GeneratePackageFiles()
     {
     cmCPackIFWPackage* package = pit->second;
     package->GeneratePackageFile();
-    }
+  }
+}
+
+void cmCPackIFWInstaller::WriteGeneratedByToStrim(cmGeneratedFileStream &xout)
+{
+  if(Generator) Generator->WriteGeneratedByToStrim(xout);
 }
diff --git a/Source/CPack/IFW/cmCPackIFWInstaller.h b/Source/CPack/IFW/cmCPackIFWInstaller.h
index 5824d33..4cba5b2 100644
--- a/Source/CPack/IFW/cmCPackIFWInstaller.h
+++ b/Source/CPack/IFW/cmCPackIFWInstaller.h
@@ -13,6 +13,7 @@
 #ifndef cmCPackIFWInstaller_h
 #define cmCPackIFWInstaller_h
 
+#include <cmGeneratedFileStream.h>
 #include <cmStandardIncludes.h>
 
 class cmCPackIFWPackage;
@@ -69,17 +70,39 @@ public: // Configuration
   /// Filename for a logo
   std::string Logo;
 
+  /// Name of the default program group in the Windows Start menu
+  std::string StartMenuDir;
+
   /// Default target directory for installation
   std::string TargetDir;
 
   /// Default target directory for installation with administrator rights
   std::string AdminTargetDir;
 
+  /// Filename of the generated maintenance tool
+  std::string MaintenanceToolName;
+
+  /// Filename for the configuration of the generated maintenance tool
+  std::string MaintenanceToolIniFile;
+
+  /// Set to true if the installation path can contain non-ASCII characters
+  std::string AllowNonAsciiCharacters;
+
+  /// Set to false if the installation path cannot contain space characters
+  std::string AllowSpaceInPath;
+
+  /// Filename for a custom installer control script
+  std::string ControlScript;
+
 public: // Internal implementation
 
   const char* GetOption(const std::string& op) const;
   bool IsOn(const std::string& op) const;
 
+  bool IsVersionLess(const char *version);
+  bool IsVersionGreater(const char *version);
+  bool IsVersionEqual(const char *version);
+
   void ConfigureFromOptions();
 
   void GenerateInstallerFile();
@@ -90,6 +113,9 @@ public: // Internal implementation
   PackagesMap Packages;
   std::vector<RepositoryStruct> Repositories;
   std::string Directory;
+
+protected:
+  void WriteGeneratedByToStrim(cmGeneratedFileStream& xout);
 };
 
 #endif // cmCPackIFWInstaller_h
diff --git a/Source/CPack/IFW/cmCPackIFWPackage.cxx b/Source/CPack/IFW/cmCPackIFWPackage.cxx
index 38cef87..5474ad1b 100644
--- a/Source/CPack/IFW/cmCPackIFWPackage.cxx
+++ b/Source/CPack/IFW/cmCPackIFWPackage.cxx
@@ -132,6 +132,24 @@ bool cmCPackIFWPackage::IsOn(const std::string &op) const
 }
 
 //----------------------------------------------------------------------------
+bool cmCPackIFWPackage::IsVersionLess(const char *version)
+{
+  return Generator ? Generator->IsVersionLess(version) : false;
+}
+
+//----------------------------------------------------------------------------
+bool cmCPackIFWPackage::IsVersionGreater(const char *version)
+{
+  return Generator ? Generator->IsVersionGreater(version) : false;
+}
+
+//----------------------------------------------------------------------------
+bool cmCPackIFWPackage::IsVersionEqual(const char *version)
+{
+  return Generator ? Generator->IsVersionEqual(version) : false;
+}
+
+//----------------------------------------------------------------------------
 std::string cmCPackIFWPackage::GetComponentName(cmCPackComponent *component)
 {
   if (!component) return "";
@@ -432,6 +450,9 @@ void cmCPackIFWPackage::GeneratePackageFile()
   cmGeneratedFileStream xout((Directory + "/meta/package.xml").data());
 
   xout << "<?xml version=\"1.0\"?>" << std::endl;
+
+  WriteGeneratedByToStrim(xout);
+
   xout << "<Package>" << std::endl;
 
   xout << "    <DisplayName>" << DisplayName
@@ -538,3 +559,8 @@ void cmCPackIFWPackage::GeneratePackageFile()
 
   xout << "</Package>" << std::endl;
 }
+
+void cmCPackIFWPackage::WriteGeneratedByToStrim(cmGeneratedFileStream &xout)
+{
+  if(Generator) Generator->WriteGeneratedByToStrim(xout);
+}
diff --git a/Source/CPack/IFW/cmCPackIFWPackage.h b/Source/CPack/IFW/cmCPackIFWPackage.h
index 9fc9bd0..d2f7927 100644
--- a/Source/CPack/IFW/cmCPackIFWPackage.h
+++ b/Source/CPack/IFW/cmCPackIFWPackage.h
@@ -14,6 +14,7 @@
 #define cmCPackIFWPackage_h
 
 #include <cmStandardIncludes.h>
+#include <cmGeneratedFileStream.h>
 
 class cmCPackComponent;
 class cmCPackComponentGroup;
@@ -107,6 +108,10 @@ public: // Internal implementation
   const char* GetOption(const std::string& op) const;
   bool IsOn(const std::string& op) const;
 
+  bool IsVersionLess(const char *version);
+  bool IsVersionGreater(const char *version);
+  bool IsVersionEqual(const char *version);
+
   std::string GetComponentName(cmCPackComponent *component);
 
   void DefaultConfiguration();
@@ -128,6 +133,9 @@ public: // Internal implementation
   std::set<DependenceStruct*> AlienDependencies;
   // Patch to package directory
   std::string Directory;
+
+protected:
+  void WriteGeneratedByToStrim(cmGeneratedFileStream& xout);
 };
 
 #endif // cmCPackIFWPackage_h
-- 
cgit v0.12