Procházet zdrojové kódy

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.
Fredrik Axelsson před 12 roky
rodič
revize
8c0e32550c

+ 6 - 0
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.

+ 115 - 9
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<std::string> 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 <executable> and "
+        "<icon name>." << 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<std::string> 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<std::string>::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<std::string>& pkgExecutables,
+  std::vector<std::string>& 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<std::string>::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);
+          }
+        }
       }
     }
 }

+ 5 - 1
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<std::string>& pkgExecutables,
+    std::vector<std::string>& dirIdExecutables
+    );
+
 
   bool RequireOption(const std::string& name, std::string& value) const;
 

+ 2 - 0
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)