diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 175a034ba..966e0f68c 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -562,7 +562,11 @@ if(WIN32) set(CPACK_SRCS ${CPACK_SRCS} CPack/WiX/cmCPackWIXGenerator.cxx CPack/WiX/cmWIXSourceWriter.cxx + CPack/WiX/cmWIXDirectoriesSourceWriter.cxx + CPack/WiX/cmWIXFeaturesSourceWriter.cxx + CPack/WiX/cmWIXFilesSourceWriter.cxx CPack/WiX/cmWIXRichTextFormatWriter.cxx + CPack/WiX/cmWIXPatch.cxx CPack/WiX/cmWIXPatchParser.cxx ) endif() diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.cxx b/Source/CPack/WiX/cmCPackWIXGenerator.cxx index 43119d6a5..8e671ccaf 100644 --- a/Source/CPack/WiX/cmCPackWIXGenerator.cxx +++ b/Source/CPack/WiX/cmCPackWIXGenerator.cxx @@ -1,6 +1,6 @@ /*============================================================================ CMake - Cross Platform Makefile Generator - Copyright 2000-2013 Kitware, Inc., Insight Software Consortium + Copyright 2000-2014 Kitware, Inc., Insight Software Consortium Distributed under the OSI-approved BSD License (the "License"); see accompanying file Copyright.txt for details. @@ -19,6 +19,9 @@ #include #include "cmWIXSourceWriter.h" +#include "cmWIXDirectoriesSourceWriter.h" +#include "cmWIXFeaturesSourceWriter.h" +#include "cmWIXFilesSourceWriter.h" #include "cmWIXRichTextFormatWriter.h" #include @@ -28,11 +31,9 @@ #include // for GUID generation -#include -#include - cmCPackWIXGenerator::cmCPackWIXGenerator(): - HasDesktopShortcuts(false) + HasDesktopShortcuts(false), + Patch(Logger) { } @@ -44,15 +45,9 @@ int cmCPackWIXGenerator::InitializeInternal() return this->Superclass::InitializeInternal(); } -bool cmCPackWIXGenerator::RunWiXCommand(const std::string& command) +bool cmCPackWIXGenerator::RunWiXCommand(std::string const& command) { - std::string cpackTopLevel; - if(!RequireOption("CPACK_TOPLEVEL_DIRECTORY", cpackTopLevel)) - { - return false; - } - - std::string logFileName = cpackTopLevel + "/wix.log"; + std::string logFileName = this->CPackTopLevel + "/wix.log"; cmCPackLogger(cmCPackLog::LOG_DEBUG, "Running WiX command: " << command << std::endl); @@ -81,7 +76,7 @@ bool cmCPackWIXGenerator::RunWiXCommand(const std::string& command) } bool cmCPackWIXGenerator::RunCandleCommand( - const std::string& sourceFile, const std::string& objectFile) + std::string const& sourceFile, std::string const& objectFile) { std::string executable; if(!RequireOption("CPACK_WIX_CANDLE_EXECUTABLE", executable)) @@ -108,7 +103,7 @@ bool cmCPackWIXGenerator::RunCandleCommand( return RunWiXCommand(command.str()); } -bool cmCPackWIXGenerator::RunLightCommand(const std::string& objectFiles) +bool cmCPackWIXGenerator::RunLightCommand(std::string const& objectFiles) { std::string executable; if(!RequireOption("CPACK_WIX_LIGHT_EXECUTABLE", executable)) @@ -121,8 +116,8 @@ bool cmCPackWIXGenerator::RunLightCommand(const std::string& objectFiles) command << " -nologo"; command << " -out " << QuotePath(packageFileNames.at(0)); - for(extension_set_t::const_iterator i = LightExtensions.begin(); - i != LightExtensions.end(); ++i) + for(extension_set_t::const_iterator i = this->LightExtensions.begin(); + i != this->LightExtensions.end(); ++i) { command << " -ext " << QuotePath(*i); } @@ -182,15 +177,14 @@ bool cmCPackWIXGenerator::InitializeWiXConfiguration() "you might want to set this explicitly." << std::endl); } - std::string cpackTopLevel; - if(!RequireOption("CPACK_TOPLEVEL_DIRECTORY", cpackTopLevel)) + if(!RequireOption("CPACK_TOPLEVEL_DIRECTORY", this->CPackTopLevel)) { return false; } if(GetOption("CPACK_WIX_LICENSE_RTF") == 0) { - std::string licenseFilename = cpackTopLevel + "/License.rtf"; + std::string licenseFilename = this->CPackTopLevel + "/License.rtf"; SetOption("CPACK_WIX_LICENSE_RTF", licenseFilename.c_str()); if(!CreateLicenseFile()) @@ -213,7 +207,7 @@ bool cmCPackWIXGenerator::InitializeWiXConfiguration() { std::string defaultRef = "WixUI_InstallDir"; - if(Components.size()) + if(this->Components.size()) { defaultRef = "WixUI_FeatureTree"; } @@ -221,17 +215,17 @@ bool cmCPackWIXGenerator::InitializeWiXConfiguration() SetOption("CPACK_WIX_UI_REF", defaultRef.c_str()); } - CollectExtensions("CPACK_WIX_EXTENSIONS", CandleExtensions); - CollectExtensions("CPACK_WIX_CANDLE_EXTENSIONS", CandleExtensions); + CollectExtensions("CPACK_WIX_EXTENSIONS", this->CandleExtensions); + CollectExtensions("CPACK_WIX_CANDLE_EXTENSIONS", this->CandleExtensions); - LightExtensions.insert("WixUIExtension"); - CollectExtensions("CPACK_WIX_EXTENSIONS", LightExtensions); - CollectExtensions("CPACK_WIX_LIGHT_EXTENSIONS", LightExtensions); + this->LightExtensions.insert("WixUIExtension"); + CollectExtensions("CPACK_WIX_EXTENSIONS", this->LightExtensions); + CollectExtensions("CPACK_WIX_LIGHT_EXTENSIONS", this->LightExtensions); const char* patchFilePath = GetOption("CPACK_WIX_PATCH_FILE"); if(patchFilePath) { - LoadPatchFragments(patchFilePath); + this->Patch.LoadFragments(patchFilePath); } return true; @@ -244,10 +238,7 @@ bool cmCPackWIXGenerator::PackageFilesImpl() return false; } - if(!CreateWiXVariablesIncludeFile()) - { - return false; - } + CreateWiXVariablesIncludeFile(); if(!CreateWiXSourceFiles()) { @@ -257,9 +248,9 @@ bool cmCPackWIXGenerator::PackageFilesImpl() AppendUserSuppliedExtraSources(); std::stringstream objectFiles; - for(size_t i = 0; i < WixSources.size(); ++i) + for(size_t i = 0; i < this->WixSources.size(); ++i) { - const std::string& sourceFilename = WixSources[i]; + std::string const& sourceFilename = this->WixSources[i]; std::string objectFilename = cmSystemTools::GetFilenameWithoutExtension(sourceFilename) + ".wixobj"; @@ -282,7 +273,7 @@ void cmCPackWIXGenerator::AppendUserSuppliedExtraSources() const char *cpackWixExtraSources = GetOption("CPACK_WIX_EXTRA_SOURCES"); if(!cpackWixExtraSources) return; - cmSystemTools::ExpandListArgument(cpackWixExtraSources, WixSources); + cmSystemTools::ExpandListArgument(cpackWixExtraSources, this->WixSources); } void cmCPackWIXGenerator::AppendUserSuppliedExtraObjects(std::ostream& stream) @@ -297,22 +288,18 @@ void cmCPackWIXGenerator::AppendUserSuppliedExtraObjects(std::ostream& stream) for(size_t i = 0; i < expandedExtraObjects.size(); ++i) { - stream << " " << QuotePath(expandedExtraObjects[i]); + stream << " " << QuotePath(expandedExtraObjects[i]); } } -bool cmCPackWIXGenerator::CreateWiXVariablesIncludeFile() +void cmCPackWIXGenerator::CreateWiXVariablesIncludeFile() { - std::string cpackTopLevel; - if(!RequireOption("CPACK_TOPLEVEL_DIRECTORY", cpackTopLevel)) - { - return false; - } - std::string includeFilename = - cpackTopLevel + "/cpack_variables.wxi"; + this->CPackTopLevel + "/cpack_variables.wxi"; + + cmWIXSourceWriter includeFile( + this->Logger, includeFilename, true); - cmWIXSourceWriter includeFile(Logger, includeFilename, true); CopyDefinition(includeFile, "CPACK_WIX_PRODUCT_GUID"); CopyDefinition(includeFile, "CPACK_WIX_UPGRADE_GUID"); CopyDefinition(includeFile, "CPACK_PACKAGE_VENDOR"); @@ -326,12 +313,10 @@ bool cmCPackWIXGenerator::CreateWiXVariablesIncludeFile() GetOption("CPACK_PACKAGE_NAME")); CopyDefinition(includeFile, "CPACK_WIX_PROGRAM_MENU_FOLDER"); CopyDefinition(includeFile, "CPACK_WIX_UI_REF"); - - return true; } void cmCPackWIXGenerator::CopyDefinition( - cmWIXSourceWriter &source, const std::string &name) + cmWIXSourceWriter &source, std::string const& name) { const char* value = GetOption(name.c_str()); if(value) @@ -341,7 +326,7 @@ void cmCPackWIXGenerator::CopyDefinition( } void cmCPackWIXGenerator::AddDefinition(cmWIXSourceWriter& source, - const std::string& name, const std::string& value) + std::string const& name, std::string const& value) { std::stringstream tmp; tmp << name << "=\"" << value << '"'; @@ -352,81 +337,47 @@ void cmCPackWIXGenerator::AddDefinition(cmWIXSourceWriter& source, bool cmCPackWIXGenerator::CreateWiXSourceFiles() { - std::string cpackTopLevel; - if(!RequireOption("CPACK_TOPLEVEL_DIRECTORY", cpackTopLevel)) + std::string directoryDefinitionsFilename = + this->CPackTopLevel + "/directories.wxs"; + + this->WixSources.push_back(directoryDefinitionsFilename); + + cmWIXDirectoriesSourceWriter directoryDefinitions( + this->Logger, directoryDefinitionsFilename); + directoryDefinitions.BeginElement("Fragment"); + + std::string installRoot; + if(!RequireOption("CPACK_PACKAGE_INSTALL_DIRECTORY", installRoot)) { return false; } - std::string directoryDefinitionsFilename = - cpackTopLevel + "/directories.wxs"; - - WixSources.push_back(directoryDefinitionsFilename); - - cmWIXSourceWriter directoryDefinitions(Logger, directoryDefinitionsFilename); - directoryDefinitions.BeginElement("Fragment"); - directoryDefinitions.BeginElement("Directory"); directoryDefinitions.AddAttribute("Id", "TARGETDIR"); directoryDefinitions.AddAttribute("Name", "SourceDir"); - directoryDefinitions.BeginElement("Directory"); - if(GetArchitecture() == "x86") - { - directoryDefinitions.AddAttribute("Id", "ProgramFilesFolder"); - } - else - { - directoryDefinitions.AddAttribute("Id", "ProgramFiles64Folder"); - } - - std::vector install_root; - - std::string tmp; - if(!RequireOption("CPACK_PACKAGE_INSTALL_DIRECTORY", tmp)) - { - return false; - } - - cmSystemTools::SplitPath(tmp.c_str(), install_root); - - if(!install_root.empty() && install_root.back().empty()) - { - install_root.pop_back(); - } - - for(size_t i = 1; i < install_root.size(); ++i) - { - directoryDefinitions.BeginElement("Directory"); - - if(i == install_root.size() - 1) - { - directoryDefinitions.AddAttribute("Id", "INSTALL_ROOT"); - } - else - { - std::stringstream ss; - ss << "INSTALL_PREFIX_" << i; - directoryDefinitions.AddAttribute("Id", ss.str()); - } - - directoryDefinitions.AddAttribute("Name", install_root[i]); - } + size_t installRootSize = + directoryDefinitions.BeginInstallationPrefixDirectory( + GetProgramFilesFolderId(), installRoot); std::string fileDefinitionsFilename = - cpackTopLevel + "/files.wxs"; + this->CPackTopLevel + "/files.wxs"; - WixSources.push_back(fileDefinitionsFilename); + this->WixSources.push_back(fileDefinitionsFilename); + + cmWIXFilesSourceWriter fileDefinitions( + this->Logger, fileDefinitionsFilename); - cmWIXSourceWriter fileDefinitions(Logger, fileDefinitionsFilename); fileDefinitions.BeginElement("Fragment"); std::string featureDefinitionsFilename = - cpackTopLevel +"/features.wxs"; + this->CPackTopLevel +"/features.wxs"; - WixSources.push_back(featureDefinitionsFilename); + this->WixSources.push_back(featureDefinitionsFilename); + + cmWIXFeaturesSourceWriter featureDefinitions( + this->Logger, featureDefinitionsFilename); - cmWIXSourceWriter featureDefinitions(Logger, featureDefinitionsFilename); featureDefinitions.BeginElement("Fragment"); featureDefinitions.BeginElement("Feature"); @@ -439,13 +390,15 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles() { return false; } - featureDefinitions.AddAttribute("Title", cpackPackageName); + featureDefinitions.AddAttribute("Title", cpackPackageName); featureDefinitions.AddAttribute("Level", "1"); - if(!CreateCMakePackageRegistryEntry(featureDefinitions)) + const char* package = GetOption("CPACK_WIX_CMAKE_PACKAGE_REGISTRY"); + if(package) { - return false; + featureDefinitions.CreateCMakePackageRegistryEntry( + package, GetOption("CPACK_WIX_UPGRADE_GUID")); } if(!CreateFeatureHierarchy(featureDefinitions)) @@ -471,7 +424,7 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles() else { for(std::map::const_iterator - i = Components.begin(); i != Components.end(); ++i) + i = this->Components.begin(); i != this->Components.end(); ++i) { cmCPackComponent const& component = i->second; @@ -513,31 +466,51 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles() featureDefinitions.EndElement("Fragment"); fileDefinitions.EndElement("Fragment"); - for(size_t i = 1; i < install_root.size(); ++i) - { - directoryDefinitions.EndElement("Directory"); - } - - directoryDefinitions.EndElement("Directory"); + directoryDefinitions.EndInstallationPrefixDirectory( + installRootSize); if(hasShortcuts) { - CreateStartMenuFolder(directoryDefinitions); + directoryDefinitions.EmitStartMenuFolder( + GetOption("CPACK_WIX_PROGRAM_MENU_FOLDER")); } if(this->HasDesktopShortcuts) { - CreateDesktopFolder(directoryDefinitions); + directoryDefinitions.EmitDesktopFolder(); } directoryDefinitions.EndElement("Directory"); directoryDefinitions.EndElement("Fragment"); + if(!GenerateMainSourceFileFromTemplate()) + { + return false; + } + + return this->Patch.CheckForUnappliedFragments(); +} + +std::string cmCPackWIXGenerator::GetProgramFilesFolderId() const +{ + if(GetArchitecture() == "x86") + { + return "ProgramFilesFolder"; + } + else + { + return "ProgramFiles64Folder"; + } +} + +bool cmCPackWIXGenerator::GenerateMainSourceFileFromTemplate() +{ std::string wixTemplate = FindTemplate("WIX.template.in"); if(GetOption("CPACK_WIX_TEMPLATE") != 0) { wixTemplate = GetOption("CPACK_WIX_TEMPLATE"); } + if(wixTemplate.empty()) { cmCPackLogger(cmCPackLog::LOG_ERROR, @@ -545,7 +518,7 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles() return false; } - std::string mainSourceFilePath = cpackTopLevel + "/main.wxs"; + std::string mainSourceFilePath = this->CPackTopLevel + "/main.wxs"; if(!ConfigureFile(wixTemplate.c_str(), mainSourceFilePath .c_str())) { @@ -556,68 +529,13 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles() return false; } - WixSources.push_back(mainSourceFilePath); - - std::string fragmentList; - for(cmWIXPatchParser::fragment_map_t::const_iterator - i = Fragments.begin(); i != Fragments.end(); ++i) - { - if(!fragmentList.empty()) - { - fragmentList += ", "; - } - - fragmentList += "'"; - fragmentList += i->first; - fragmentList += "'"; - } - - if(fragmentList.size()) - { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Some XML patch fragments did not have matching IDs: " << - fragmentList << std::endl); - return false; - } - - return true; -} - -bool cmCPackWIXGenerator::CreateCMakePackageRegistryEntry( - cmWIXSourceWriter& featureDefinitions) -{ - const char* package = GetOption("CPACK_WIX_CMAKE_PACKAGE_REGISTRY"); - if(!package) - { - return true; - } - - featureDefinitions.BeginElement("Component"); - featureDefinitions.AddAttribute("Id", "CM_PACKAGE_REGISTRY"); - featureDefinitions.AddAttribute("Directory", "TARGETDIR"); - featureDefinitions.AddAttribute("Guid", "*"); - - std::string registryKey = - std::string("Software\\Kitware\\CMake\\Packages\\") + package; - - std::string upgradeGuid = GetOption("CPACK_WIX_UPGRADE_GUID"); - - featureDefinitions.BeginElement("RegistryValue"); - featureDefinitions.AddAttribute("Root", "HKLM"); - featureDefinitions.AddAttribute("Key", registryKey); - featureDefinitions.AddAttribute("Name", upgradeGuid); - featureDefinitions.AddAttribute("Type", "string"); - featureDefinitions.AddAttribute("Value", "[INSTALL_ROOT]"); - featureDefinitions.AddAttribute("KeyPath", "yes"); - featureDefinitions.EndElement("RegistryValue"); - - featureDefinitions.EndElement("Component"); + this->WixSources.push_back(mainSourceFilePath); return true; } bool cmCPackWIXGenerator::CreateFeatureHierarchy( - cmWIXSourceWriter& featureDefinitions) + cmWIXFeaturesSourceWriter& featureDefinitions) { for(std::map::const_iterator i = ComponentGroups.begin(); i != ComponentGroups.end(); ++i) @@ -625,105 +543,30 @@ bool cmCPackWIXGenerator::CreateFeatureHierarchy( cmCPackComponentGroup const& group = i->second; if(group.ParentGroup == 0) { - if(!EmitFeatureForComponentGroup(featureDefinitions, group)) - { - return false; - } + featureDefinitions.EmitFeatureForComponentGroup(group); } } for(std::map::const_iterator - i = Components.begin(); i != Components.end(); ++i) + i = this->Components.begin(); i != this->Components.end(); ++i) { cmCPackComponent const& component = i->second; if(!component.Group) { - if(!EmitFeatureForComponent(featureDefinitions, component)) - { - return false; - } + featureDefinitions.EmitFeatureForComponent(component); } } return true; } -bool cmCPackWIXGenerator::EmitFeatureForComponentGroup( - cmWIXSourceWriter& featureDefinitions, - cmCPackComponentGroup const& group) -{ - featureDefinitions.BeginElement("Feature"); - featureDefinitions.AddAttribute("Id", "CM_G_" + group.Name); - - if(group.IsExpandedByDefault) - { - featureDefinitions.AddAttribute("Display", "expand"); - } - - featureDefinitions.AddAttributeUnlessEmpty( - "Title", group.DisplayName); - - featureDefinitions.AddAttributeUnlessEmpty( - "Description", group.Description); - - for(std::vector::const_iterator - i = group.Subgroups.begin(); i != group.Subgroups.end(); ++i) - { - if(!EmitFeatureForComponentGroup(featureDefinitions, **i)) - { - return false; - } - } - - for(std::vector::const_iterator - i = group.Components.begin(); i != group.Components.end(); ++i) - { - if(!EmitFeatureForComponent(featureDefinitions, **i)) - { - return false; - } - } - - featureDefinitions.EndElement("Feature"); - - return true; -} - -bool cmCPackWIXGenerator::EmitFeatureForComponent( - cmWIXSourceWriter& featureDefinitions, - cmCPackComponent const& component) -{ - featureDefinitions.BeginElement("Feature"); - featureDefinitions.AddAttribute("Id", "CM_C_" + component.Name); - - featureDefinitions.AddAttributeUnlessEmpty( - "Title", component.DisplayName); - - featureDefinitions.AddAttributeUnlessEmpty( - "Description", component.Description); - - if(component.IsRequired) - { - featureDefinitions.AddAttribute("Absent", "disallow"); - } - - if(component.IsHidden) - { - featureDefinitions.AddAttribute("Display", "hidden"); - } - - featureDefinitions.EndElement("Feature"); - - return true; -} - bool cmCPackWIXGenerator::AddComponentsToFeature( std::string const& rootPath, std::string const& featureId, - cmWIXSourceWriter& directoryDefinitions, - cmWIXSourceWriter& fileDefinitions, - cmWIXSourceWriter& featureDefinitions, + cmWIXDirectoriesSourceWriter& directoryDefinitions, + cmWIXFilesSourceWriter& fileDefinitions, + cmWIXFeaturesSourceWriter& featureDefinitions, shortcut_map_t& shortcutMap) { featureDefinitions.BeginElement("FeatureRef"); @@ -768,8 +611,8 @@ bool cmCPackWIXGenerator::CreateStartMenuShortcuts( std::string const& cpackComponentName, std::string const& featureId, shortcut_map_t& shortcutMap, - cmWIXSourceWriter& fileDefinitions, - cmWIXSourceWriter& featureDefinitions) + cmWIXFilesSourceWriter& fileDefinitions, + cmWIXFeaturesSourceWriter& featureDefinitions) { bool thisHasDesktopShortcuts = false; @@ -799,6 +642,7 @@ bool cmCPackWIXGenerator::CreateStartMenuShortcuts( fileDefinitions.BeginElement("DirectoryRef"); fileDefinitions.AddAttribute("Id", "PROGRAM_MENU_FOLDER"); + fileDefinitions.BeginElement("Component"); fileDefinitions.AddAttribute("Id", componentId); fileDefinitions.AddAttribute("Guid", "*"); @@ -809,63 +653,34 @@ bool cmCPackWIXGenerator::CreateStartMenuShortcuts( std::string const& id = i->first; cmWIXShortcut const& shortcut = i->second; - std::string shortcutId = std::string("CM_S") + id; - std::string fileId = std::string("CM_F") + id; + fileDefinitions.EmitShortcut(id, shortcut, false); - fileDefinitions.BeginElement("Shortcut"); - fileDefinitions.AddAttribute("Id", shortcutId); - fileDefinitions.AddAttribute("Name", shortcut.textLabel); - std::string target = "[#" + fileId + "]"; - fileDefinitions.AddAttribute("Target", target); - fileDefinitions.AddAttribute("WorkingDirectory", - shortcut.workingDirectoryId); - fileDefinitions.EndElement("Shortcut"); - - if (shortcut.desktop) + if(shortcut.desktop) { - thisHasDesktopShortcuts = true; + thisHasDesktopShortcuts = true; } } if(cpackComponentName.empty()) { - CreateUninstallShortcut(cpackPackageName, fileDefinitions); + fileDefinitions.EmitUninstallShortcut(cpackPackageName); } - fileDefinitions.BeginElement("RemoveFolder"); - fileDefinitions.AddAttribute("Id", + fileDefinitions.EmitRemoveFolder( "CM_REMOVE_PROGRAM_MENU_FOLDER" + idSuffix); - fileDefinitions.AddAttribute("On", "uninstall"); - fileDefinitions.EndElement("RemoveFolder"); std::string registryKey = std::string("Software\\") + cpackVendor + "\\" + cpackPackageName; - fileDefinitions.BeginElement("RegistryValue"); - fileDefinitions.AddAttribute("Root", "HKCU"); - fileDefinitions.AddAttribute("Key", registryKey); - - std::string valueName; - if(!cpackComponentName.empty()) - { - valueName = cpackComponentName + "_"; - } - valueName += "installed"; - - fileDefinitions.AddAttribute("Name", valueName); - fileDefinitions.AddAttribute("Type", "integer"); - fileDefinitions.AddAttribute("Value", "1"); - fileDefinitions.AddAttribute("KeyPath", "yes"); - fileDefinitions.EndElement("RegistryValue"); + fileDefinitions.EmitStartMenuShortcutRegistryValue( + registryKey, cpackComponentName); fileDefinitions.EndElement("Component"); fileDefinitions.EndElement("DirectoryRef"); - featureDefinitions.BeginElement("ComponentRef"); - featureDefinitions.AddAttribute("Id", componentId); - featureDefinitions.EndElement("ComponentRef"); + featureDefinitions.EmitComponentRef(componentId); - if (thisHasDesktopShortcuts) + if(thisHasDesktopShortcuts) { this->HasDesktopShortcuts = true; componentId = "CM_DESKTOP_SHORTCUT" + idSuffix; @@ -876,7 +691,7 @@ bool cmCPackWIXGenerator::CreateStartMenuShortcuts( fileDefinitions.AddAttribute("Id", componentId); fileDefinitions.AddAttribute("Guid", "*"); - for (shortcut_map_t::const_iterator + for(shortcut_map_t::const_iterator i = shortcutMap.begin(); i != shortcutMap.end(); ++i) { std::string const& id = i->first; @@ -885,34 +700,16 @@ bool cmCPackWIXGenerator::CreateStartMenuShortcuts( if (!shortcut.desktop) continue; - std::string shortcutId = std::string("CM_DS") + id; - std::string fileId = std::string("CM_F") + id; - - fileDefinitions.BeginElement("Shortcut"); - fileDefinitions.AddAttribute("Id", shortcutId); - fileDefinitions.AddAttribute("Name", shortcut.textLabel); - std::string target = "[#" + fileId + "]"; - fileDefinitions.AddAttribute("Target", target); - fileDefinitions.AddAttribute("WorkingDirectory", - shortcut.workingDirectoryId); - fileDefinitions.EndElement("Shortcut"); + fileDefinitions.EmitShortcut(id, shortcut, true); } - fileDefinitions.BeginElement("RegistryValue"); - fileDefinitions.AddAttribute("Root", "HKCU"); - fileDefinitions.AddAttribute("Key", registryKey); - fileDefinitions.AddAttribute("Name", valueName + "_desktop"); - fileDefinitions.AddAttribute("Type", "integer"); - fileDefinitions.AddAttribute("Value", "1"); - fileDefinitions.AddAttribute("KeyPath", "yes"); - fileDefinitions.EndElement("RegistryValue"); + fileDefinitions.EmitDesktopShortcutRegistryValue( + registryKey, cpackComponentName); fileDefinitions.EndElement("Component"); fileDefinitions.EndElement("DirectoryRef"); - featureDefinitions.BeginElement("ComponentRef"); - featureDefinitions.AddAttribute("Id", componentId); - featureDefinitions.EndElement("ComponentRef"); + featureDefinitions.EmitComponentRef(componentId); } featureDefinitions.EndElement("FeatureRef"); @@ -920,19 +717,6 @@ bool cmCPackWIXGenerator::CreateStartMenuShortcuts( return true; } -void cmCPackWIXGenerator::CreateUninstallShortcut( - std::string const& packageName, - cmWIXSourceWriter& fileDefinitions) -{ - fileDefinitions.BeginElement("Shortcut"); - fileDefinitions.AddAttribute("Id", "UNINSTALL"); - fileDefinitions.AddAttribute("Name", "Uninstall " + packageName); - fileDefinitions.AddAttribute("Description", "Uninstalls " + packageName); - fileDefinitions.AddAttribute("Target", "[SystemFolder]msiexec.exe"); - fileDefinitions.AddAttribute("Arguments", "/x [ProductCode]"); - fileDefinitions.EndElement("Shortcut"); -} - bool cmCPackWIXGenerator::CreateLicenseFile() { std::string licenseSourceFilename; @@ -981,11 +765,11 @@ bool cmCPackWIXGenerator::CreateLicenseFile() } void cmCPackWIXGenerator::AddDirectoryAndFileDefinitons( - const std::string& topdir, - const std::string& directoryId, - cmWIXSourceWriter& directoryDefinitions, - cmWIXSourceWriter& fileDefinitions, - cmWIXSourceWriter& featureDefinitions, + std::string const& topdir, + std::string const& directoryId, + cmWIXDirectoriesSourceWriter& directoryDefinitions, + cmWIXFilesSourceWriter& fileDefinitions, + cmWIXFeaturesSourceWriter& featureDefinitions, const std::vector& packageExecutables, const std::vector& desktopExecutables, shortcut_map_t& shortcutMap) @@ -1026,44 +810,15 @@ void cmCPackWIXGenerator::AddDirectoryAndFileDefinitons( desktopExecutables, shortcutMap); - ApplyPatchFragment(subDirectoryId, directoryDefinitions); + this->Patch.ApplyFragment(subDirectoryId, directoryDefinitions); directoryDefinitions.EndElement("Directory"); } else { - std::string componentId = std::string("CM_C") + id; - std::string fileId = std::string("CM_F") + id; + std::string componentId = fileDefinitions.EmitComponentFile( + directoryId, id, fullPath, this->Patch); - fileDefinitions.BeginElement("DirectoryRef"); - fileDefinitions.AddAttribute("Id", directoryId); - - fileDefinitions.BeginElement("Component"); - fileDefinitions.AddAttribute("Id", componentId); - fileDefinitions.AddAttribute("Guid", "*"); - - fileDefinitions.BeginElement("File"); - fileDefinitions.AddAttribute("Id", fileId); - fileDefinitions.AddAttribute("Source", fullPath); - fileDefinitions.AddAttribute("KeyPath", "yes"); - - mode_t fileMode = 0; - cmSystemTools::GetPermissions(fullPath.c_str(), fileMode); - - if(!(fileMode & S_IWRITE)) - { - fileDefinitions.AddAttribute("ReadOnly", "yes"); - } - - ApplyPatchFragment(fileId, fileDefinitions); - fileDefinitions.EndElement("File"); - - ApplyPatchFragment(componentId, fileDefinitions); - fileDefinitions.EndElement("Component"); - fileDefinitions.EndElement("DirectoryRef"); - - featureDefinitions.BeginElement("ComponentRef"); - featureDefinitions.AddAttribute("Id", componentId); - featureDefinitions.EndElement("ComponentRef"); + featureDefinitions.EmitComponentRef(componentId); for(size_t j = 0; j < packageExecutables.size(); ++j) { @@ -1092,7 +847,7 @@ void cmCPackWIXGenerator::AddDirectoryAndFileDefinitons( } bool cmCPackWIXGenerator::RequireOption( - const std::string& name, std::string &value) const + std::string const& name, std::string &value) const { const char* tmp = GetOption(name.c_str()); if(tmp) @@ -1140,13 +895,13 @@ std::string cmCPackWIXGenerator::GenerateGUID() return cmSystemTools::UpperCase(result); } -std::string cmCPackWIXGenerator::QuotePath(const std::string& path) +std::string cmCPackWIXGenerator::QuotePath(std::string const& path) { return std::string("\"") + path + '"'; } std::string cmCPackWIXGenerator::GetRightmostExtension( - const std::string& filename) + std::string const& filename) { std::string extension; @@ -1159,7 +914,7 @@ std::string cmCPackWIXGenerator::GetRightmostExtension( return cmSystemTools::LowerCase(extension); } -std::string cmCPackWIXGenerator::PathToId(const std::string& path) +std::string cmCPackWIXGenerator::PathToId(std::string const& path) { id_map_t::const_iterator i = PathToIdMap.find(path); if(i != PathToIdMap.end()) return i->second; @@ -1168,7 +923,7 @@ std::string cmCPackWIXGenerator::PathToId(const std::string& path) return id; } -std::string cmCPackWIXGenerator::CreateNewIdForPath(const std::string& path) +std::string cmCPackWIXGenerator::CreateNewIdForPath(std::string const& path) { std::vector components; cmSystemTools::SplitPath(path.c_str(), components, false); @@ -1222,7 +977,7 @@ std::string cmCPackWIXGenerator::CreateNewIdForPath(const std::string& path) } std::string cmCPackWIXGenerator::CreateHashedId( - const std::string& path, const std::string& normalizedFilename) + std::string const& path, std::string const& normalizedFilename) { cmsys::auto_ptr sha1 = cmCryptoHash::New("SHA1"); std::string hash = sha1->HashString(path.c_str()); @@ -1245,7 +1000,7 @@ std::string cmCPackWIXGenerator::CreateHashedId( } std::string cmCPackWIXGenerator::NormalizeComponentForId( - const std::string& component, size_t& replacementCount) + std::string const& component, size_t& replacementCount) { std::string result; result.resize(component.size()); @@ -1276,7 +1031,7 @@ bool cmCPackWIXGenerator::IsLegalIdCharacter(char c) } void cmCPackWIXGenerator::CollectExtensions( - const std::string& variableName, extension_set_t& extensions) + std::string const& variableName, extension_set_t& extensions) { const char *variableContent = GetOption(variableName.c_str()); if(!variableContent) return; @@ -1292,7 +1047,7 @@ void cmCPackWIXGenerator::CollectExtensions( } void cmCPackWIXGenerator::AddCustomFlags( - const std::string& variableName, std::ostream& stream) + std::string const& variableName, std::ostream& stream) { const char *variableContent = GetOption(variableName.c_str()); if(!variableContent) return; @@ -1306,69 +1061,3 @@ void cmCPackWIXGenerator::AddCustomFlags( stream << " " << QuotePath(*i); } } - -void cmCPackWIXGenerator::CreateStartMenuFolder( - cmWIXSourceWriter& directoryDefinitions) -{ - directoryDefinitions.BeginElement("Directory"); - directoryDefinitions.AddAttribute("Id", "ProgramMenuFolder"); - - directoryDefinitions.BeginElement("Directory"); - directoryDefinitions.AddAttribute("Id", "PROGRAM_MENU_FOLDER"); - const char *startMenuFolder = GetOption("CPACK_WIX_PROGRAM_MENU_FOLDER"); - directoryDefinitions.AddAttribute("Name", startMenuFolder); - directoryDefinitions.EndElement("Directory"); - - directoryDefinitions.EndElement("Directory"); -} - -void cmCPackWIXGenerator::CreateDesktopFolder( - cmWIXSourceWriter& directoryDefinitions) -{ - directoryDefinitions.BeginElement("Directory"); - directoryDefinitions.AddAttribute("Id", "DesktopFolder"); - directoryDefinitions.AddAttribute("Name", "Desktop"); - directoryDefinitions.EndElement("Directory"); -} - -void cmCPackWIXGenerator::LoadPatchFragments(const std::string& patchFilePath) -{ - cmWIXPatchParser parser(Fragments, Logger); - parser.ParseFile(patchFilePath.c_str()); -} - -void cmCPackWIXGenerator::ApplyPatchFragment( - const std::string& id, cmWIXSourceWriter& writer) -{ - cmWIXPatchParser::fragment_map_t::iterator i = Fragments.find(id); - if(i == Fragments.end()) return; - - const cmWIXPatchElement& fragment = i->second; - for(cmWIXPatchElement::child_list_t::const_iterator - j = fragment.children.begin(); j != fragment.children.end(); ++j) - { - ApplyPatchElement(**j, writer); - } - - Fragments.erase(i); -} - -void cmCPackWIXGenerator::ApplyPatchElement( - const cmWIXPatchElement& element, cmWIXSourceWriter& writer) -{ - writer.BeginElement(element.name); - - for(cmWIXPatchElement::attributes_t::const_iterator - i = element.attributes.begin(); i != element.attributes.end(); ++i) - { - writer.AddAttribute(i->first, i->second); - } - - for(cmWIXPatchElement::child_list_t::const_iterator - i = element.children.begin(); i != element.children.end(); ++i) - { - ApplyPatchElement(**i, writer); - } - - writer.EndElement(element.name); -} diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.h b/Source/CPack/WiX/cmCPackWIXGenerator.h index 1de4810ba..ee66c05d0 100644 --- a/Source/CPack/WiX/cmCPackWIXGenerator.h +++ b/Source/CPack/WiX/cmCPackWIXGenerator.h @@ -13,25 +13,18 @@ #ifndef cmCPackWIXGenerator_h #define cmCPackWIXGenerator_h -#include "cmWIXPatchParser.h" +#include "cmWIXPatch.h" +#include "cmWIXShortcut.h" #include #include #include -struct cmWIXShortcut -{ - cmWIXShortcut() - :desktop(false) - {} - - std::string textLabel; - std::string workingDirectoryId; - bool desktop; -}; - class cmWIXSourceWriter; +class cmWIXDirectoriesSourceWriter; +class cmWIXFilesSourceWriter; +class cmWIXFeaturesSourceWriter; /** \class cmCPackWIXGenerator * \brief A generator for WIX files @@ -78,48 +71,37 @@ private: bool PackageFilesImpl(); - bool CreateWiXVariablesIncludeFile(); + void CreateWiXVariablesIncludeFile(); void CopyDefinition( - cmWIXSourceWriter &source, const std::string &name); + cmWIXSourceWriter &source, std::string const& name); void AddDefinition(cmWIXSourceWriter& source, - const std::string& name, const std::string& value); + std::string const& name, std::string const& value); bool CreateWiXSourceFiles(); - bool CreateCMakePackageRegistryEntry( - cmWIXSourceWriter& featureDefinitions); + std::string GetProgramFilesFolderId() const; + + bool GenerateMainSourceFileFromTemplate(); bool CreateFeatureHierarchy( - cmWIXSourceWriter& featureDefinitions); - - bool EmitFeatureForComponentGroup( - cmWIXSourceWriter& featureDefinitions, - cmCPackComponentGroup const& group); - - bool EmitFeatureForComponent( - cmWIXSourceWriter& featureDefinitions, - cmCPackComponent const& component); + cmWIXFeaturesSourceWriter& featureDefinitions); bool AddComponentsToFeature( std::string const& rootPath, std::string const& featureId, - cmWIXSourceWriter& directoryDefinitions, - cmWIXSourceWriter& fileDefinitions, - cmWIXSourceWriter& featureDefinitions, + cmWIXDirectoriesSourceWriter& directoryDefinitions, + cmWIXFilesSourceWriter& fileDefinitions, + cmWIXFeaturesSourceWriter& featureDefinitions, shortcut_map_t& shortcutMap); bool CreateStartMenuShortcuts( std::string const& cpackComponentName, std::string const& featureId, shortcut_map_t& shortcutMap, - cmWIXSourceWriter& fileDefinitions, - cmWIXSourceWriter& featureDefinitions); - - void CreateUninstallShortcut( - std::string const& packageName, - cmWIXSourceWriter& fileDefinitions); + cmWIXFilesSourceWriter& fileDefinitions, + cmWIXFeaturesSourceWriter& featureDefinitions); void AppendUserSuppliedExtraSources(); @@ -127,60 +109,49 @@ private: bool CreateLicenseFile(); - bool RunWiXCommand(const std::string& command); + bool RunWiXCommand(std::string const& command); bool RunCandleCommand( - const std::string& sourceFile, const std::string& objectFile); + std::string const& sourceFile, std::string const& objectFile); - bool RunLightCommand(const std::string& objectFiles); + bool RunLightCommand(std::string const& objectFiles); - void AddDirectoryAndFileDefinitons(const std::string& topdir, - const std::string& directoryId, - cmWIXSourceWriter& directoryDefinitions, - cmWIXSourceWriter& fileDefinitions, - cmWIXSourceWriter& featureDefinitions, + void AddDirectoryAndFileDefinitons(std::string const& topdir, + std::string const& directoryId, + cmWIXDirectoriesSourceWriter& directoryDefinitions, + cmWIXFilesSourceWriter& fileDefinitions, + cmWIXFeaturesSourceWriter& featureDefinitions, const std::vector& pkgExecutables, const std::vector& desktopExecutables, shortcut_map_t& shortcutMap); - bool RequireOption(const std::string& name, std::string& value) const; + bool RequireOption(std::string const& name, std::string& value) const; std::string GetArchitecture() const; static std::string GenerateGUID(); - static std::string QuotePath(const std::string& path); + static std::string QuotePath(std::string const& path); - static std::string GetRightmostExtension(const std::string& filename); + static std::string GetRightmostExtension(std::string const& filename); - std::string PathToId(const std::string& path); + std::string PathToId(std::string const& path); - std::string CreateNewIdForPath(const std::string& path); + std::string CreateNewIdForPath(std::string const& path); static std::string CreateHashedId( - const std::string& path, const std::string& normalizedFilename); + std::string const& path, std::string const& normalizedFilename); std::string NormalizeComponentForId( - const std::string& component, size_t& replacementCount); + std::string const& component, size_t& replacementCount); static bool IsLegalIdCharacter(char c); void CollectExtensions( - const std::string& variableName, extension_set_t& extensions); + std::string const& variableName, extension_set_t& extensions); void AddCustomFlags( - const std::string& variableName, std::ostream& stream); - - void CreateStartMenuFolder(cmWIXSourceWriter& directoryDefinitions); - - void CreateDesktopFolder(cmWIXSourceWriter& directoryDefinitions); - - void LoadPatchFragments(const std::string& patchFilePath); - - void ApplyPatchFragment(const std::string& id, cmWIXSourceWriter& writer); - - void ApplyPatchElement(const cmWIXPatchElement& element, - cmWIXSourceWriter& writer); + std::string const& variableName, std::ostream& stream); std::vector WixSources; id_map_t PathToIdMap; @@ -189,9 +160,11 @@ private: extension_set_t CandleExtensions; extension_set_t LightExtensions; - cmWIXPatchParser::fragment_map_t Fragments; - bool HasDesktopShortcuts; + + std::string CPackTopLevel; + + cmWIXPatch Patch; }; #endif diff --git a/Source/CPack/WiX/cmWIXDirectoriesSourceWriter.cxx b/Source/CPack/WiX/cmWIXDirectoriesSourceWriter.cxx new file mode 100644 index 000000000..a93f89bae --- /dev/null +++ b/Source/CPack/WiX/cmWIXDirectoriesSourceWriter.cxx @@ -0,0 +1,87 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2014 Kitware, Inc. + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ + +#include "cmWIXDirectoriesSourceWriter.h" + +cmWIXDirectoriesSourceWriter::cmWIXDirectoriesSourceWriter(cmCPackLog* logger, + std::string const& filename): + cmWIXSourceWriter(logger, filename) +{ + +} + +void cmWIXDirectoriesSourceWriter::EmitStartMenuFolder( + std::string const& startMenuFolder) +{ + BeginElement("Directory"); + AddAttribute("Id", "ProgramMenuFolder"); + + BeginElement("Directory"); + AddAttribute("Id", "PROGRAM_MENU_FOLDER"); + AddAttribute("Name", startMenuFolder); + EndElement("Directory"); + + EndElement("Directory"); +} + +void cmWIXDirectoriesSourceWriter::EmitDesktopFolder() +{ + BeginElement("Directory"); + AddAttribute("Id", "DesktopFolder"); + AddAttribute("Name", "Desktop"); + EndElement("Directory"); +} + +size_t cmWIXDirectoriesSourceWriter::BeginInstallationPrefixDirectory( + std::string const& programFilesFolderId, + std::string const& installRootString) +{ + BeginElement("Directory"); + AddAttribute("Id", programFilesFolderId); + + std::vector installRoot; + + cmSystemTools::SplitPath(installRootString.c_str(), installRoot); + + if(!installRoot.empty() && installRoot.back().empty()) + { + installRoot.pop_back(); + } + + for(size_t i = 1; i < installRoot.size(); ++i) + { + BeginElement("Directory"); + + if(i == installRoot.size() - 1) + { + AddAttribute("Id", "INSTALL_ROOT"); + } + else + { + std::stringstream tmp; + tmp << "INSTALL_PREFIX_" << i; + AddAttribute("Id", tmp.str()); + } + + AddAttribute("Name", installRoot[i]); + } + + return installRoot.size(); +} + +void cmWIXDirectoriesSourceWriter::EndInstallationPrefixDirectory(size_t size) +{ + for(size_t i = 0; i < size; ++i) + { + EndElement("Directory"); + } +} diff --git a/Source/CPack/WiX/cmWIXDirectoriesSourceWriter.h b/Source/CPack/WiX/cmWIXDirectoriesSourceWriter.h new file mode 100644 index 000000000..f51fdb4bb --- /dev/null +++ b/Source/CPack/WiX/cmWIXDirectoriesSourceWriter.h @@ -0,0 +1,42 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2014 Kitware, Inc. + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ + +#ifndef cmWIXDirectoriesSourceWriter_h +#define cmWIXDirectoriesSourceWriter_h + +#include "cmWIXSourceWriter.h" + +#include + +#include + +/** \class cmWIXDirectoriesSourceWriter + * \brief Helper class to generate directories.wxs + */ +class cmWIXDirectoriesSourceWriter : public cmWIXSourceWriter +{ +public: + cmWIXDirectoriesSourceWriter(cmCPackLog* logger, + std::string const& filename); + + void EmitStartMenuFolder(std::string const& startMenuFolder); + + void EmitDesktopFolder(); + + size_t BeginInstallationPrefixDirectory( + std::string const& programFilesFolderId, + std::string const& installRootString); + + void EndInstallationPrefixDirectory(size_t size); +}; + +#endif diff --git a/Source/CPack/WiX/cmWIXFeaturesSourceWriter.cxx b/Source/CPack/WiX/cmWIXFeaturesSourceWriter.cxx new file mode 100644 index 000000000..0bcfc389f --- /dev/null +++ b/Source/CPack/WiX/cmWIXFeaturesSourceWriter.cxx @@ -0,0 +1,102 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2014 Kitware, Inc. + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ + +#include "cmWIXFeaturesSourceWriter.h" + +cmWIXFeaturesSourceWriter::cmWIXFeaturesSourceWriter(cmCPackLog* logger, + std::string const& filename): + cmWIXSourceWriter(logger, filename) +{ + +} + +void cmWIXFeaturesSourceWriter::CreateCMakePackageRegistryEntry( + std::string const& package, + std::string const& upgradeGuid) +{ + BeginElement("Component"); + AddAttribute("Id", "CM_PACKAGE_REGISTRY"); + AddAttribute("Directory", "TARGETDIR"); + AddAttribute("Guid", "*"); + + std::string registryKey = + std::string("Software\\Kitware\\CMake\\Packages\\") + package; + + BeginElement("RegistryValue"); + AddAttribute("Root", "HKLM"); + AddAttribute("Key", registryKey); + AddAttribute("Name", upgradeGuid); + AddAttribute("Type", "string"); + AddAttribute("Value", "[INSTALL_ROOT]"); + AddAttribute("KeyPath", "yes"); + EndElement("RegistryValue"); + + EndElement("Component"); +} + +void cmWIXFeaturesSourceWriter::EmitFeatureForComponentGroup( + cmCPackComponentGroup const& group) +{ + BeginElement("Feature"); + AddAttribute("Id", "CM_G_" + group.Name); + + if(group.IsExpandedByDefault) + { + AddAttribute("Display", "expand"); + } + + AddAttributeUnlessEmpty("Title", group.DisplayName); + AddAttributeUnlessEmpty("Description", group.Description); + + for(std::vector::const_iterator + i = group.Subgroups.begin(); i != group.Subgroups.end(); ++i) + { + EmitFeatureForComponentGroup(**i); + } + + for(std::vector::const_iterator + i = group.Components.begin(); i != group.Components.end(); ++i) + { + EmitFeatureForComponent(**i); + } + + EndElement("Feature"); +} + +void cmWIXFeaturesSourceWriter::EmitFeatureForComponent( + cmCPackComponent const& component) +{ + BeginElement("Feature"); + AddAttribute("Id", "CM_C_" + component.Name); + + AddAttributeUnlessEmpty("Title", component.DisplayName); + AddAttributeUnlessEmpty("Description", component.Description); + + if(component.IsRequired) + { + AddAttribute("Absent", "disallow"); + } + + if(component.IsHidden) + { + AddAttribute("Display", "hidden"); + } + + EndElement("Feature"); +} + +void cmWIXFeaturesSourceWriter::EmitComponentRef(std::string const& id) +{ + BeginElement("ComponentRef"); + AddAttribute("Id", id); + EndElement("ComponentRef"); +} diff --git a/Source/CPack/WiX/cmWIXFeaturesSourceWriter.h b/Source/CPack/WiX/cmWIXFeaturesSourceWriter.h new file mode 100644 index 000000000..767041755 --- /dev/null +++ b/Source/CPack/WiX/cmWIXFeaturesSourceWriter.h @@ -0,0 +1,39 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2014 Kitware, Inc. + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ + +#ifndef cmWIXFeaturesSourceWriter_h +#define cmWIXFeaturesSourceWriter_h + +#include "cmWIXSourceWriter.h" +#include + +/** \class cmWIXFeaturesSourceWriter + * \brief Helper class to generate features.wxs + */ +class cmWIXFeaturesSourceWriter : public cmWIXSourceWriter +{ +public: + cmWIXFeaturesSourceWriter(cmCPackLog* logger, + std::string const& filename); + + void CreateCMakePackageRegistryEntry( + std::string const& package, + std::string const& upgradeGuid); + + void EmitFeatureForComponentGroup(const cmCPackComponentGroup& group); + + void EmitFeatureForComponent(const cmCPackComponent& component); + + void EmitComponentRef(std::string const& id); +}; + +#endif diff --git a/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx b/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx new file mode 100644 index 000000000..0835f3ade --- /dev/null +++ b/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx @@ -0,0 +1,149 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2014 Kitware, Inc. + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ + +#include "cmWIXFilesSourceWriter.h" + +#include +#include + +cmWIXFilesSourceWriter::cmWIXFilesSourceWriter(cmCPackLog* logger, + std::string const& filename): + cmWIXSourceWriter(logger, filename) +{ + +} + +void cmWIXFilesSourceWriter::EmitShortcut( + std::string const& id, + cmWIXShortcut const& shortcut, + bool desktop) +{ + std::string shortcutId; + + if(desktop) + { + shortcutId = "CM_DS"; + } + else + { + shortcutId = "CM_S"; + } + + shortcutId += id; + + std::string fileId = std::string("CM_F") + id; + + BeginElement("Shortcut"); + AddAttribute("Id", shortcutId); + AddAttribute("Name", shortcut.textLabel); + std::string target = "[#" + fileId + "]"; + AddAttribute("Target", target); + AddAttribute("WorkingDirectory", shortcut.workingDirectoryId); + EndElement("Shortcut"); +} + +void cmWIXFilesSourceWriter::EmitRemoveFolder(std::string const& id) +{ + BeginElement("RemoveFolder"); + AddAttribute("Id", id); + AddAttribute("On", "uninstall"); + EndElement("RemoveFolder"); +} + +void cmWIXFilesSourceWriter::EmitStartMenuShortcutRegistryValue( + std::string const& registryKey, + std::string const& cpackComponentName) +{ + EmitInstallRegistryValue(registryKey, cpackComponentName, std::string()); +} + +void cmWIXFilesSourceWriter::EmitDesktopShortcutRegistryValue( + std::string const& registryKey, + std::string const& cpackComponentName) +{ + EmitInstallRegistryValue(registryKey, cpackComponentName, "_desktop"); +} + +void cmWIXFilesSourceWriter::EmitInstallRegistryValue( + std::string const& registryKey, + std::string const& cpackComponentName, + std::string const& suffix) +{ + std::string valueName; + if(!cpackComponentName.empty()) + { + valueName = cpackComponentName + "_"; + } + + valueName += "installed"; + valueName += suffix; + + BeginElement("RegistryValue"); + AddAttribute("Root", "HKCU"); + AddAttribute("Key", registryKey); + AddAttribute("Name", valueName); + AddAttribute("Type", "integer"); + AddAttribute("Value", "1"); + AddAttribute("KeyPath", "yes"); + EndElement("RegistryValue"); +} + +void cmWIXFilesSourceWriter::EmitUninstallShortcut( + std::string const& packageName) +{ + BeginElement("Shortcut"); + AddAttribute("Id", "UNINSTALL"); + AddAttribute("Name", "Uninstall " + packageName); + AddAttribute("Description", "Uninstalls " + packageName); + AddAttribute("Target", "[SystemFolder]msiexec.exe"); + AddAttribute("Arguments", "/x [ProductCode]"); + EndElement("Shortcut"); +} + +std::string cmWIXFilesSourceWriter::EmitComponentFile( + std::string const& directoryId, + std::string const& id, + std::string const& filePath, + cmWIXPatch &patch) +{ + std::string componentId = std::string("CM_C") + id; + std::string fileId = std::string("CM_F") + id; + + BeginElement("DirectoryRef"); + AddAttribute("Id", directoryId); + + BeginElement("Component"); + AddAttribute("Id", componentId); + AddAttribute("Guid", "*"); + + BeginElement("File"); + AddAttribute("Id", fileId); + AddAttribute("Source", filePath); + AddAttribute("KeyPath", "yes"); + + mode_t fileMode = 0; + cmSystemTools::GetPermissions(filePath.c_str(), fileMode); + + if(!(fileMode & S_IWRITE)) + { + AddAttribute("ReadOnly", "yes"); + } + + patch.ApplyFragment(fileId, *this); + EndElement("File"); + + patch.ApplyFragment(componentId, *this); + EndElement("Component"); + EndElement("DirectoryRef"); + + return componentId; +} diff --git a/Source/CPack/WiX/cmWIXFilesSourceWriter.h b/Source/CPack/WiX/cmWIXFilesSourceWriter.h new file mode 100644 index 000000000..d22d27006 --- /dev/null +++ b/Source/CPack/WiX/cmWIXFilesSourceWriter.h @@ -0,0 +1,62 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2014 Kitware, Inc. + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ + +#ifndef cmWIXFilesSourceWriter_h +#define cmWIXFilesSourceWriter_h + +#include "cmWIXSourceWriter.h" +#include "cmWIXShortcut.h" +#include "cmWIXPatch.h" + +#include + +/** \class cmWIXFilesSourceWriter + * \brief Helper class to generate files.wxs + */ +class cmWIXFilesSourceWriter : public cmWIXSourceWriter +{ +public: + cmWIXFilesSourceWriter(cmCPackLog* logger, + std::string const& filename); + + void EmitShortcut( + std::string const& id, + cmWIXShortcut const& shortcut, + bool desktop); + + void EmitRemoveFolder(std::string const& id); + + void EmitStartMenuShortcutRegistryValue( + std::string const& registryKey, + std::string const& cpackComponentName); + + void EmitDesktopShortcutRegistryValue( + std::string const& registryKey, + std::string const& cpackComponentName); + + void EmitUninstallShortcut(std::string const& packageName); + + std::string EmitComponentFile( + std::string const& directoryId, + std::string const& id, + std::string const& filePath, + cmWIXPatch &patch); + +private: + void EmitInstallRegistryValue( + std::string const& registryKey, + std::string const& cpackComponentName, + std::string const& suffix); +}; + + +#endif diff --git a/Source/CPack/WiX/cmWIXPatch.cxx b/Source/CPack/WiX/cmWIXPatch.cxx new file mode 100644 index 000000000..b5202e0c0 --- /dev/null +++ b/Source/CPack/WiX/cmWIXPatch.cxx @@ -0,0 +1,91 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2014 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ + +#include "cmWIXPatch.h" + +#include + +cmWIXPatch::cmWIXPatch(cmCPackLog* logger): + Logger(logger) +{ + +} + +void cmWIXPatch::LoadFragments(std::string const& patchFilePath) +{ + cmWIXPatchParser parser(Fragments, Logger); + parser.ParseFile(patchFilePath.c_str()); +} + +void cmWIXPatch::ApplyFragment( + std::string const& id, cmWIXSourceWriter& writer) +{ + cmWIXPatchParser::fragment_map_t::iterator i = Fragments.find(id); + if(i == Fragments.end()) return; + + const cmWIXPatchElement& fragment = i->second; + for(cmWIXPatchElement::child_list_t::const_iterator + j = fragment.children.begin(); j != fragment.children.end(); ++j) + { + ApplyElement(**j, writer); + } + + Fragments.erase(i); +} + +void cmWIXPatch::ApplyElement( + const cmWIXPatchElement& element, cmWIXSourceWriter& writer) +{ + writer.BeginElement(element.name); + + for(cmWIXPatchElement::attributes_t::const_iterator + i = element.attributes.begin(); i != element.attributes.end(); ++i) + { + writer.AddAttribute(i->first, i->second); + } + + for(cmWIXPatchElement::child_list_t::const_iterator + i = element.children.begin(); i != element.children.end(); ++i) + { + ApplyElement(**i, writer); + } + + writer.EndElement(element.name); +} + + +bool cmWIXPatch::CheckForUnappliedFragments() +{ + std::string fragmentList; + for(cmWIXPatchParser::fragment_map_t::const_iterator + i = Fragments.begin(); i != Fragments.end(); ++i) + { + if(!fragmentList.empty()) + { + fragmentList += ", "; + } + + fragmentList += "'"; + fragmentList += i->first; + fragmentList += "'"; + } + + if(fragmentList.size()) + { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Some XML patch fragments did not have matching IDs: " << + fragmentList << std::endl); + return false; + } + + return true; +} diff --git a/Source/CPack/WiX/cmWIXPatch.h b/Source/CPack/WiX/cmWIXPatch.h new file mode 100644 index 000000000..7b7b2f170 --- /dev/null +++ b/Source/CPack/WiX/cmWIXPatch.h @@ -0,0 +1,45 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2014 Kitware, Inc. + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ + +#ifndef cmWIXPatch_h +#define cmWIXPatch_h + +#include "cmWIXSourceWriter.h" +#include "cmWIXPatchParser.h" + +#include + +/** \class cmWIXPatch + * \brief Class that maintains and applies patch fragments + */ +class cmWIXPatch +{ +public: + cmWIXPatch(cmCPackLog* logger); + + void LoadFragments(std::string const& patchFilePath); + + void ApplyFragment(std::string const& id, cmWIXSourceWriter& writer); + + bool CheckForUnappliedFragments(); + +private: + void ApplyElement(const cmWIXPatchElement& element, + cmWIXSourceWriter& writer); + + cmCPackLog* Logger; + + cmWIXPatchParser::fragment_map_t Fragments; +}; + + +#endif diff --git a/Source/CPack/WiX/cmWIXPatchParser.cxx b/Source/CPack/WiX/cmWIXPatchParser.cxx index 7ceaf1f86..10af1f6af 100644 --- a/Source/CPack/WiX/cmWIXPatchParser.cxx +++ b/Source/CPack/WiX/cmWIXPatchParser.cxx @@ -132,7 +132,7 @@ void cmWIXPatchParser::ReportError(int line, int column, const char* msg) Valid = false; } -void cmWIXPatchParser::ReportValidationError(const std::string& message) +void cmWIXPatchParser::ReportValidationError(std::string const& message) { ReportError(XML_GetCurrentLineNumber(Parser), XML_GetCurrentColumnNumber(Parser), diff --git a/Source/CPack/WiX/cmWIXPatchParser.h b/Source/CPack/WiX/cmWIXPatchParser.h index 91b3b6616..da3adf509 100644 --- a/Source/CPack/WiX/cmWIXPatchParser.h +++ b/Source/CPack/WiX/cmWIXPatchParser.h @@ -50,7 +50,7 @@ private: virtual void EndElement(const char *name); virtual void ReportError(int line, int column, const char* msg); - void ReportValidationError(const std::string& message); + void ReportValidationError(std::string const& message); bool IsValid() const; diff --git a/Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx b/Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx index ddc1d7138..f27caa941 100644 --- a/Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx +++ b/Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx @@ -15,7 +15,7 @@ #include cmWIXRichTextFormatWriter::cmWIXRichTextFormatWriter( - const std::string& filename): + std::string const& filename): File(filename.c_str(), std::ios::binary) { StartGroup(); @@ -33,7 +33,7 @@ cmWIXRichTextFormatWriter::~cmWIXRichTextFormatWriter() File.put(0); } -void cmWIXRichTextFormatWriter::AddText(const std::string& text) +void cmWIXRichTextFormatWriter::AddText(std::string const& text) { typedef unsigned char rtf_byte_t; @@ -167,12 +167,12 @@ void cmWIXRichTextFormatWriter::WriteDocumentPrefix() ControlWord("fs20"); } -void cmWIXRichTextFormatWriter::ControlWord(const std::string& keyword) +void cmWIXRichTextFormatWriter::ControlWord(std::string const& keyword) { File << "\\" << keyword; } -void cmWIXRichTextFormatWriter::NewControlWord(const std::string& keyword) +void cmWIXRichTextFormatWriter::NewControlWord(std::string const& keyword) { File << "\\*\\" << keyword; } diff --git a/Source/CPack/WiX/cmWIXRichTextFormatWriter.h b/Source/CPack/WiX/cmWIXRichTextFormatWriter.h index 2b665d47e..f6327fbd5 100644 --- a/Source/CPack/WiX/cmWIXRichTextFormatWriter.h +++ b/Source/CPack/WiX/cmWIXRichTextFormatWriter.h @@ -22,10 +22,10 @@ class cmWIXRichTextFormatWriter { public: - cmWIXRichTextFormatWriter(const std::string& filename); + cmWIXRichTextFormatWriter(std::string const& filename); ~cmWIXRichTextFormatWriter(); - void AddText(const std::string& text); + void AddText(std::string const& text); private: void WriteHeader(); @@ -35,8 +35,8 @@ private: void WriteDocumentPrefix(); - void ControlWord(const std::string& keyword); - void NewControlWord(const std::string& keyword); + void ControlWord(std::string const& keyword); + void NewControlWord(std::string const& keyword); void StartGroup(); void EndGroup(); diff --git a/Source/CPack/WiX/cmWIXShortcut.h b/Source/CPack/WiX/cmWIXShortcut.h new file mode 100644 index 000000000..93095e03f --- /dev/null +++ b/Source/CPack/WiX/cmWIXShortcut.h @@ -0,0 +1,29 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2014 Kitware, Inc. + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ + +#ifndef cmWIXFilesShortcut_h +#define cmWIXFilesShortcut_h + +#include + +struct cmWIXShortcut +{ + cmWIXShortcut() + :desktop(false) + {} + + std::string textLabel; + std::string workingDirectoryId; + bool desktop; +}; + +#endif diff --git a/Source/CPack/WiX/cmWIXSourceWriter.cxx b/Source/CPack/WiX/cmWIXSourceWriter.cxx index e83c22618..aad19daf1 100644 --- a/Source/CPack/WiX/cmWIXSourceWriter.cxx +++ b/Source/CPack/WiX/cmWIXSourceWriter.cxx @@ -17,7 +17,7 @@ #include cmWIXSourceWriter::cmWIXSourceWriter(cmCPackLog* logger, - const std::string& filename, + std::string const& filename, bool isIncludeFile): Logger(logger), File(filename.c_str()), @@ -51,7 +51,7 @@ cmWIXSourceWriter::~cmWIXSourceWriter() EndElement(Elements.back()); } -void cmWIXSourceWriter::BeginElement(const std::string& name) +void cmWIXSourceWriter::BeginElement(std::string const& name) { if(State == BEGIN) { @@ -101,7 +101,7 @@ void cmWIXSourceWriter::EndElement(std::string const& name) } void cmWIXSourceWriter::AddProcessingInstruction( - const std::string& target, const std::string& content) + std::string const& target, std::string const& content) { if(State == BEGIN) { @@ -116,7 +116,7 @@ void cmWIXSourceWriter::AddProcessingInstruction( } void cmWIXSourceWriter::AddAttribute( - const std::string& key, const std::string& value) + std::string const& key, std::string const& value) { std::string utf8 = WindowsCodepageToUtf8(value); @@ -124,7 +124,7 @@ void cmWIXSourceWriter::AddAttribute( } void cmWIXSourceWriter::AddAttributeUnlessEmpty( - const std::string& key, const std::string& value) + std::string const& key, std::string const& value) { if(value.size()) { @@ -132,7 +132,7 @@ void cmWIXSourceWriter::AddAttributeUnlessEmpty( } } -std::string cmWIXSourceWriter::WindowsCodepageToUtf8(const std::string& value) +std::string cmWIXSourceWriter::WindowsCodepageToUtf8(std::string const& value) { if(value.empty()) { @@ -184,7 +184,7 @@ void cmWIXSourceWriter::Indent(size_t count) } std::string cmWIXSourceWriter::EscapeAttributeValue( - const std::string& value) + std::string const& value) { std::string result; result.reserve(value.size()); diff --git a/Source/CPack/WiX/cmWIXSourceWriter.h b/Source/CPack/WiX/cmWIXSourceWriter.h index 894ad78a0..65b724056 100644 --- a/Source/CPack/WiX/cmWIXSourceWriter.h +++ b/Source/CPack/WiX/cmWIXSourceWriter.h @@ -26,24 +26,24 @@ class cmWIXSourceWriter { public: cmWIXSourceWriter(cmCPackLog* logger, - const std::string& filename, bool isIncludeFile = false); + std::string const& filename, bool isIncludeFile = false); ~cmWIXSourceWriter(); - void BeginElement(const std::string& name); + void BeginElement(std::string const& name); - void EndElement(const std::string& name); + void EndElement(std::string const& name); void AddProcessingInstruction( - const std::string& target, const std::string& content); + std::string const& target, std::string const& content); void AddAttribute( - const std::string& key, const std::string& value); + std::string const& key, std::string const& value); void AddAttributeUnlessEmpty( - const std::string& key, const std::string& value); + std::string const& key, std::string const& value); - static std::string WindowsCodepageToUtf8(const std::string& value); + static std::string WindowsCodepageToUtf8(std::string const& value); private: enum State @@ -56,7 +56,7 @@ private: void Indent(size_t count); - static std::string EscapeAttributeValue(const std::string& value); + static std::string EscapeAttributeValue(std::string const& value); cmCPackLog* Logger;