Merge topic 'wix-components'

7b390f7 CPackWiX: add CPack component support
This commit is contained in:
Brad King 2013-12-02 12:07:24 -05:00 committed by CMake Topic Stage
commit ed1de30da0
7 changed files with 326 additions and 49 deletions

View File

@ -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

View File

@ -39,6 +39,6 @@
<FeatureRef Id="ProductFeature"/>
<UIRef Id="WixUI_InstallDir" />
<UIRef Id="$(var.CPACK_WIX_UI_REF)" />
</Product>
</Wix>

View File

@ -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 )
{
cmCPackLogger(cmCPackLog::LOG_ERROR,
"CPACK_PACKAGE_EXECUTABLES should contain pairs of <executable> and "
"<text label>." << std::endl);
return false;
}
}
AddDirectoryAndFileDefinitons(
toplevel, "INSTALL_ROOT",
AddComponentsToFeature(toplevel, "ProductFeature",
directoryDefinitions, fileDefinitions, featureDefinitions,
cpackPackageExecutablesList);
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;
if(!CreateStartMenuShortcuts(
directoryDefinitions, fileDefinitions, featureDefinitions))
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())
{
hasShortcuts = true;
}
if(featureShortcuts.size())
{
if(!CreateStartMenuShortcuts(component.Name, componentFeatureId,
featureShortcuts, fileDefinitions, featureDefinitions))
{
return false;
}
}
}
}
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,15 +531,153 @@ 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,
shortcut_map_t& shortcutMap)
{
featureDefinitions.BeginElement("FeatureRef");
featureDefinitions.AddAttribute("Id", featureId);
std::vector<std::string> cpackPackageExecutablesList;
const char *cpackPackageExecutables = GetOption("CPACK_PACKAGE_EXECUTABLES");
if(cpackPackageExecutables)
{
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)
{
if(shortcutMap.empty())
{
return true;
}
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");
}
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");
}

View File

@ -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;

View File

@ -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())

View File

@ -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:

View File

@ -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"