summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Modules/CPackWIX.cmake8
-rw-r--r--Modules/WIX.template.in2
-rw-r--r--Source/CPack/WiX/cmCPackWIXGenerator.cxx306
-rw-r--r--Source/CPack/WiX/cmCPackWIXGenerator.h31
-rw-r--r--Source/CPack/WiX/cmWIXSourceWriter.cxx9
-rw-r--r--Source/CPack/WiX/cmWIXSourceWriter.h3
-rw-r--r--Tests/CPackWiXGenerator/CMakeLists.txt14
7 files changed, 325 insertions, 48 deletions
diff --git a/Modules/CPackWIX.cmake b/Modules/CPackWIX.cmake
index 3f0978d..237c5bc 100644
--- a/Modules/CPackWIX.cmake
+++ b/Modules/CPackWIX.cmake
@@ -63,6 +63,14 @@
#
# If set, this icon is used in place of the default icon.
#
+# .. variable:: CPACK_WIX_UI_REF
+#
+# This variable allows you to override the Id of the ``<UIRef>`` element
+# in the WiX template.
+#
+# The default is ``WixUI_InstallDir`` in case no CPack components have
+# been defined and ``WixUI_FeatureTree`` otherwise.
+#
# .. variable:: CPACK_WIX_UI_BANNER
#
# The bitmap will appear at the top of all installer pages other than the
diff --git a/Modules/WIX.template.in b/Modules/WIX.template.in
index 0bc7e10..59a75c7 100644
--- a/Modules/WIX.template.in
+++ b/Modules/WIX.template.in
@@ -39,6 +39,6 @@
<FeatureRef Id="ProductFeature"/>
- <UIRef Id="WixUI_InstallDir" />
+ <UIRef Id="$(var.CPACK_WIX_UI_REF)" />
</Product>
</Wix>
diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.cxx b/Source/CPack/WiX/cmCPackWIXGenerator.cxx
index 1d7681b..91701c2 100644
--- a/Source/CPack/WiX/cmCPackWIXGenerator.cxx
+++ b/Source/CPack/WiX/cmCPackWIXGenerator.cxx
@@ -198,6 +198,18 @@ bool cmCPackWIXGenerator::InitializeWiXConfiguration()
<< std::endl);
}
+ if(GetOption("CPACK_WIX_UI_REF") == 0)
+ {
+ std::string defaultRef = "WixUI_InstallDir";
+
+ if(Components.size())
+ {
+ defaultRef = "WixUI_FeatureTree";
+ }
+
+ SetOption("CPACK_WIX_UI_REF", defaultRef.c_str());
+ }
+
CollectExtensions("CPACK_WIX_EXTENSIONS", candleExtensions);
CollectExtensions("CPACK_WIX_CANDLE_EXTENSIONS", candleExtensions);
@@ -296,6 +308,7 @@ bool cmCPackWIXGenerator::CreateWiXVariablesIncludeFile()
SetOptionIfNotSet("CPACK_WIX_PROGRAM_MENU_FOLDER",
GetOption("CPACK_PACKAGE_NAME"));
CopyDefinition(includeFile, "CPACK_WIX_PROGRAM_MENU_FOLDER");
+ CopyDefinition(includeFile, "CPACK_WIX_UI_REF");
return true;
}
@@ -401,40 +414,77 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles()
featureDefinitions.BeginElement("Feature");
featureDefinitions.AddAttribute("Id", "ProductFeature");
- featureDefinitions.AddAttribute("Title", Name);
+ featureDefinitions.AddAttribute("Display", "expand");
+ featureDefinitions.AddAttribute("ConfigurableDirectory", "INSTALL_ROOT");
+
+ std::string cpackPackageName;
+ if(!RequireOption("CPACK_PACKAGE_NAME", cpackPackageName))
+ {
+ return false;
+ }
+ featureDefinitions.AddAttribute("Title", cpackPackageName);
+
featureDefinitions.AddAttribute("Level", "1");
+
+ CreateFeatureHierarchy(featureDefinitions);
+
featureDefinitions.EndElement("Feature");
- featureDefinitions.BeginElement("FeatureRef");
- featureDefinitions.AddAttribute("Id", "ProductFeature");
+ bool hasShortcuts = false;
- std::vector<std::string> cpackPackageExecutablesList;
- const char *cpackPackageExecutables = GetOption("CPACK_PACKAGE_EXECUTABLES");
- if(cpackPackageExecutables)
+ shortcut_map_t globalShortcuts;
+ if(Components.empty())
{
- cmSystemTools::ExpandListArgument(cpackPackageExecutables,
- cpackPackageExecutablesList);
- if(cpackPackageExecutablesList.size() % 2 != 0 )
+ AddComponentsToFeature(toplevel, "ProductFeature",
+ directoryDefinitions, fileDefinitions, featureDefinitions,
+ globalShortcuts);
+ if(globalShortcuts.size())
+ {
+ hasShortcuts = true;
+ }
+ }
+ else
+ {
+ for(std::map<std::string, cmCPackComponent>::const_iterator
+ i = Components.begin(); i != Components.end(); ++i)
+ {
+ cmCPackComponent const& component = i->second;
+
+ std::string componentPath = toplevel;
+ componentPath += "/";
+ componentPath += component.Name;
+
+ std::string componentFeatureId = "CM_C_" + component.Name;
+
+ shortcut_map_t featureShortcuts;
+ AddComponentsToFeature(componentPath, componentFeatureId,
+ directoryDefinitions, fileDefinitions,
+ featureDefinitions, featureShortcuts);
+ if(featureShortcuts.size())
{
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "CPACK_PACKAGE_EXECUTABLES should contain pairs of <executable> and "
- "<text label>." << std::endl);
- return false;
+ hasShortcuts = true;
}
- }
- AddDirectoryAndFileDefinitons(
- toplevel, "INSTALL_ROOT",
- directoryDefinitions, fileDefinitions, featureDefinitions,
- cpackPackageExecutablesList);
+ if(featureShortcuts.size())
+ {
+ if(!CreateStartMenuShortcuts(component.Name, componentFeatureId,
+ featureShortcuts, fileDefinitions, featureDefinitions))
+ {
+ return false;
+ }
+ }
+ }
+ }
- if(!CreateStartMenuShortcuts(
- directoryDefinitions, fileDefinitions, featureDefinitions))
+ if(hasShortcuts)
{
+ if(!CreateStartMenuShortcuts(std::string(), "ProductFeature",
+ globalShortcuts, fileDefinitions, featureDefinitions))
+ {
return false;
+ }
}
- featureDefinitions.EndElement("FeatureRef");
featureDefinitions.EndElement("Fragment");
fileDefinitions.EndElement("Fragment");
@@ -444,6 +494,12 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles()
}
directoryDefinitions.EndElement("Directory");
+
+ if(hasShortcuts)
+ {
+ CreateStartMenuFolder(directoryDefinitions);
+ }
+
directoryDefinitions.EndElement("Directory");
directoryDefinitions.EndElement("Fragment");
@@ -475,16 +531,154 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles()
return true;
}
-bool cmCPackWIXGenerator::CreateStartMenuShortcuts(
+bool cmCPackWIXGenerator::CreateFeatureHierarchy(
+ cmWIXSourceWriter& featureDefinitions)
+{
+ for(std::map<std::string, cmCPackComponentGroup>::const_iterator
+ i = ComponentGroups.begin(); i != ComponentGroups.end(); ++i)
+ {
+ cmCPackComponentGroup const& group = i->second;
+ if(group.ParentGroup == 0)
+ {
+ if(!EmitFeatureForComponentGroup(featureDefinitions, group))
+ {
+ return false;
+ }
+ }
+ }
+
+ for(std::map<std::string, cmCPackComponent>::const_iterator
+ i = Components.begin(); i != Components.end(); ++i)
+ {
+ cmCPackComponent const& component = i->second;
+
+ if(!component.Group)
+ {
+ if(!EmitFeatureForComponent(featureDefinitions, component))
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+bool cmCPackWIXGenerator::EmitFeatureForComponentGroup(
+ cmWIXSourceWriter& featureDefinitions,
+ cmCPackComponentGroup const& group)
+{
+ featureDefinitions.BeginElement("Feature");
+ featureDefinitions.AddAttribute("Id", "CM_G_" + group.Name);
+
+ if(group.IsExpandedByDefault)
+ {
+ featureDefinitions.AddAttribute("Display", "expand");
+ }
+
+ featureDefinitions.AddAttributeUnlessEmpty(
+ "Title", group.DisplayName);
+
+ featureDefinitions.AddAttributeUnlessEmpty(
+ "Description", group.Description);
+
+ for(std::vector<cmCPackComponentGroup*>::const_iterator
+ i = group.Subgroups.begin(); i != group.Subgroups.end(); ++i)
+ {
+ if(!EmitFeatureForComponentGroup(featureDefinitions, **i))
+ {
+ return false;
+ }
+ }
+
+ for(std::vector<cmCPackComponent*>::const_iterator
+ i = group.Components.begin(); i != group.Components.end(); ++i)
+ {
+ if(!EmitFeatureForComponent(featureDefinitions, **i))
+ {
+ return false;
+ }
+ }
+
+ featureDefinitions.EndElement("Feature");
+
+ return true;
+}
+
+bool cmCPackWIXGenerator::EmitFeatureForComponent(
+ cmWIXSourceWriter& featureDefinitions,
+ cmCPackComponent const& component)
+{
+ featureDefinitions.BeginElement("Feature");
+ featureDefinitions.AddAttribute("Id", "CM_C_" + component.Name);
+
+ featureDefinitions.AddAttributeUnlessEmpty(
+ "Title", component.DisplayName);
+
+ featureDefinitions.AddAttributeUnlessEmpty(
+ "Description", component.Description);
+
+ if(component.IsRequired)
+ {
+ featureDefinitions.AddAttribute("Absent", "disallow");
+ }
+
+ if(component.IsHidden)
+ {
+ featureDefinitions.AddAttribute("Display", "hidden");
+ }
+
+ featureDefinitions.EndElement("Feature");
+
+ return true;
+}
+
+bool cmCPackWIXGenerator::AddComponentsToFeature(
+ std::string const& rootPath,
+ std::string const& featureId,
cmWIXSourceWriter& directoryDefinitions,
cmWIXSourceWriter& fileDefinitions,
- cmWIXSourceWriter& featureDefinitions)
+ cmWIXSourceWriter& featureDefinitions,
+ shortcut_map_t& shortcutMap)
{
- if(shortcutMap.empty())
+ featureDefinitions.BeginElement("FeatureRef");
+ featureDefinitions.AddAttribute("Id", featureId);
+
+ std::vector<std::string> cpackPackageExecutablesList;
+ const char *cpackPackageExecutables = GetOption("CPACK_PACKAGE_EXECUTABLES");
+ if(cpackPackageExecutables)
{
- return true;
+ cmSystemTools::ExpandListArgument(cpackPackageExecutables,
+ cpackPackageExecutablesList);
+ if(cpackPackageExecutablesList.size() % 2 != 0 )
+ {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "CPACK_PACKAGE_EXECUTABLES should contain pairs of <executable> and "
+ "<text label>." << std::endl);
+ return false;
+ }
}
+ AddDirectoryAndFileDefinitons(
+ rootPath, "INSTALL_ROOT",
+ directoryDefinitions, fileDefinitions, featureDefinitions,
+ cpackPackageExecutablesList, shortcutMap);
+
+ featureDefinitions.EndElement("FeatureRef");
+
+ return true;
+}
+
+bool cmCPackWIXGenerator::CreateStartMenuShortcuts(
+ std::string const& cpackComponentName,
+ std::string const& featureId,
+ shortcut_map_t& shortcutMap,
+ cmWIXSourceWriter& fileDefinitions,
+ cmWIXSourceWriter& featureDefinitions)
+{
+ featureDefinitions.BeginElement("FeatureRef");
+ featureDefinitions.AddAttribute("Id", featureId);
+
std::string cpackVendor;
if(!RequireOption("CPACK_PACKAGE_VENDOR", cpackVendor))
{
@@ -497,10 +691,19 @@ bool cmCPackWIXGenerator::CreateStartMenuShortcuts(
return false;
}
+ std::string idSuffix;
+ if(!cpackComponentName.empty())
+ {
+ idSuffix += "_";
+ idSuffix += cpackComponentName;
+ }
+
+ std::string componentId = "CM_SHORTCUT" + idSuffix;
+
fileDefinitions.BeginElement("DirectoryRef");
fileDefinitions.AddAttribute("Id", "PROGRAM_MENU_FOLDER");
fileDefinitions.BeginElement("Component");
- fileDefinitions.AddAttribute("Id", "SHORTCUT");
+ fileDefinitions.AddAttribute("Id", componentId);
fileDefinitions.AddAttribute("Guid", "*");
for(shortcut_map_t::const_iterator
@@ -522,10 +725,13 @@ bool cmCPackWIXGenerator::CreateStartMenuShortcuts(
fileDefinitions.EndElement("Shortcut");
}
- CreateUninstallShortcut(cpackPackageName, fileDefinitions);
+ if(cpackComponentName.empty())
+ {
+ CreateUninstallShortcut(cpackPackageName, fileDefinitions);
+ }
fileDefinitions.BeginElement("RemoveFolder");
- fileDefinitions.AddAttribute("Id", "PROGRAM_MENU_FOLDER");
+ fileDefinitions.AddAttribute("Id", "PROGRAM_MENU_FOLDER" + idSuffix);
fileDefinitions.AddAttribute("On", "uninstall");
fileDefinitions.EndElement("RemoveFolder");
@@ -535,7 +741,15 @@ bool cmCPackWIXGenerator::CreateStartMenuShortcuts(
fileDefinitions.BeginElement("RegistryValue");
fileDefinitions.AddAttribute("Root", "HKCU");
fileDefinitions.AddAttribute("Key", registryKey);
- fileDefinitions.AddAttribute("Name", "installed");
+
+ std::string valueName;
+ if(!cpackComponentName.empty())
+ {
+ valueName = cpackComponentName + "_";
+ }
+ valueName += "installed";
+
+ fileDefinitions.AddAttribute("Name", valueName);
fileDefinitions.AddAttribute("Type", "integer");
fileDefinitions.AddAttribute("Value", "1");
fileDefinitions.AddAttribute("KeyPath", "yes");
@@ -545,19 +759,10 @@ bool cmCPackWIXGenerator::CreateStartMenuShortcuts(
fileDefinitions.EndElement("DirectoryRef");
featureDefinitions.BeginElement("ComponentRef");
- featureDefinitions.AddAttribute("Id", "SHORTCUT");
+ featureDefinitions.AddAttribute("Id", componentId);
featureDefinitions.EndElement("ComponentRef");
- 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);
- directoryDefinitions.EndElement("Directory");
-
- directoryDefinitions.EndElement("Directory");
+ featureDefinitions.EndElement("FeatureRef");
return true;
}
@@ -628,7 +833,8 @@ void cmCPackWIXGenerator::AddDirectoryAndFileDefinitons(
cmWIXSourceWriter& directoryDefinitions,
cmWIXSourceWriter& fileDefinitions,
cmWIXSourceWriter& featureDefinitions,
- const std::vector<std::string>& packageExecutables)
+ const std::vector<std::string>& packageExecutables,
+ shortcut_map_t& shortcutMap)
{
cmsys::Directory dir;
dir.Load(topdir.c_str());
@@ -662,7 +868,8 @@ void cmCPackWIXGenerator::AddDirectoryAndFileDefinitons(
directoryDefinitions,
fileDefinitions,
featureDefinitions,
- packageExecutables);
+ packageExecutables,
+ shortcutMap);
directoryDefinitions.EndElement("Directory");
}
@@ -922,3 +1129,18 @@ void cmCPackWIXGenerator::AddCustomFlags(
stream << " " << QuotePath(*i);
}
}
+
+void cmCPackWIXGenerator::CreateStartMenuFolder(
+ cmWIXSourceWriter& directoryDefinitions)
+{
+ 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);
+ directoryDefinitions.EndElement("Directory");
+
+ directoryDefinitions.EndElement("Directory");
+}
diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.h b/Source/CPack/WiX/cmCPackWIXGenerator.h
index 481a07d..84f68b6 100644
--- a/Source/CPack/WiX/cmCPackWIXGenerator.h
+++ b/Source/CPack/WiX/cmCPackWIXGenerator.h
@@ -56,7 +56,7 @@ protected:
virtual bool SupportsComponentInstallation() const
{
- return false;
+ return true;
}
private:
@@ -79,9 +79,30 @@ private:
bool CreateWiXSourceFiles();
- bool CreateStartMenuShortcuts(
+ bool CreateFeatureHierarchy(
+ cmWIXSourceWriter& featureDefinitions);
+
+ bool EmitFeatureForComponentGroup(
+ cmWIXSourceWriter& featureDefinitions,
+ cmCPackComponentGroup const& group);
+
+ bool EmitFeatureForComponent(
+ cmWIXSourceWriter& featureDefinitions,
+ cmCPackComponent const& component);
+
+ bool AddComponentsToFeature(
+ std::string const& rootPath,
+ std::string const& featureId,
cmWIXSourceWriter& directoryDefinitions,
cmWIXSourceWriter& fileDefinitions,
+ cmWIXSourceWriter& featureDefinitions,
+ shortcut_map_t& shortcutMap);
+
+ bool CreateStartMenuShortcuts(
+ std::string const& cpackComponentName,
+ std::string const& featureId,
+ shortcut_map_t& shortcutMap,
+ cmWIXSourceWriter& fileDefinitions,
cmWIXSourceWriter& featureDefinitions);
void CreateUninstallShortcut(
@@ -106,7 +127,8 @@ private:
cmWIXSourceWriter& directoryDefinitions,
cmWIXSourceWriter& fileDefinitions,
cmWIXSourceWriter& featureDefinitions,
- const std::vector<std::string>& pkgExecutables);
+ const std::vector<std::string>& pkgExecutables,
+ shortcut_map_t& shortcutMap);
bool RequireOption(const std::string& name, std::string& value) const;
@@ -136,10 +158,11 @@ private:
void AddCustomFlags(
const std::string& variableName, std::ostream& stream);
+ void CreateStartMenuFolder(cmWIXSourceWriter& directoryDefinitions);
+
std::vector<std::string> wixSources;
id_map_t pathToIdMap;
ambiguity_map_t idAmbiguityCounter;
- shortcut_map_t shortcutMap;
extension_set_t candleExtensions;
extension_set_t lightExtensions;
diff --git a/Source/CPack/WiX/cmWIXSourceWriter.cxx b/Source/CPack/WiX/cmWIXSourceWriter.cxx
index 214b8ac..c8a3922 100644
--- a/Source/CPack/WiX/cmWIXSourceWriter.cxx
+++ b/Source/CPack/WiX/cmWIXSourceWriter.cxx
@@ -123,6 +123,15 @@ void cmWIXSourceWriter::AddAttribute(
file << " " << key << "=\"" << EscapeAttributeValue(utf8) << '"';
}
+void cmWIXSourceWriter::AddAttributeUnlessEmpty(
+ const std::string& key, const std::string& value)
+{
+ if(value.size())
+ {
+ AddAttribute(key, value);
+ }
+}
+
std::string cmWIXSourceWriter::WindowsCodepageToUtf8(const std::string& value)
{
if(value.empty())
diff --git a/Source/CPack/WiX/cmWIXSourceWriter.h b/Source/CPack/WiX/cmWIXSourceWriter.h
index 0c7803c..670d4c0 100644
--- a/Source/CPack/WiX/cmWIXSourceWriter.h
+++ b/Source/CPack/WiX/cmWIXSourceWriter.h
@@ -40,6 +40,9 @@ public:
void AddAttribute(
const std::string& key, const std::string& value);
+ void AddAttributeUnlessEmpty(
+ const std::string& key, const std::string& value);
+
static std::string WindowsCodepageToUtf8(const std::string& value);
private:
diff --git a/Tests/CPackWiXGenerator/CMakeLists.txt b/Tests/CPackWiXGenerator/CMakeLists.txt
index b54925a..ecfecdb 100644
--- a/Tests/CPackWiXGenerator/CMakeLists.txt
+++ b/Tests/CPackWiXGenerator/CMakeLists.txt
@@ -14,11 +14,16 @@ install(TARGETS mylib
DESTINATION lib
COMPONENT libraries)
-install(TARGETS my-libapp my-other-app
+install(TARGETS my-libapp
RUNTIME
DESTINATION bin
COMPONENT applications)
+install(TARGETS my-other-app
+ RUNTIME
+ DESTINATION bin
+ COMPONENT applications2)
+
install(FILES mylib.h "file with spaces.h"
DESTINATION include
COMPONENT headers)
@@ -56,11 +61,18 @@ cpack_add_component_group(Development
DESCRIPTION "All of the tools you'll ever need to develop software")
cpack_add_component(applications
+ REQUIRED
DISPLAY_NAME "MyLib Application"
DESCRIPTION "An extremely useful application that makes use of MyLib"
GROUP Runtime
INSTALL_TYPES Full)
+cpack_add_component(applications2
+ DISPLAY_NAME "MyLib Extra Application"
+ DESCRIPTION "Another extremely useful application that makes use of MyLib"
+ GROUP Runtime
+ INSTALL_TYPES Full)
+
cpack_add_component(documentation
DISPLAY_NAME "MyLib Documentation"
DESCRIPTION "The extensive suite of MyLib Application documentation files"