瀏覽代碼

CPackIFW: Add 'cpack_ifw_add_package_resources' command

Konstantin Podsvirov 9 年之前
父節點
當前提交
b807cd9b54

+ 6 - 0
Help/release/dev/ifw-package-resources.rst

@@ -0,0 +1,6 @@
+ifw-package-resources
+---------------------
+
+* The :module:`CPackIFW` module gained a new
+  :command:`cpack_ifw_add_package_resources` command to include additional
+  resources in the installer binary.

+ 32 - 0
Modules/CPackIFW.cmake

@@ -131,6 +131,14 @@
 #
 #  Filename for a custom installer control script.
 #
+# .. variable:: CPACK_IFW_PACKAGE_RESOURCES
+#
+#  List of additional resources ('.qrc' files) to include in the installer
+#  binary.
+#
+#  You can use :command:`cpack_ifw_add_package_resources` command to resolve
+#  relative paths.
+#
 # .. variable:: CPACK_IFW_REPOSITORIES_ALL
 #
 #  The list of remote repositories.
@@ -337,6 +345,19 @@
 #   ``DISPLAY_NAME``
 #     is string to display instead of the URL.
 #
+#
+# .. command:: cpack_ifw_add_package_resources
+#
+#   Add additional resources in the installer binary.
+#
+#   ::
+#
+#     cpack_ifw_add_package_resources(<file_path> <file_path> ...)
+#
+#   This command will also add the specified files
+#   to a variable :variable:`CPACK_IFW_PACKAGE_RESOURCES`.
+#
+#
 # Example usage
 # ^^^^^^^^^^^^^
 #
@@ -741,6 +762,17 @@ macro(cpack_ifw_update_repository reponame)
 
 endmacro()
 
+# Macro for adding resources
+macro(cpack_ifw_add_package_resources)
+  set(_CPACK_IFW_PACKAGE_RESOURCES ${ARGV})
+  _cpack_ifw_resolve_file_list(_CPACK_IFW_PACKAGE_RESOURCES)
+  list(APPEND CPACK_IFW_PACKAGE_RESOURCES ${_CPACK_IFW_PACKAGE_RESOURCES})
+  set(_CPACK_IFWQRC_STR "list(APPEND CPACK_IFW_PACKAGE_RESOURCES \"${_CPACK_IFW_PACKAGE_RESOURCES}\")\n")
+  if(CPack_CMake_INCLUDED)
+    file(APPEND "${CPACK_OUTPUT_CONFIG_FILE}" "${_CPACK_IFWQRC_STR}")
+  endif()
+endmacro()
+
 # Resolve package control script
 _cpack_ifw_resolve_script(CPACK_IFW_PACKAGE_CONTROL_SCRIPT)
 

+ 13 - 0
Source/CPack/IFW/cmCPackIFWGenerator.cxx

@@ -130,6 +130,19 @@ int cmCPackIFWGenerator::PackageFiles()
   {
     std::string ifwCmd = BinCreator;
     ifwCmd += " -c " + this->toplevel + "/config/config.xml";
+
+    if (!Installer.Resources.empty()) {
+      ifwCmd += " -r ";
+      std::vector<std::string>::iterator it = Installer.Resources.begin();
+      std::string path = this->toplevel + "/resources/";
+      ifwCmd += path + *it;
+      ++it;
+      while (it != Installer.Resources.end()) {
+        ifwCmd += "," + path + *it;
+        ++it;
+      }
+    }
+
     ifwCmd += " -p " + this->toplevel + "/packages";
 
     if (!PkgsDirsVector.empty()) {

+ 84 - 0
Source/CPack/IFW/cmCPackIFWInstaller.cxx

@@ -13,11 +13,13 @@
 #include "cmCPackIFWInstaller.h"
 
 #include "CPack/cmCPackGenerator.h"
+#include "CPack/cmCPackLog.h"
 #include "cmCPackIFWGenerator.h"
 #include "cmCPackIFWPackage.h"
 #include "cmCPackIFWRepository.h"
 #include "cmGeneratedFileStream.h"
 #include "cmSystemTools.h"
+#include "cmXMLParser.h"
 #include "cmXMLWriter.h"
 
 #include <cmConfigure.h>
@@ -198,8 +200,70 @@ void cmCPackIFWInstaller::ConfigureFromOptions()
         this->GetOption("CPACK_IFW_PACKAGE_CONTROL_SCRIPT")) {
     ControlScript = optIFW_CONTROL_SCRIPT;
   }
+
+  // Resources
+  if (const char* optIFW_PACKAGE_RESOURCES =
+        this->GetOption("CPACK_IFW_PACKAGE_RESOURCES")) {
+    Resources.clear();
+    cmSystemTools::ExpandListArgument(optIFW_PACKAGE_RESOURCES, Resources);
+  }
 }
 
+/** \class cmCPackIFWResourcesParser
+ * \brief Helper class that parse resources form .qrc (Qt)
+ */
+class cmCPackIFWResourcesParser : public cmXMLParser
+{
+public:
+  cmCPackIFWResourcesParser(cmCPackIFWInstaller* i)
+    : installer(i)
+    , file(false)
+  {
+    path = i->Directory + "/resources";
+  }
+
+  bool ParseResource(size_t r)
+  {
+    hasFiles = false;
+    hasErrors = false;
+
+    basePath = cmSystemTools::GetFilenamePath(installer->Resources[r].data());
+
+    ParseFile(installer->Resources[r].data());
+
+    return hasFiles && !hasErrors;
+  }
+
+  cmCPackIFWInstaller* installer;
+  bool file, hasFiles, hasErrors;
+  std::string path, basePath;
+
+protected:
+  void StartElement(const std::string& name, const char** /*atts*/) CM_OVERRIDE
+  {
+    file = name == "file" ? true : false;
+    if (file) {
+      hasFiles = true;
+    }
+  }
+
+  void CharacterDataHandler(const char* data, int length) CM_OVERRIDE
+  {
+    if (file) {
+      std::string content(data, data + length);
+      content = cmSystemTools::TrimWhitespace(content);
+      std::string source = basePath + "/" + content;
+      std::string destination = path + "/" + content;
+      if (!cmSystemTools::CopyFileIfDifferent(source.data(),
+                                              destination.data())) {
+        hasErrors = true;
+      }
+    }
+  }
+
+  void EndElement(const std::string& /*name*/) CM_OVERRIDE {}
+};
+
 void cmCPackIFWInstaller::GenerateInstallerFile()
 {
   // Lazy directory initialization
@@ -315,6 +379,26 @@ void cmCPackIFWInstaller::GenerateInstallerFile()
     xout.Element("ControlScript", name);
   }
 
+  // Resources (copy to resources dir)
+  if (!Resources.empty()) {
+    std::vector<std::string> resources;
+    cmCPackIFWResourcesParser parser(this);
+    for (size_t i = 0; i < Resources.size(); i++) {
+      if (parser.ParseResource(i)) {
+        std::string name = cmSystemTools::GetFilenameName(Resources[i]);
+        std::string path = Directory + "/resources/" + name;
+        cmsys::SystemTools::CopyFileIfDifferent(Resources[i].data(),
+                                                path.data());
+        resources.push_back(name);
+      } else {
+        cmCPackLogger(cmCPackLog::LOG_WARNING, "Can't copy resources from \""
+                        << Resources[i] << "\". Resource will be skipped."
+                        << std::endl);
+      }
+    }
+    Resources = resources;
+  }
+
   xout.EndElement();
   xout.EndDocument();
 }

+ 3 - 0
Source/CPack/IFW/cmCPackIFWInstaller.h

@@ -94,6 +94,9 @@ public:
   /// Filename for a custom installer control script
   std::string ControlScript;
 
+  /// List of resources to include in the installer binary
+  std::vector<std::string> Resources;
+
 public:
   // Internal implementation