summaryrefslogtreecommitdiffstats
path: root/Source/CPack/IFW
diff options
context:
space:
mode:
Diffstat (limited to 'Source/CPack/IFW')
-rw-r--r--Source/CPack/IFW/cmCPackIFWGenerator.cxx584
-rw-r--r--Source/CPack/IFW/cmCPackIFWGenerator.h164
-rw-r--r--Source/CPack/IFW/cmCPackIFWInstaller.cxx546
-rw-r--r--Source/CPack/IFW/cmCPackIFWInstaller.h140
-rw-r--r--Source/CPack/IFW/cmCPackIFWPackage.cxx725
-rw-r--r--Source/CPack/IFW/cmCPackIFWPackage.h160
-rw-r--r--Source/CPack/IFW/cmCPackIFWRepository.cxx334
-rw-r--r--Source/CPack/IFW/cmCPackIFWRepository.h98
8 files changed, 2751 insertions, 0 deletions
diff --git a/Source/CPack/IFW/cmCPackIFWGenerator.cxx b/Source/CPack/IFW/cmCPackIFWGenerator.cxx
new file mode 100644
index 0000000..ee46d86
--- /dev/null
+++ b/Source/CPack/IFW/cmCPackIFWGenerator.cxx
@@ -0,0 +1,584 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmCPackIFWGenerator.h"
+
+#include "CPack/cmCPackComponentGroup.h"
+#include "CPack/cmCPackGenerator.h"
+#include "CPack/cmCPackLog.h"
+#include "cmCPackIFWInstaller.h"
+#include "cmCPackIFWPackage.h"
+#include "cmCPackIFWRepository.h"
+#include "cmGeneratedFileStream.h"
+#include "cmSystemTools.h"
+#include "cmTimestamp.h"
+#include "cmVersionConfig.h"
+#include "cmXMLWriter.h"
+
+#include <sstream>
+#include <utility>
+
+cmCPackIFWGenerator::cmCPackIFWGenerator()
+{
+}
+
+cmCPackIFWGenerator::~cmCPackIFWGenerator()
+{
+}
+
+bool cmCPackIFWGenerator::IsVersionLess(const char* version)
+{
+ return cmSystemTools::VersionCompare(cmSystemTools::OP_LESS,
+ FrameworkVersion.data(), version);
+}
+
+bool cmCPackIFWGenerator::IsVersionGreater(const char* version)
+{
+ return cmSystemTools::VersionCompare(cmSystemTools::OP_GREATER,
+ FrameworkVersion.data(), version);
+}
+
+bool cmCPackIFWGenerator::IsVersionEqual(const char* version)
+{
+ return cmSystemTools::VersionCompare(cmSystemTools::OP_EQUAL,
+ FrameworkVersion.data(), version);
+}
+
+int cmCPackIFWGenerator::PackageFiles()
+{
+ cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Configuration" << std::endl);
+
+ // Installer configuragion
+ Installer.GenerateInstallerFile();
+
+ // Packages configuration
+ Installer.GeneratePackageFiles();
+
+ std::string ifwTLD = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
+ std::string ifwTmpFile = ifwTLD;
+ ifwTmpFile += "/IFWOutput.log";
+
+ // Run repogen
+ if (!Installer.RemoteRepositories.empty()) {
+ std::string ifwCmd = RepoGen;
+
+ if (IsVersionLess("2.0.0")) {
+ ifwCmd += " -c " + this->toplevel + "/config/config.xml";
+ }
+
+ ifwCmd += " -p " + this->toplevel + "/packages";
+
+ if (!PkgsDirsVector.empty()) {
+ for (std::vector<std::string>::iterator it = PkgsDirsVector.begin();
+ it != PkgsDirsVector.end(); ++it) {
+ ifwCmd += " -p " + *it;
+ }
+ }
+
+ if (!OnlineOnly && !DownloadedPackages.empty()) {
+ ifwCmd += " -i ";
+ std::set<cmCPackIFWPackage*>::iterator it = DownloadedPackages.begin();
+ ifwCmd += (*it)->Name;
+ ++it;
+ while (it != DownloadedPackages.end()) {
+ ifwCmd += "," + (*it)->Name;
+ ++it;
+ }
+ }
+ 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,
+ &output, &retVal, CM_NULLPTR,
+ 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;
+ }
+
+ if (!Repository.RepositoryUpdate.empty() &&
+ !Repository.PatchUpdatesXml()) {
+ cmCPackLogger(cmCPackLog::LOG_WARNING, "Problem patch IFW \"Updates\" "
+ << "file: " << this->toplevel + "/repository/Updates.xml"
+ << std::endl);
+ }
+
+ cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- repository: "
+ << this->toplevel << "/repository generated" << std::endl);
+ }
+
+ // Run binary creator
+ {
+ 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()) {
+ for (std::vector<std::string>::iterator it = PkgsDirsVector.begin();
+ it != PkgsDirsVector.end(); ++it) {
+ ifwCmd += " -p " + *it;
+ }
+ }
+
+ if (OnlineOnly) {
+ ifwCmd += " --online-only";
+ } else if (!DownloadedPackages.empty() &&
+ !Installer.RemoteRepositories.empty()) {
+ ifwCmd += " -e ";
+ std::set<cmCPackIFWPackage*>::iterator it = DownloadedPackages.begin();
+ ifwCmd += (*it)->Name;
+ ++it;
+ while (it != DownloadedPackages.end()) {
+ ifwCmd += "," + (*it)->Name;
+ ++it;
+ }
+ } else if (!DependentPackages.empty()) {
+ ifwCmd += " -i ";
+ // Binary
+ std::set<cmCPackIFWPackage*>::iterator bit = BinaryPackages.begin();
+ while (bit != BinaryPackages.end()) {
+ ifwCmd += (*bit)->Name + ",";
+ ++bit;
+ }
+ // Depend
+ DependenceMap::iterator it = DependentPackages.begin();
+ ifwCmd += it->second.Name;
+ ++it;
+ while (it != DependentPackages.end()) {
+ ifwCmd += "," + it->second.Name;
+ ++it;
+ }
+ }
+ // TODO: set correct name for multipackages
+ if (!this->packageFileNames.empty()) {
+ 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,
+ &output, &retVal, CM_NULLPTR,
+ 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/" + GetRootPackageName() + "/data";
+ }
+
+ this->SetOption("CPACK_IFW_PACKAGING_INSTALL_PREFIX", tmpPref.c_str());
+
+ return this->GetOption("CPACK_IFW_PACKAGING_INSTALL_PREFIX");
+}
+
+const char* cmCPackIFWGenerator::GetOutputExtension()
+{
+ return ExecutableSuffix.c_str();
+}
+
+int cmCPackIFWGenerator::InitializeInternal()
+{
+ // Search Qt Installer Framework tools
+
+ const std::string BinCreatorOpt = "CPACK_IFW_BINARYCREATOR_EXECUTABLE";
+ const std::string RepoGenOpt = "CPACK_IFW_REPOGEN_EXECUTABLE";
+ const std::string FrameworkVersionOpt = "CPACK_IFW_FRAMEWORK_VERSION";
+
+ if (!this->IsSet(BinCreatorOpt) || !this->IsSet(RepoGenOpt) ||
+ !this->IsSet(FrameworkVersionOpt)) {
+ this->ReadListFile("CPackIFW.cmake");
+ }
+
+ // Look 'binarycreator' executable (needs)
+
+ const char* BinCreatorStr = this->GetOption(BinCreatorOpt);
+ if (!BinCreatorStr || cmSystemTools::IsNOTFOUND(BinCreatorStr)) {
+ BinCreator = "";
+ } else {
+ BinCreator = BinCreatorStr;
+ }
+
+ if (BinCreator.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)
+
+ const char* RepoGenStr = this->GetOption(RepoGenOpt);
+ if (!RepoGenStr || cmSystemTools::IsNOTFOUND(RepoGenStr)) {
+ RepoGen = "";
+ } else {
+ RepoGen = RepoGenStr;
+ }
+
+ // Framework version
+ if (const char* FrameworkVersionSrt = this->GetOption(FrameworkVersionOpt)) {
+ FrameworkVersion = FrameworkVersionSrt;
+ } else {
+ FrameworkVersion = "1.9.9";
+ }
+
+ // Variables that Change Behavior
+
+ // Resolve duplicate names
+ ResolveDuplicateNames = this->IsOn("CPACK_IFW_RESOLVE_DUPLICATE_NAMES");
+
+ // Additional packages dirs
+ PkgsDirsVector.clear();
+ if (const char* dirs = this->GetOption("CPACK_IFW_PACKAGES_DIRECTORIES")) {
+ cmSystemTools::ExpandListArgument(dirs, PkgsDirsVector);
+ }
+
+ // Installer
+ Installer.Generator = this;
+ Installer.ConfigureFromOptions();
+
+ // Repository
+ Repository.Generator = this;
+ Repository.Name = "Unspecified";
+ if (const char* site = this->GetOption("CPACK_DOWNLOAD_SITE")) {
+ Repository.Url = site;
+ Installer.RemoteRepositories.push_back(&Repository);
+ }
+
+ // Repositories
+ if (const char* RepoAllStr = this->GetOption("CPACK_IFW_REPOSITORIES_ALL")) {
+ std::vector<std::string> RepoAllVector;
+ cmSystemTools::ExpandListArgument(RepoAllStr, RepoAllVector);
+ for (std::vector<std::string>::iterator rit = RepoAllVector.begin();
+ rit != RepoAllVector.end(); ++rit) {
+ GetRepository(*rit);
+ }
+ }
+
+ if (const char* ifwDownloadAll = this->GetOption("CPACK_IFW_DOWNLOAD_ALL")) {
+ OnlineOnly = cmSystemTools::IsOn(ifwDownloadAll);
+ } else if (const char* cpackDownloadAll =
+ this->GetOption("CPACK_DOWNLOAD_ALL")) {
+ OnlineOnly = cmSystemTools::IsOn(cpackDownloadAll);
+ } else {
+ OnlineOnly = false;
+ }
+
+ if (!Installer.RemoteRepositories.empty() && RepoGen.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;
+ }
+
+ // Executable suffix
+ if (const char* optExeSuffix = this->GetOption("CMAKE_EXECUTABLE_SUFFIX")) {
+ ExecutableSuffix = optExeSuffix;
+ if (ExecutableSuffix.empty()) {
+ std::string sysName(this->GetOption("CMAKE_SYSTEM_NAME"));
+ if (sysName == "Linux") {
+ ExecutableSuffix = ".run";
+ }
+ }
+ } else {
+ ExecutableSuffix = cmCPackGenerator::GetOutputExtension();
+ }
+
+ return this->Superclass::InitializeInternal();
+}
+
+std::string cmCPackIFWGenerator::GetComponentInstallDirNameSuffix(
+ const std::string& componentName)
+{
+ const std::string prefix = "packages/";
+ const std::string suffix = "/data";
+
+ if (componentPackageMethod == ONE_PACKAGE) {
+ return std::string(prefix + GetRootPackageName() + suffix);
+ }
+
+ return prefix + GetComponentPackageName(&Components[componentName]) + suffix;
+}
+
+cmCPackComponent* cmCPackIFWGenerator::GetComponent(
+ const std::string& projectName, const std::string& componentName)
+{
+ ComponentsMap::iterator cit = Components.find(componentName);
+ if (cit != Components.end()) {
+ return &(cit->second);
+ }
+
+ cmCPackComponent* component =
+ cmCPackGenerator::GetComponent(projectName, componentName);
+ if (!component) {
+ return component;
+ }
+
+ std::string name = GetComponentPackageName(component);
+ PackagesMap::iterator pit = Packages.find(name);
+ if (pit != Packages.end()) {
+ return component;
+ }
+
+ cmCPackIFWPackage* package = &Packages[name];
+ package->Name = name;
+ package->Generator = this;
+ if (package->ConfigureFromComponent(component)) {
+ package->Installer = &Installer;
+ Installer.Packages.insert(
+ std::pair<std::string, cmCPackIFWPackage*>(name, package));
+ ComponentPackages.insert(
+ std::pair<cmCPackComponent*, cmCPackIFWPackage*>(component, package));
+ if (component->IsDownloaded) {
+ DownloadedPackages.insert(package);
+ } else {
+ BinaryPackages.insert(package);
+ }
+ } else {
+ Packages.erase(name);
+ cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot configure package \""
+ << name << "\" for component \"" << component->Name << "\""
+ << std::endl);
+ }
+
+ return component;
+}
+
+cmCPackComponentGroup* cmCPackIFWGenerator::GetComponentGroup(
+ const std::string& projectName, const std::string& groupName)
+{
+ cmCPackComponentGroup* group =
+ cmCPackGenerator::GetComponentGroup(projectName, groupName);
+ if (!group) {
+ return group;
+ }
+
+ std::string name = GetGroupPackageName(group);
+ PackagesMap::iterator pit = Packages.find(name);
+ if (pit != Packages.end()) {
+ return group;
+ }
+
+ cmCPackIFWPackage* package = &Packages[name];
+ package->Name = name;
+ package->Generator = this;
+ if (package->ConfigureFromGroup(group)) {
+ package->Installer = &Installer;
+ Installer.Packages.insert(
+ std::pair<std::string, cmCPackIFWPackage*>(name, package));
+ GroupPackages.insert(
+ std::pair<cmCPackComponentGroup*, cmCPackIFWPackage*>(group, package));
+ BinaryPackages.insert(package);
+ } else {
+ Packages.erase(name);
+ cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot configure package \""
+ << name << "\" for component group \"" << group->Name
+ << "\"" << std::endl);
+ }
+ return group;
+}
+
+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;
+}
+
+bool cmCPackIFWGenerator::IsOnePackage() const
+{
+ return componentPackageMethod == ONE_PACKAGE;
+}
+
+std::string cmCPackIFWGenerator::GetRootPackageName()
+{
+ // Default value
+ std::string name = "root";
+ if (const char* optIFW_PACKAGE_GROUP =
+ this->GetOption("CPACK_IFW_PACKAGE_GROUP")) {
+ // Configure from root group
+ cmCPackIFWPackage package;
+ package.Generator = this;
+ package.ConfigureFromGroup(optIFW_PACKAGE_GROUP);
+ name = package.Name;
+ } else if (const char* optIFW_PACKAGE_NAME =
+ this->GetOption("CPACK_IFW_PACKAGE_NAME")) {
+ // Configure from root package name
+ name = optIFW_PACKAGE_NAME;
+ } else if (const char* optPACKAGE_NAME =
+ this->GetOption("CPACK_PACKAGE_NAME")) {
+ // Configure from package name
+ name = optPACKAGE_NAME;
+ }
+ return name;
+}
+
+std::string cmCPackIFWGenerator::GetGroupPackageName(
+ cmCPackComponentGroup* group) const
+{
+ std::string name;
+ if (!group) {
+ return name;
+ }
+ if (cmCPackIFWPackage* package = GetGroupPackage(group)) {
+ return package->Name;
+ }
+ const char* option =
+ GetOption("CPACK_IFW_COMPONENT_GROUP_" +
+ cmsys::SystemTools::UpperCase(group->Name) + "_NAME");
+ name = option ? option : group->Name;
+ if (group->ParentGroup) {
+ cmCPackIFWPackage* package = GetGroupPackage(group->ParentGroup);
+ bool dot = !ResolveDuplicateNames;
+ if (dot && name.substr(0, package->Name.size()) == package->Name) {
+ dot = false;
+ }
+ if (dot) {
+ name = package->Name + "." + name;
+ }
+ }
+ return name;
+}
+
+std::string cmCPackIFWGenerator::GetComponentPackageName(
+ cmCPackComponent* component) const
+{
+ std::string name;
+ if (!component) {
+ return name;
+ }
+ if (cmCPackIFWPackage* package = GetComponentPackage(component)) {
+ return package->Name;
+ }
+ std::string prefix = "CPACK_IFW_COMPONENT_" +
+ cmsys::SystemTools::UpperCase(component->Name) + "_";
+ const char* option = GetOption(prefix + "NAME");
+ name = option ? option : component->Name;
+ if (component->Group) {
+ cmCPackIFWPackage* package = GetGroupPackage(component->Group);
+ if ((componentPackageMethod == ONE_PACKAGE_PER_GROUP) ||
+ IsOn(prefix + "COMMON")) {
+ return package->Name;
+ }
+ bool dot = !ResolveDuplicateNames;
+ if (dot && name.substr(0, package->Name.size()) == package->Name) {
+ dot = false;
+ }
+ if (dot) {
+ name = package->Name + "." + name;
+ }
+ }
+ return name;
+}
+
+cmCPackIFWPackage* cmCPackIFWGenerator::GetGroupPackage(
+ cmCPackComponentGroup* group) const
+{
+ std::map<cmCPackComponentGroup*, cmCPackIFWPackage*>::const_iterator pit =
+ GroupPackages.find(group);
+ return pit != GroupPackages.end() ? pit->second : CM_NULLPTR;
+}
+
+cmCPackIFWPackage* cmCPackIFWGenerator::GetComponentPackage(
+ cmCPackComponent* component) const
+{
+ std::map<cmCPackComponent*, cmCPackIFWPackage*>::const_iterator pit =
+ ComponentPackages.find(component);
+ return pit != ComponentPackages.end() ? pit->second : CM_NULLPTR;
+}
+
+cmCPackIFWRepository* cmCPackIFWGenerator::GetRepository(
+ const std::string& repositoryName)
+{
+ RepositoriesMap::iterator rit = Repositories.find(repositoryName);
+ if (rit != Repositories.end()) {
+ return &(rit->second);
+ }
+
+ cmCPackIFWRepository* repository = &Repositories[repositoryName];
+ repository->Name = repositoryName;
+ repository->Generator = this;
+ if (repository->ConfigureFromOptions()) {
+ if (repository->Update == cmCPackIFWRepository::None) {
+ Installer.RemoteRepositories.push_back(repository);
+ } else {
+ Repository.RepositoryUpdate.push_back(repository);
+ }
+ } else {
+ Repositories.erase(repositoryName);
+ repository = CM_NULLPTR;
+ cmCPackLogger(cmCPackLog::LOG_WARNING, "Invalid repository \""
+ << repositoryName << "\""
+ << " configuration. Repository will be skipped."
+ << std::endl);
+ }
+ return repository;
+}
+
+void cmCPackIFWGenerator::WriteGeneratedByToStrim(cmXMLWriter& xout)
+{
+ std::ostringstream comment;
+ comment << "Generated by CPack " << CMake_VERSION << " IFW generator "
+ << "for QtIFW ";
+ if (IsVersionLess("2.0")) {
+ comment << "less 2.0";
+ } else {
+ comment << FrameworkVersion;
+ }
+ comment << " tools at " << cmTimestamp().CurrentTime("", true);
+ xout.Comment(comment.str().c_str());
+}
diff --git a/Source/CPack/IFW/cmCPackIFWGenerator.h b/Source/CPack/IFW/cmCPackIFWGenerator.h
new file mode 100644
index 0000000..d656063
--- /dev/null
+++ b/Source/CPack/IFW/cmCPackIFWGenerator.h
@@ -0,0 +1,164 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmCPackIFWGenerator_h
+#define cmCPackIFWGenerator_h
+
+#include <cmConfigure.h>
+
+#include "CPack/cmCPackComponentGroup.h"
+#include "CPack/cmCPackGenerator.h"
+#include "cmCPackIFWInstaller.h"
+#include "cmCPackIFWPackage.h"
+#include "cmCPackIFWRepository.h"
+
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+class cmXMLWriter;
+
+/** \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);
+
+ typedef std::map<std::string, cmCPackIFWPackage> PackagesMap;
+ typedef std::map<std::string, cmCPackIFWRepository> RepositoriesMap;
+ typedef std::map<std::string, cmCPackComponent> ComponentsMap;
+ typedef std::map<std::string, cmCPackComponentGroup> ComponentGoupsMap;
+ typedef std::map<std::string, cmCPackIFWPackage::DependenceStruct>
+ DependenceMap;
+
+ /**
+ * Construct IFW generator
+ */
+ cmCPackIFWGenerator();
+
+ /**
+ * Destruct IFW generator
+ */
+ ~cmCPackIFWGenerator() CM_OVERRIDE;
+
+ /**
+ * Compare \a version with QtIFW framework version
+ */
+ bool IsVersionLess(const char* version);
+
+ /**
+ * Compare \a version with QtIFW framework version
+ */
+ bool IsVersionGreater(const char* version);
+
+ /**
+ * Compare \a version with QtIFW framework version
+ */
+ bool IsVersionEqual(const char* version);
+
+protected:
+ // cmCPackGenerator reimplementation
+
+ /**
+ * @brief Initialize generator
+ * @return 0 on failure
+ */
+ int InitializeInternal() CM_OVERRIDE;
+ int PackageFiles() CM_OVERRIDE;
+ const char* GetPackagingInstallPrefix() CM_OVERRIDE;
+
+ /**
+ * @brief Extension of binary installer
+ * @return Executable suffix or value from default implementation
+ */
+ const char* GetOutputExtension() CM_OVERRIDE;
+
+ std::string GetComponentInstallDirNameSuffix(
+ const std::string& componentName) CM_OVERRIDE;
+
+ /**
+ * @brief Get Component
+ * @param projectName Project name
+ * @param componentName Component name
+ *
+ * This method calls the base implementation.
+ *
+ * @return Pointer to component
+ */
+ cmCPackComponent* GetComponent(const std::string& projectName,
+ const std::string& componentName) CM_OVERRIDE;
+
+ /**
+ * @brief Get group of component
+ * @param projectName Project name
+ * @param groupName Component group name
+ *
+ * This method calls the base implementation.
+ *
+ * @return Pointer to component group
+ */
+ cmCPackComponentGroup* GetComponentGroup(
+ const std::string& projectName, const std::string& groupName) CM_OVERRIDE;
+
+ enum cmCPackGenerator::CPackSetDestdirSupport SupportsSetDestdir() const
+ CM_OVERRIDE;
+ bool SupportsAbsoluteDestination() const CM_OVERRIDE;
+ bool SupportsComponentInstallation() const CM_OVERRIDE;
+
+protected:
+ // Methods
+
+ bool IsOnePackage() const;
+
+ std::string GetRootPackageName();
+
+ std::string GetGroupPackageName(cmCPackComponentGroup* group) const;
+ std::string GetComponentPackageName(cmCPackComponent* component) const;
+
+ cmCPackIFWPackage* GetGroupPackage(cmCPackComponentGroup* group) const;
+ cmCPackIFWPackage* GetComponentPackage(cmCPackComponent* component) const;
+
+ cmCPackIFWRepository* GetRepository(const std::string& repositoryName);
+
+ void WriteGeneratedByToStrim(cmXMLWriter& xout);
+
+protected:
+ // Data
+
+ friend class cmCPackIFWPackage;
+ friend class cmCPackIFWInstaller;
+ friend class cmCPackIFWRepository;
+
+ // Installer
+ cmCPackIFWInstaller Installer;
+ // Repository
+ cmCPackIFWRepository Repository;
+ // Collection of packages
+ PackagesMap Packages;
+ // Collection of repositories
+ RepositoriesMap Repositories;
+ // Collection of binary packages
+ std::set<cmCPackIFWPackage*> BinaryPackages;
+ // Collection of downloaded packages
+ std::set<cmCPackIFWPackage*> DownloadedPackages;
+ // Dependent packages
+ DependenceMap DependentPackages;
+ std::map<cmCPackComponent*, cmCPackIFWPackage*> ComponentPackages;
+ std::map<cmCPackComponentGroup*, cmCPackIFWPackage*> GroupPackages;
+
+private:
+ std::string RepoGen;
+ std::string BinCreator;
+ std::string FrameworkVersion;
+ std::string ExecutableSuffix;
+
+ bool OnlineOnly;
+ bool ResolveDuplicateNames;
+ std::vector<std::string> PkgsDirsVector;
+};
+
+#endif
diff --git a/Source/CPack/IFW/cmCPackIFWInstaller.cxx b/Source/CPack/IFW/cmCPackIFWInstaller.cxx
new file mode 100644
index 0000000..d8bafee
--- /dev/null
+++ b/Source/CPack/IFW/cmCPackIFWInstaller.cxx
@@ -0,0 +1,546 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmCPackIFWInstaller.h"
+
+#include <cmConfigure.h>
+#include <sstream>
+#include <stddef.h>
+#include <utility>
+
+#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"
+
+#ifdef cmCPackLogger
+#undef cmCPackLogger
+#endif
+#define cmCPackLogger(logType, msg) \
+ do { \
+ std::ostringstream cmCPackLog_msg; \
+ cmCPackLog_msg << msg; \
+ if (Generator) { \
+ Generator->Logger->Log(logType, __FILE__, __LINE__, \
+ cmCPackLog_msg.str().c_str()); \
+ } \
+ } while (false)
+
+cmCPackIFWInstaller::cmCPackIFWInstaller()
+ : Generator(CM_NULLPTR)
+{
+}
+
+const char* cmCPackIFWInstaller::GetOption(const std::string& op) const
+{
+ return Generator ? Generator->GetOption(op) : CM_NULLPTR;
+}
+
+bool cmCPackIFWInstaller::IsOn(const std::string& op) const
+{
+ return Generator ? Generator->IsOn(op) : false;
+}
+
+bool cmCPackIFWInstaller::IsVersionLess(const char* version)
+{
+ return Generator ? Generator->IsVersionLess(version) : false;
+}
+
+bool cmCPackIFWInstaller::IsVersionGreater(const char* version)
+{
+ return Generator ? Generator->IsVersionGreater(version) : false;
+}
+
+bool cmCPackIFWInstaller::IsVersionEqual(const char* version)
+{
+ return Generator ? Generator->IsVersionEqual(version) : false;
+}
+
+void cmCPackIFWInstaller::printSkippedOptionWarning(
+ const std::string& optionName, const std::string& optionValue)
+{
+ cmCPackLogger(
+ cmCPackLog::LOG_WARNING, "Option "
+ << optionName << " is set to \"" << optionValue
+ << "\" but will be skipped because the specified file does not exist."
+ << std::endl);
+}
+
+void cmCPackIFWInstaller::ConfigureFromOptions()
+{
+ // Name;
+ if (const char* optIFW_PACKAGE_NAME =
+ this->GetOption("CPACK_IFW_PACKAGE_NAME")) {
+ Name = optIFW_PACKAGE_NAME;
+ } else if (const char* optPACKAGE_NAME =
+ this->GetOption("CPACK_PACKAGE_NAME")) {
+ Name = optPACKAGE_NAME;
+ } else {
+ Name = "Your package";
+ }
+
+ // Title;
+ if (const char* optIFW_PACKAGE_TITLE =
+ GetOption("CPACK_IFW_PACKAGE_TITLE")) {
+ Title = optIFW_PACKAGE_TITLE;
+ } else if (const char* optPACKAGE_DESCRIPTION_SUMMARY =
+ GetOption("CPACK_PACKAGE_DESCRIPTION_SUMMARY")) {
+ Title = optPACKAGE_DESCRIPTION_SUMMARY;
+ } else {
+ Title = "Your package description";
+ }
+
+ // Version;
+ if (const char* option = GetOption("CPACK_PACKAGE_VERSION")) {
+ Version = option;
+ } else {
+ Version = "1.0.0";
+ }
+
+ // Publisher
+ if (const char* optIFW_PACKAGE_PUBLISHER =
+ GetOption("CPACK_IFW_PACKAGE_PUBLISHER")) {
+ Publisher = optIFW_PACKAGE_PUBLISHER;
+ } else if (const char* optPACKAGE_VENDOR =
+ GetOption("CPACK_PACKAGE_VENDOR")) {
+ Publisher = optPACKAGE_VENDOR;
+ }
+
+ // ProductUrl
+ if (const char* option = GetOption("CPACK_IFW_PRODUCT_URL")) {
+ ProductUrl = option;
+ }
+
+ // ApplicationIcon
+ if (const char* option = GetOption("CPACK_IFW_PACKAGE_ICON")) {
+ if (cmSystemTools::FileExists(option)) {
+ InstallerApplicationIcon = option;
+ } else {
+ printSkippedOptionWarning("CPACK_IFW_PACKAGE_ICON", option);
+ }
+ }
+
+ // WindowIcon
+ if (const char* option = GetOption("CPACK_IFW_PACKAGE_WINDOW_ICON")) {
+ if (cmSystemTools::FileExists(option)) {
+ InstallerWindowIcon = option;
+ } else {
+ printSkippedOptionWarning("CPACK_IFW_PACKAGE_WINDOW_ICON", option);
+ }
+ }
+
+ // Logo
+ if (const char* option = GetOption("CPACK_IFW_PACKAGE_LOGO")) {
+ if (cmSystemTools::FileExists(option)) {
+ Logo = option;
+ } else {
+ printSkippedOptionWarning("CPACK_IFW_PACKAGE_LOGO", option);
+ }
+ }
+
+ // Watermark
+ if (const char* option = GetOption("CPACK_IFW_PACKAGE_WATERMARK")) {
+ if (cmSystemTools::FileExists(option)) {
+ Watermark = option;
+ } else {
+ printSkippedOptionWarning("CPACK_IFW_PACKAGE_WATERMARK", option);
+ }
+ }
+
+ // Banner
+ if (const char* option = GetOption("CPACK_IFW_PACKAGE_BANNER")) {
+ if (cmSystemTools::FileExists(option)) {
+ Banner = option;
+ } else {
+ printSkippedOptionWarning("CPACK_IFW_PACKAGE_BANNER", option);
+ }
+ }
+
+ // Background
+ if (const char* option = GetOption("CPACK_IFW_PACKAGE_BACKGROUND")) {
+ if (cmSystemTools::FileExists(option)) {
+ Background = option;
+ } else {
+ printSkippedOptionWarning("CPACK_IFW_PACKAGE_BACKGROUND", option);
+ }
+ }
+
+ // WizardStyle
+ if (const char* option = GetOption("CPACK_IFW_PACKAGE_WIZARD_STYLE")) {
+ if (WizardStyle.compare("Modern") == 0 &&
+ WizardStyle.compare("Aero") == 0 && WizardStyle.compare("Mac") == 0 &&
+ WizardStyle.compare("Classic") == 0) {
+ cmCPackLogger(
+ cmCPackLog::LOG_WARNING,
+ "Option CPACK_IFW_PACKAGE_WIZARD_STYLE has unknown value \""
+ << option << "\". Expected values are: Modern, Aero, Mac, Classic."
+ << std::endl);
+ }
+
+ WizardStyle = option;
+ }
+
+ // WizardDefaultWidth
+ if (const char* option =
+ GetOption("CPACK_IFW_PACKAGE_WIZARD_DEFAULT_WIDTH")) {
+ WizardDefaultWidth = option;
+ }
+
+ // WizardDefaultHeight
+ if (const char* option =
+ GetOption("CPACK_IFW_PACKAGE_WIZARD_DEFAULT_HEIGHT")) {
+ WizardDefaultHeight = option;
+ }
+
+ // TitleColor
+ if (const char* option = GetOption("CPACK_IFW_PACKAGE_TITLE_COLOR")) {
+ TitleColor = option;
+ }
+
+ // Start menu
+ if (const char* optIFW_START_MENU_DIR =
+ this->GetOption("CPACK_IFW_PACKAGE_START_MENU_DIRECTORY")) {
+ StartMenuDir = optIFW_START_MENU_DIR;
+ } else {
+ StartMenuDir = Name;
+ }
+
+ // Default target directory for installation
+ if (const char* optIFW_TARGET_DIRECTORY =
+ GetOption("CPACK_IFW_TARGET_DIRECTORY")) {
+ TargetDir = optIFW_TARGET_DIRECTORY;
+ } else if (const char* optPACKAGE_INSTALL_DIRECTORY =
+ GetOption("CPACK_PACKAGE_INSTALL_DIRECTORY")) {
+ TargetDir = "@ApplicationsDir@/";
+ TargetDir += optPACKAGE_INSTALL_DIRECTORY;
+ } else {
+ TargetDir = "@RootDir@/usr/local";
+ }
+
+ // Default target directory for installation with administrator rights
+ if (const char* option = GetOption("CPACK_IFW_ADMIN_TARGET_DIRECTORY")) {
+ AdminTargetDir = option;
+ }
+
+ // Maintenance tool
+ if (const char* optIFW_MAINTENANCE_TOOL =
+ this->GetOption("CPACK_IFW_PACKAGE_MAINTENANCE_TOOL_NAME")) {
+ MaintenanceToolName = optIFW_MAINTENANCE_TOOL;
+ }
+
+ // Maintenance tool ini file
+ if (const char* optIFW_MAINTENANCE_TOOL_INI =
+ this->GetOption("CPACK_IFW_PACKAGE_MAINTENANCE_TOOL_INI_FILE")) {
+ MaintenanceToolIniFile = optIFW_MAINTENANCE_TOOL_INI;
+ }
+
+ // Allow non-ASCII characters
+ if (this->GetOption("CPACK_IFW_PACKAGE_ALLOW_NON_ASCII_CHARACTERS")) {
+ if (IsOn("CPACK_IFW_PACKAGE_ALLOW_NON_ASCII_CHARACTERS")) {
+ AllowNonAsciiCharacters = "true";
+ } else {
+ AllowNonAsciiCharacters = "false";
+ }
+ }
+
+ // Space in path
+ if (this->GetOption("CPACK_IFW_PACKAGE_ALLOW_SPACE_IN_PATH")) {
+ if (IsOn("CPACK_IFW_PACKAGE_ALLOW_SPACE_IN_PATH")) {
+ AllowSpaceInPath = "true";
+ } else {
+ AllowSpaceInPath = "false";
+ }
+ }
+
+ // Control script
+ if (const char* optIFW_CONTROL_SCRIPT =
+ this->GetOption("CPACK_IFW_PACKAGE_CONTROL_SCRIPT")) {
+ ControlScript = optIFW_CONTROL_SCRIPT;
+ }
+
+ // 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";
+ 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
+ if (Directory.empty() && Generator) {
+ Directory = Generator->toplevel;
+ }
+
+ // Output stream
+ cmGeneratedFileStream fout((Directory + "/config/config.xml").data());
+ cmXMLWriter xout(fout);
+
+ xout.StartDocument();
+
+ WriteGeneratedByToStrim(xout);
+
+ xout.StartElement("Installer");
+
+ xout.Element("Name", Name);
+ xout.Element("Version", Version);
+ xout.Element("Title", Title);
+
+ if (!Publisher.empty()) {
+ xout.Element("Publisher", Publisher);
+ }
+
+ if (!ProductUrl.empty()) {
+ xout.Element("ProductUrl", ProductUrl);
+ }
+
+ // ApplicationIcon
+ if (!InstallerApplicationIcon.empty()) {
+ std::string name =
+ cmSystemTools::GetFilenameName(InstallerApplicationIcon);
+ std::string path = Directory + "/config/" + name;
+ name = cmSystemTools::GetFilenameWithoutExtension(name);
+ cmsys::SystemTools::CopyFileIfDifferent(InstallerApplicationIcon.data(),
+ path.data());
+ xout.Element("InstallerApplicationIcon", name);
+ }
+
+ // WindowIcon
+ if (!InstallerWindowIcon.empty()) {
+ std::string name = cmSystemTools::GetFilenameName(InstallerWindowIcon);
+ std::string path = Directory + "/config/" + name;
+ cmsys::SystemTools::CopyFileIfDifferent(InstallerWindowIcon.data(),
+ path.data());
+ xout.Element("InstallerWindowIcon", name);
+ }
+
+ // Logo
+ if (!Logo.empty()) {
+ std::string name = cmSystemTools::GetFilenameName(Logo);
+ std::string path = Directory + "/config/" + name;
+ cmsys::SystemTools::CopyFileIfDifferent(Logo.data(), path.data());
+ xout.Element("Logo", name);
+ }
+
+ // Banner
+ if (!Banner.empty()) {
+ std::string name = cmSystemTools::GetFilenameName(Banner);
+ std::string path = Directory + "/config/" + name;
+ cmsys::SystemTools::CopyFileIfDifferent(Banner.data(), path.data());
+ xout.Element("Banner", name);
+ }
+
+ // Watermark
+ if (!Watermark.empty()) {
+ std::string name = cmSystemTools::GetFilenameName(Watermark);
+ std::string path = Directory + "/config/" + name;
+ cmsys::SystemTools::CopyFileIfDifferent(Watermark.data(), path.data());
+ xout.Element("Watermark", name);
+ }
+
+ // Background
+ if (!Background.empty()) {
+ std::string name = cmSystemTools::GetFilenameName(Background);
+ std::string path = Directory + "/config/" + name;
+ cmsys::SystemTools::CopyFileIfDifferent(Background.data(), path.data());
+ xout.Element("Background", name);
+ }
+
+ // WizardStyle
+ if (!WizardStyle.empty()) {
+ xout.Element("WizardStyle", WizardStyle);
+ }
+
+ // WizardDefaultWidth
+ if (!WizardDefaultWidth.empty()) {
+ xout.Element("WizardDefaultWidth", WizardDefaultWidth);
+ }
+
+ // WizardDefaultHeight
+ if (!WizardDefaultHeight.empty()) {
+ xout.Element("WizardDefaultHeight", WizardDefaultHeight);
+ }
+
+ // TitleColor
+ if (!TitleColor.empty()) {
+ xout.Element("TitleColor", TitleColor);
+ }
+
+ // Start menu
+ if (!IsVersionLess("2.0")) {
+ xout.Element("StartMenuDir", StartMenuDir);
+ }
+
+ // Target dir
+ if (!TargetDir.empty()) {
+ xout.Element("TargetDir", TargetDir);
+ }
+
+ // Admin target dir
+ if (!AdminTargetDir.empty()) {
+ xout.Element("AdminTargetDir", AdminTargetDir);
+ }
+
+ // Remote repositories
+ if (!RemoteRepositories.empty()) {
+ xout.StartElement("RemoteRepositories");
+ for (RepositoriesVector::iterator rit = RemoteRepositories.begin();
+ rit != RemoteRepositories.end(); ++rit) {
+ (*rit)->WriteRepositoryConfig(xout);
+ }
+ xout.EndElement();
+ }
+
+ // Maintenance tool
+ if (!IsVersionLess("2.0") && !MaintenanceToolName.empty()) {
+ xout.Element("MaintenanceToolName", MaintenanceToolName);
+ }
+
+ // Maintenance tool ini file
+ if (!IsVersionLess("2.0") && !MaintenanceToolIniFile.empty()) {
+ xout.Element("MaintenanceToolIniFile", MaintenanceToolIniFile);
+ }
+
+ // Different allows
+ if (IsVersionLess("2.0")) {
+ // CPack IFW default policy
+ xout.Comment("CPack IFW default policy for QtIFW less 2.0");
+ xout.Element("AllowNonAsciiCharacters", "true");
+ xout.Element("AllowSpaceInPath", "true");
+ } else {
+ if (!AllowNonAsciiCharacters.empty()) {
+ xout.Element("AllowNonAsciiCharacters", AllowNonAsciiCharacters);
+ }
+ if (!AllowSpaceInPath.empty()) {
+ xout.Element("AllowSpaceInPath", AllowSpaceInPath);
+ }
+ }
+
+ // Control script (copy to config dir)
+ if (!IsVersionLess("2.0") && !ControlScript.empty()) {
+ std::string name = cmSystemTools::GetFilenameName(ControlScript);
+ std::string path = Directory + "/config/" + name;
+ cmsys::SystemTools::CopyFileIfDifferent(ControlScript.data(), path.data());
+ xout.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();
+}
+
+void cmCPackIFWInstaller::GeneratePackageFiles()
+{
+ if (Packages.empty() || Generator->IsOnePackage()) {
+ // Generate default package
+ cmCPackIFWPackage package;
+ package.Generator = Generator;
+ package.Installer = this;
+ // Check package group
+ if (const char* option = GetOption("CPACK_IFW_PACKAGE_GROUP")) {
+ package.ConfigureFromGroup(option);
+ std::string forcedOption = "CPACK_IFW_COMPONENT_GROUP_" +
+ cmsys::SystemTools::UpperCase(option) + "_FORCED_INSTALLATION";
+ if (!GetOption(forcedOption)) {
+ package.ForcedInstallation = "true";
+ }
+ } else {
+ package.ConfigureFromOptions();
+ }
+ package.GeneratePackageFile();
+ return;
+ }
+
+ // Generate packages meta information
+ for (PackagesMap::iterator pit = Packages.begin(); pit != Packages.end();
+ ++pit) {
+ cmCPackIFWPackage* package = pit->second;
+ package->GeneratePackageFile();
+ }
+}
+
+void cmCPackIFWInstaller::WriteGeneratedByToStrim(cmXMLWriter& xout)
+{
+ if (Generator) {
+ Generator->WriteGeneratedByToStrim(xout);
+ }
+}
diff --git a/Source/CPack/IFW/cmCPackIFWInstaller.h b/Source/CPack/IFW/cmCPackIFWInstaller.h
new file mode 100644
index 0000000..4ec3e70
--- /dev/null
+++ b/Source/CPack/IFW/cmCPackIFWInstaller.h
@@ -0,0 +1,140 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmCPackIFWInstaller_h
+#define cmCPackIFWInstaller_h
+
+#include <cmConfigure.h> // IWYU pragma: keep
+
+#include <map>
+#include <string>
+#include <vector>
+
+class cmCPackIFWGenerator;
+class cmCPackIFWPackage;
+class cmCPackIFWRepository;
+class cmXMLWriter;
+
+/** \class cmCPackIFWInstaller
+ * \brief A binary installer to be created CPack IFW generator
+ */
+class cmCPackIFWInstaller
+{
+public:
+ // Types
+
+ typedef std::map<std::string, cmCPackIFWPackage*> PackagesMap;
+ typedef std::vector<cmCPackIFWRepository*> RepositoriesVector;
+
+public:
+ // Constructor
+
+ /**
+ * Construct installer
+ */
+ cmCPackIFWInstaller();
+
+public:
+ // Configuration
+
+ /// Name of the product being installed
+ std::string Name;
+
+ /// Version number of the product being installed
+ std::string Version;
+
+ /// Name of the installer as displayed on the title bar
+ std::string Title;
+
+ /// Publisher of the software (as shown in the Windows Control Panel)
+ std::string Publisher;
+
+ /// URL to a page that contains product information on your web site
+ std::string ProductUrl;
+
+ /// Filename for a custom installer icon
+ std::string InstallerApplicationIcon;
+
+ /// Filename for a custom window icon
+ std::string InstallerWindowIcon;
+
+ /// Filename for a logo
+ std::string Logo;
+
+ /// Filename for a watermark
+ std::string Watermark;
+
+ /// Filename for a banner
+ std::string Banner;
+
+ /// Filename for a background
+ std::string Background;
+
+ /// Wizard style name
+ std::string WizardStyle;
+
+ /// Wizard width
+ std::string WizardDefaultWidth;
+
+ /// Wizard height
+ std::string WizardDefaultHeight;
+
+ /// Title color
+ std::string TitleColor;
+
+ /// Name of the default program group in the Windows Start menu
+ std::string StartMenuDir;
+
+ /// Default target directory for installation
+ std::string TargetDir;
+
+ /// Default target directory for installation with administrator rights
+ std::string AdminTargetDir;
+
+ /// Filename of the generated maintenance tool
+ std::string MaintenanceToolName;
+
+ /// Filename for the configuration of the generated maintenance tool
+ std::string MaintenanceToolIniFile;
+
+ /// Set to true if the installation path can contain non-ASCII characters
+ std::string AllowNonAsciiCharacters;
+
+ /// Set to false if the installation path cannot contain space characters
+ std::string AllowSpaceInPath;
+
+ /// Filename for a custom installer control script
+ std::string ControlScript;
+
+ /// List of resources to include in the installer binary
+ std::vector<std::string> Resources;
+
+public:
+ // Internal implementation
+
+ const char* GetOption(const std::string& op) const;
+ bool IsOn(const std::string& op) const;
+
+ bool IsVersionLess(const char* version);
+ bool IsVersionGreater(const char* version);
+ bool IsVersionEqual(const char* version);
+
+ void ConfigureFromOptions();
+
+ void GenerateInstallerFile();
+
+ void GeneratePackageFiles();
+
+ cmCPackIFWGenerator* Generator;
+ PackagesMap Packages;
+ RepositoriesVector RemoteRepositories;
+ std::string Directory;
+
+protected:
+ void WriteGeneratedByToStrim(cmXMLWriter& xout);
+
+private:
+ void printSkippedOptionWarning(const std::string& optionName,
+ const std::string& optionValue);
+};
+
+#endif // cmCPackIFWInstaller_h
diff --git a/Source/CPack/IFW/cmCPackIFWPackage.cxx b/Source/CPack/IFW/cmCPackIFWPackage.cxx
new file mode 100644
index 0000000..e23b1b9
--- /dev/null
+++ b/Source/CPack/IFW/cmCPackIFWPackage.cxx
@@ -0,0 +1,725 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmCPackIFWPackage.h"
+
+#include "CPack/cmCPackComponentGroup.h"
+#include "CPack/cmCPackGenerator.h"
+#include "CPack/cmCPackLog.h"
+#include "cmCPackIFWGenerator.h"
+#include "cmCPackIFWInstaller.h"
+#include "cmGeneratedFileStream.h"
+#include "cmSystemTools.h"
+#include "cmTimestamp.h"
+#include "cmXMLWriter.h"
+
+#include <cmConfigure.h>
+#include <map>
+#include <sstream>
+#include <stddef.h>
+
+//----------------------------------------------------------------- Logger ---
+#ifdef cmCPackLogger
+#undef cmCPackLogger
+#endif
+#define cmCPackLogger(logType, msg) \
+ do { \
+ std::ostringstream cmCPackLog_msg; \
+ cmCPackLog_msg << msg; \
+ if (Generator) { \
+ Generator->Logger->Log(logType, __FILE__, __LINE__, \
+ cmCPackLog_msg.str().c_str()); \
+ } \
+ } while (false)
+
+//---------------------------------------------------------- CompareStruct ---
+cmCPackIFWPackage::CompareStruct::CompareStruct()
+ : Type(CompareNone)
+{
+}
+
+//------------------------------------------------------- DependenceStruct ---
+cmCPackIFWPackage::DependenceStruct::DependenceStruct()
+{
+}
+
+cmCPackIFWPackage::DependenceStruct::DependenceStruct(
+ const std::string& dependence)
+{
+ // Search compare section
+ size_t pos = std::string::npos;
+ if ((pos = dependence.find("<=")) != std::string::npos) {
+ Compare.Type = CompareLessOrEqual;
+ Compare.Value = dependence.substr(pos + 2);
+ } else if ((pos = dependence.find(">=")) != std::string::npos) {
+ Compare.Type = CompareGreaterOrEqual;
+ Compare.Value = dependence.substr(pos + 2);
+ } else if ((pos = dependence.find('<')) != std::string::npos) {
+ Compare.Type = CompareLess;
+ Compare.Value = dependence.substr(pos + 1);
+ } else if ((pos = dependence.find('=')) != std::string::npos) {
+ Compare.Type = CompareEqual;
+ Compare.Value = dependence.substr(pos + 1);
+ } else if ((pos = dependence.find('>')) != std::string::npos) {
+ Compare.Type = CompareGreater;
+ Compare.Value = dependence.substr(pos + 1);
+ } else if ((pos = dependence.find('-')) != std::string::npos) {
+ Compare.Type = CompareNone;
+ Compare.Value = dependence.substr(pos + 1);
+ }
+ size_t dashPos = dependence.find('-');
+ if (dashPos != std::string::npos) {
+ pos = dashPos;
+ }
+ Name = pos == std::string::npos ? dependence : dependence.substr(0, pos);
+}
+
+std::string cmCPackIFWPackage::DependenceStruct::NameWithCompare() const
+{
+ if (Compare.Type == CompareNone) {
+ return Name;
+ }
+
+ std::string result = Name;
+
+ if (Compare.Type != CompareNone || !Compare.Value.empty()) {
+ result += "-";
+ }
+
+ if (Compare.Type == CompareLessOrEqual) {
+ result += "<=";
+ } else if (Compare.Type == CompareGreaterOrEqual) {
+ result += ">=";
+ } else if (Compare.Type == CompareLess) {
+ result += "<";
+ } else if (Compare.Type == CompareEqual) {
+ result += "=";
+ } else if (Compare.Type == CompareGreater) {
+ result += ">";
+ }
+
+ result += Compare.Value;
+
+ return result;
+}
+
+//------------------------------------------------------ cmCPackIFWPackage ---
+cmCPackIFWPackage::cmCPackIFWPackage()
+ : Generator(CM_NULLPTR)
+ , Installer(CM_NULLPTR)
+{
+}
+
+const char* cmCPackIFWPackage::GetOption(const std::string& op) const
+{
+ const char* option = Generator ? Generator->GetOption(op) : CM_NULLPTR;
+ return option && *option ? option : CM_NULLPTR;
+}
+
+bool cmCPackIFWPackage::IsOn(const std::string& op) const
+{
+ return Generator ? Generator->IsOn(op) : false;
+}
+
+bool cmCPackIFWPackage::IsSetToOff(const std::string& op) const
+{
+ return Generator ? Generator->IsSetToOff(op) : false;
+}
+
+bool cmCPackIFWPackage::IsSetToEmpty(const std::string& op) const
+{
+ return Generator ? Generator->IsSetToEmpty(op) : false;
+}
+
+bool cmCPackIFWPackage::IsVersionLess(const char* version)
+{
+ return Generator ? Generator->IsVersionLess(version) : false;
+}
+
+bool cmCPackIFWPackage::IsVersionGreater(const char* version)
+{
+ return Generator ? Generator->IsVersionGreater(version) : false;
+}
+
+bool cmCPackIFWPackage::IsVersionEqual(const char* version)
+{
+ return Generator ? Generator->IsVersionEqual(version) : false;
+}
+
+std::string cmCPackIFWPackage::GetComponentName(cmCPackComponent* component)
+{
+ if (!component) {
+ return "";
+ }
+ const char* option =
+ GetOption("CPACK_IFW_COMPONENT_" +
+ cmsys::SystemTools::UpperCase(component->Name) + "_NAME");
+ return option ? option : component->Name;
+}
+
+void cmCPackIFWPackage::DefaultConfiguration()
+{
+ DisplayName = "";
+ Description = "";
+ Version = "";
+ ReleaseDate = "";
+ Script = "";
+ Licenses.clear();
+ UserInterfaces.clear();
+ Translations.clear();
+ SortingPriority = "";
+ UpdateText = "";
+ Default = "";
+ Essential = "";
+ Virtual = "";
+ ForcedInstallation = "";
+ RequiresAdminRights = "";
+}
+
+// Defaul configuration (all in one package)
+int cmCPackIFWPackage::ConfigureFromOptions()
+{
+ // Restore defaul configuration
+ DefaultConfiguration();
+
+ // Name
+ Name = Generator->GetRootPackageName();
+
+ // Display name
+ if (const char* option = this->GetOption("CPACK_PACKAGE_NAME")) {
+ DisplayName = option;
+ } else {
+ DisplayName = "Your package";
+ }
+
+ // Description
+ if (const char* option =
+ this->GetOption("CPACK_PACKAGE_DESCRIPTION_SUMMARY")) {
+ Description = option;
+ } else {
+ Description = "Your package description";
+ }
+
+ // Version
+ if (const char* option = GetOption("CPACK_PACKAGE_VERSION")) {
+ Version = option;
+ } else {
+ Version = "1.0.0";
+ }
+
+ ForcedInstallation = "true";
+
+ return 1;
+}
+
+int cmCPackIFWPackage::ConfigureFromComponent(cmCPackComponent* component)
+{
+ if (!component) {
+ return 0;
+ }
+
+ // Restore defaul configuration
+ DefaultConfiguration();
+
+ std::string prefix = "CPACK_IFW_COMPONENT_" +
+ cmsys::SystemTools::UpperCase(component->Name) + "_";
+
+ // Display name
+ DisplayName = component->DisplayName;
+
+ // Description
+ Description = component->Description;
+
+ // Version
+ if (const char* optVERSION = GetOption(prefix + "VERSION")) {
+ Version = optVERSION;
+ } else if (const char* optPACKAGE_VERSION =
+ GetOption("CPACK_PACKAGE_VERSION")) {
+ Version = optPACKAGE_VERSION;
+ } else {
+ Version = "1.0.0";
+ }
+
+ // Script
+ if (const char* option = GetOption(prefix + "SCRIPT")) {
+ Script = option;
+ }
+
+ // User interfaces
+ if (const char* option = this->GetOption(prefix + "USER_INTERFACES")) {
+ UserInterfaces.clear();
+ cmSystemTools::ExpandListArgument(option, UserInterfaces);
+ }
+
+ // CMake dependencies
+ if (!component->Dependencies.empty()) {
+ std::vector<cmCPackComponent*>::iterator dit;
+ for (dit = component->Dependencies.begin();
+ dit != component->Dependencies.end(); ++dit) {
+ Dependencies.insert(Generator->ComponentPackages[*dit]);
+ }
+ }
+
+ // Licenses
+ if (const char* option = this->GetOption(prefix + "LICENSES")) {
+ Licenses.clear();
+ cmSystemTools::ExpandListArgument(option, Licenses);
+ if (Licenses.size() % 2 != 0) {
+ cmCPackLogger(
+ cmCPackLog::LOG_WARNING, prefix
+ << "LICENSES"
+ << " should contain pairs of <display_name> and <file_path>."
+ << std::endl);
+ Licenses.clear();
+ }
+ }
+
+ // Priority
+ if (const char* option = this->GetOption(prefix + "PRIORITY")) {
+ SortingPriority = option;
+ cmCPackLogger(
+ cmCPackLog::LOG_WARNING, "The \"PRIORITY\" option is set "
+ << "for component \"" << component->Name << "\", but there option is "
+ << "deprecated. Please use \"SORTING_PRIORITY\" option instead."
+ << std::endl);
+ }
+
+ // Default
+ Default = component->IsDisabledByDefault ? "false" : "true";
+
+ // Essential
+ if (this->IsOn(prefix + "ESSENTIAL")) {
+ Essential = "true";
+ }
+
+ // Virtual
+ Virtual = component->IsHidden ? "true" : "";
+
+ // ForcedInstallation
+ ForcedInstallation = component->IsRequired ? "true" : "false";
+
+ return ConfigureFromPrefix(prefix);
+}
+
+int cmCPackIFWPackage::ConfigureFromGroup(cmCPackComponentGroup* group)
+{
+ if (!group) {
+ return 0;
+ }
+
+ // Restore defaul configuration
+ DefaultConfiguration();
+
+ std::string prefix = "CPACK_IFW_COMPONENT_GROUP_" +
+ cmsys::SystemTools::UpperCase(group->Name) + "_";
+
+ DisplayName = group->DisplayName;
+ Description = group->Description;
+
+ // Version
+ if (const char* optVERSION = GetOption(prefix + "VERSION")) {
+ Version = optVERSION;
+ } else if (const char* optPACKAGE_VERSION =
+ GetOption("CPACK_PACKAGE_VERSION")) {
+ Version = optPACKAGE_VERSION;
+ } else {
+ Version = "1.0.0";
+ }
+
+ // Script
+ if (const char* option = GetOption(prefix + "SCRIPT")) {
+ Script = option;
+ }
+
+ // User interfaces
+ if (const char* option = this->GetOption(prefix + "USER_INTERFACES")) {
+ UserInterfaces.clear();
+ cmSystemTools::ExpandListArgument(option, UserInterfaces);
+ }
+
+ // Licenses
+ if (const char* option = this->GetOption(prefix + "LICENSES")) {
+ Licenses.clear();
+ cmSystemTools::ExpandListArgument(option, Licenses);
+ if (Licenses.size() % 2 != 0) {
+ cmCPackLogger(
+ cmCPackLog::LOG_WARNING, prefix
+ << "LICENSES"
+ << " should contain pairs of <display_name> and <file_path>."
+ << std::endl);
+ Licenses.clear();
+ }
+ }
+
+ // Priority
+ if (const char* option = this->GetOption(prefix + "PRIORITY")) {
+ SortingPriority = option;
+ cmCPackLogger(
+ cmCPackLog::LOG_WARNING, "The \"PRIORITY\" option is set "
+ << "for component group \"" << group->Name
+ << "\", but there option is "
+ << "deprecated. Please use \"SORTING_PRIORITY\" option instead."
+ << std::endl);
+ }
+
+ return ConfigureFromPrefix(prefix);
+}
+
+int cmCPackIFWPackage::ConfigureFromGroup(const std::string& groupName)
+{
+ // Group configuration
+
+ cmCPackComponentGroup group;
+ std::string prefix =
+ "CPACK_COMPONENT_GROUP_" + cmsys::SystemTools::UpperCase(groupName) + "_";
+
+ if (const char* option = GetOption(prefix + "DISPLAY_NAME")) {
+ group.DisplayName = option;
+ } else {
+ group.DisplayName = group.Name;
+ }
+
+ if (const char* option = GetOption(prefix + "DESCRIPTION")) {
+ group.Description = option;
+ }
+ group.IsBold = IsOn(prefix + "BOLD_TITLE");
+ group.IsExpandedByDefault = IsOn(prefix + "EXPANDED");
+
+ // Package configuration
+
+ group.Name = groupName;
+
+ if (Generator) {
+ Name = Generator->GetGroupPackageName(&group);
+ } else {
+ Name = group.Name;
+ }
+
+ return ConfigureFromGroup(&group);
+}
+
+// Common options for components and groups
+int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix)
+{
+ // Temporary variable for full option name
+ std::string option;
+
+ // Display name
+ option = prefix + "DISPLAY_NAME";
+ if (IsSetToEmpty(option)) {
+ DisplayName.clear();
+ } else if (const char* value = GetOption(option)) {
+ DisplayName = value;
+ }
+
+ // Description
+ option = prefix + "DESCRIPTION";
+ if (IsSetToEmpty(option)) {
+ Description.clear();
+ } else if (const char* value = GetOption(option)) {
+ Description = value;
+ }
+
+ // Release date
+ option = prefix + "RELEASE_DATE";
+ if (IsSetToEmpty(option)) {
+ ReleaseDate.clear();
+ } else if (const char* value = GetOption(option)) {
+ ReleaseDate = value;
+ }
+
+ // Sorting priority
+ option = prefix + "SORTING_PRIORITY";
+ if (IsSetToEmpty(option)) {
+ SortingPriority.clear();
+ } else if (const char* value = GetOption(option)) {
+ SortingPriority = value;
+ }
+
+ // Update text
+ option = prefix + "UPDATE_TEXT";
+ if (IsSetToEmpty(option)) {
+ UpdateText.clear();
+ } else if (const char* value = GetOption(option)) {
+ UpdateText = value;
+ }
+
+ // Translations
+ option = prefix + "TRANSLATIONS";
+ if (IsSetToEmpty(option)) {
+ Translations.clear();
+ } else if (const char* value = this->GetOption(option)) {
+ Translations.clear();
+ cmSystemTools::ExpandListArgument(value, Translations);
+ }
+
+ // QtIFW dependencies
+ std::vector<std::string> deps;
+ option = prefix + "DEPENDS";
+ if (const char* value = this->GetOption(option)) {
+ cmSystemTools::ExpandListArgument(value, deps);
+ }
+ option = prefix + "DEPENDENCIES";
+ if (const char* value = this->GetOption(option)) {
+ cmSystemTools::ExpandListArgument(value, deps);
+ }
+ for (std::vector<std::string>::iterator dit = deps.begin();
+ dit != deps.end(); ++dit) {
+ DependenceStruct dep(*dit);
+ if (Generator->Packages.count(dep.Name)) {
+ cmCPackIFWPackage& depPkg = Generator->Packages[dep.Name];
+ dep.Name = depPkg.Name;
+ }
+ bool hasDep = Generator->DependentPackages.count(dep.Name) > 0;
+ DependenceStruct& depRef = Generator->DependentPackages[dep.Name];
+ if (!hasDep) {
+ depRef = dep;
+ }
+ AlienDependencies.insert(&depRef);
+ }
+
+ // Automatic dependency on
+ option = prefix + "AUTO_DEPEND_ON";
+ if (IsSetToEmpty(option)) {
+ AlienAutoDependOn.clear();
+ } else if (const char* value = this->GetOption(option)) {
+ std::vector<std::string> depsOn;
+ cmSystemTools::ExpandListArgument(value, depsOn);
+ for (std::vector<std::string>::iterator dit = depsOn.begin();
+ dit != depsOn.end(); ++dit) {
+ DependenceStruct dep(*dit);
+ if (Generator->Packages.count(dep.Name)) {
+ cmCPackIFWPackage& depPkg = Generator->Packages[dep.Name];
+ dep.Name = depPkg.Name;
+ }
+ bool hasDep = Generator->DependentPackages.count(dep.Name) > 0;
+ DependenceStruct& depRef = Generator->DependentPackages[dep.Name];
+ if (!hasDep) {
+ depRef = dep;
+ }
+ AlienAutoDependOn.insert(&depRef);
+ }
+ }
+
+ // Visibility
+ option = prefix + "VIRTUAL";
+ if (IsSetToEmpty(option)) {
+ Virtual.clear();
+ } else if (IsOn(option)) {
+ Virtual = "true";
+ }
+
+ // Default selection
+ option = prefix + "DEFAULT";
+ if (IsSetToEmpty(option)) {
+ Default.clear();
+ } else if (const char* value = GetOption(option)) {
+ std::string lowerValue = cmsys::SystemTools::LowerCase(value);
+ if (lowerValue.compare("true") == 0) {
+ Default = "true";
+ } else if (lowerValue.compare("false") == 0) {
+ Default = "false";
+ } else if (lowerValue.compare("script") == 0) {
+ Default = "script";
+ } else {
+ Default = value;
+ }
+ }
+
+ // Forsed installation
+ option = prefix + "FORCED_INSTALLATION";
+ if (IsSetToEmpty(option)) {
+ ForcedInstallation.clear();
+ } else if (IsOn(option)) {
+ ForcedInstallation = "true";
+ } else if (IsSetToOff(option)) {
+ ForcedInstallation = "false";
+ }
+
+ // Requires admin rights
+ option = prefix + "REQUIRES_ADMIN_RIGHTS";
+ if (IsSetToEmpty(option)) {
+ RequiresAdminRights.clear();
+ } else if (IsOn(option)) {
+ RequiresAdminRights = "true";
+ } else if (IsSetToOff(option)) {
+ RequiresAdminRights = "false";
+ }
+
+ return 1;
+}
+
+void cmCPackIFWPackage::GeneratePackageFile()
+{
+ // Lazy directory initialization
+ if (Directory.empty()) {
+ if (Installer) {
+ Directory = Installer->Directory + "/packages/" + Name;
+ } else if (Generator) {
+ Directory = Generator->toplevel + "/packages/" + Name;
+ }
+ }
+
+ // Output stream
+ cmGeneratedFileStream fout((Directory + "/meta/package.xml").data());
+ cmXMLWriter xout(fout);
+
+ xout.StartDocument();
+
+ WriteGeneratedByToStrim(xout);
+
+ xout.StartElement("Package");
+
+ xout.Element("DisplayName", DisplayName);
+ xout.Element("Description", Description);
+
+ // Update text
+ if (!UpdateText.empty()) {
+ xout.Element("UpdateText", UpdateText);
+ }
+
+ xout.Element("Name", Name);
+ xout.Element("Version", Version);
+
+ if (!ReleaseDate.empty()) {
+ xout.Element("ReleaseDate", ReleaseDate);
+ } else {
+ xout.Element("ReleaseDate", cmTimestamp().CurrentTime("%Y-%m-%d", true));
+ }
+
+ // Script (copy to meta dir)
+ if (!Script.empty()) {
+ std::string name = cmSystemTools::GetFilenameName(Script);
+ std::string path = Directory + "/meta/" + name;
+ cmsys::SystemTools::CopyFileIfDifferent(Script.data(), path.data());
+ xout.Element("Script", name);
+ }
+
+ // User Interfaces (copy to meta dir)
+ std::vector<std::string> userInterfaces = UserInterfaces;
+ for (size_t i = 0; i < userInterfaces.size(); i++) {
+ std::string name = cmSystemTools::GetFilenameName(userInterfaces[i]);
+ std::string path = Directory + "/meta/" + name;
+ cmsys::SystemTools::CopyFileIfDifferent(userInterfaces[i].data(),
+ path.data());
+ userInterfaces[i] = name;
+ }
+ if (!userInterfaces.empty()) {
+ xout.StartElement("UserInterfaces");
+ for (size_t i = 0; i < userInterfaces.size(); i++) {
+ xout.Element("UserInterface", userInterfaces[i]);
+ }
+ xout.EndElement();
+ }
+
+ // Translations (copy to meta dir)
+ std::vector<std::string> translations = Translations;
+ for (size_t i = 0; i < translations.size(); i++) {
+ std::string name = cmSystemTools::GetFilenameName(translations[i]);
+ std::string path = Directory + "/meta/" + name;
+ cmsys::SystemTools::CopyFileIfDifferent(translations[i].data(),
+ path.data());
+ translations[i] = name;
+ }
+ if (!translations.empty()) {
+ xout.StartElement("Translations");
+ for (size_t i = 0; i < translations.size(); i++) {
+ xout.Element("Translation", translations[i]);
+ }
+ xout.EndElement();
+ }
+
+ // Dependencies
+ std::set<DependenceStruct> compDepSet;
+ for (std::set<DependenceStruct*>::iterator ait = AlienDependencies.begin();
+ ait != AlienDependencies.end(); ++ait) {
+ compDepSet.insert(*(*ait));
+ }
+ for (std::set<cmCPackIFWPackage*>::iterator it = Dependencies.begin();
+ it != Dependencies.end(); ++it) {
+ compDepSet.insert(DependenceStruct((*it)->Name));
+ }
+ // Write dependencies
+ if (!compDepSet.empty()) {
+ std::ostringstream dependencies;
+ std::set<DependenceStruct>::iterator it = compDepSet.begin();
+ dependencies << it->NameWithCompare();
+ ++it;
+ while (it != compDepSet.end()) {
+ dependencies << "," << it->NameWithCompare();
+ ++it;
+ }
+ xout.Element("Dependencies", dependencies.str());
+ }
+
+ // Automatic dependency on
+ std::set<DependenceStruct> compAutoDepSet;
+ for (std::set<DependenceStruct*>::iterator ait = AlienAutoDependOn.begin();
+ ait != AlienAutoDependOn.end(); ++ait) {
+ compAutoDepSet.insert(*(*ait));
+ }
+ // Write automatic dependency on
+ if (!compAutoDepSet.empty()) {
+ std::ostringstream dependencies;
+ std::set<DependenceStruct>::iterator it = compAutoDepSet.begin();
+ dependencies << it->NameWithCompare();
+ ++it;
+ while (it != compAutoDepSet.end()) {
+ dependencies << "," << it->NameWithCompare();
+ ++it;
+ }
+ xout.Element("AutoDependOn", dependencies.str());
+ }
+
+ // Licenses (copy to meta dir)
+ std::vector<std::string> licenses = Licenses;
+ for (size_t i = 1; i < licenses.size(); i += 2) {
+ std::string name = cmSystemTools::GetFilenameName(licenses[i]);
+ std::string path = Directory + "/meta/" + name;
+ cmsys::SystemTools::CopyFileIfDifferent(licenses[i].data(), path.data());
+ licenses[i] = name;
+ }
+ if (!licenses.empty()) {
+ xout.StartElement("Licenses");
+ for (size_t i = 0; i < licenses.size(); i += 2) {
+ xout.StartElement("License");
+ xout.Attribute("name", licenses[i]);
+ xout.Attribute("file", licenses[i + 1]);
+ xout.EndElement();
+ }
+ xout.EndElement();
+ }
+
+ if (!ForcedInstallation.empty()) {
+ xout.Element("ForcedInstallation", ForcedInstallation);
+ }
+
+ if (!RequiresAdminRights.empty()) {
+ xout.Element("RequiresAdminRights", RequiresAdminRights);
+ }
+
+ if (!Virtual.empty()) {
+ xout.Element("Virtual", Virtual);
+ } else if (!Default.empty()) {
+ xout.Element("Default", Default);
+ }
+
+ // Essential
+ if (!Essential.empty()) {
+ xout.Element("Essential", Essential);
+ }
+
+ // Priority
+ if (!SortingPriority.empty()) {
+ xout.Element("SortingPriority", SortingPriority);
+ }
+
+ xout.EndElement();
+ xout.EndDocument();
+}
+
+void cmCPackIFWPackage::WriteGeneratedByToStrim(cmXMLWriter& xout)
+{
+ if (Generator) {
+ Generator->WriteGeneratedByToStrim(xout);
+ }
+}
diff --git a/Source/CPack/IFW/cmCPackIFWPackage.h b/Source/CPack/IFW/cmCPackIFWPackage.h
new file mode 100644
index 0000000..bd1d6c5
--- /dev/null
+++ b/Source/CPack/IFW/cmCPackIFWPackage.h
@@ -0,0 +1,160 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmCPackIFWPackage_h
+#define cmCPackIFWPackage_h
+
+#include <cmConfigure.h> // IWYU pragma: keep
+
+#include <set>
+#include <string>
+#include <vector>
+
+class cmCPackComponent;
+class cmCPackComponentGroup;
+class cmCPackIFWGenerator;
+class cmCPackIFWInstaller;
+class cmXMLWriter;
+
+/** \class cmCPackIFWPackage
+ * \brief A single component to be installed by CPack IFW generator
+ */
+class cmCPackIFWPackage
+{
+public:
+ // Types
+
+ enum CompareTypes
+ {
+ CompareNone = 0x0,
+ CompareEqual = 0x1,
+ CompareLess = 0x2,
+ CompareLessOrEqual = 0x3,
+ CompareGreater = 0x4,
+ CompareGreaterOrEqual = 0x5
+ };
+
+ struct CompareStruct
+ {
+ CompareStruct();
+
+ unsigned int Type;
+ std::string Value;
+ };
+
+ struct DependenceStruct
+ {
+ DependenceStruct();
+ DependenceStruct(const std::string& dependence);
+
+ std::string Name;
+ CompareStruct Compare;
+
+ std::string NameWithCompare() const;
+
+ bool operator<(const DependenceStruct& other) const
+ {
+ return Name < other.Name;
+ }
+ };
+
+public:
+ // [Con|De]structor
+
+ /**
+ * Construct package
+ */
+ cmCPackIFWPackage();
+
+public:
+ // Configuration
+
+ /// Human-readable name of the component
+ std::string DisplayName;
+
+ /// Human-readable description of the component
+ std::string Description;
+
+ /// Version number of the component
+ std::string Version;
+
+ /// Date when this component version was released
+ std::string ReleaseDate;
+
+ /// Domain-like identification for this component
+ std::string Name;
+
+ /// File name of a script being loaded
+ std::string Script;
+
+ /// List of license agreements to be accepted by the installing user
+ std::vector<std::string> Licenses;
+
+ /// List of pages to load
+ std::vector<std::string> UserInterfaces;
+
+ /// List of translation files to load
+ std::vector<std::string> Translations;
+
+ /// Priority of the component in the tree
+ std::string SortingPriority;
+
+ /// Description added to the component description
+ std::string UpdateText;
+
+ /// Set to true to preselect the component in the installer
+ std::string Default;
+
+ /// Marks the package as essential to force a restart of the MaintenanceTool
+ std::string Essential;
+
+ /// Set to true to hide the component from the installer
+ std::string Virtual;
+
+ /// Determines that the package must always be installed
+ std::string ForcedInstallation;
+
+ /// Package needs to be installed with elevated permissions
+ std::string RequiresAdminRights;
+
+public:
+ // Internal implementation
+
+ const char* GetOption(const std::string& op) const;
+ bool IsOn(const std::string& op) const;
+ bool IsSetToOff(const std::string& op) const;
+ bool IsSetToEmpty(const std::string& op) const;
+
+ bool IsVersionLess(const char* version);
+ bool IsVersionGreater(const char* version);
+ bool IsVersionEqual(const char* version);
+
+ std::string GetComponentName(cmCPackComponent* component);
+
+ void DefaultConfiguration();
+
+ int ConfigureFromOptions();
+ int ConfigureFromComponent(cmCPackComponent* component);
+ int ConfigureFromGroup(cmCPackComponentGroup* group);
+ int ConfigureFromGroup(const std::string& groupName);
+ int ConfigureFromPrefix(const std::string& prefix);
+
+ void GeneratePackageFile();
+
+ // Pointer to generator
+ cmCPackIFWGenerator* Generator;
+ // Pointer to installer
+ cmCPackIFWInstaller* Installer;
+ // Collection of dependencies
+ std::set<cmCPackIFWPackage*> Dependencies;
+ // Collection of unresolved dependencies
+ std::set<DependenceStruct*> AlienDependencies;
+ // Collection of unresolved automatic dependency on
+ std::set<DependenceStruct*> AlienAutoDependOn;
+ // Patch to package directory
+ std::string Directory;
+
+protected:
+ void WriteGeneratedByToStrim(cmXMLWriter& xout);
+};
+
+#endif // cmCPackIFWPackage_h
diff --git a/Source/CPack/IFW/cmCPackIFWRepository.cxx b/Source/CPack/IFW/cmCPackIFWRepository.cxx
new file mode 100644
index 0000000..cc204e8
--- /dev/null
+++ b/Source/CPack/IFW/cmCPackIFWRepository.cxx
@@ -0,0 +1,334 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmCPackIFWRepository.h"
+
+#include "CPack/cmCPackGenerator.h"
+#include "cmCPackIFWGenerator.h"
+#include "cmGeneratedFileStream.h"
+#include "cmSystemTools.h"
+#include "cmXMLParser.h"
+#include "cmXMLWriter.h"
+
+#include <cmConfigure.h>
+#include <stddef.h>
+
+#ifdef cmCPackLogger
+#undef cmCPackLogger
+#endif
+#define cmCPackLogger(logType, msg) \
+ do { \
+ std::ostringstream cmCPackLog_msg; \
+ cmCPackLog_msg << msg; \
+ if (Generator) { \
+ Generator->Logger->Log(logType, __FILE__, __LINE__, \
+ cmCPackLog_msg.str().c_str()); \
+ } \
+ } while (false)
+
+cmCPackIFWRepository::cmCPackIFWRepository()
+ : Update(None)
+ , Generator(CM_NULLPTR)
+{
+}
+
+bool cmCPackIFWRepository::IsValid() const
+{
+ bool valid = true;
+
+ switch (Update) {
+ case None:
+ valid = !Url.empty();
+ break;
+ case Add:
+ valid = !Url.empty();
+ break;
+ case Remove:
+ valid = !Url.empty();
+ break;
+ case Replace:
+ valid = !OldUrl.empty() && !NewUrl.empty();
+ break;
+ }
+
+ return valid;
+}
+
+const char* cmCPackIFWRepository::GetOption(const std::string& op) const
+{
+ return Generator ? Generator->GetOption(op) : CM_NULLPTR;
+}
+
+bool cmCPackIFWRepository::IsOn(const std::string& op) const
+{
+ return Generator ? Generator->IsOn(op) : false;
+}
+
+bool cmCPackIFWRepository::IsVersionLess(const char* version)
+{
+ return Generator ? Generator->IsVersionLess(version) : false;
+}
+
+bool cmCPackIFWRepository::IsVersionGreater(const char* version)
+{
+ return Generator ? Generator->IsVersionGreater(version) : false;
+}
+
+bool cmCPackIFWRepository::IsVersionEqual(const char* version)
+{
+ return Generator ? Generator->IsVersionEqual(version) : false;
+}
+
+bool cmCPackIFWRepository::ConfigureFromOptions()
+{
+ // Name;
+ if (Name.empty()) {
+ return false;
+ }
+
+ std::string prefix =
+ "CPACK_IFW_REPOSITORY_" + cmsys::SystemTools::UpperCase(Name) + "_";
+
+ // Update
+ if (IsOn(prefix + "ADD")) {
+ Update = Add;
+ } else if (IsOn(prefix + "REMOVE")) {
+ Update = Remove;
+ } else if (IsOn(prefix + "REPLACE")) {
+ Update = Replace;
+ } else {
+ Update = None;
+ }
+
+ // Url
+ if (const char* url = GetOption(prefix + "URL")) {
+ Url = url;
+ } else {
+ Url = "";
+ }
+
+ // Old url
+ if (const char* oldUrl = GetOption(prefix + "OLD_URL")) {
+ OldUrl = oldUrl;
+ } else {
+ OldUrl = "";
+ }
+
+ // New url
+ if (const char* newUrl = GetOption(prefix + "NEW_URL")) {
+ NewUrl = newUrl;
+ } else {
+ NewUrl = "";
+ }
+
+ // Enabled
+ if (IsOn(prefix + "DISABLED")) {
+ Enabled = "0";
+ } else {
+ Enabled = "";
+ }
+
+ // Username
+ if (const char* username = GetOption(prefix + "USERNAME")) {
+ Username = username;
+ } else {
+ Username = "";
+ }
+
+ // Password
+ if (const char* password = GetOption(prefix + "PASSWORD")) {
+ Password = password;
+ } else {
+ Password = "";
+ }
+
+ // DisplayName
+ if (const char* displayName = GetOption(prefix + "DISPLAY_NAME")) {
+ DisplayName = displayName;
+ } else {
+ DisplayName = "";
+ }
+
+ return IsValid();
+}
+
+/** \class cmCPackeIFWUpdatesPatcher
+ * \brief Helper class that parses and patch Updates.xml file (QtIFW)
+ */
+class cmCPackeIFWUpdatesPatcher : public cmXMLParser
+{
+public:
+ cmCPackeIFWUpdatesPatcher(cmCPackIFWRepository* r, cmXMLWriter& x)
+ : repository(r)
+ , xout(x)
+ , patched(false)
+ {
+ }
+
+ cmCPackIFWRepository* repository;
+ cmXMLWriter& xout;
+ bool patched;
+
+protected:
+ void StartElement(const std::string& name, const char** atts) CM_OVERRIDE
+ {
+ xout.StartElement(name);
+ StartFragment(atts);
+ }
+
+ void StartFragment(const char** atts)
+ {
+ for (size_t i = 0; atts[i]; i += 2) {
+ const char* key = atts[i];
+ const char* value = atts[i + 1];
+ xout.Attribute(key, value);
+ }
+ }
+
+ void EndElement(const std::string& name) CM_OVERRIDE
+ {
+ if (name == "Updates" && !patched) {
+ repository->WriteRepositoryUpdates(xout);
+ patched = true;
+ }
+ xout.EndElement();
+ if (patched) {
+ return;
+ }
+ if (name == "Checksum") {
+ repository->WriteRepositoryUpdates(xout);
+ patched = true;
+ }
+ }
+
+ void CharacterDataHandler(const char* data, int length) CM_OVERRIDE
+ {
+ std::string content(data, data + length);
+ if (content == "" || content == " " || content == " " ||
+ content == "\n") {
+ return;
+ }
+ xout.Content(content);
+ }
+};
+
+bool cmCPackIFWRepository::PatchUpdatesXml()
+{
+ // Lazy directory initialization
+ if (Directory.empty() && Generator) {
+ Directory = Generator->toplevel;
+ }
+
+ // Filenames
+ std::string updatesXml = Directory + "/repository/Updates.xml";
+ std::string updatesPatchXml = Directory + "/repository/UpdatesPatch.xml";
+
+ // Output stream
+ cmGeneratedFileStream fout(updatesPatchXml.data());
+ cmXMLWriter xout(fout);
+
+ xout.StartDocument();
+
+ WriteGeneratedByToStrim(xout);
+
+ // Patch
+ {
+ cmCPackeIFWUpdatesPatcher patcher(this, xout);
+ patcher.ParseFile(updatesXml.data());
+ }
+
+ xout.EndDocument();
+
+ fout.Close();
+
+ return cmSystemTools::RenameFile(updatesPatchXml.data(), updatesXml.data());
+}
+
+void cmCPackIFWRepository::WriteRepositoryConfig(cmXMLWriter& xout)
+{
+ xout.StartElement("Repository");
+
+ // Url
+ xout.Element("Url", Url);
+ // Enabled
+ if (!Enabled.empty()) {
+ xout.Element("Enabled", Enabled);
+ }
+ // Username
+ if (!Username.empty()) {
+ xout.Element("Username", Username);
+ }
+ // Password
+ if (!Password.empty()) {
+ xout.Element("Password", Password);
+ }
+ // DisplayName
+ if (!DisplayName.empty()) {
+ xout.Element("DisplayName", DisplayName);
+ }
+
+ xout.EndElement();
+}
+
+void cmCPackIFWRepository::WriteRepositoryUpdate(cmXMLWriter& xout)
+{
+ xout.StartElement("Repository");
+
+ switch (Update) {
+ case None:
+ break;
+ case Add:
+ xout.Attribute("action", "add");
+ break;
+ case Remove:
+ xout.Attribute("action", "remove");
+ break;
+ case Replace:
+ xout.Attribute("action", "replace");
+ break;
+ }
+
+ // Url
+ if (Update == Add || Update == Remove) {
+ xout.Attribute("url", Url);
+ } else if (Update == Replace) {
+ xout.Attribute("oldUrl", OldUrl);
+ xout.Attribute("newUrl", NewUrl);
+ }
+ // Enabled
+ if (!Enabled.empty()) {
+ xout.Attribute("enabled", Enabled);
+ }
+ // Username
+ if (!Username.empty()) {
+ xout.Attribute("username", Username);
+ }
+ // Password
+ if (!Password.empty()) {
+ xout.Attribute("password", Password);
+ }
+ // DisplayName
+ if (!DisplayName.empty()) {
+ xout.Attribute("displayname", DisplayName);
+ }
+
+ xout.EndElement();
+}
+
+void cmCPackIFWRepository::WriteRepositoryUpdates(cmXMLWriter& xout)
+{
+ if (!RepositoryUpdate.empty()) {
+ xout.StartElement("RepositoryUpdate");
+ for (RepositoriesVector::iterator rit = RepositoryUpdate.begin();
+ rit != RepositoryUpdate.end(); ++rit) {
+ (*rit)->WriteRepositoryUpdate(xout);
+ }
+ xout.EndElement();
+ }
+}
+
+void cmCPackIFWRepository::WriteGeneratedByToStrim(cmXMLWriter& xout)
+{
+ if (Generator) {
+ Generator->WriteGeneratedByToStrim(xout);
+ }
+}
diff --git a/Source/CPack/IFW/cmCPackIFWRepository.h b/Source/CPack/IFW/cmCPackIFWRepository.h
new file mode 100644
index 0000000..36f46da
--- /dev/null
+++ b/Source/CPack/IFW/cmCPackIFWRepository.h
@@ -0,0 +1,98 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmCPackIFWRepository_h
+#define cmCPackIFWRepository_h
+
+#include <cmConfigure.h> // IWYU pragma: keep
+
+#include <string>
+#include <vector>
+
+class cmCPackIFWGenerator;
+class cmXMLWriter;
+
+/** \class cmCPackIFWRepository
+ * \brief A remote repository to be created CPack IFW generator
+ */
+class cmCPackIFWRepository
+{
+public:
+ // Types
+
+ enum Action
+ {
+ None,
+ Add,
+ Remove,
+ Replace
+ };
+
+ typedef std::vector<cmCPackIFWRepository*> RepositoriesVector;
+
+public:
+ // Constructor
+
+ /**
+ * Construct repository
+ */
+ cmCPackIFWRepository();
+
+public:
+ // Configuration
+
+ /// Internal repository name
+ std::string Name;
+
+ /// Optional update action
+ Action Update;
+
+ /// Is points to a list of available components
+ std::string Url;
+
+ /// Is points to a list that will replaced
+ std::string OldUrl;
+
+ /// Is points to a list that will replace to
+ std::string NewUrl;
+
+ /// With "0" disabling this repository
+ std::string Enabled;
+
+ /// Is used as user on a protected repository
+ std::string Username;
+
+ /// Is password to use on a protected repository
+ std::string Password;
+
+ /// Is optional string to display instead of the URL
+ std::string DisplayName;
+
+public:
+ // Internal implementation
+
+ bool IsValid() const;
+
+ const char* GetOption(const std::string& op) const;
+ bool IsOn(const std::string& op) const;
+
+ bool IsVersionLess(const char* version);
+ bool IsVersionGreater(const char* version);
+ bool IsVersionEqual(const char* version);
+
+ bool ConfigureFromOptions();
+
+ bool PatchUpdatesXml();
+
+ void WriteRepositoryConfig(cmXMLWriter& xout);
+ void WriteRepositoryUpdate(cmXMLWriter& xout);
+ void WriteRepositoryUpdates(cmXMLWriter& xout);
+
+ cmCPackIFWGenerator* Generator;
+ RepositoriesVector RepositoryUpdate;
+ std::string Directory;
+
+protected:
+ void WriteGeneratedByToStrim(cmXMLWriter& xout);
+};
+
+#endif // cmCPackIFWRepository_h