mirror of
https://gitlab.kitware.com/cmake/cmake.git
synced 2026-10-08 23:44:00 +03:00
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).
189 lines
5.1 KiB
C++
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;
|
|
}
|