diff --git a/Help/release/dev/ifw-package-resources.rst b/Help/release/dev/ifw-package-resources.rst new file mode 100644 index 000000000..28ea5c440 --- /dev/null +++ b/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. diff --git a/Modules/CPackIFW.cmake b/Modules/CPackIFW.cmake index 36fc27633..bb1285d78 100644 --- a/Modules/CPackIFW.cmake +++ b/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( ...) +# +# 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) diff --git a/Source/CPack/IFW/cmCPackIFWGenerator.cxx b/Source/CPack/IFW/cmCPackIFWGenerator.cxx index a6f158598..fa7e0aa02 100644 --- a/Source/CPack/IFW/cmCPackIFWGenerator.cxx +++ b/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::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()) { diff --git a/Source/CPack/IFW/cmCPackIFWInstaller.cxx b/Source/CPack/IFW/cmCPackIFWInstaller.cxx index 5a3efc966..aa609e27f 100644 --- a/Source/CPack/IFW/cmCPackIFWInstaller.cxx +++ b/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 @@ -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 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(); } diff --git a/Source/CPack/IFW/cmCPackIFWInstaller.h b/Source/CPack/IFW/cmCPackIFWInstaller.h index f72d37960..c9265ec86 100644 --- a/Source/CPack/IFW/cmCPackIFWInstaller.h +++ b/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 Resources; + public: // Internal implementation