Browse Source

CPack: Add an "IFW" generator for Qt Framework Installer

Add support for packaging with the Qt Framework Installer tools:

 http://qt-project.org/doc/qtinstallerframework/index.html

Reviewed-by: Nils Gladitz <[email protected]>
Konstantin Podsvirov 11 years ago
parent
commit
44850a267d

+ 32 - 0
CMakeCPack.cmake

@@ -59,11 +59,43 @@ if(EXISTS "${CMAKE_ROOT}/Modules/CPack.cmake")
   if(${CPACK_SYSTEM_NAME} MATCHES Windows)
     if(CMAKE_CL_64)
       set(CPACK_SYSTEM_NAME win64-x64)
+      set(CPACK_IFW_TARGET_DIRECTORY "@RootDir@/Program Files/${CMAKE_PROJECT_NAME}")
     else()
       set(CPACK_SYSTEM_NAME win32-x86)
     endif()
   endif()
 
+  # default component for IFW
+  if(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME)
+    set(_CPACK_IFW_COMPONENT_NAME ${CMAKE_INSTALL_DEFAULT_COMPONENT_NAME})
+  else()
+    set(_CPACK_IFW_COMPONENT_NAME Unspecified)
+  endif()
+  string(TOUPPER ${_CPACK_IFW_COMPONENT_NAME} _CPACK_IFW_COMPONENT_UNAME)
+
+  if(${CMAKE_SYSTEM_NAME} MATCHES Windows)
+    if(BUILD_QtDialog)
+      set(_CPACK_IFW_SHORTCUT_OPTIONAL "${_CPACK_IFW_SHORTCUT_OPTIONAL}component.addOperation(\"CreateShortcut\", \"@TargetDir@/bin/cmake-gui.exe\", \"@StartMenuDir@/CMake (cmake-gui).lnk\");\n")
+    endif()
+    if(SPHINX_HTML)
+      set(_CPACK_IFW_SHORTCUT_OPTIONAL "${_CPACK_IFW_SHORTCUT_OPTIONAL}component.addOperation(\"CreateShortcut\", \"@TargetDir@/doc/cmake-${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}/html/index.html\", \"@StartMenuDir@/CMake Documentation.lnk\");\n")
+    endif()
+    configure_file("${CMake_SOURCE_DIR}/Source/QtIFW/installscript.qs.in"
+      "${CMake_BINARY_DIR}/installscript.qs" @ONLY
+    )
+    install(FILES "${CMake_SOURCE_DIR}/Source/QtIFW/cmake.org.html"
+      DESTINATION "."
+    )
+    set(_CPACK_IFW_COMPONENT_SCRIPT "set(CPACK_IFW_COMPONENT_${_CPACK_IFW_COMPONENT_UNAME}_SCRIPT \"${CMake_BINARY_DIR}/installscript.qs\")")
+  endif()
+
+  if(${CMAKE_SYSTEM_NAME} MATCHES Linux)
+    set(CPACK_IFW_TARGET_DIRECTORY "@HomeDir@/${CMAKE_PROJECT_NAME}")
+    set(CPACK_IFW_ADMIN_TARGET_DIRECTORY "@ApplicationsDir@/${CMAKE_PROJECT_NAME}")
+  endif()
+
+  set(_CPACK_IFW_PACKAGE_VERSION ${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}.${CMake_VERSION_PATCH})
+
   if(NOT DEFINED CPACK_PACKAGE_FILE_NAME)
     # if the CPACK_PACKAGE_FILE_NAME is not defined by the cache
     # default to source package - system, on cygwin system is not

+ 14 - 0
CMakeCPackOptions.cmake.in

@@ -31,6 +31,20 @@ endif()
 # they might not if qt was not enabled for the build
 include("@QT_DIALOG_CPACK_OPTIONS_FILE@" OPTIONAL)
 
+if(CPACK_GENERATOR MATCHES "IFW")
+  # Version with QtIFW limitations
+  set(CPACK_PACKAGE_VERSION "@_CPACK_IFW_PACKAGE_VERSION@")
+  # Enable install default component
+  set(CPACK_COMPONENTS_ALL "@_CPACK_IFW_COMPONENT_NAME@")
+  # Configuration
+  set(CPACK_COMPONENT_@_CPACK_IFW_COMPONENT_UNAME@_DISPLAY_NAME "@CPACK_PACKAGE_NAME@")
+  set(CPACK_COMPONENT_@_CPACK_IFW_COMPONENT_UNAME@_DESCRIPTION "@CPACK_PACKAGE_DESCRIPTION_SUMMARY@")
+  # IFW Configuration
+  set(CPACK_IFW_COMPONENT_@_CPACK_IFW_COMPONENT_UNAME@_NAME "@CPACK_PACKAGE_NAME@")
+  set(CPACK_IFW_COMPONENT_@_CPACK_IFW_COMPONENT_UNAME@_LICENSES "@CPACK_PACKAGE_NAME@ Copyright" "@CPACK_RESOURCE_FILE_LICENSE@")
+  @_CPACK_IFW_COMPONENT_SCRIPT@
+endif()
+
 if(CPACK_GENERATOR MATCHES "CygwinSource")
   # when packaging source make sure the .build directory is not included
     set(CPACK_SOURCE_IGNORE_FILES

+ 1 - 0
Help/manual/cmake-modules.7.rst

@@ -55,6 +55,7 @@ All Modules
    /module/CPackCygwin
    /module/CPackDeb
    /module/CPackDMG
+   /module/CPackIFW
    /module/CPackNSIS
    /module/CPackPackageMaker
    /module/CPackRPM

+ 1 - 0
Help/module/CPackIFW.rst

@@ -0,0 +1 @@
+.. cmake-module:: ../../Modules/CPackIFW.cmake

+ 2 - 0
Modules/CPack.cmake

@@ -435,6 +435,7 @@ if(NOT CPACK_GENERATOR)
     option(CPACK_BINARY_WIX  "Enable to build WiX packages" OFF)
     option(CPACK_BINARY_ZIP  "Enable to build ZIP packages" OFF)
   endif()
+  option(CPACK_BINARY_IFW "Enable to build IFW packages" OFF)
 
   cpack_optional_append(CPACK_GENERATOR  CPACK_BINARY_BUNDLE       Bundle)
   cpack_optional_append(CPACK_GENERATOR  CPACK_BINARY_DRAGNDROP    DragNDrop)
@@ -450,6 +451,7 @@ if(NOT CPACK_GENERATOR)
   cpack_optional_append(CPACK_GENERATOR  CPACK_BINARY_TZ           TZ)
   cpack_optional_append(CPACK_GENERATOR  CPACK_BINARY_WIX          WIX)
   cpack_optional_append(CPACK_GENERATOR  CPACK_BINARY_ZIP          ZIP)
+  cpack_optional_append(CPACK_GENERATOR  CPACK_BINARY_IFW          IFW)
 
 endif()
 

+ 3 - 0
Modules/CPackComponent.cmake

@@ -458,6 +458,9 @@ macro(cpack_add_component_group grpname)
   cpack_append_string_variable_set_command(
     CPACK_COMPONENT_GROUP_${CPACK_ADDGRP_UNAME}_DESCRIPTION
     CPACK_ADDGRP_STR)
+  cpack_append_string_variable_set_command(
+    CPACK_COMPONENT_GROUP_${CPACK_ADDGRP_UNAME}_PARENT_GROUP
+    CPACK_ADDGRP_STR)
   cpack_append_option_set_command(
     CPACK_COMPONENT_GROUP_${CPACK_ADDGRP_UNAME}_EXPANDED
     CPACK_ADDGRP_STR)

+ 384 - 0
Modules/CPackIFW.cmake

@@ -0,0 +1,384 @@
+#.rst:
+# CPackIFW
+# --------
+#
+# .. _QtIFW: http://qt-project.org/doc/qtinstallerframework/index.html
+#
+# This module looks for the location of the command line utilities supplied with
+# the Qt Installer Framework (QtIFW_).
+#
+# The module also defines several commands to control the behavior of the
+# CPack ``IFW`` generator.
+#
+#
+# Overview
+# ^^^^^^^^
+#
+# CPack ``IFW`` generator helps you create online and offline
+# binary cross-platform installers with a graphical user interface.
+#
+# CPack IFW generator prepare project installation and generate configuration
+# and meta information for QtIFW_ tools.
+#
+# The QtIFW_ provides a set of tools and utilities to create
+# installers for the supported desktop Qt platforms: Linux, Microsoft Windows,
+# and Mac OS X.
+#
+# To use CPack ``IFW`` generator you must also install QtIFW_.
+#
+# Variables
+# ^^^^^^^^^
+#
+# Variables that Change Behavior
+# """"""""""""""""""""""""""""""
+#
+# .. variable:: CPACK_IFW_TARGET_DIRECTORY
+#
+#  Default target directory for installation.
+#  By default used "@ApplicationsDir@/:variable:`CPACK_PACKAGE_INSTALL_DIRECTORY`"
+#
+#  You can use predefined variables.
+#
+# .. variable:: CPACK_IFW_ADMIN_TARGET_DIRECTORY
+#
+#  Default target directory for installation with administrator rights.
+#
+#  You can use predefined variables.
+#
+# .. variable:: CPACK_IFW_RESOLVE_DUPLICATE_NAMES
+#
+#  Resolve duplicate names when installing components with groups.
+#
+# .. variable:: CPACK_IFW_PACKAGES_DIRECTORIES
+#
+#  Additional prepared packages dirs that will be used to resolve
+#  dependent components.
+#
+# Advanced Variables
+# """"""""""""""""""
+#
+# .. variable:: CPACK_IFW_BINARYCREATOR_EXECUTABLE
+#
+#  The path to "binarycreator" command line client.
+#
+#  This variable is cached and can be configured user if need.
+#
+# .. variable:: CPACK_IFW_BINARYCREATOR_EXECUTABLE_FOUND
+#
+#  True if the "binarycreator" command line client was found.
+#
+# .. variable:: CPACK_IFW_REPOGEN_EXECUTABLE
+#
+#  The path to "repogen" command line client.
+#
+#  This variable is cached and can be configured user if need.
+#
+# .. variable:: CPACK_IFW_REPOGEN_EXECUTABLE_FOUND
+#
+#  True if the "repogen" command line client was found.
+#
+# Commands
+# ^^^^^^^^^
+#
+# The module defines the following commands:
+#
+# --------------------------------------------------------------------------
+#
+# .. command:: cpack_ifw_configure_component
+#
+# Sets the arguments specific to the CPack IFW generator.
+#
+# ::
+#
+#   cpack_ifw_configure_component(<compname>
+#                       [VERSION <version>]
+#                       [SCRIPT <script>]
+#                       [NAME <name>]
+#                       [PRIORITY <priority>]
+#                       [LICENSES <display_name> <file_path> ...])
+#
+# This command should be called after cpack_add_component command.
+#
+# ``VERSION`` is version of component. By default used :variable:`CPACK_PACKAGE_VERSION`.
+#
+# ``SCRIPT`` is relative or absolute path to operations script
+# for this component.
+#
+# ``NAME`` is used to create domain-like identification for this component.
+# By default used origin component name.
+#
+# ``PRIORITY`` is priority of the component in the tree.
+#
+# ``LICENSES`` pair of <display_name> and <file_path> of license text for this
+# component. You can specify more then one license.
+#
+# --------------------------------------------------------------------------
+#
+# .. command:: cpack_ifw_configure_component_group
+#
+# Sets the arguments specific to the CPack IFW generator.
+#
+# ::
+#
+#   cpack_ifw_configure_component_group(<grpname>
+#                       [VERSION <version>]
+#                       [NAME <name>]
+#                       [PRIORITY <priority>]
+#                       [LICENSES <display_name> <file_path> ...])
+#
+# This command should be called after cpack_add_component_group command.
+#
+# ``VERSION`` is version of component group. By default used :variable:`CPACK_PACKAGE_VERSION`.
+#
+# ``NAME`` is used to create domain-like identification for this component group.
+# By default used origin component group name.
+#
+# ``PRIORITY`` is priority of the component group in the tree.
+#
+# ``LICENSES`` pair of <display_name> and <file_path> of license text for this
+# component group. You can specify more then one license.
+#
+# Example usage
+# ^^^^^^^^^^^^^
+#
+# .. code-block:: cmake
+#
+#    set(CPACK_PACKAGE_NAME "MyPackage")
+#    set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "MyPackage Installation Example")
+#    set(CPACK_PACKAGE_VERSION "1.0.0")
+#
+#    include(CPack)
+#    include(CPackIFW)
+#
+#    cpack_add_component(myapp
+#        DISPLAY_NAME "MyApp"
+#        DESCRIPTION "My Application")
+#    cpack_ifw_configure_component(myapp
+#        VERSION "1.2.3"
+#        SCRIPT "operations.qs")
+#
+#
+# Online installer
+# ^^^^^^^^^^^^^^^^
+#
+# By defaul CPack IFW generator make offline installer. This means that all
+# components will be packaged into a binary file.
+#
+# To make a component downloaded, you must set the ``DOWNLOADED`` option in
+# :command:`cpack_add_component`.
+#
+# Then you would use the command :command:`cpack_configure_downloads`.
+# If you set ``ALL`` option all components will be downloaded.
+#
+# CPack IFW generator create "repository" dir in current binary dir. You
+# would copy content of this dir to specified ``site``.
+#
+# See Also
+# ^^^^^^^^
+#
+# Qt Installer Framework Manual:
+#
+#  Index page
+#   http://qt-project.org/doc/qtinstallerframework/index.html
+#
+#  Component Scripting
+#   http://qt-project.org/doc/qtinstallerframework/scripting.html
+#
+#  Predefined Variables
+#   http://qt-project.org/doc/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/
+#
+
+#=============================================================================
+# Copyright 2014 Kitware, Inc.
+# Copyright 2014 Konstantin Podsvirov <[email protected]>
+#
+# 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.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+#  License text for the above reference.)
+
+#=============================================================================
+# Search Qt Installer Framework tools
+#=============================================================================
+
+# Default path
+
+if(WIN32)
+        set(_CPACK_IFW_PATHS
+            "$ENV{HOMEDRIVE}/Qt"
+            "C:/Qt"
+        )
+else()
+        set(_CPACK_IFW_PATHS
+            "$ENV{HOME}/Qt"
+            "/opt/Qt"
+        )
+endif()
+
+set(_CPACK_IFW_SUFFIXES
+        "QtIFW-1.7.0/bin"
+        "QtIFW-1.6.0/bin"
+        "QtIFW-1.5.0/bin"
+        "QtIFW-1.4.0/bin"
+        "QtIFW-1.3.0/bin"
+)
+
+# Look for 'binarycreator'
+
+if(NOT CPACK_IFW_BINARYCREATOR_EXECUTABLE_FOUND)
+
+find_program(CPACK_IFW_BINARYCREATOR_EXECUTABLE
+  NAMES binarycreator
+  PATHS ${_CPACK_IFW_PATHS}
+  PATH_SUFFIXES ${_CPACK_IFW_SUFFIXES}
+  DOC "QtIFW binarycreator command line client"
+  )
+mark_as_advanced(CPACK_IFW_BINARYCREATOR_EXECUTABLE)
+
+if(EXISTS ${CPACK_IFW_BINARYCREATOR_EXECUTABLE})
+  set(CPACK_IFW_BINARYCREATOR_EXECUTABLE_FOUND 1)
+endif()
+
+endif() # NOT CPACK_IFW_BINARYCREATOR_EXECUTABLE_FOUND
+
+# Look for 'repogen'
+
+if(NOT CPACK_IFW_REPOGEN_EXECUTABLE_FOUND)
+
+find_program(CPACK_IFW_REPOGEN_EXECUTABLE
+  NAMES repogen
+  PATHS ${_CPACK_IFW_PATHS}
+  PATH_SUFFIXES ${_CPACK_IFW_SUFFIXES}
+  DOC "QtIFW repogen command line client"
+  )
+mark_as_advanced(CPACK_IFW_REPOGEN_EXECUTABLE)
+
+if(EXISTS ${CPACK_IFW_REPOGEN_EXECUTABLE})
+  set(CPACK_IFW_REPOGEN_EXECUTABLE_FOUND 1)
+endif()
+
+endif() # NOT CPACK_IFW_REPOGEN_EXECUTABLE_FOUND
+
+#
+## Next code is included only once
+#
+
+if(NOT CPackIFW_CMake_INCLUDED)
+set(CPackIFW_CMake_INCLUDED 1)
+
+#=============================================================================
+# Macro definition
+#=============================================================================
+
+# Macro definition based on CPackComponent
+
+if(NOT CPackComponent_CMake_INCLUDED)
+    include(CPackComponent)
+endif()
+
+if(NOT __CMAKE_PARSE_ARGUMENTS_INCLUDED)
+    include(CMakeParseArguments)
+endif()
+
+# Resolve full path to lisense file
+macro(_cpack_ifw_resolve_lisenses _variable)
+  if(${_variable})
+    set(_ifw_license_file FALSE)
+    set(_ifw_licenses_fix)
+    foreach(_ifw_licenses_arg ${${_variable}})
+      if(_ifw_license_file)
+        get_filename_component(_ifw_licenses_arg "${_ifw_licenses_arg}" ABSOLUTE)
+        set(_ifw_license_file FALSE)
+      else()
+        set(_ifw_license_file TRUE)
+      endif()
+      list(APPEND _ifw_licenses_fix "${_ifw_licenses_arg}")
+    endforeach(_ifw_licenses_arg)
+    set(${_variable} "${_ifw_licenses_fix}")
+  endif()
+endmacro()
+
+# Macro for configure component
+macro(cpack_ifw_configure_component compname)
+
+  string(TOUPPER ${compname} _CPACK_IFWCOMP_UNAME)
+
+  set(_IFW_OPT)
+  set(_IFW_ARGS VERSION SCRIPT NAME PRIORITY)
+  set(_IFW_MULTI_ARGS DEPENDS LICENSES)
+  cmake_parse_arguments(CPACK_IFW_COMPONENT_${_CPACK_IFWCOMP_UNAME} "${_IFW_OPT}" "${_IFW_ARGS}" "${_IFW_MULTI_ARGS}" ${ARGN})
+
+  # Resolve full filename for script file
+  set(_IFW_SCRIPT_MACRO CPACK_IFW_COMPONENT_${_CPACK_IFWCOMP_UNAME}_SCRIPT)
+  set(_IFW_SCRIPT_FILE ${${_IFW_SCRIPT_MACRO}})
+  if(DEFINED ${_IFW_SCRIPT_MACRO})
+    get_filename_component(${_IFW_SCRIPT_MACRO} ${_IFW_SCRIPT_FILE} ABSOLUTE)
+    set(_IFW_SCRIPT_FILE ${${_IFW_SCRIPT_MACRO}})
+    if(NOT EXISTS ${_IFW_SCRIPT_FILE})
+        message(WARNING "CPack IFW: script file \"${_IFW_SCRIPT_FILE}\" for component \"${compname}\" is not exists" )
+        set(${_IFW_SCRIPT_MACRO})
+    endif()
+  endif()
+
+  _cpack_ifw_resolve_lisenses(CPACK_IFW_COMPONENT_${_CPACK_IFWCOMP_UNAME}_LICENSES)
+
+  set(_CPACK_IFWCOMP_STR "\n# Configuration for IFW component \"${compname}\"\n")
+
+  foreach(_IFW_ARG_NAME ${_IFW_ARGS})
+  cpack_append_string_variable_set_command(
+    CPACK_IFW_COMPONENT_${_CPACK_IFWCOMP_UNAME}_${_IFW_ARG_NAME}
+    _CPACK_IFWCOMP_STR)
+  endforeach()
+
+  foreach(_IFW_ARG_NAME ${_IFW_MULTI_ARGS})
+  cpack_append_variable_set_command(
+    CPACK_IFW_COMPONENT_${_CPACK_IFWCOMP_UNAME}_${_IFW_ARG_NAME}
+    _CPACK_IFWCOMP_STR)
+  endforeach()
+
+  if(CPack_CMake_INCLUDED)
+    file(APPEND "${CPACK_OUTPUT_CONFIG_FILE}" "${_CPACK_IFWCOMP_STR}")
+  endif()
+
+endmacro()
+
+# Macro for configure group
+macro(cpack_ifw_configure_component_group grpname)
+
+  string(TOUPPER ${grpname} _CPACK_IFWGRP_UNAME)
+
+  set(_IFW_OPT)
+  set(_IFW_ARGS VERSION NAME PRIORITY)
+  set(_IFW_MULTI_ARGS LICENSES)
+  cmake_parse_arguments(CPACK_IFW_COMPONENT_GROUP_${_CPACK_IFWGRP_UNAME} "${_IFW_OPT}" "${_IFW_ARGS}" "${_IFW_MULTI_ARGS}" ${ARGN})
+
+  _cpack_ifw_resolve_lisenses(CPACK_IFW_COMPONENT_GROUP_${_CPACK_IFWGRP_UNAME}_LICENSES)
+
+  set(_CPACK_IFWGRP_STR "\n# Configuration for IFW component group \"${grpname}\"\n")
+
+  foreach(_IFW_ARG_NAME ${_IFW_ARGS})
+  cpack_append_string_variable_set_command(
+    CPACK_IFW_COMPONENT_GROUP_${_CPACK_IFWGRP_UNAME}_${_IFW_ARG_NAME}
+    _CPACK_IFWGRP_STR)
+  endforeach()
+
+  foreach(_IFW_ARG_NAME ${_IFW_MULTI_ARGS})
+  cpack_append_variable_set_command(
+    CPACK_IFW_COMPONENT_GROUP_${_CPACK_IFWGRP_UNAME}_${_IFW_ARG_NAME}
+    _CPACK_IFWGRP_STR)
+  endforeach()
+
+  if(CPack_CMake_INCLUDED)
+    file(APPEND "${CPACK_OUTPUT_CONFIG_FILE}" "${_CPACK_IFWGRP_STR}")
+  endif()
+endmacro()
+
+endif() # NOT CPackIFW_CMake_INCLUDED

+ 1 - 0
Source/CMakeLists.txt

@@ -577,6 +577,7 @@ set(CPACK_SRCS
   CPack/cmCPackGenerator.cxx
   CPack/cmCPackLog.cxx
   CPack/cmCPackNSISGenerator.cxx
+  CPack/cmCPackIFWGenerator.cxx
   CPack/cmCPackSTGZGenerator.cxx
   CPack/cmCPackTGZGenerator.cxx
   CPack/cmCPackTarBZip2Generator.cxx

+ 6 - 0
Source/CPack/cmCPackGeneratorFactory.cxx

@@ -19,6 +19,7 @@
 #include "cmCPackZIPGenerator.h"
 #include "cmCPackSTGZGenerator.h"
 #include "cmCPackNSISGenerator.h"
+#include "cmCPackIFWGenerator.h"
 
 #ifdef __APPLE__
 #  include "cmCPackDragNDropGenerator.h"
@@ -68,6 +69,11 @@ cmCPackGeneratorFactory::cmCPackGeneratorFactory()
     this->RegisterGenerator("NSIS64", "Null Soft Installer (64-bit)",
       cmCPackNSISGenerator::CreateGenerator64);
     }
+  if (cmCPackIFWGenerator::CanGenerate())
+    {
+    this->RegisterGenerator("IFW", "Qt Installer Framework",
+      cmCPackIFWGenerator::CreateGenerator);
+    }
 #ifdef __CYGWIN__
   if (cmCPackCygwinBinaryGenerator::CanGenerate())
     {

+ 856 - 0
Source/CPack/cmCPackIFWGenerator.cxx

@@ -0,0 +1,856 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2000-2009 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 "cmCPackIFWGenerator.h"
+
+#include "cmGlobalGenerator.h"
+#include "cmLocalGenerator.h"
+#include "cmSystemTools.h"
+#include "cmMakefile.h"
+#include "cmGeneratedFileStream.h"
+#include "cmCPackLog.h"
+#include "cmCPackComponentGroup.h"
+
+#include <cmsys/SystemTools.hxx>
+#include <cmsys/Glob.hxx>
+#include <cmsys/Directory.hxx>
+#include <cmsys/RegularExpression.hxx>
+#include <cmXMLSafe.h>
+
+//----------------------------------------------------------------------
+cmCPackIFWGenerator::cmCPackIFWGenerator()
+{
+}
+
+//----------------------------------------------------------------------
+cmCPackIFWGenerator::~cmCPackIFWGenerator()
+{
+}
+
+//----------------------------------------------------------------------
+int cmCPackIFWGenerator::PackageFiles()
+{
+  cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Configuration" << std::endl);
+
+  if (!IfwCreateConfigFile())
+    {
+    cmCPackLogger(cmCPackLog::LOG_ERROR,
+                  "CPack error: Could not create IFW \"config.xml\" file."
+                  << std::endl);
+    return false;
+    }
+
+  if (Components.empty() && !IfwCreatePackageFile())
+    {
+    cmCPackLogger(cmCPackLog::LOG_ERROR,
+                  "CPack error: Could not create IFW "
+                  "\"root/meta/package.xml\" file."
+                  << std::endl);
+    return false;
+    }
+
+  std::string ifwTLD = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
+  std::string ifwTmpFile = ifwTLD;
+  ifwTmpFile += "/IFWOutput.log";
+
+  std::set<std::string> ifwDependsComponents;
+  std::string ifwBinaryComponents;
+  std::string ifwDownloadedComponents;
+
+  // Create groups meta information
+  std::map<std::string, cmCPackComponentGroup>::iterator groupIt;
+  for(groupIt = this->ComponentGroups.begin();
+      groupIt != this->ComponentGroups.end();
+      ++groupIt
+    )
+    {
+    std::string macroPrefix = "CPACK_IFW_COMPONENT_GROUP_"
+      + cmsys::SystemTools::UpperCase(groupIt->second.Name);
+
+    std::string groupId = IfwGetGroupId(&groupIt->second);
+
+    if(!ifwBinaryComponents.empty()) ifwBinaryComponents += ",";
+    ifwBinaryComponents += groupId;
+
+    std::string pkgMetaDir = this->toplevel + "/packages/"
+      + groupId
+      + "/meta";
+
+    std::string pkgXmlFileName = pkgMetaDir
+      + "/package.xml";
+
+    cmGeneratedFileStream pkgXml(pkgXmlFileName.data());
+    pkgXml << "<?xml version=\"1.0\"?>" << std::endl;
+    pkgXml << "<Package>" << std::endl;
+    pkgXml << "    <DisplayName>" << groupIt->second.DisplayName
+           << "</DisplayName>" << std::endl;
+    pkgXml << "    <Description>" << groupIt->second.Description
+           << "</Description>" << std::endl;
+    pkgXml << "    <Name>" << groupId << "</Name>" << std::endl;
+
+    // Version
+    const char* ifwPackageVersion = this->GetOption("CPACK_PACKAGE_VERSION");
+    const char* ifwGroupVersion = this->GetOption(macroPrefix + "_VERSION");
+    pkgXml << "    <Version>"
+           << (ifwGroupVersion ? ifwGroupVersion : ifwPackageVersion)
+           << "</Version>" << std::endl;
+    pkgXml << "    <ReleaseDate>" << IfwCreateCurrentDate()
+           << "</ReleaseDate>" << std::endl;
+
+    // Licenses
+    std::vector<std::string> licenses;
+    if(IfwParseLicenses(licenses, macroPrefix + "_LICENSES", pkgMetaDir))
+      {
+      pkgXml << "    <Licenses>" << std::endl;
+      for(size_t i = 0; i < licenses.size(); i += 2)
+        {
+        pkgXml << "        <License "
+               << "name=\"" << licenses[i] << "\" "
+               << "file=\"" << licenses[i + 1] << "\" "
+               << "/>" <<std::endl;
+        }
+      pkgXml << "    </Licenses>" << std::endl;
+      }
+
+    // Priority
+    if(const char* ifwGroupPriority =
+       this->GetOption(macroPrefix + "_PRIORITY"))
+      {
+      pkgXml << "    <SortingPriority>" << ifwGroupPriority
+             << "</SortingPriority>" << std::endl;
+      }
+    pkgXml << "</Package>" << std::endl;
+    }
+
+  // Create components meta information
+  std::map<std::string, cmCPackComponent>::iterator compIt;
+  for (compIt = this->Components.begin();
+       compIt != this->Components.end();
+       ++compIt)
+    {
+    // Component id
+    std::string ifwCompId = IfwGetComponentId(&compIt->second);
+
+    std::string pkgMetaDir = this->toplevel + "/"
+      + GetComponentInstallDirNamePrefix(compIt->second.Name)
+      + ifwCompId + "/meta";
+    std::string pkgXmlFileName = pkgMetaDir + "/package.xml";
+    cmGeneratedFileStream pkgXml(pkgXmlFileName.data());
+
+    // Check IFW version for component
+    std::string macroPrefix = "CPACK_IFW_COMPONENT_"
+      + cmsys::SystemTools::UpperCase(compIt->second.Name);
+
+    pkgXml << "<?xml version=\"1.0\"?>" << std::endl;
+    pkgXml << "<Package>" << std::endl;
+    pkgXml << "    <DisplayName>" << compIt->second.DisplayName
+           << "</DisplayName>" << std::endl;
+    pkgXml << "    <Description>" << compIt->second.Description
+           << "</Description>" << std::endl;
+    pkgXml << "    <Name>" << ifwCompId << "</Name>" << std::endl;
+
+    // Version
+    const char* ifwPackageVersion = this->GetOption("CPACK_PACKAGE_VERSION");
+    const char* ifwCompVersion =
+      this->GetOption(macroPrefix + "_VERSION");
+    pkgXml << "    <Version>"
+           <<  (ifwCompVersion ? ifwCompVersion : ifwPackageVersion)
+           << "</Version>" << std::endl;
+
+    pkgXml << "    <ReleaseDate>" << IfwCreateCurrentDate()
+           << "</ReleaseDate>" << std::endl;
+
+    // Script
+    const char* ifwCompScript =
+      this->GetOption(macroPrefix + "_SCRIPT");
+    if (ifwCompScript)
+      {
+      // Copy file
+      std::string ifwCompScriptFile = pkgMetaDir + "/operations.qs";
+      cmsys::SystemTools::CopyFileIfDifferent(ifwCompScript,
+                                              ifwCompScriptFile.data());
+      pkgXml << "    <Script>" << "operations.qs" << "</Script>" << std::endl;
+      }
+
+    // Check dependencies
+    std::set<std::string> compDepSet;
+    // CMake dependencies
+    if (!compIt->second.Dependencies.empty())
+      {
+      std::vector<cmCPackComponent *>::iterator depCompIt;
+      for(depCompIt = compIt->second.Dependencies.begin();
+          depCompIt != compIt->second.Dependencies.end();
+          ++depCompIt)
+        {
+        compDepSet.insert(IfwGetComponentId(*depCompIt));
+        }
+      }
+    // QtIFW dependencies
+    if(const char *ifwCompDepsStr = this->GetOption(macroPrefix + "_DEPENDS"))
+      {
+      std::vector<std::string> ifwCompDepsVector;
+      cmSystemTools::ExpandListArgument(ifwCompDepsStr,
+                                        ifwCompDepsVector);
+      for(std::vector<std::string>::iterator
+            depCompIt = ifwCompDepsVector.begin();
+          depCompIt != ifwCompDepsVector.end(); ++depCompIt)
+        {
+        compDepSet.insert(*depCompIt);
+        ifwDependsComponents.insert(*depCompIt);
+        }
+      }
+
+    // Write dependencies
+    if  (!compDepSet.empty())
+      {
+      pkgXml << "    <Dependencies>";
+      std::set<std::string>::iterator it = compDepSet.begin();
+      pkgXml << *it;
+      ++it;
+      while(it != compDepSet.end())
+        {
+        pkgXml << "," << *it;
+        ++it;
+        }
+      pkgXml << "</Dependencies>" << std::endl;
+      }
+
+    // Licenses
+    std::vector<std::string> licenses;
+    if(IfwParseLicenses(licenses, macroPrefix + "_LICENSES", pkgMetaDir))
+      {
+      pkgXml << "    <Licenses>" << std::endl;
+      for(size_t i = 0; i < licenses.size(); i += 2)
+        {
+        pkgXml << "        <License "
+               << "name=\"" << licenses[i] << "\" "
+               << "file=\"" << licenses[i + 1] << "\" "
+               << "/>" <<std::endl;
+        }
+      pkgXml << "    </Licenses>" << std::endl;
+      }
+
+    // TODO: Check how enable virtual component (now it's allways disabled)
+    if (compIt->second.IsRequired) {
+    pkgXml << "    <ForcedInstallation>true</ForcedInstallation>"
+           << std::endl;
+    } else if (compIt->second.IsDisabledByDefault) {
+    pkgXml << "    <Default>false</Default>" << std::endl;
+    } else if (compIt->second.IsHidden) {
+    pkgXml << "    <Virtual>true</Virtual>" << std::endl;
+    } else {
+    pkgXml << "    <Default>true</Default>" << std::endl;
+    }
+
+    // Priority
+    if(const char* ifwCompPriority =
+       this->GetOption(macroPrefix + "_PRIORITY"))
+      {
+      pkgXml << "    <SortingPriority>" << ifwCompPriority
+             << "</SortingPriority>" << std::endl;
+      }
+
+    pkgXml << "</Package>" << std::endl;
+
+    // Downloaded
+    if (compIt->second.IsDownloaded)
+      {
+      if (!ifwDownloadedComponents.empty()) ifwDownloadedComponents += ",";
+      ifwDownloadedComponents += ifwCompId;
+      }
+    else
+      {
+      if (!ifwBinaryComponents.empty()) ifwBinaryComponents += ",";
+      ifwBinaryComponents += ifwCompId;
+      }
+    }
+
+  // Run repogen
+  if (!ifwDownloadSite.empty())
+    {
+    std::string ifwCmd = ifwRepoGen;
+    ifwCmd += " -c " + this->toplevel + "/config/config.xml";
+    ifwCmd += " -p " + this->toplevel + "/packages";
+
+    if(!ifwPkgsDirsVector.empty())
+      {
+      for(std::vector<std::string>::iterator it = ifwPkgsDirsVector.begin();
+          it != ifwPkgsDirsVector.end(); ++it)
+        {
+        ifwCmd += " -p " + *it;
+        }
+      }
+
+    if (!ifwOnlineOnly && !ifwDownloadedComponents.empty()) {
+    ifwCmd += " -i " + ifwDownloadedComponents;
+    }
+    ifwCmd += " " + this->toplevel + "/repository";
+    cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << ifwCmd
+                  << std::endl);
+    std::string output;
+    int retVal = 1;
+    cmCPackLogger(cmCPackLog::LOG_OUTPUT,
+                  "- Generate repository" << std::endl);
+    bool res = cmSystemTools::RunSingleCommand(
+      ifwCmd.c_str(), &output, &retVal, 0, this->GeneratorVerbose, 0);
+    if ( !res || retVal )
+      {
+      cmGeneratedFileStream ofs(ifwTmpFile.c_str());
+      ofs << "# Run command: " << ifwCmd << std::endl
+          << "# Output:" << std::endl
+          << output << std::endl;
+      cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem running IFW command: "
+                    << ifwCmd << std::endl
+                    << "Please check " << ifwTmpFile << " for errors"
+                    << std::endl);
+      return 0;
+      }
+    }
+
+  // Run binary creator
+  {
+  std::string ifwCmd = ifwBinCreator;
+  ifwCmd += " -c " + this->toplevel + "/config/config.xml";
+  ifwCmd += " -p " + this->toplevel + "/packages";
+
+  if(!ifwPkgsDirsVector.empty())
+    {
+    for(std::vector<std::string>::iterator it = ifwPkgsDirsVector.begin();
+        it != ifwPkgsDirsVector.end(); ++it)
+      {
+      ifwCmd += " -p " + *it;
+      }
+    }
+
+  if (ifwOnlineOnly)
+    {
+    ifwCmd += " --online-only";
+    }
+  else if (!ifwDownloadedComponents.empty() && !ifwDownloadSite.empty())
+    {
+    ifwCmd += " -e " + ifwDownloadedComponents;
+    }
+  else if (!ifwDependsComponents.empty())
+    {
+    ifwCmd += " -i ";
+    std::set<std::string>::iterator it = ifwDependsComponents.begin();
+    ifwCmd += *it;
+    ++it;
+    while(it != ifwDependsComponents.end())
+      {
+      ifwCmd += "," + (*it);
+      ++it;
+      }
+
+    ifwCmd += "," + ifwBinaryComponents;
+    }
+  // TODO: set correct name for multipackages
+  if (this->packageFileNames.size() > 0)
+    {
+    ifwCmd += " " + packageFileNames[0];
+    }
+  else
+    {
+    ifwCmd += " installer";
+    }
+  cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << ifwCmd
+                << std::endl);
+  std::string output;
+  int retVal = 1;
+  cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Generate package" << std::endl);
+  bool res = cmSystemTools::RunSingleCommand(
+    ifwCmd.c_str(), &output, &retVal, 0, this->GeneratorVerbose, 0);
+  if ( !res || retVal )
+    {
+    cmGeneratedFileStream ofs(ifwTmpFile.c_str());
+    ofs << "# Run command: " << ifwCmd << std::endl
+        << "# Output:" << std::endl
+        << output << std::endl;
+    cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem running IFW command: "
+                  << ifwCmd << std::endl
+                  << "Please check " << ifwTmpFile << " for errors"
+                  << std::endl);
+    return 0;
+    }
+  }
+
+  return 1;
+}
+
+//----------------------------------------------------------------------
+const char *cmCPackIFWGenerator::GetPackagingInstallPrefix()
+{
+  const char *defPrefix = cmCPackGenerator::GetPackagingInstallPrefix();
+
+  std::string tmpPref = defPrefix ? defPrefix : "";
+
+  if(this->Components.empty())
+    {
+    tmpPref += "packages/root/data";
+    }
+
+  this->SetOption("CPACK_IFW_PACKAGING_INSTALL_PREFIX", tmpPref.c_str());
+
+  return this->GetOption("CPACK_IFW_PACKAGING_INSTALL_PREFIX");
+}
+
+//----------------------------------------------------------------------
+const char *cmCPackIFWGenerator::GetOutputExtension()
+{
+  const char *suffix = this->GetOption("CMAKE_EXECUTABLE_SUFFIX");
+  return suffix ? suffix : "";
+}
+
+//----------------------------------------------------------------------
+std::string cmCPackIFWGenerator::IfwGetGroupId(cmCPackComponentGroup *group)
+{
+  std::string ifwGroupId;
+  std::string ifwGroupName;
+  std::list<cmCPackComponentGroup*> groups;
+  while(group)
+    {
+    groups.push_front(group);
+    group = group->ParentGroup;
+    }
+  std::list<cmCPackComponentGroup*>::iterator it = groups.begin();
+  if(it != groups.end())
+    {
+    ifwGroupId = IfwGetGroupName(*it);
+    ++it;
+    }
+  while(it != groups.end())
+    {
+    ifwGroupName = IfwGetGroupName(*it);
+
+    if(ifwResolveDuplicateNames)
+      {
+      if(ifwGroupName.substr(0, ifwGroupId.size()) == ifwGroupId)
+        {
+        ifwGroupId = ifwGroupName;
+        ++it;
+        continue;
+        }
+      }
+
+    ifwGroupId += "." + ifwGroupName;
+
+    ++it;
+    }
+
+  return ifwGroupId;
+}
+
+//----------------------------------------------------------------------
+std::string cmCPackIFWGenerator::IfwGetComponentId(cmCPackComponent *component)
+{
+  std::string ifwCompId;
+  if(component) {
+  ifwCompId = IfwGetGroupId(component->Group);
+  if(!ifwCompId.empty()) ifwCompId += ".";
+  std::string ifwCompName = IfwGetComponentName(component);
+  if(ifwResolveDuplicateNames &&
+     (ifwCompName.substr(0, ifwCompId.size()) == ifwCompId))
+    {
+    ifwCompId = ifwCompName;
+    }
+  else
+    {
+    ifwCompId += ifwCompName;
+    }
+  }
+  return ifwCompId;
+}
+
+//----------------------------------------------------------------------
+std::string cmCPackIFWGenerator::IfwGetGroupName(cmCPackComponentGroup *group)
+{
+  std::string ifwGroupName = group->Name;
+  if(const char* name =
+     this->GetOption("CPACK_IFW_COMPONENT_GROUP_"
+                     + cmsys::SystemTools::UpperCase(group->Name) + "_NAME"))
+    {
+    ifwGroupName = name;
+    }
+  return ifwGroupName;
+}
+
+//----------------------------------------------------------------------
+std::string
+cmCPackIFWGenerator::IfwGetComponentName(cmCPackComponent *component)
+{
+  return IfwGetComponentName(component->Name);
+}
+
+//----------------------------------------------------------------------
+std::string
+cmCPackIFWGenerator::IfwGetComponentName(const std::string &componentName)
+{
+  std::string ifwCompName = componentName;
+  if(const char* name =
+     this->GetOption("CPACK_IFW_COMPONENT_"
+                     + cmsys::SystemTools::UpperCase(componentName) + "_NAME"))
+    {
+    ifwCompName = name;
+    }
+  return ifwCompName;
+}
+
+//----------------------------------------------------------------------
+int cmCPackIFWGenerator::InitializeInternal()
+{
+  // Search Qt Installer Framework tools
+
+  if(!this->IsOn("CPACK_IFW_BINARYCREATOR_EXECUTABLE_FOUND") ||
+     !this->IsOn("CPACK_IFW_REPOGEN_EXECUTABLE_FOUND"))
+    {
+    this->ReadListFile("CPackIFW.cmake");
+    }
+
+  // Look 'binarycreator' executable (needs)
+
+  if(this->IsOn("CPACK_IFW_BINARYCREATOR_EXECUTABLE_FOUND"))
+    {
+    const char *ifwBinCreatorStr =
+      this->GetOption("CPACK_IFW_BINARYCREATOR_EXECUTABLE");
+    ifwBinCreator = ifwBinCreatorStr ? ifwBinCreatorStr : "";
+    }
+  else
+    {
+    ifwBinCreator = "";
+    }
+
+  if (ifwBinCreator.empty())
+    {
+    cmCPackLogger(cmCPackLog::LOG_ERROR,
+                  "Cannot find QtIFW compiler \"binarycreator\": "
+                  "likely it is not installed, or not in your PATH"
+                  << std::endl);
+    return 0;
+    }
+
+  // Look 'repogen' executable (optional)
+
+  if(this->IsOn("CPACK_IFW_REPOGEN_EXECUTABLE_FOUND"))
+    {
+    const char *ifwRepoGenStr =
+      this->GetOption("CPACK_IFW_REPOGEN_EXECUTABLE");
+    ifwRepoGen = ifwRepoGenStr ? ifwRepoGenStr : "";
+    }
+  else
+    {
+    ifwRepoGen = "";
+    }
+
+  // // Variables that Change Behavior
+
+  // Resolve duplicate names
+  ifwResolveDuplicateNames = this->IsOn("CPACK_IFW_RESOLVE_DUPLICATE_NAMES");
+
+  // Additional packages dirs
+  ifwPkgsDirsVector.clear();
+  if(const char* dirs = this->GetOption("CPACK_IFW_PACKAGES_DIRECTORIES"))
+    {
+    cmSystemTools::ExpandListArgument(dirs,
+                                      ifwPkgsDirsVector);
+    }
+
+  // Remote repository
+
+  if (const char *site = this->GetOption("CPACK_DOWNLOAD_SITE"))
+    {
+    ifwDownloadSite = site;
+    }
+
+  ifwOnlineOnly = this->IsOn("CPACK_DOWNLOAD_ALL") ? true : false;
+
+  if (!ifwDownloadSite.empty() && ifwRepoGen.empty()) {
+  cmCPackLogger(cmCPackLog::LOG_ERROR,
+                "Cannot find QtIFW repository generator \"repogen\": "
+                "likely it is not installed, or not in your PATH"
+                << std::endl);
+  return 0;
+  }
+
+  return this->Superclass::InitializeInternal();
+}
+
+//----------------------------------------------------------------------
+std::string
+cmCPackIFWGenerator::GetComponentInstallDirNamePrefix(
+  const std::string& /*componentName*/)
+{
+  return "packages/";
+}
+
+//----------------------------------------------------------------------
+std::string
+cmCPackIFWGenerator::GetComponentInstallDirNameSuffix(
+  const std::string& componentName)
+{
+  std::map<std::string, cmCPackComponent>::iterator
+    compIt = this->Components.find(componentName);
+
+  cmCPackComponent *comp =
+    compIt != this->Components.end() ? &compIt->second : 0;
+
+  const std::string prefix = GetComponentInstallDirNamePrefix(componentName);
+  const std::string suffix = "/data";
+
+  if (componentPackageMethod == ONE_PACKAGE_PER_COMPONENT) {
+  return prefix + IfwGetComponentId(comp) + suffix;
+  }
+
+  if (componentPackageMethod == ONE_PACKAGE) {
+  return std::string(prefix + "ALL_COMPONENTS_IN_ONE" + suffix);
+  }
+
+  return prefix + IfwGetComponentId(comp) + suffix;
+}
+
+//----------------------------------------------------------------------
+bool cmCPackIFWGenerator::GetListOfSubdirectories(
+  const char* topdir, std::vector<std::string>& dirs)
+{
+  cmsys::Directory dir;
+  dir.Load(topdir);
+  size_t fileNum;
+  for (fileNum = 0; fileNum <  dir.GetNumberOfFiles(); ++fileNum)
+    {
+    if (strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)),".") &&
+        strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)),".."))
+      {
+      cmsys_stl::string fullPath = topdir;
+      fullPath += "/";
+      fullPath += dir.GetFile(static_cast<unsigned long>(fileNum));
+      if(cmsys::SystemTools::FileIsDirectory(fullPath.c_str()) &&
+         !cmsys::SystemTools::FileIsSymlink(fullPath.c_str()))
+        {
+        if (!this->GetListOfSubdirectories(fullPath.c_str(), dirs))
+          {
+          return false;
+          }
+        }
+      }
+    }
+  dirs.push_back(topdir);
+  return true;
+}
+
+//----------------------------------------------------------------------
+enum cmCPackGenerator::CPackSetDestdirSupport
+cmCPackIFWGenerator::SupportsSetDestdir() const
+{
+  return cmCPackGenerator::SETDESTDIR_SHOULD_NOT_BE_USED;
+}
+
+//----------------------------------------------------------------------
+bool cmCPackIFWGenerator::SupportsAbsoluteDestination() const
+{
+  return false;
+}
+
+//----------------------------------------------------------------------
+bool cmCPackIFWGenerator::SupportsComponentInstallation() const
+{
+  return true;
+}
+
+//----------------------------------------------------------------------
+int cmCPackIFWGenerator::IfwCreateConfigFile()
+{
+  cmGeneratedFileStream cfg((this->toplevel + "/config/config.xml").data());
+
+  std::string ifwPkgName;
+  if (const char *name = this->GetOption("CPACK_PACKAGE_NAME"))
+    {
+    ifwPkgName = name;
+    }
+  else
+    {
+    ifwPkgName = "Your package";
+    }
+
+  std::string ifwPkgDescription;
+  if (const char *name = this->GetOption("CPACK_PACKAGE_DESCRIPTION_SUMMARY"))
+    {
+    ifwPkgDescription = name;
+    }
+  else
+    {
+    ifwPkgDescription = "Your package description";
+    }
+
+  std::string ifwPkgVersion;
+  if (const char *version = this->GetOption("CPACK_PACKAGE_VERSION"))
+    {
+    ifwPkgVersion = version;
+    }
+  else
+    {
+    ifwPkgVersion = "1.0.0";
+    }
+
+  const char *ifwPkgInstDir =
+    this->GetOption("CPACK_PACKAGE_INSTALL_DIRECTORY");
+  const char *ifwTargetDir =
+    this->GetOption("CPACK_IFW_TARGET_DIRECTORY");
+  const char *ifwAdminTargetDir =
+    this->GetOption("CPACK_IFW_ADMIN_TARGET_DIRECTORY");
+
+  cfg << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
+  cfg << "<Installer>" << std::endl;
+  cfg << "    <Name>" << cmXMLSafe(ifwPkgName).str() << "</Name>" << std::endl;
+  cfg << "    <Version>" << ifwPkgVersion << "</Version>" << std::endl;
+  cfg << "    <Title>" << cmXMLSafe(ifwPkgDescription).str() << "</Title>"
+      << std::endl;
+
+  // Default target directory for installation
+  if (ifwTargetDir)
+    {
+    cfg << "    <TargetDir>" << ifwTargetDir << "</TargetDir>" << std::endl;
+    }
+  else if (ifwPkgInstDir)
+    {
+    cfg << "    <TargetDir>@ApplicationsDir@/" << ifwPkgInstDir
+        << "</TargetDir>" << std::endl;
+    }
+  else
+    {
+    cfg << "    <TargetDir>@RootDir@/usr/local</TargetDir>" << std::endl;
+    }
+
+  // Default target directory for installation with administrator rights
+  if (ifwAdminTargetDir)
+    {
+    cfg << "    <AdminTargetDir>" << ifwAdminTargetDir
+        << "</AdminTargetDir>" << std::endl;
+    }
+
+  if (!ifwDownloadSite.empty())
+    {
+    cfg << "    <RemoteRepositories>" << std::endl;
+    cfg << "        <Repository>" << std::endl;
+    cfg << "            <Url>" << ifwDownloadSite << "</Url>" << std::endl;
+    // These properties can now be set from "cpack_configure_downloads"
+    //                 <Enabled>1</Enabled>
+    //                 <Username>user</Username>
+    //                 <Password>password</Password>
+    //                 <DisplayName>Example repository</DisplayName>
+    cfg << "        </Repository>" << std::endl;
+    cfg << "    </RemoteRepositories>" << std::endl;
+    }
+
+  // CPack IFW default policy
+  cfg << "    <!-- CPack IFW default policy -->" << std::endl;
+  cfg << "    <AllowNonAsciiCharacters>true</AllowNonAsciiCharacters>"
+      << std::endl;
+  cfg << "    <AllowSpaceInPath>true</AllowSpaceInPath>" << std::endl;
+
+  cfg << "</Installer>" << std::endl;
+
+  return 1;
+}
+
+//----------------------------------------------------------------------
+// Create default package file
+int cmCPackIFWGenerator::IfwCreatePackageFile()
+{
+  std::string ifwPkgName;
+  if (const char *name = this->GetOption("CPACK_PACKAGE_NAME"))
+    {
+    ifwPkgName = name;
+    }
+  else
+    {
+    ifwPkgName = "Your package";
+    }
+
+  std::string ifwPkgDescription;
+  if (const char *name = this->GetOption("CPACK_PACKAGE_DESCRIPTION_SUMMARY"))
+    {
+    ifwPkgDescription = name;
+    }
+  else
+    {
+    ifwPkgDescription = "Your package description";
+    }
+
+  cmGeneratedFileStream
+    pkgXml((this->toplevel + "/packages/root/meta/package.xml").data());
+  pkgXml << "<?xml version=\"1.0\"?>" << std::endl;
+  pkgXml << "<Package>" << std::endl;
+
+  pkgXml << "    <DisplayName>" << ifwPkgName << "</DisplayName>" << std::endl;
+  pkgXml << "    <Description>" << ifwPkgDescription
+         << "</Description>" << std::endl;
+  pkgXml << "    <Name>" << "root" << "</Name>" << std::endl;
+  pkgXml << "    <Version>" << this->GetOption("CPACK_PACKAGE_VERSION")
+         << "</Version>" << std::endl;
+  pkgXml << "    <ReleaseDate>" << IfwCreateCurrentDate() << "</ReleaseDate>"
+         << std::endl;
+
+  pkgXml << "    <ForcedInstallation>true</ForcedInstallation>" << std::endl;
+  pkgXml << "    <Default>true</Default>" << std::endl;
+
+  pkgXml << "</Package>" << std::endl;
+
+  return 1;
+}
+
+//----------------------------------------------------------------------
+std::string cmCPackIFWGenerator::IfwCreateCurrentDate()
+{
+  time_t rawtime;
+  struct tm * timeinfo;
+  char buffer[80];
+
+  time (&rawtime);
+  timeinfo = localtime(&rawtime);
+
+  strftime(buffer, 80, "%Y-%m-%d", timeinfo);
+
+  return buffer;
+}
+
+//----------------------------------------------------------------------
+bool cmCPackIFWGenerator::IfwParseLicenses(std::vector<std::string> &licenses,
+                                           const std::string &variable,
+                                           const std::string &metaDir)
+{
+  if (const char *option = this->GetOption(variable))
+    {
+    if(!licenses.empty()) licenses.clear();
+    cmSystemTools::ExpandListArgument( option, licenses );
+    }
+  else
+    {
+    return false;
+    }
+
+  if ( licenses.size() % 2 != 0 )
+    {
+    cmCPackLogger(cmCPackLog::LOG_ERROR, variable
+                  << " should contain pairs of <display_name> and <file_path>."
+                  << std::endl);
+    return false;
+    }
+
+  for(size_t i = 1; i < licenses.size(); i += 2)
+    {
+    std::string name = cmSystemTools::GetFilenameName(licenses[i]);
+    std::string path = metaDir + "/" + name;
+    cmsys::SystemTools::CopyFileIfDifferent(licenses[i].data(), path.data());
+    licenses[i] = name;
+    }
+
+  return licenses.size() > 1;
+}

+ 82 - 0
Source/CPack/cmCPackIFWGenerator.h

@@ -0,0 +1,82 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2000-2009 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 cmCPackIFWGenerator_h
+#define cmCPackIFWGenerator_h
+
+
+#include "cmCPackGenerator.h"
+#include <set>
+
+/** \class cmCPackIFWGenerator
+ * \brief A generator for Qt Installer Framework tools
+ *
+ * http://qt-project.org/doc/qtinstallerframework/index.html
+ */
+class cmCPackIFWGenerator : public cmCPackGenerator
+{
+public:
+  cmCPackTypeMacro(cmCPackIFWGenerator, cmCPackGenerator);
+
+  /**
+   * Construct generator
+   */
+  cmCPackIFWGenerator();
+  virtual ~cmCPackIFWGenerator();
+
+protected:
+  virtual int InitializeInternal();
+  virtual int PackageFiles();
+  virtual const char* GetPackagingInstallPrefix();
+
+  virtual const char* GetOutputExtension();
+
+  std::string IfwGetGroupId(cmCPackComponentGroup *group);
+  std::string IfwGetComponentId(cmCPackComponent *component);
+
+   std::string IfwGetGroupName(cmCPackComponentGroup *group);
+
+  std::string IfwGetComponentName(cmCPackComponent *component);
+  std::string IfwGetComponentName(const std::string &componentName);
+
+  virtual std::string GetComponentInstallDirNamePrefix(
+      const std::string& componentName);
+
+  virtual std::string GetComponentInstallDirNameSuffix(
+      const std::string& componentName);
+
+  bool GetListOfSubdirectories(const char* dir,
+    std::vector<std::string>& dirs);
+
+  enum cmCPackGenerator::CPackSetDestdirSupport SupportsSetDestdir() const;
+  virtual bool SupportsAbsoluteDestination() const;
+  virtual bool SupportsComponentInstallation() const;
+
+private:
+  int IfwCreateConfigFile();
+  int IfwCreatePackageFile();
+  std::string IfwCreateCurrentDate();
+  bool IfwParseLicenses(std::vector<std::string> &licenses,
+                        const std::string &variable,
+                        const std::string &metaDir);
+
+  std::string ifwRepoGen;
+  std::string ifwBinCreator;
+
+  std::string ifwDownloadSite;
+
+  bool ifwOnlineOnly;
+  bool ifwResolveDuplicateNames;
+  std::vector<std::string> ifwPkgsDirsVector;
+};
+
+#endif

+ 7 - 0
Source/QtIFW/cmake.org.html

@@ -0,0 +1,7 @@
+<html>
+<head>
+<meta http-equiv="Refresh" content="0; url=http://cmake.org/" />
+</head>
+<body>
+</body>
+</html>

+ 24 - 0
Source/QtIFW/installscript.qs.in

@@ -0,0 +1,24 @@
+function Component()
+{
+    // default constructor
+}
+
+Component.prototype.createOperations = function()
+{
+    // call default implementation to actually install applications!
+    component.createOperations();
+
+    // Create shortcut
+    if (installer.value("os") === "win") {
+
+@_CPACK_IFW_SHORTCUT_OPTIONAL@
+
+        component.addOperation("CreateShortcut",
+                               installer.value("TargetDir") + "/cmake.org.html",
+                               installer.value("StartMenuDir") + "/CMake Web Site.lnk");
+
+        component.addOperation("CreateShortcut",
+                               installer.value("TargetDir") + "/uninstall.exe",
+                               installer.value("StartMenuDir") + "/Uninstall.lnk");
+    }
+}