diff options
Diffstat (limited to 'Source/CPack/IFW/cmCPackIFWInstaller.cxx')
-rw-r--r-- | Source/CPack/IFW/cmCPackIFWInstaller.cxx | 511 |
1 files changed, 511 insertions, 0 deletions
diff --git a/Source/CPack/IFW/cmCPackIFWInstaller.cxx b/Source/CPack/IFW/cmCPackIFWInstaller.cxx new file mode 100644 index 0000000..01e3ea4 --- /dev/null +++ b/Source/CPack/IFW/cmCPackIFWInstaller.cxx @@ -0,0 +1,511 @@ +/* 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 "cmCPackIFWCommon.h" +#include "cmCPackIFWGenerator.h" +#include "cmCPackIFWPackage.h" +#include "cmCPackIFWRepository.h" +#include "cmCPackLog.h" // IWYU pragma: keep +#include "cmGeneratedFileStream.h" +#include "cmSystemTools.h" +#include "cmXMLParser.h" +#include "cmXMLWriter.h" + +#include <sstream> +#include <stddef.h> +#include <utility> + +cmCPackIFWInstaller::cmCPackIFWInstaller() = default; + +void cmCPackIFWInstaller::printSkippedOptionWarning( + const std::string& optionName, const std::string& optionValue) +{ + cmCPackIFWLogger( + 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")) { + this->Name = optIFW_PACKAGE_NAME; + } else if (const char* optPACKAGE_NAME = + this->GetOption("CPACK_PACKAGE_NAME")) { + this->Name = optPACKAGE_NAME; + } else { + this->Name = "Your package"; + } + + // Title; + if (const char* optIFW_PACKAGE_TITLE = + this->GetOption("CPACK_IFW_PACKAGE_TITLE")) { + this->Title = optIFW_PACKAGE_TITLE; + } else if (const char* optPACKAGE_DESCRIPTION_SUMMARY = + this->GetOption("CPACK_PACKAGE_DESCRIPTION_SUMMARY")) { + this->Title = optPACKAGE_DESCRIPTION_SUMMARY; + } else { + this->Title = "Your package description"; + } + + // Version; + if (const char* option = this->GetOption("CPACK_PACKAGE_VERSION")) { + this->Version = option; + } else { + this->Version = "1.0.0"; + } + + // Publisher + if (const char* optIFW_PACKAGE_PUBLISHER = + this->GetOption("CPACK_IFW_PACKAGE_PUBLISHER")) { + this->Publisher = optIFW_PACKAGE_PUBLISHER; + } else if (const char* optPACKAGE_VENDOR = + GetOption("CPACK_PACKAGE_VENDOR")) { + this->Publisher = optPACKAGE_VENDOR; + } + + // ProductUrl + if (const char* option = this->GetOption("CPACK_IFW_PRODUCT_URL")) { + this->ProductUrl = option; + } + + // ApplicationIcon + if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_ICON")) { + if (cmSystemTools::FileExists(option)) { + this->InstallerApplicationIcon = option; + } else { + this->printSkippedOptionWarning("CPACK_IFW_PACKAGE_ICON", option); + } + } + + // WindowIcon + if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_WINDOW_ICON")) { + if (cmSystemTools::FileExists(option)) { + this->InstallerWindowIcon = option; + } else { + this->printSkippedOptionWarning("CPACK_IFW_PACKAGE_WINDOW_ICON", option); + } + } + + // RemoveTargetDir + if (this->IsSetToOff("CPACK_IFW_PACKAGE_REMOVE_TARGET_DIR")) { + this->RemoveTargetDir = "false"; + } else if (this->IsOn("CPACK_IFW_PACKAGE_REMOVE_TARGET_DIR")) { + this->RemoveTargetDir = "true"; + } else { + this->RemoveTargetDir.clear(); + } + + // Logo + if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_LOGO")) { + if (cmSystemTools::FileExists(option)) { + this->Logo = option; + } else { + this->printSkippedOptionWarning("CPACK_IFW_PACKAGE_LOGO", option); + } + } + + // Watermark + if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_WATERMARK")) { + if (cmSystemTools::FileExists(option)) { + this->Watermark = option; + } else { + this->printSkippedOptionWarning("CPACK_IFW_PACKAGE_WATERMARK", option); + } + } + + // Banner + if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_BANNER")) { + if (cmSystemTools::FileExists(option)) { + this->Banner = option; + } else { + this->printSkippedOptionWarning("CPACK_IFW_PACKAGE_BANNER", option); + } + } + + // Background + if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_BACKGROUND")) { + if (cmSystemTools::FileExists(option)) { + this->Background = option; + } else { + this->printSkippedOptionWarning("CPACK_IFW_PACKAGE_BACKGROUND", option); + } + } + + // WizardStyle + if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_WIZARD_STYLE")) { + // Setting the user value in any case + this->WizardStyle = option; + // Check known values + if (this->WizardStyle != "Modern" && this->WizardStyle != "Aero" && + this->WizardStyle != "Mac" && this->WizardStyle != "Classic") { + cmCPackIFWLogger( + WARNING, + "Option CPACK_IFW_PACKAGE_WIZARD_STYLE has unknown value \"" + << option << "\". Expected values are: Modern, Aero, Mac, Classic." + << std::endl); + } + } + + // WizardDefaultWidth + if (const char* option = + this->GetOption("CPACK_IFW_PACKAGE_WIZARD_DEFAULT_WIDTH")) { + this->WizardDefaultWidth = option; + } + + // WizardDefaultHeight + if (const char* option = + this->GetOption("CPACK_IFW_PACKAGE_WIZARD_DEFAULT_HEIGHT")) { + this->WizardDefaultHeight = option; + } + + // TitleColor + if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_TITLE_COLOR")) { + this->TitleColor = option; + } + + // Start menu + if (const char* optIFW_START_MENU_DIR = + this->GetOption("CPACK_IFW_PACKAGE_START_MENU_DIRECTORY")) { + this->StartMenuDir = optIFW_START_MENU_DIR; + } else { + this->StartMenuDir = Name; + } + + // Default target directory for installation + if (const char* optIFW_TARGET_DIRECTORY = + this->GetOption("CPACK_IFW_TARGET_DIRECTORY")) { + this->TargetDir = optIFW_TARGET_DIRECTORY; + } else if (const char* optPACKAGE_INSTALL_DIRECTORY = + this->GetOption("CPACK_PACKAGE_INSTALL_DIRECTORY")) { + this->TargetDir = "@ApplicationsDir@/"; + this->TargetDir += optPACKAGE_INSTALL_DIRECTORY; + } else { + this->TargetDir = "@RootDir@/usr/local"; + } + + // Default target directory for installation with administrator rights + if (const char* option = + this->GetOption("CPACK_IFW_ADMIN_TARGET_DIRECTORY")) { + this->AdminTargetDir = option; + } + + // Maintenance tool + if (const char* optIFW_MAINTENANCE_TOOL = + this->GetOption("CPACK_IFW_PACKAGE_MAINTENANCE_TOOL_NAME")) { + this->MaintenanceToolName = optIFW_MAINTENANCE_TOOL; + } + + // Maintenance tool ini file + if (const char* optIFW_MAINTENANCE_TOOL_INI = + this->GetOption("CPACK_IFW_PACKAGE_MAINTENANCE_TOOL_INI_FILE")) { + this->MaintenanceToolIniFile = optIFW_MAINTENANCE_TOOL_INI; + } + + // Allow non-ASCII characters + if (this->GetOption("CPACK_IFW_PACKAGE_ALLOW_NON_ASCII_CHARACTERS")) { + if (this->IsOn("CPACK_IFW_PACKAGE_ALLOW_NON_ASCII_CHARACTERS")) { + this->AllowNonAsciiCharacters = "true"; + } else { + this->AllowNonAsciiCharacters = "false"; + } + } + + // Space in path + if (this->GetOption("CPACK_IFW_PACKAGE_ALLOW_SPACE_IN_PATH")) { + if (this->IsOn("CPACK_IFW_PACKAGE_ALLOW_SPACE_IN_PATH")) { + this->AllowSpaceInPath = "true"; + } else { + this->AllowSpaceInPath = "false"; + } + } + + // Control script + if (const char* optIFW_CONTROL_SCRIPT = + this->GetOption("CPACK_IFW_PACKAGE_CONTROL_SCRIPT")) { + this->ControlScript = optIFW_CONTROL_SCRIPT; + } + + // Resources + if (const char* optIFW_PACKAGE_RESOURCES = + this->GetOption("CPACK_IFW_PACKAGE_RESOURCES")) { + this->Resources.clear(); + cmSystemTools::ExpandListArgument(optIFW_PACKAGE_RESOURCES, + this->Resources); + } +} + +/** \class cmCPackIFWResourcesParser + * \brief Helper class that parse resources form .qrc (Qt) + */ +class cmCPackIFWResourcesParser : public cmXMLParser +{ +public: + cmCPackIFWResourcesParser(cmCPackIFWInstaller* i) + : installer(i) + , file(false) + { + this->path = i->Directory + "/resources"; + } + + bool ParseResource(size_t r) + { + this->hasFiles = false; + this->hasErrors = false; + + this->basePath = + cmSystemTools::GetFilenamePath(this->installer->Resources[r]); + + this->ParseFile(this->installer->Resources[r].data()); + + return this->hasFiles && !this->hasErrors; + } + + cmCPackIFWInstaller* installer; + bool file, hasFiles, hasErrors; + std::string path, basePath; + +protected: + void StartElement(const std::string& name, const char** /*atts*/) override + { + this->file = name == "file"; + if (file) { + this->hasFiles = true; + } + } + + void CharacterDataHandler(const char* data, int length) override + { + if (this->file) { + std::string content(data, data + length); + content = cmSystemTools::TrimWhitespace(content); + std::string source = this->basePath + "/" + content; + std::string destination = this->path + "/" + content; + if (!cmSystemTools::CopyFileIfDifferent(source, destination)) { + this->hasErrors = true; + } + } + } + + void EndElement(const std::string& /*name*/) override {} +}; + +void cmCPackIFWInstaller::GenerateInstallerFile() +{ + // Lazy directory initialization + if (this->Directory.empty() && this->Generator) { + this->Directory = this->Generator->toplevel; + } + + // Output stream + cmGeneratedFileStream fout(this->Directory + "/config/config.xml"); + cmXMLWriter xout(fout); + + xout.StartDocument(); + + WriteGeneratedByToStrim(xout); + + xout.StartElement("Installer"); + + xout.Element("Name", this->Name); + xout.Element("Version", this->Version); + xout.Element("Title", this->Title); + + if (!this->Publisher.empty()) { + xout.Element("Publisher", this->Publisher); + } + + if (!this->ProductUrl.empty()) { + xout.Element("ProductUrl", this->ProductUrl); + } + + // ApplicationIcon + if (!this->InstallerApplicationIcon.empty()) { + std::string name = + cmSystemTools::GetFilenameName(this->InstallerApplicationIcon); + std::string path = this->Directory + "/config/" + name; + name = cmSystemTools::GetFilenameWithoutExtension(name); + cmsys::SystemTools::CopyFileIfDifferent(this->InstallerApplicationIcon, + path); + xout.Element("InstallerApplicationIcon", name); + } + + // WindowIcon + if (!this->InstallerWindowIcon.empty()) { + std::string name = + cmSystemTools::GetFilenameName(this->InstallerWindowIcon); + std::string path = this->Directory + "/config/" + name; + cmsys::SystemTools::CopyFileIfDifferent(this->InstallerWindowIcon, path); + xout.Element("InstallerWindowIcon", name); + } + + // Logo + if (!this->Logo.empty()) { + std::string name = cmSystemTools::GetFilenameName(this->Logo); + std::string path = this->Directory + "/config/" + name; + cmsys::SystemTools::CopyFileIfDifferent(this->Logo, path); + xout.Element("Logo", name); + } + + // Banner + if (!this->Banner.empty()) { + std::string name = cmSystemTools::GetFilenameName(this->Banner); + std::string path = this->Directory + "/config/" + name; + cmsys::SystemTools::CopyFileIfDifferent(this->Banner, path); + xout.Element("Banner", name); + } + + // Watermark + if (!this->Watermark.empty()) { + std::string name = cmSystemTools::GetFilenameName(this->Watermark); + std::string path = this->Directory + "/config/" + name; + cmsys::SystemTools::CopyFileIfDifferent(this->Watermark, path); + xout.Element("Watermark", name); + } + + // Background + if (!this->Background.empty()) { + std::string name = cmSystemTools::GetFilenameName(this->Background); + std::string path = this->Directory + "/config/" + name; + cmsys::SystemTools::CopyFileIfDifferent(this->Background, path); + xout.Element("Background", name); + } + + // WizardStyle + if (!this->WizardStyle.empty()) { + xout.Element("WizardStyle", this->WizardStyle); + } + + // WizardDefaultWidth + if (!this->WizardDefaultWidth.empty()) { + xout.Element("WizardDefaultWidth", this->WizardDefaultWidth); + } + + // WizardDefaultHeight + if (!this->WizardDefaultHeight.empty()) { + xout.Element("WizardDefaultHeight", this->WizardDefaultHeight); + } + + // TitleColor + if (!this->TitleColor.empty()) { + xout.Element("TitleColor", this->TitleColor); + } + + // Start menu + if (!this->IsVersionLess("2.0")) { + xout.Element("StartMenuDir", this->StartMenuDir); + } + + // Target dir + if (!this->TargetDir.empty()) { + xout.Element("TargetDir", this->TargetDir); + } + + // Admin target dir + if (!this->AdminTargetDir.empty()) { + xout.Element("AdminTargetDir", this->AdminTargetDir); + } + + // Remote repositories + if (!this->RemoteRepositories.empty()) { + xout.StartElement("RemoteRepositories"); + for (cmCPackIFWRepository* r : this->RemoteRepositories) { + r->WriteRepositoryConfig(xout); + } + xout.EndElement(); + } + + // Maintenance tool + if (!this->IsVersionLess("2.0") && !this->MaintenanceToolName.empty()) { + xout.Element("MaintenanceToolName", this->MaintenanceToolName); + } + + // Maintenance tool ini file + if (!this->IsVersionLess("2.0") && !this->MaintenanceToolIniFile.empty()) { + xout.Element("MaintenanceToolIniFile", this->MaintenanceToolIniFile); + } + + if (!this->RemoveTargetDir.empty()) { + xout.Element("RemoveTargetDir", this->RemoveTargetDir); + } + + // Different allows + if (this->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 (!this->AllowNonAsciiCharacters.empty()) { + xout.Element("AllowNonAsciiCharacters", this->AllowNonAsciiCharacters); + } + if (!this->AllowSpaceInPath.empty()) { + xout.Element("AllowSpaceInPath", this->AllowSpaceInPath); + } + } + + // Control script (copy to config dir) + if (!this->IsVersionLess("2.0") && !this->ControlScript.empty()) { + std::string name = cmSystemTools::GetFilenameName(this->ControlScript); + std::string path = this->Directory + "/config/" + name; + cmsys::SystemTools::CopyFileIfDifferent(this->ControlScript, path); + xout.Element("ControlScript", name); + } + + // Resources (copy to resources dir) + if (!this->Resources.empty()) { + std::vector<std::string> resources; + cmCPackIFWResourcesParser parser(this); + for (size_t i = 0; i < this->Resources.size(); i++) { + if (parser.ParseResource(i)) { + std::string name = cmSystemTools::GetFilenameName(this->Resources[i]); + std::string path = this->Directory + "/resources/" + name; + cmsys::SystemTools::CopyFileIfDifferent(this->Resources[i], path); + resources.push_back(std::move(name)); + } else { + cmCPackIFWLogger(WARNING, + "Can't copy resources from \"" + << this->Resources[i] + << "\". Resource will be skipped." << std::endl); + } + } + this->Resources = resources; + } + + xout.EndElement(); + xout.EndDocument(); +} + +void cmCPackIFWInstaller::GeneratePackageFiles() +{ + if (this->Packages.empty() || this->Generator->IsOnePackage()) { + // Generate default package + cmCPackIFWPackage package; + package.Generator = this->Generator; + package.Installer = this; + // Check package group + if (const char* option = this->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 (auto& p : this->Packages) { + cmCPackIFWPackage* package = p.second; + package->GeneratePackageFile(); + } +} |