From 8c0e32550cf8afbb8419dff3698915b550e9c86d Mon Sep 17 00:00:00 2001 From: Fredrik Axelsson Date: Fri, 1 Mar 2013 11:09:58 +0900 Subject: CPackWIX: Handle CPACK_PACKAGE_EXECUTABLES (#13967) Add start menu items including an uninstall shortcut. Add variable CPACK_WIX_PROGRAM_MENU_FOLDER to configure folder name. --- Modules/CPackWIX.cmake | 6 ++ Source/CPack/WiX/cmCPackWIXGenerator.cxx | 124 ++++++++++++++++++++++++++++--- Source/CPack/WiX/cmCPackWIXGenerator.h | 6 +- Tests/CPackWiXGenerator/CMakeLists.txt | 2 + 4 files changed, 128 insertions(+), 10 deletions(-) diff --git a/Modules/CPackWIX.cmake b/Modules/CPackWIX.cmake index 0c0a8f1..69a181e 100644 --- a/Modules/CPackWIX.cmake +++ b/Modules/CPackWIX.cmake @@ -76,6 +76,12 @@ # This image must be 493 by 312 pixels. # ##end +# +##variable +# CPACK_WIX_PROGRAM_MENU_FOLDER - Start menu folder name for launcher. +# +# If this variable is not set, it will be initialized with CPACK_PACKAGE_NAME +##end #============================================================================= # Copyright 2012 Kitware, Inc. diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.cxx b/Source/CPack/WiX/cmCPackWIXGenerator.cxx index e8b0ea9..fc51b77 100644 --- a/Source/CPack/WiX/cmCPackWIXGenerator.cxx +++ b/Source/CPack/WiX/cmCPackWIXGenerator.cxx @@ -224,6 +224,9 @@ bool cmCPackWIXGenerator::CreateWiXVariablesIncludeFile() CopyDefinition(includeFile, "CPACK_WIX_PRODUCT_ICON"); CopyDefinition(includeFile, "CPACK_WIX_UI_BANNER"); CopyDefinition(includeFile, "CPACK_WIX_UI_DIALOG"); + SetOptionIfNotSet("CPACK_WIX_PROGRAM_MENU_FOLDER", + GetOption("CPACK_PACKAGE_NAME")); + CopyDefinition(includeFile, "CPACK_WIX_PROGRAM_MENU_FOLDER"); return true; } @@ -339,22 +342,105 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles() featureDefinitions.BeginElement("FeatureRef"); featureDefinitions.AddAttribute("Id", "ProductFeature"); + const char *cpackPackageExecutables = GetOption("CPACK_PACKAGE_EXECUTABLES"); + std::vector cpackPkgExecutables; + std::string regKey; + if ( cpackPackageExecutables ) + { + cmSystemTools::ExpandListArgument(cpackPackageExecutables, + cpackPkgExecutables); + if ( cpackPkgExecutables.size() % 2 != 0 ) + { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "CPACK_PACKAGE_EXECUTABLES should contain pairs of and " + "." << std::endl); + cpackPkgExecutables.clear(); + } + + const char *cpackVendor = GetOption("CPACK_PACKAGE_VENDOR"); + const char *cpackPkgName = GetOption("CPACK_PACKAGE_NAME"); + if (!cpackVendor || !cpackPkgName) + { + cmCPackLogger(cmCPackLog::LOG_WARNING, "CPACK_PACKAGE_VENDOR and " + "CPACK_PACKAGE_NAME must be defined for shortcut creation" << std::endl); + cpackPkgExecutables.clear(); + } + else + { + regKey = std::string("Software/") + cpackVendor + "/" + cpackPkgName; + } + } + + std::vector dirIdExecutables; AddDirectoryAndFileDefinitons( toplevel, "INSTALL_ROOT", directoryDefinitions, fileDefinitions, featureDefinitions, - directoryCounter, fileCounter); - - featureDefinitions.EndElement(); - featureDefinitions.EndElement(); - fileDefinitions.EndElement(); + directoryCounter, fileCounter, cpackPkgExecutables, dirIdExecutables); for(size_t i = 1; i < install_root.size(); ++i) { directoryDefinitions.EndElement(); } - directoryDefinitions.EndElement(); directoryDefinitions.EndElement(); + + if (dirIdExecutables.size() > 0 && dirIdExecutables.size() % 3 == 0) { + std::vector::iterator it; + for ( it = dirIdExecutables.begin() ; + it != dirIdExecutables.end(); + ++it) + { + std::string fileName = *it++; + std::string iconName = *it++; + std::string directoryId = *it; + + fileDefinitions.BeginElement("DirectoryRef"); + fileDefinitions.AddAttribute("Id", "PROGRAM_MENU_FOLDER"); + fileDefinitions.BeginElement("Component"); + fileDefinitions.AddAttribute("Id", "SHORTCUT"); + fileDefinitions.AddAttribute("Guid", "*"); + fileDefinitions.BeginElement("Shortcut"); + fileDefinitions.AddAttribute("Id", "SHORTCUT_"); + fileDefinitions.AddAttribute("Name", iconName); + std::string target = "[" + directoryId + "]" + fileName; + fileDefinitions.AddAttribute("Target", target); + fileDefinitions.AddAttribute("WorkingDirectory", directoryId); + fileDefinitions.EndElement(); + } + fileDefinitions.BeginElement("Shortcut"); + fileDefinitions.AddAttribute("Id", "UNINSTALL"); + std::string pkgName = GetOption("CPACK_PACKAGE_NAME"); + fileDefinitions.AddAttribute("Name", "Uninstall " + pkgName); + fileDefinitions.AddAttribute("Description", "Uninstalls " + pkgName); + fileDefinitions.AddAttribute("Target", "[SystemFolder]msiexec.exe"); + fileDefinitions.AddAttribute("Arguments", "/x [ProductCode]"); + fileDefinitions.EndElement(); + fileDefinitions.BeginElement("RemoveFolder"); + fileDefinitions.AddAttribute("Id", "PROGRAM_MENU_FOLDER"); + fileDefinitions.AddAttribute("On", "uninstall"); + fileDefinitions.EndElement(); + fileDefinitions.BeginElement("RegistryValue"); + fileDefinitions.AddAttribute("Root", "HKCU"); + fileDefinitions.AddAttribute("Key", regKey); + fileDefinitions.AddAttribute("Name", "installed"); + fileDefinitions.AddAttribute("Type", "integer"); + fileDefinitions.AddAttribute("Value", "1"); + fileDefinitions.AddAttribute("KeyPath", "yes"); + + featureDefinitions.BeginElement("ComponentRef"); + featureDefinitions.AddAttribute("Id", "SHORTCUT"); + featureDefinitions.EndElement(); + 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); + } + + featureDefinitions.EndElement(); + featureDefinitions.EndElement(); + fileDefinitions.EndElement(); directoryDefinitions.EndElement(); std::string wixTemplate = FindTemplate("WIX.template.in"); @@ -435,7 +521,9 @@ void cmCPackWIXGenerator::AddDirectoryAndFileDefinitons( cmWIXSourceWriter& fileDefinitions, cmWIXSourceWriter& featureDefinitions, size_t& directoryCounter, - size_t& fileCounter) + size_t& fileCounter, + const std::vector& pkgExecutables, + std::vector& dirIdExecutables) { cmsys::Directory dir; dir.Load(topdir.c_str()); @@ -467,9 +555,10 @@ void cmCPackWIXGenerator::AddDirectoryAndFileDefinitons( fileDefinitions, featureDefinitions, directoryCounter, - fileCounter); + fileCounter, + pkgExecutables, + dirIdExecutables); - directoryDefinitions.EndElement(); } else { @@ -499,6 +588,23 @@ void cmCPackWIXGenerator::AddDirectoryAndFileDefinitons( featureDefinitions.BeginElement("ComponentRef"); featureDefinitions.AddAttribute("Id", componentId); featureDefinitions.EndElement(); + + std::vector::const_iterator it; + for (it = pkgExecutables.begin() ; + it != pkgExecutables.end() ; + ++it) + { + std::string execName = *it++; + std::string iconName = *it; + + if (cmSystemTools::LowerCase(fileName) == + cmSystemTools::LowerCase(execName) + ".exe") + { + dirIdExecutables.push_back(fileName); + dirIdExecutables.push_back(iconName); + dirIdExecutables.push_back(directoryId); + } + } } } } diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.h b/Source/CPack/WiX/cmCPackWIXGenerator.h index 0e95d70..aaccf9d 100644 --- a/Source/CPack/WiX/cmCPackWIXGenerator.h +++ b/Source/CPack/WiX/cmCPackWIXGenerator.h @@ -83,7 +83,11 @@ private: cmWIXSourceWriter& fileDefinitions, cmWIXSourceWriter& featureDefinitions, size_t& directoryCounter, - size_t& fileCounter); + size_t& fileCounter, + const std::vector& pkgExecutables, + std::vector& dirIdExecutables + ); + bool RequireOption(const std::string& name, std::string& value) const; diff --git a/Tests/CPackWiXGenerator/CMakeLists.txt b/Tests/CPackWiXGenerator/CMakeLists.txt index ce02f11..475e60d 100644 --- a/Tests/CPackWiXGenerator/CMakeLists.txt +++ b/Tests/CPackWiXGenerator/CMakeLists.txt @@ -35,6 +35,8 @@ set(CPACK_PACKAGE_VERSION_PATCH "0") set(CPACK_PACKAGE_INSTALL_DIRECTORY "CPack Component Example") set(CPACK_WIX_UPGRADE_GUID "BF20CE5E-7F7C-401D-8F7C-AB45E8D170E6") +set(CPACK_WIX_UNINSTALL "1") +set(CPACK_PACKAGE_EXECUTABLES "mylibapp; CPack Wix Test") include(CPack) -- cgit v0.12 From 6d77e1ab3f6cfe5e2019a418da7c18cc3515ab54 Mon Sep 17 00:00:00 2001 From: Ian Monroe Date: Thu, 18 Apr 2013 10:19:13 -0700 Subject: CPackWIX: Fix MSI package layout regression from parent The parent commit added a regression where if the install directory had: parent child A child B the produced MSI would install: parent child A child B --- Source/CPack/WiX/cmCPackWIXGenerator.cxx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.cxx b/Source/CPack/WiX/cmCPackWIXGenerator.cxx index fc51b77..f443905 100644 --- a/Source/CPack/WiX/cmCPackWIXGenerator.cxx +++ b/Source/CPack/WiX/cmCPackWIXGenerator.cxx @@ -377,10 +377,6 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles() directoryDefinitions, fileDefinitions, featureDefinitions, directoryCounter, fileCounter, cpackPkgExecutables, dirIdExecutables); - for(size_t i = 1; i < install_root.size(); ++i) - { - directoryDefinitions.EndElement(); - } directoryDefinitions.EndElement(); directoryDefinitions.EndElement(); @@ -558,7 +554,7 @@ void cmCPackWIXGenerator::AddDirectoryAndFileDefinitons( fileCounter, pkgExecutables, dirIdExecutables); - + directoryDefinitions.EndElement(); } else { -- cgit v0.12 From 6e51ea9870658ca39e9b3050caada121519da673 Mon Sep 17 00:00:00 2001 From: Richard Ulrich Date: Wed, 8 May 2013 16:39:32 +0200 Subject: CPackWIX: Handle multiple shortcuts in the start menu --- Source/CPack/WiX/cmCPackWIXGenerator.cxx | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.cxx b/Source/CPack/WiX/cmCPackWIXGenerator.cxx index f443905..cfb655b 100644 --- a/Source/CPack/WiX/cmCPackWIXGenerator.cxx +++ b/Source/CPack/WiX/cmCPackWIXGenerator.cxx @@ -380,7 +380,14 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles() directoryDefinitions.EndElement(); directoryDefinitions.EndElement(); - if (dirIdExecutables.size() > 0 && dirIdExecutables.size() % 3 == 0) { + if (dirIdExecutables.size() > 0 && dirIdExecutables.size() % 3 == 0) + { + fileDefinitions.BeginElement("DirectoryRef"); + fileDefinitions.AddAttribute("Id", "PROGRAM_MENU_FOLDER"); + fileDefinitions.BeginElement("Component"); + fileDefinitions.AddAttribute("Id", "SHORTCUT"); + fileDefinitions.AddAttribute("Guid", "*"); + std::vector::iterator it; for ( it = dirIdExecutables.begin() ; it != dirIdExecutables.end(); @@ -390,13 +397,12 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles() std::string iconName = *it++; std::string directoryId = *it; - fileDefinitions.BeginElement("DirectoryRef"); - fileDefinitions.AddAttribute("Id", "PROGRAM_MENU_FOLDER"); - fileDefinitions.BeginElement("Component"); - fileDefinitions.AddAttribute("Id", "SHORTCUT"); - fileDefinitions.AddAttribute("Guid", "*"); fileDefinitions.BeginElement("Shortcut"); - fileDefinitions.AddAttribute("Id", "SHORTCUT_"); + std::string shortcutName = fileName; // the iconName is mor likely to contain blanks early on + std::string::size_type const dotPos = shortcutName.find('.'); + if(std::string::npos == dotPos) + { shortcutName = shortcutName.substr(0, dotPos); } + fileDefinitions.AddAttribute("Id", "SHORTCUT_" + shortcutName); fileDefinitions.AddAttribute("Name", iconName); std::string target = "[" + directoryId + "]" + fileName; fileDefinitions.AddAttribute("Target", target); -- cgit v0.12 From bfa2e299ae9a8687c6f13e701c87e68b9e4a5054 Mon Sep 17 00:00:00 2001 From: Richard Ulrich Date: Mon, 6 May 2013 17:21:42 +0200 Subject: CPackWIX: Add option to specify the language(s) of the installer Add option "CPACK_WIX_CULTURES". --- Modules/CPackWIX.cmake | 11 +++++++++++ Source/CPack/WiX/cmCPackWIXGenerator.cxx | 5 +++++ 2 files changed, 16 insertions(+) diff --git a/Modules/CPackWIX.cmake b/Modules/CPackWIX.cmake index 69a181e..4f57efa 100644 --- a/Modules/CPackWIX.cmake +++ b/Modules/CPackWIX.cmake @@ -81,6 +81,17 @@ # CPACK_WIX_PROGRAM_MENU_FOLDER - Start menu folder name for launcher. # # If this variable is not set, it will be initialized with CPACK_PACKAGE_NAME +# +##end +##variable +# CPACK_WIX_CULTURES - Language(s) of the installer +# +# Languages are compiled into the WixUI extension library. To use them, +# simply provide the name of the culture. If you specify more than one +# culture identifier in a comma or semicolon delimited list, the first one +# that is found will be used. You can find a list of supported languages at: +# http://wix.sourceforge.net/manual-wix3/WixUI_localization.htm +# ##end #============================================================================= diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.cxx b/Source/CPack/WiX/cmCPackWIXGenerator.cxx index cfb655b..373a14d 100644 --- a/Source/CPack/WiX/cmCPackWIXGenerator.cxx +++ b/Source/CPack/WiX/cmCPackWIXGenerator.cxx @@ -100,6 +100,11 @@ bool cmCPackWIXGenerator::RunLightCommand(const std::string& objectFiles) command << " -nologo"; command << " -out " << QuotePath(packageFileNames.at(0)); command << " -ext WixUIExtension"; + const char* const cultures = GetOption("CPACK_WIX_CULTURES"); + if(cultures) + { + command << " -cultures:" << cultures; + } command << " " << objectFiles; return RunWiXCommand(command.str()); -- cgit v0.12 From 155bb01bd5126f36066653a209a3209f6363a7cd Mon Sep 17 00:00:00 2001 From: Richard Ulrich Date: Wed, 8 May 2013 17:13:31 +0200 Subject: CMakeCPack: Provide an upgrade guid for WiX Set CPACK_WIX_UPGRADE_GUID. Without this upgrade GUID, you end up with multiple instances of the same installation when installing cmake from a WIX generated installer. --- CMakeCPack.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeCPack.cmake b/CMakeCPack.cmake index a27d000..2495c44 100644 --- a/CMakeCPack.cmake +++ b/CMakeCPack.cmake @@ -113,6 +113,8 @@ if(EXISTS "${CMAKE_ROOT}/Modules/CPack.cmake") include(Utilities/Release/Cygwin/CMakeLists.txt) endif() + set(CPACK_WIX_UPGRADE_GUID "8ffd1d72-b7f1-11e2-8ee5-00238bca4991") + # Set the options file that needs to be included inside CMakeCPackOptions.cmake set(QT_DIALOG_CPACK_OPTIONS_FILE ${CMake_BINARY_DIR}/Source/QtDialog/QtDialogCPack.cmake) configure_file("${CMake_SOURCE_DIR}/CMakeCPackOptions.cmake.in" -- cgit v0.12 From bf23891942d95a4075f349f6c4043647d47e546b Mon Sep 17 00:00:00 2001 From: "Adam J. Weigold" Date: Tue, 2 Jul 2013 17:19:31 -0500 Subject: CPackWIX: Add support for custom WiX templates WiX provides a lot of functionality for installers that cannot be supported (easily) in the default WIX.template.in file. For most users, the default template should be fine. However if users want to produce merge modules, include custom actions, etc, this new option allows for a hook into how the wxs is produced. --- Modules/CPackWIX.cmake | 9 +++++++++ Source/CPack/WiX/cmCPackWIXGenerator.cxx | 4 ++++ 2 files changed, 13 insertions(+) diff --git a/Modules/CPackWIX.cmake b/Modules/CPackWIX.cmake index 4f57efa..fce25f0 100644 --- a/Modules/CPackWIX.cmake +++ b/Modules/CPackWIX.cmake @@ -93,6 +93,15 @@ # http://wix.sourceforge.net/manual-wix3/WixUI_localization.htm # ##end +##variable +# CPACK_WIX_TEMPLATE - Template file for WiX generation +# +# If this variable is set, the specified template will be used to generate the WiX wxs file. +# This should be used if further customization of the output is required. +# +# If this variable is not set, the default MSI template included with CMake will be used. +# +##end #============================================================================= # Copyright 2012 Kitware, Inc. diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.cxx b/Source/CPack/WiX/cmCPackWIXGenerator.cxx index 373a14d..cc9dec7 100644 --- a/Source/CPack/WiX/cmCPackWIXGenerator.cxx +++ b/Source/CPack/WiX/cmCPackWIXGenerator.cxx @@ -451,6 +451,10 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles() directoryDefinitions.EndElement(); 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, -- cgit v0.12