Files
cmake/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx
T
Nils Gladitz 193f17102f 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).
2025-09-10 12:24:42 +02:00

189 lines
5.1 KiB
C++

/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file LICENSE.rst or https://cmake.org/licensing for details. */
#if defined(__CYGWIN__)
// For S_IWRITE symbol
# define _DEFAULT_SOURCE
#endif
#include "cmWIXFilesSourceWriter.h"
#include "cm_sys_stat.h"
#include "cmCMakeToWixPath.h"
#include "cmInstalledFile.h"
#include "cmSystemTools.h"
#include "cmUuid.h"
#include "cmWIXAccessControlList.h"
#ifdef _WIN32
# include "cmsys/Encoding.hxx"
#endif
cmWIXFilesSourceWriter::cmWIXFilesSourceWriter(unsigned long wixVersion,
cmCPackLog* logger,
std::string const& filename,
GuidType componentGuidType)
: cmWIXSourceWriter(wixVersion, logger, filename, componentGuidType)
{
}
void cmWIXFilesSourceWriter::EmitShortcut(std::string const& id,
cmWIXShortcut const& shortcut,
std::string const& shortcutPrefix,
size_t shortcutIndex)
{
std::ostringstream shortcutId;
shortcutId << shortcutPrefix << id;
if (shortcutIndex > 0) {
shortcutId << "_" << shortcutIndex;
}
std::string fileId = std::string("CM_F") + id;
BeginElement("Shortcut");
AddAttribute("Id", shortcutId.str());
AddAttribute("Name", shortcut.label);
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::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::EmitComponentCreateFolder(
std::string const& directoryId, std::string const& guid,
cmInstalledFile const* installedFile)
{
std::string componentId = std::string("CM_C_EMPTY_") + directoryId;
BeginElement("DirectoryRef");
AddAttribute("Id", directoryId);
BeginElement("Component");
AddAttribute("Id", componentId);
AddAttribute("Guid", guid);
BeginElement("CreateFolder");
if (installedFile) {
cmWIXAccessControlList acl(Logger, *installedFile, *this);
acl.Apply();
}
EndElement("CreateFolder");
EndElement("Component");
EndElement("DirectoryRef");
return componentId;
}
std::string cmWIXFilesSourceWriter::EmitComponentFile(
std::string const& directoryId, std::string const& id,
std::string const& filePath, cmWIXPatch& patch,
cmInstalledFile const* installedFile, int diskId)
{
std::string componentId = std::string("CM_C") + id;
std::string fileId = std::string("CM_F") + id;
std::string guid = CreateGuidFromComponentId(componentId);
BeginElement("DirectoryRef");
AddAttribute("Id", directoryId);
BeginElement("Component");
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");
}
if (installedFile->GetPropertyAsBool("CPACK_PERMANENT")) {
AddAttribute("Permanent", "yes");
}
}
patch.ApplyFragment(componentId, *this);
BeginElement("File");
AddAttribute("Id", fileId);
std::string sourcePath = CMakeToWixPath(filePath);
#ifdef _WIN32
// WiX cannot handle long paths natively, but since v4,
// it supports long paths via UNC prefixes.
if (this->WixVersion >= 4) {
sourcePath = cmsys::Encoding::ToNarrow(
cmsys::Encoding::ToWindowsExtendedPath(sourcePath));
}
#endif
AddAttribute("Source", sourcePath);
AddAttribute("KeyPath", "yes");
mode_t fileMode = 0;
cmSystemTools::GetPermissions(filePath.c_str(), fileMode);
if (!(fileMode & S_IWRITE)) {
AddAttribute("ReadOnly", "yes");
}
patch.ApplyFragment(fileId, *this);
if (installedFile) {
cmWIXAccessControlList acl(Logger, *installedFile, *this);
acl.Apply();
}
EndElement("File");
EndElement("Component");
EndElement("DirectoryRef");
return componentId;
}