On 05/08/2014 03:14 AM, Konstantin Podsvirov wrote:
> Qt is distributed with of his Qt Installer Framework (QtIFW). 

For reference, here is a link:

 http://qt-project.org/wiki/Qt-Installer-Framework

> I decided to make friends CMake and QtIFW. 
> 
> I added CPack IFW generator and module FindIFW.cmake.

Thanks for working on this.

> You can copy the code and test it:
> 
> git clone git://podsvirov.pro/cmake/cpackifwgenerator.git

For reference, I constructed a patch with the net change from
your topic.  I revised some whitespace too.  See attachment.

I'd appreciate comments from others on this mailing list that
have worked on developing CPack generators.  Also, I'm not
familiar with IFW so I can only comment on this from the
CMake/CPack side.

The patch adds a FindIFW module and has CPack use it to find
the packaging tools and add macro cpack_configure_ifw_component.
In general find modules may not run reliably outside of a
find_package() call in project CMake code (e.g. CMakeLists.txt)
because no information about the host or target platform is
available otherwise.  Normally CPack generators have their own
logic for finding the packaging tools.  The location should
not be needed outside of CPack.  A separate module like
CPackIFW could be used to provide the macro.  We should not
need a FindIFW module at all.

-Brad

>From af34b92edb7712ffe5c4fff582e3f40dce67defc Mon Sep 17 00:00:00 2001
Message-Id: <af34b92edb7712ffe5c4fff582e3f40dce67defc.1399904456.git.brad.k...@kitware.com>
From: Konstantin Podsvirov <konstan...@podsvirov.pro>
Date: Thu, 8 May 2014 10:22:51 +0400
Subject: [PATCH] CPack: Add IFW generator

---
 Help/manual/cmake-modules.7.rst          |   1 +
 Help/module/FindIFW.rst                  |   1 +
 Modules/CPackComponent.cmake             |   3 +
 Modules/FindIFW.cmake                    | 165 +++++++++
 Source/CMakeLists.txt                    |   1 +
 Source/CPack/cmCPackGeneratorFactory.cxx |   6 +
 Source/CPack/cmCPackIFWGenerator.cxx     | 568 +++++++++++++++++++++++++++++++
 Source/CPack/cmCPackIFWGenerator.h       |  72 ++++
 8 files changed, 817 insertions(+)
 create mode 100644 Help/module/FindIFW.rst
 create mode 100644 Modules/FindIFW.cmake
 create mode 100644 Source/CPack/cmCPackIFWGenerator.cxx
 create mode 100644 Source/CPack/cmCPackIFWGenerator.h

diff --git a/Help/manual/cmake-modules.7.rst b/Help/manual/cmake-modules.7.rst
index 2bbe622..0d97233 100644
--- a/Help/manual/cmake-modules.7.rst
+++ b/Help/manual/cmake-modules.7.rst
@@ -114,6 +114,7 @@ All Modules
    /module/FindHSPELL
    /module/FindHTMLHelp
    /module/FindIcotool
+   /module/FindIFW
    /module/FindImageMagick
    /module/FindITK
    /module/FindJasper
diff --git a/Help/module/FindIFW.rst b/Help/module/FindIFW.rst
new file mode 100644
index 0000000..5188cd2
--- /dev/null
+++ b/Help/module/FindIFW.rst
@@ -0,0 +1 @@
+.. cmake-module:: ../../Modules/FindIFW.cmake
diff --git a/Modules/CPackComponent.cmake b/Modules/CPackComponent.cmake
index 1433d9e..5524a3f 100644
--- a/Modules/CPackComponent.cmake
+++ b/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)
diff --git a/Modules/FindIFW.cmake b/Modules/FindIFW.cmake
new file mode 100644
index 0000000..edcede1
--- /dev/null
+++ b/Modules/FindIFW.cmake
@@ -0,0 +1,165 @@
+#.rst:
+# FindIFW
+# -------
+#
+# This module looks for the location of the command line utilities supplied with
+# the Qt Installer Framework (QtIFW_).
+#
+# .. _QtIFW: http://qt-project.org/doc/qtinstallerframework-1.5/index.html
+#
+# The module also defines several commands to control the behavior of the
+# CPack IFW generator.
+#
+# Variables
+# ^^^^^^^^^
+#
+# The module defines the following variables:
+#
+# ::
+#
+#    IFW_BINARYCREATOR_EXECUTABLE - path to binarycreator command line client
+#    IFW_REPOGEN_EXECUTABLE - path to repogen command line client
+#    IFW_FOUND - true if the binarycreator command line client was found
+#
+# Commands
+# ^^^^^^^^^
+#
+# The module defines the following commands:
+#
+# .. command:: cpack_configure_ifw_component
+#
+# Sets the arguments specific to the CPack IFW generator.
+#
+# ::
+#
+#   cpack_configure_ifw_component(compname
+#                       [VERSION version]
+#                       [SCRIPT script])
+#
+# This command should be called after cpack_add_component command.
+#
+# VERSION is version of component.
+#
+# SCRIPT is relative or absolute path to operations script
+# for this component.
+#
+# Example usage
+# ^^^^^^^^^^^^^
+#
+# ::
+#
+#    set(CPACK_PACKAGE_NAME "MyPackage")
+#    set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "MyPackage Installation Example")
+#    set(CPACK_PACKAGE_VERSION "1.0.0")
+#
+#    include(CPack)
+#    find_package(IFW)
+#
+#    cpack_add_component(myapp
+#        DISPLAY_NAME "MyApp"
+#        DESCRIPTION "My Application")
+#    if(IFW_FOUND)
+#    cpack_configure_ifw_component(myapp
+#        VERSION "1.2.3"
+#        SCRIPT "operations.qs")
+#    endif()
+#
+
+#=============================================================================
+# Copyright 2014 Kitware, Inc.
+# Copyright 2014 Konstantin Podsvirov <konstan...@podsvirov.pro>
+#
+# 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.)
+
+# Default path
+
+if(WIN32)
+        set(_IFW_PATHS "C:/Qt")
+else()
+        set(_IFW_PATHS "/opt/qt")
+endif()
+
+set(_IFW_SUFFIXES
+        "QtIFW-1.5.0/bin"
+        "QtIFW-1.5.1/bin")
+
+# Look for 'binarycreator'
+
+find_program(IFW_BINARYCREATOR_EXECUTABLE
+  NAMES binarycreator
+  PATHS ${_IFW_PATHS}
+  PATH_SUFFIXES ${_IFW_SUFFIXES}
+  DOC "QtIFW binarycreator command line client"
+  )
+mark_as_advanced(IFW_BINARYCREATOR_EXECUTABLE)
+
+# Look for 'repogen'
+
+find_program(IFW_REPOGEN_EXECUTABLE
+  NAMES repogen
+  PATHS ${_IFW_PATHS}
+  PATH_SUFFIXES ${_IFW_SUFFIXES}
+  DOC "QtIFW repogen command line client"
+  )
+
+# Handle the QUIETLY and REQUIRED arguments and set IFW_FOUND to TRUE if
+# all listed variables are TRUE
+
+include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
+find_package_handle_standard_args(IFW
+                                  REQUIRED_VARS IFW_BINARYCREATOR_EXECUTABLE)
+
+# Macro definition based on CPackComponent
+
+if(NOT CPackComponent_CMake_INCLUDED)
+    include(CPackComponent)
+endif()
+
+# Macro for configure component
+macro(cpack_configure_ifw_component compname)
+
+  set(_IFW_ARG_NAMES
+    "VERSION"
+    "SCRIPT"
+  )
+
+  string(TOUPPER ${compname} _CPACK_ADDCOMP_UNAME)
+  cpack_parse_arguments(CPACK_IFW_COMPONENT_${_CPACK_ADDCOMP_UNAME}
+    "${_IFW_ARG_NAMES}"
+    ""
+    ${ARGN}
+  )
+
+  # Resolve full filename for script file
+  set(_IFW_SCRIPT_MACRO CPACK_IFW_COMPONENT_${_CPACK_ADDCOMP_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()
+
+  set(_CPACK_ADDCOMP_STR "\n# Configuration for IFW component \"${compname}\"\n")
+
+  foreach(_IFW_ARG_NAME ${_IFW_ARG_NAMES})
+  cpack_append_string_variable_set_command(
+    CPACK_IFW_COMPONENT_${_CPACK_ADDCOMP_UNAME}_${_IFW_ARG_NAME}
+    _CPACK_ADDCOMP_STR)
+  endforeach()
+
+  if(CPack_CMake_INCLUDED)
+    file(APPEND "${CPACK_OUTPUT_CONFIG_FILE}" "${_CPACK_ADDCOMP_STR}")
+  endif()
+
+endmacro()
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 660c0c5..7b7be6a 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -570,6 +570,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
diff --git a/Source/CPack/cmCPackGeneratorFactory.cxx b/Source/CPack/cmCPackGeneratorFactory.cxx
index 9faf2b0..788e785 100644
--- a/Source/CPack/cmCPackGeneratorFactory.cxx
+++ b/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())
     {
diff --git a/Source/CPack/cmCPackIFWGenerator.cxx b/Source/CPack/cmCPackIFWGenerator.cxx
new file mode 100644
index 0000000..c61f689
--- /dev/null
+++ b/Source/CPack/cmCPackIFWGenerator.cxx
@@ -0,0 +1,568 @@
+/*============================================================================
+  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>
+
+/* NSIS uses different command line syntax on Windows and others */
+#ifdef _WIN32
+# define IFW_OPT "/"
+#else
+# define IFW_OPT "-"
+#endif
+
+//----------------------------------------------------------------------
+cmCPackIFWGenerator::cmCPackIFWGenerator()
+{
+}
+
+//----------------------------------------------------------------------
+cmCPackIFWGenerator::~cmCPackIFWGenerator()
+{
+}
+
+//----------------------------------------------------------------------
+int cmCPackIFWGenerator::PackageFiles()
+{
+  // TODO: Fix nsis to force out file name
+/*
+  std::string nsisInFileName = this->FindTemplate("NSIS.template.in");
+  if ( nsisInFileName.size() == 0 )
+    {
+    cmCPackLogger(cmCPackLog::LOG_ERROR,
+      "CPack error: Could not find NSIS installer template file."
+      << std::endl);
+    return false;
+    }
+  std::string nsisInInstallOptions
+    = this->FindTemplate("NSIS.InstallOptions.ini.in");
+  if ( nsisInInstallOptions.size() == 0 )
+    {
+    cmCPackLogger(cmCPackLog::LOG_ERROR,
+      "CPack error: Could not find NSIS installer options file."
+      << std::endl);
+    return false;
+    }
+*/
+  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";
+
+  // Create group meta information
+  std::map<std::string, cmCPackComponentGroup>::iterator groupIt;
+  for(groupIt = this->ComponentGroups.begin();
+      groupIt != this->ComponentGroups.end();
+      ++groupIt
+      )
+  {
+      std::string groupId = IfwGetGroupId(&groupIt->second);
+      std::string pkgXmlFileName = this->toplevel + "/packages/"
+              + groupId
+              + "/meta/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;
+      pkgXml << "    <Version>" << this->GetOption("CPACK_PACKAGE_VERSION") << "</Version>" << std::endl;
+      pkgXml << "    <ReleaseDate>" << createCurrentDate() << "</ReleaseDate>" << std::endl;
+      pkgXml << "</Package>" << std::endl;
+  }
+
+  std::string ifwDownloadedComponents;
+
+  // Create the remaining components, which aren't associated with groups.
+  std::map<std::string, cmCPackComponent>::iterator compIt;
+  for (compIt = this->Components.begin();
+       compIt != this->Components.end();
+       ++compIt)
+  {
+  if (!compIt->second.Group || true)
+    {
+        std::string pkgMetaDir = this->toplevel + "/"
+                + GetComponentInstallDirNamePrefix(compIt->second.Name)
+                + compIt->second.Name + "/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>" << compIt->second.Name << "</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>" << createCurrentDate() << "</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;
+        }
+
+        // Dependencies
+        if (!compIt->second.Dependencies.empty())
+        {
+            pkgXml << "    <Dependencies>";
+            std::vector<cmCPackComponent *>::iterator depCompIt;
+            for(depCompIt = compIt->second.Dependencies.begin();
+                depCompIt != compIt->second.Dependencies.end();
+                ++depCompIt)
+            {
+                pkgXml << IfwGetComponentId(*depCompIt);
+                if (depCompIt + 1 != compIt->second.Dependencies.end())
+                    pkgXml << ",";
+            }
+            pkgXml << "</Dependencies>" << 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;
+        }
+
+        pkgXml << "</Package>" << std::endl;
+    }
+  if (compIt->second.IsDownloaded)
+    {
+      if (!ifwDownloadedComponents.empty()) ifwDownloadedComponents += ",";
+      ifwDownloadedComponents += compIt->second.Name;
+    }
+  }
+
+  // Run repogen
+  if (!ifwDownloadSite.empty())
+  {
+      std::string ifwCmd = ifwRepoGen;
+      ifwCmd += " -c " + this->toplevel + "/config/config.xml";
+      ifwCmd += " -p " + this->toplevel + "/packages";
+      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;
+      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 (ifwOnlineOnly) {
+          ifwCmd += " --online-only";
+      } else if (!ifwDownloadedComponents.empty() && !ifwDownloadSite.empty()) {
+          ifwCmd += " -e " + ifwDownloadedComponents;
+      }
+      // 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;
+      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;
+    if (group)
+    {
+        ifwGroupId = group->Name;
+        group = group->ParentGroup;
+    }
+    while(group) {
+        ifwGroupId = group->Name + "." + ifwGroupId;
+        group = group->ParentGroup;
+    }
+    return ifwGroupId;
+}
+
+std::string cmCPackIFWGenerator::IfwGetComponentId(cmCPackComponent *component)
+{
+    std::string ifwCompId;
+    if(component) {
+        std::string ifwGroupId = IfwGetGroupId(component->Group);
+        if(!ifwGroupId.empty()) ifwCompId += ifwGroupId + ".";
+        ifwCompId += component->Name;
+    }
+    return ifwCompId;
+}
+
+//----------------------------------------------------------------------
+int cmCPackIFWGenerator::InitializeInternal()
+{
+    // Find IFW package
+
+    if(!this->IsSet("IFW_FOUND"))
+    {
+        this->ReadListFile("FindIFW.cmake");
+    }
+
+    if(!this->IsSet("IFW_FOUND"))
+    {
+        cmCPackLogger(cmCPackLog::LOG_ERROR,
+          "Cannot find IFW package: likely it is not installed"
+          << std::endl);
+        return 0;
+    }
+
+    // Look 'binarycreator' executable (needs)
+
+    const char *ifwBinCratorStr = this->GetOption("IFW_BINARYCREATOR_EXECUTABLE");
+
+    ifwBinCreator = ifwBinCratorStr ? ifwBinCratorStr : "";
+
+    if (ifwBinCreator.empty())
+    {
+      cmCPackLogger(cmCPackLog::LOG_ERROR,
+        "Cannot find IFW compiler \"binarycreator\": likely it is not installed, "
+        "or not in your PATH"
+        << std::endl);
+      return 0;
+    }
+
+    // Look 'repogen' executable (optional)
+
+    const char *ifwRepoGenStr = this->GetOption("IFW_REPOGEN_EXECUTABLE");
+
+    ifwRepoGen = ifwRepoGenStr ? ifwRepoGenStr : "";
+
+    // 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 IFW 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)
+{
+    std::string prefix = "packages/";
+
+    std::map<std::string, cmCPackComponent>::iterator compIt = this->Components.find(componentName);
+
+    cmCPackComponent *comp = compIt != this->Components.end() ? &compIt->second : 0;
+
+    std::string groupPrefix = comp ? this->IfwGetGroupId(comp->Group) : "";
+
+    if(!groupPrefix.empty()) groupPrefix += ".";
+
+    return prefix + groupPrefix;
+}
+
+//----------------------------------------------------------------------
+std::string cmCPackIFWGenerator::GetComponentInstallDirNameSuffix(const std::string &componentName)
+{
+    const std::string prefix = GetComponentInstallDirNamePrefix(componentName);
+    const std::string suffix = "/data";
+
+    if (componentPackageMethod == ONE_PACKAGE_PER_COMPONENT) {
+      return prefix + componentName + suffix;
+    }
+
+    if (componentPackageMethod == ONE_PACKAGE) {
+      return std::string(prefix + "ALL_COMPONENTS_IN_ONE" + suffix);
+    }
+    // We have to find the name of the COMPONENT GROUP
+    // the current COMPONENT belongs to.
+//    std::string groupVar = "CPACK_COMPONENT_" +
+//          cmSystemTools::UpperCase(componentName) + "_GROUP";
+//      if (NULL != GetOption(groupVar))
+//        {
+//        return preffix + std::string(GetOption(groupVar)) + "." + componentName + suffix;
+//        }
+//      else
+//        {
+//        return preffix + componentName + suffix;
+//        }
+    return prefix + componentName + 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";
+    }
+
+    std::string ifwPkgInstDir;
+    if (const char *dir = this->GetOption("CPACK_PACKAGE_INSTALL_DIRECTORY")) {
+        ifwPkgInstDir = dir;
+    } else {
+        ifwPkgVersion = "InstallationDirectory";
+    }
+
+    cfg << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
+    cfg << "<Installer>" << std::endl;
+    cfg << "    <Name>" << ifwPkgName << "</Name>" << std::endl;
+    cfg << "    <Version>" << ifwPkgVersion << "</Version>" << std::endl;
+    cfg << "    <Title>" << ifwPkgDescription << "</Title>" << std::endl;
+    cfg << "    <TargetDir>@RootDir@" << ifwPkgInstDir << "</TargetDir>" << std::endl;
+
+    if (!ifwDownloadSite.empty())
+    {
+    cfg << "    <RemoteRepositories>" << std::endl;
+    cfg << "        <Repository>" << std::endl;
+    cfg << "            <Url>" << ifwDownloadSite << "</Url>" << std::endl;
+//                 <Enabled>1</Enabled>
+//                 <Username>user</Username>
+//                 <Password>password</Password>
+//                 <DisplayName>Example repository</DisplayName>
+    cfg << "        </Repository>" << std::endl;
+    cfg << "    </RemoteRepositories>" << std::endl;
+    }
+
+    cfg << "</Installer>" << std::endl;
+
+    return 1;
+}
+
+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 << "    <Version>" << "1.0.0" << "</Version>" << std::endl;
+    pkgXml << "    <ReleaseDate>" << createCurrentDate() << "</ReleaseDate>" << 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;
+//    }
+
+    pkgXml << "</Package>" << std::endl;
+
+    return 1;
+}
+
+std::string cmCPackIFWGenerator::createCurrentDate()
+{
+    time_t rawtime;
+    struct tm * timeinfo;
+    char buffer[80];
+
+    time (&rawtime);
+    timeinfo = localtime(&rawtime);
+
+    //strftime(buffer,80,"%d-%m-%Y %I:%M:%S",timeinfo);
+    strftime(buffer,80,"%Y-%m-%d",timeinfo);
+
+    return buffer;
+}
diff --git a/Source/CPack/cmCPackIFWGenerator.h b/Source/CPack/cmCPackIFWGenerator.h
new file mode 100644
index 0000000..3f70ae6
--- /dev/null
+++ b/Source/CPack/cmCPackIFWGenerator.h
@@ -0,0 +1,72 @@
+/*============================================================================
+  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 cmCPackNSISGenerator
+ * \brief A generator for NSIS files
+ *
+ * http://people.freebsd.org/~kientzle/libarchive/
+ */
+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);
+
+  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 createCurrentDate();
+
+  std::string ifwRepoGen;
+  std::string ifwBinCreator;
+
+  std::string ifwDownloadSite;
+
+  bool ifwOnlineOnly;
+};
+
+#endif
-- 
1.9.2

-- 

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: 
http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more 
information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at 
http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/cgi-bin/mailman/listinfo/cmake-developers

Reply via email to