Просмотр исходного кода

CPack/WiX: Implement opt-in per component .cab

By setting CPACK_WIX_CAB_PER_COMPONENT users can generate one
.cab per component instead of one .cab per installer.

WiX compresses .cab files in parallel.
This may potentially speed up installer creation.

May also allow larger installers (there is a 2GB per .cab limit).
Nils Gladitz 1 месяц назад
Родитель
Сommit
193f17102f

+ 9 - 0
Help/cpack_gen/wix.rst

@@ -487,3 +487,12 @@ Windows using WiX.
      first manually uninstall any older version.
 
  See https://docs.firegiant.com/wix3/xsd/wix/package/
+
+.. variable:: CPACK_WIX_CAB_PER_COMPONENT
+
+ .. versionadded:: 4.2
+
+ If this variable is set to true one `.cab` file per component is created.
+ The default is to create a single `.cab` file for all files in the installer.
+
+ WiX creates `.cab` files in parallel so multiple `.cab` files may be desirable for faster packaging.

+ 6 - 0
Help/release/dev/wix-multi-cab.rst

@@ -0,0 +1,6 @@
+wix-multi-cab
+-------------
+
+* :variable:`CPACK_WIX_CAB_PER_COMPONENT` allows CPack WIX opt-in generation of one
+  `.cab` file per component. Having multiple `.cab` files may improve the time it takes
+  to generate installers and may also work around per `.cab` size constraints.

+ 2 - 0
Modules/Internal/CPack/WIX-v3/WIX.template.in

@@ -19,7 +19,9 @@
         <Package InstallerVersion="301" Compressed="yes" InstallScope="$(var.CPACK_WIX_INSTALL_SCOPE)"/>
         <?endif?>
 
+        <?ifndef CPACK_WIX_CAB_PER_COMPONENT?>
         <Media Id="1" Cabinet="media1.cab" EmbedCab="yes"/>
+        <?endif?>
 
         <MajorUpgrade
             Schedule="afterInstallInitialize"

+ 2 - 0
Modules/Internal/CPack/WIX.template.in

@@ -19,7 +19,9 @@
         Compressed="yes"
         >
 
+        <?ifndef CPACK_WIX_CAB_PER_COMPONENT?>
         <Media Id="1" Cabinet="media1.cab" EmbedCab="yes"/>
+        <?endif?>
 
         <MajorUpgrade
             Schedule="afterInstallInitialize"

+ 35 - 9
Source/CPack/WiX/cmCPackWIXGenerator.cxx

@@ -430,6 +430,7 @@ void cmCPackWIXGenerator::CreateWiXVariablesIncludeFile()
   CopyDefinition(includeFile, "CPACK_WIX_PROGRAM_MENU_FOLDER");
   CopyDefinition(includeFile, "CPACK_WIX_UI_REF");
   CopyDefinition(includeFile, "CPACK_WIX_INSTALL_SCOPE");
+  CopyDefinition(includeFile, "CPACK_WIX_CAB_PER_COMPONENT");
 }
 
 void cmCPackWIXGenerator::CreateWiXPropertiesIncludeFile()
@@ -492,6 +493,22 @@ void cmCPackWIXGenerator::CreateWiXProductFragmentIncludeFile()
                                 cmWIXSourceWriter::INCLUDE_ELEMENT_ROOT);
   InjectXmlNamespaces(includeFile);
 
+  bool perComponentCab = GetOption("CPACK_WIX_CAB_PER_COMPONENT").IsOn();
+
+  if (perComponentCab) {
+    std::size_t cabCount = std::max<std::size_t>(1, this->Components.size());
+
+    for (std::size_t i = 0; i < cabCount; ++i) {
+      std::string diskId = std::to_string(i + 1);
+
+      includeFile.BeginElement("Media");
+      includeFile.AddAttribute("Id", diskId);
+      includeFile.AddAttribute("Cabinet", "media" + diskId + ".cab");
+      includeFile.AddAttribute("EmbedCab", "yes");
+      includeFile.EndElement("Media");
+    }
+  }
+
   this->Patch->ApplyFragment("#PRODUCT", includeFile);
 }
 
@@ -617,11 +634,17 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles()
   if (Components.empty()) {
     AddComponentsToFeature(toplevel, "ProductFeature", directoryDefinitions,
                            fileDefinitions, featureDefinitions,
-                           globalShortcuts);
+                           globalShortcuts, 0);
 
     globalShortcuts.AddShortcutTypes(emittedShortcutTypes);
   } else {
+    bool perComponentCab = GetOption("CPACK_WIX_CAB_PER_COMPONENT").IsOn();
+
+    std::size_t componentDiskId = 0;
+
     for (auto const& i : this->Components) {
+      ++componentDiskId;
+
       cmCPackComponent const& component = i.second;
 
       std::string componentPath = cmStrCat(toplevel, '/', component.Name);
@@ -631,7 +654,8 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles()
       cmWIXShortcuts featureShortcuts;
       AddComponentsToFeature(componentPath, componentFeatureId,
                              directoryDefinitions, fileDefinitions,
-                             featureDefinitions, featureShortcuts);
+                             featureDefinitions, featureShortcuts,
+                             perComponentCab ? componentDiskId : 0);
 
       featureShortcuts.AddShortcutTypes(emittedShortcutTypes);
 
@@ -779,7 +803,8 @@ bool cmCPackWIXGenerator::AddComponentsToFeature(
   std::string const& rootPath, std::string const& featureId,
   cmWIXDirectoriesSourceWriter& directoryDefinitions,
   cmWIXFilesSourceWriter& fileDefinitions,
-  cmWIXFeaturesSourceWriter& featureDefinitions, cmWIXShortcuts& shortcuts)
+  cmWIXFeaturesSourceWriter& featureDefinitions, cmWIXShortcuts& shortcuts,
+  int diskId)
 {
   featureDefinitions.BeginElement("FeatureRef");
   featureDefinitions.AddAttribute("Id", featureId);
@@ -807,7 +832,7 @@ bool cmCPackWIXGenerator::AddComponentsToFeature(
   AddDirectoryAndFileDefinitions(
     rootPath, "INSTALL_ROOT", directoryDefinitions, fileDefinitions,
     featureDefinitions, cpackPackageExecutablesList,
-    cpackPackageDesktopLinksList, shortcuts);
+    cpackPackageDesktopLinksList, shortcuts, diskId);
 
   featureDefinitions.EndElement("FeatureRef");
 
@@ -995,7 +1020,7 @@ void cmCPackWIXGenerator::AddDirectoryAndFileDefinitions(
   cmWIXFeaturesSourceWriter& featureDefinitions,
   std::vector<std::string> const& packageExecutables,
   std::vector<std::string> const& desktopExecutables,
-  cmWIXShortcuts& shortcuts)
+  cmWIXShortcuts& shortcuts, int diskId)
 {
   cmsys::Directory dir;
   dir.Load(topdir.c_str());
@@ -1054,9 +1079,10 @@ void cmCPackWIXGenerator::AddDirectoryAndFileDefinitions(
       directoryDefinitions.AddAttribute("Name", fileName);
       this->Patch->ApplyFragment(subDirectoryId, directoryDefinitions);
 
-      AddDirectoryAndFileDefinitions(
-        fullPath, subDirectoryId, directoryDefinitions, fileDefinitions,
-        featureDefinitions, packageExecutables, desktopExecutables, shortcuts);
+      AddDirectoryAndFileDefinitions(fullPath, subDirectoryId,
+                                     directoryDefinitions, fileDefinitions,
+                                     featureDefinitions, packageExecutables,
+                                     desktopExecutables, shortcuts, diskId);
 
       directoryDefinitions.EndElement("Directory");
     } else {
@@ -1068,7 +1094,7 @@ void cmCPackWIXGenerator::AddDirectoryAndFileDefinitions(
       }
 
       std::string componentId = fileDefinitions.EmitComponentFile(
-        directoryId, id, fullPath, *(this->Patch), installedFile);
+        directoryId, id, fullPath, *(this->Patch), installedFile, diskId);
 
       featureDefinitions.EmitComponentRef(componentId);
 

+ 3 - 2
Source/CPack/WiX/cmCPackWIXGenerator.h

@@ -86,7 +86,8 @@ private:
     std::string const& rootPath, std::string const& featureId,
     cmWIXDirectoriesSourceWriter& directoryDefinitions,
     cmWIXFilesSourceWriter& fileDefinitions,
-    cmWIXFeaturesSourceWriter& featureDefinitions, cmWIXShortcuts& shortcuts);
+    cmWIXFeaturesSourceWriter& featureDefinitions, cmWIXShortcuts& shortcuts,
+    int diskId);
 
   bool CreateShortcuts(std::string const& cpackComponentName,
                        std::string const& featureId,
@@ -122,7 +123,7 @@ private:
     cmWIXFeaturesSourceWriter& featureDefinitions,
     std::vector<std::string> const& packageExecutables,
     std::vector<std::string> const& desktopExecutables,
-    cmWIXShortcuts& shortcuts);
+    cmWIXShortcuts& shortcuts, int diskId);
 
   bool RequireOption(std::string const& name, std::string& value) const;
 

+ 5 - 1
Source/CPack/WiX/cmWIXFilesSourceWriter.cxx

@@ -122,7 +122,7 @@ std::string cmWIXFilesSourceWriter::EmitComponentCreateFolder(
 std::string cmWIXFilesSourceWriter::EmitComponentFile(
   std::string const& directoryId, std::string const& id,
   std::string const& filePath, cmWIXPatch& patch,
-  cmInstalledFile const* installedFile)
+  cmInstalledFile const* installedFile, int diskId)
 {
   std::string componentId = std::string("CM_C") + id;
   std::string fileId = std::string("CM_F") + id;
@@ -136,6 +136,10 @@ std::string cmWIXFilesSourceWriter::EmitComponentFile(
   AddAttribute("Id", componentId);
   AddAttribute("Guid", guid);
 
+  if (diskId) {
+    AddAttribute("DiskId", std::to_string(diskId));
+  }
+
   if (installedFile) {
     if (installedFile->GetPropertyAsBool("CPACK_NEVER_OVERWRITE")) {
       AddAttribute("NeverOverwrite", "yes");

+ 2 - 1
Source/CPack/WiX/cmWIXFilesSourceWriter.h

@@ -35,5 +35,6 @@ public:
   std::string EmitComponentFile(std::string const& directoryId,
                                 std::string const& id,
                                 std::string const& filePath, cmWIXPatch& patch,
-                                cmInstalledFile const* installedFile);
+                                cmInstalledFile const* installedFile,
+                                int diskId);
 };