cpack wix: support WiX generator on Cygwin

Cygwin-built CMake now converts paths from Cygwin to Windows form
(using cygpath -w) before they're passed to WiX.

The Wix generator on Cygwin requires the libuuid-dev package when
building CMake. However, the DLL it links to is installed by default
as part of Cygwin's core libs, so it does not need to be distributed.

If libuuid-dev isn't available, CMake is simply built without Wix
support on Cygwin.
This commit is contained in:
Stephen Sorley
2017-10-09 11:39:29 -04:00
parent e258fe0396
commit e1409101c9
8 changed files with 192 additions and 16 deletions

View File

@@ -936,8 +936,13 @@ if(UNIX)
endif()
endif()
if(WIN32)
if(CYGWIN)
find_package(LibUUID)
endif()
if(WIN32 OR (CYGWIN AND LibUUID_FOUND))
set(CPACK_SRCS ${CPACK_SRCS}
CPack/Wix/cmCMakeToWixPath.cxx
CPack/Wix/cmCMakeToWixPath.h
CPack/WiX/cmCPackWIXGenerator.cxx
CPack/WiX/cmCPackWIXGenerator.h
CPack/WiX/cmWIXAccessControlList.cxx
@@ -958,7 +963,7 @@ if(WIN32)
CPack/WiX/cmWIXShortcut.h
CPack/WiX/cmWIXSourceWriter.cxx
CPack/WiX/cmWIXSourceWriter.h
)
)
endif()
if(APPLE)
@@ -991,6 +996,11 @@ if(APPLE)
"See CMakeFiles/CMakeError.log for details of the failure.")
endif()
endif()
if(CYGWIN AND LibUUID_FOUND)
target_link_libraries(CPackLib ${LibUUID_LIBRARIES})
include_directories(CPackLib ${LibUUID_INCLUDE_DIRS})
set_property(SOURCE CPack/cmCPackGeneratorFactory.cxx PROPERTY COMPILE_DEFINITIONS HAVE_LIBUUID)
endif()
if(CPACK_ENABLE_FREEBSD_PKG AND FREEBSD_PKG_INCLUDE_DIRS AND FREEBSD_PKG_LIBRARIES)
target_link_libraries(CPackLib ${FREEBSD_PKG_LIBRARIES})
include_directories(${FREEBSD_PKG_INCLUDE_DIRS})

View File

@@ -0,0 +1,39 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCMakeToWixPath.h"
#include "cmSystemTools.h"
#include <string>
#include <vector>
#ifdef __CYGWIN__
#include <sys/cygwin.h>
std::string CMakeToWixPath(const std::string& cygpath)
{
std::vector<char> winpath_chars;
ssize_t winpath_size;
// Get the required buffer size.
winpath_size =
cygwin_conv_path(CCP_POSIX_TO_WIN_A, cygpath.c_str(), nullptr, 0);
if (winpath_size <= 0) {
return cygpath;
}
winpath_chars.assign(static_cast<size_t>(winpath_size) + 1, '\0');
winpath_size = cygwin_conv_path(CCP_POSIX_TO_WIN_A, cygpath.c_str(),
winpath_chars.data(), winpath_size);
if (winpath_size < 0) {
return cygpath;
}
return cmSystemTools::TrimWhitespace(winpath_chars.data());
}
#else
std::string CMakeToWixPath(const std::string& path)
{
return path;
}
#endif

View File

@@ -0,0 +1,12 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCMakeToWixPath_h
#define cmCMakeToWixPath_h
#include "cmConfigure.h" //IWYU pragma: keep
#include <string>
std::string CMakeToWixPath(const std::string& cygpath);
#endif // cmCMakeToWixPath_h

View File

@@ -22,7 +22,13 @@
#include "cmsys/FStream.hxx"
#include "cmsys/SystemTools.hxx"
#include <rpc.h> // for GUID generation
#ifdef _WIN32
#include <rpc.h> // for GUID generation (windows only)
#else
#include <uuid/uuid.h> // for GUID generation (libuuid)
#endif
#include "cmCMakeToWixPath.h"
cmCPackWIXGenerator::cmCPackWIXGenerator()
: Patch(0)
@@ -110,7 +116,7 @@ bool cmCPackWIXGenerator::RunLightCommand(std::string const& objectFiles)
std::ostringstream command;
command << QuotePath(executable);
command << " -nologo";
command << " -out " << QuotePath(packageFileNames.at(0));
command << " -out " << QuotePath(CMakeToWixPath(packageFileNames.at(0)));
for (std::string const& ext : this->LightExtensions) {
command << " -ext " << QuotePath(ext);
@@ -270,11 +276,12 @@ bool cmCPackWIXGenerator::PackageFilesImpl()
std::string objectFilename =
this->CPackTopLevel + "/" + uniqueBaseName + ".wixobj";
if (!RunCandleCommand(sourceFilename, objectFilename)) {
if (!RunCandleCommand(CMakeToWixPath(sourceFilename),
CMakeToWixPath(objectFilename))) {
return false;
}
objectFiles << " " << QuotePath(objectFilename);
objectFiles << " " << QuotePath(CMakeToWixPath(objectFilename));
}
AppendUserSuppliedExtraObjects(objectFiles);
@@ -320,10 +327,10 @@ void cmCPackWIXGenerator::CreateWiXVariablesIncludeFile()
CopyDefinition(includeFile, "CPACK_PACKAGE_VENDOR");
CopyDefinition(includeFile, "CPACK_PACKAGE_NAME");
CopyDefinition(includeFile, "CPACK_PACKAGE_VERSION");
CopyDefinition(includeFile, "CPACK_WIX_LICENSE_RTF");
CopyDefinition(includeFile, "CPACK_WIX_PRODUCT_ICON");
CopyDefinition(includeFile, "CPACK_WIX_UI_BANNER");
CopyDefinition(includeFile, "CPACK_WIX_UI_DIALOG");
CopyDefinition(includeFile, "CPACK_WIX_LICENSE_RTF", DefinitionType::PATH);
CopyDefinition(includeFile, "CPACK_WIX_PRODUCT_ICON", DefinitionType::PATH);
CopyDefinition(includeFile, "CPACK_WIX_UI_BANNER", DefinitionType::PATH);
CopyDefinition(includeFile, "CPACK_WIX_UI_DIALOG", DefinitionType::PATH);
SetOptionIfNotSet("CPACK_WIX_PROGRAM_MENU_FOLDER",
GetOption("CPACK_PACKAGE_NAME"));
CopyDefinition(includeFile, "CPACK_WIX_PROGRAM_MENU_FOLDER");
@@ -390,11 +397,16 @@ void cmCPackWIXGenerator::CreateWiXProductFragmentIncludeFile()
}
void cmCPackWIXGenerator::CopyDefinition(cmWIXSourceWriter& source,
std::string const& name)
std::string const& name,
DefinitionType type)
{
const char* value = GetOption(name.c_str());
if (value) {
AddDefinition(source, name, value);
if (type == DefinitionType::PATH) {
AddDefinition(source, name, CMakeToWixPath(value));
} else {
AddDefinition(source, name, value);
}
}
}
@@ -966,6 +978,7 @@ std::string cmCPackWIXGenerator::GetArchitecture() const
std::string cmCPackWIXGenerator::GenerateGUID()
{
#ifdef _WIN32
UUID guid;
UuidCreate(&guid);
@@ -975,6 +988,14 @@ std::string cmCPackWIXGenerator::GenerateGUID()
std::string result =
cmsys::Encoding::ToNarrow(reinterpret_cast<wchar_t*>(tmp));
RpcStringFreeW(&tmp);
#else
uuid_t guid;
char guid_ch[37] = { 0 };
uuid_generate(guid);
uuid_unparse(guid, guid_ch);
std::string result = guid_ch;
#endif
return cmSystemTools::UpperCase(result);
}

View File

@@ -48,6 +48,12 @@ private:
typedef std::map<std::string, size_t> ambiguity_map_t;
typedef std::set<std::string> extension_set_t;
enum class DefinitionType
{
STRING,
PATH
};
bool InitializeWiXConfiguration();
bool PackageFilesImpl();
@@ -58,7 +64,8 @@ private:
void CreateWiXProductFragmentIncludeFile();
void CopyDefinition(cmWIXSourceWriter& source, std::string const& name);
void CopyDefinition(cmWIXSourceWriter& source, std::string const& name,
DefinitionType type = DefinitionType::STRING);
void AddDefinition(cmWIXSourceWriter& source, std::string const& name,
std::string const& value);

View File

@@ -11,6 +11,8 @@
#include "cm_sys_stat.h"
#include "cmCMakeToWixPath.h"
cmWIXFilesSourceWriter::cmWIXFilesSourceWriter(cmCPackLog* logger,
std::string const& filename,
GuidType componentGuidType)
@@ -139,7 +141,7 @@ std::string cmWIXFilesSourceWriter::EmitComponentFile(
patch.ApplyFragment(componentId, *this);
BeginElement("File");
AddAttribute("Id", fileId);
AddAttribute("Source", filePath);
AddAttribute("Source", CMakeToWixPath(filePath));
AddAttribute("KeyPath", "yes");
mode_t fileMode = 0;

View File

@@ -40,7 +40,7 @@
#include "cmCPackRPMGenerator.h"
#endif
#ifdef _WIN32
#if defined(_WIN32) || (defined(__CYGWIN__) && defined(HAVE_LIBUUID))
#include "WiX/cmCPackWIXGenerator.h"
#endif
@@ -87,7 +87,7 @@ cmCPackGeneratorFactory::cmCPackGeneratorFactory()
this->RegisterGenerator("7Z", "7-Zip file format",
cmCPack7zGenerator::CreateGenerator);
}
#ifdef _WIN32
#if defined(_WIN32) || (defined(__CYGWIN__) && defined(HAVE_LIBUUID))
if (cmCPackWIXGenerator::CanGenerate()) {
this->RegisterGenerator("WIX", "MSI file format via WiX tools",
cmCPackWIXGenerator::CreateGenerator);

View File

@@ -0,0 +1,85 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
#[=======================================================================[.rst:
FindLibUUID
------------
Find LibUUID include directory and library.
Imported Targets
^^^^^^^^^^^^^^^^
An :ref:`imported target <Imported targets>` named
``LibUUID::LibUUID`` is provided if LibUUID has been found.
Result Variables
^^^^^^^^^^^^^^^^
This module defines the following variables:
``LibUUID_FOUND``
True if LibUUID was found, false otherwise.
``LibUUID_INCLUDE_DIRS``
Include directories needed to include LibUUID headers.
``LibUUID_LIBRARIES``
Libraries needed to link to LibUUID.
Cache Variables
^^^^^^^^^^^^^^^
This module uses the following cache variables:
``LibUUID_LIBRARY``
The location of the LibUUID library file.
``LibUUID_INCLUDE_DIR``
The location of the LibUUID include directory containing ``uuid/uuid.h``.
The cache variables should not be used by project code.
They may be set by end users to point at LibUUID components.
#]=======================================================================]
#-----------------------------------------------------------------------------
if(CYGWIN)
# Note: on current version of Cygwin, linking to libuuid.dll.a doesn't
# import the right symbols sometimes. Fix this by linking directly
# to the DLL that provides the symbols, instead.
set(old_suffixes ${CMAKE_FIND_LIBRARY_SUFFIXES})
set(CMAKE_FIND_LIBRARY_SUFFIXES .dll)
find_library(LibUUID_LIBRARY
NAMES cyguuid-1.dll
)
set(CMAKE_FIND_LIBRARY_SUFFIXES ${old_suffixes})
else()
find_library(LibUUID_LIBRARY
NAMES uuid
)
endif()
mark_as_advanced(LibUUID_LIBRARY)
find_path(LibUUID_INCLUDE_DIR
NAMES uuid/uuid.h
)
mark_as_advanced(LibUUID_INCLUDE_DIR)
#-----------------------------------------------------------------------------
include(${CMAKE_CURRENT_LIST_DIR}/../../Modules/FindPackageHandleStandardArgs.cmake)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibUUID
FOUND_VAR LibUUID_FOUND
REQUIRED_VARS LibUUID_LIBRARY LibUUID_INCLUDE_DIR
)
set(LIBUUID_FOUND ${LibUUID_FOUND})
#-----------------------------------------------------------------------------
# Provide documented result variables and targets.
if(LibUUID_FOUND)
set(LibUUID_INCLUDE_DIRS ${LibUUID_INCLUDE_DIR})
set(LibUUID_LIBRARIES ${LibUUID_LIBRARY})
if(NOT TARGET LibUUID::LibUUID)
add_library(LibUUID::LibUUID UNKNOWN IMPORTED)
set_target_properties(LibUUID::LibUUID PROPERTIES
IMPORTED_LOCATION "${LibUUID_LIBRARY}"
INTERFACE_INCLUDE_DIRECTORIES "${LibUUID_INCLUDE_DIRS}"
)
endif()
endif()