diff options
Diffstat (limited to 'Source/CPack')
20 files changed, 1292 insertions, 596 deletions
diff --git a/Source/CPack/OSXScriptLauncher.cxx b/Source/CPack/OSXScriptLauncher.cxx index a9842c1..d9d6236 100644 --- a/Source/CPack/OSXScriptLauncher.cxx +++ b/Source/CPack/OSXScriptLauncher.cxx @@ -11,8 +11,8 @@ ============================================================================*/ #include <cmsys/SystemTools.hxx> #include <cmsys/Process.h> -#include <cmsys/ios/fstream> #include <cmsys/ios/iostream> +#include <cmsys/FStream.hxx> #include <CoreFoundation/CoreFoundation.h> @@ -27,7 +27,7 @@ int main(int argc, char* argv[]) { //if ( cmsys::SystemTools::FileExists( cmsys_stl::string cwd = cmsys::SystemTools::GetCurrentWorkingDirectory(); - cmsys_ios::ofstream ofs("/tmp/output.txt"); + cmsys::ofstream ofs("/tmp/output.txt"); CFStringRef fileName; CFBundleRef appBundle; diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.cxx b/Source/CPack/WiX/cmCPackWIXGenerator.cxx index cc9dec7..998b5f1 100644 --- a/Source/CPack/WiX/cmCPackWIXGenerator.cxx +++ b/Source/CPack/WiX/cmCPackWIXGenerator.cxx @@ -1,6 +1,6 @@ /*============================================================================ CMake - Cross Platform Makefile Generator - Copyright 2000-2012 Kitware, Inc., Insight Software Consortium + Copyright 2000-2013 Kitware, Inc., Insight Software Consortium Distributed under the OSI-approved BSD License (the "License"); see accompanying file Copyright.txt for details. @@ -14,6 +14,7 @@ #include <cmSystemTools.h> #include <cmGeneratedFileStream.h> +#include <cmCryptoHash.h> #include <CPack/cmCPackLog.h> #include <CPack/cmCPackComponentGroup.h> @@ -22,9 +23,14 @@ #include <cmsys/SystemTools.hxx> #include <cmsys/Directory.hxx> +#include <cmsys/Encoding.hxx> +#include <cmsys/FStream.hxx> #include <rpc.h> // for GUID generation +#include <sys/types.h> +#include <sys/stat.h> + int cmCPackWIXGenerator::InitializeInternal() { componentPackageMethod = ONE_PACKAGE; @@ -51,7 +57,7 @@ bool cmCPackWIXGenerator::RunWiXCommand(const std::string& command) bool status = cmSystemTools::RunSingleCommand(command.c_str(), &output, &returnValue, 0, cmSystemTools::OUTPUT_NONE); - std::ofstream logFile(logFileName.c_str(), std::ios::app); + cmsys::ofstream logFile(logFileName.c_str(), std::ios::app); logFile << command << std::endl; logFile << output; logFile.close(); @@ -82,6 +88,15 @@ bool cmCPackWIXGenerator::RunCandleCommand( command << " -nologo"; command << " -arch " << GetArchitecture(); command << " -out " << QuotePath(objectFile); + + for(extension_set_t::const_iterator i = CandleExtensions.begin(); + i != CandleExtensions.end(); ++i) + { + command << " -ext " << QuotePath(*i); + } + + AddCustomFlags("CPACK_WIX_CANDLE_EXTRA_FLAGS", command); + command << " " << QuotePath(sourceFile); return RunWiXCommand(command.str()); @@ -99,12 +114,21 @@ bool cmCPackWIXGenerator::RunLightCommand(const std::string& objectFiles) command << QuotePath(executable); command << " -nologo"; command << " -out " << QuotePath(packageFileNames.at(0)); - command << " -ext WixUIExtension"; + + for(extension_set_t::const_iterator i = LightExtensions.begin(); + i != LightExtensions.end(); ++i) + { + command << " -ext " << QuotePath(*i); + } + const char* const cultures = GetOption("CPACK_WIX_CULTURES"); if(cultures) { command << " -cultures:" << cultures; } + + AddCustomFlags("CPACK_WIX_LIGHT_EXTRA_FLAGS", command); + command << " " << objectFiles; return RunWiXCommand(command.str()); @@ -169,6 +193,41 @@ bool cmCPackWIXGenerator::InitializeWiXConfiguration() } } + if(GetOption("CPACK_PACKAGE_VENDOR") == 0) + { + std::string defaultVendor = "Humanity"; + SetOption("CPACK_PACKAGE_VENDOR", defaultVendor.c_str()); + + cmCPackLogger(cmCPackLog::LOG_VERBOSE, + "CPACK_PACKAGE_VENDOR implicitly set to " << defaultVendor << " . " + << 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); + + LightExtensions.insert("WixUIExtension"); + CollectExtensions("CPACK_WIX_EXTENSIONS", LightExtensions); + CollectExtensions("CPACK_WIX_LIGHT_EXTENSIONS", LightExtensions); + + const char* patchFilePath = GetOption("CPACK_WIX_PATCH_FILE"); + if(patchFilePath) + { + LoadPatchFragments(patchFilePath); + } + return true; } @@ -189,10 +248,12 @@ bool cmCPackWIXGenerator::PackageFilesImpl() return false; } + AppendUserSuppliedExtraSources(); + std::stringstream objectFiles; - for(size_t i = 0; i < wixSources.size(); ++i) + for(size_t i = 0; i < WixSources.size(); ++i) { - const std::string& sourceFilename = wixSources[i]; + const std::string& sourceFilename = WixSources[i]; std::string objectFilename = cmSystemTools::GetFilenameWithoutExtension(sourceFilename) + ".wixobj"; @@ -205,9 +266,35 @@ bool cmCPackWIXGenerator::PackageFilesImpl() objectFiles << " " << QuotePath(objectFilename); } + AppendUserSuppliedExtraObjects(objectFiles); + return RunLightCommand(objectFiles.str()); } +void cmCPackWIXGenerator::AppendUserSuppliedExtraSources() +{ + const char *cpackWixExtraSources = GetOption("CPACK_WIX_EXTRA_SOURCES"); + if(!cpackWixExtraSources) return; + + cmSystemTools::ExpandListArgument(cpackWixExtraSources, WixSources); +} + +void cmCPackWIXGenerator::AppendUserSuppliedExtraObjects(std::ostream& stream) +{ + const char *cpackWixExtraObjects = GetOption("CPACK_WIX_EXTRA_OBJECTS"); + if(!cpackWixExtraObjects) return; + + std::vector<std::string> expandedExtraObjects; + + cmSystemTools::ExpandListArgument( + cpackWixExtraObjects, expandedExtraObjects); + + for(size_t i = 0; i < expandedExtraObjects.size(); ++i) + { + stream << " " << QuotePath(expandedExtraObjects[i]); + } +} + bool cmCPackWIXGenerator::CreateWiXVariablesIncludeFile() { std::string cpackTopLevel; @@ -232,6 +319,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; } @@ -267,7 +355,7 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles() std::string directoryDefinitionsFilename = cpackTopLevel + "/directories.wxs"; - wixSources.push_back(directoryDefinitionsFilename); + WixSources.push_back(directoryDefinitionsFilename); cmWIXSourceWriter directoryDefinitions(Logger, directoryDefinitionsFilename); directoryDefinitions.BeginElement("Fragment"); @@ -319,13 +407,10 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles() directoryDefinitions.AddAttribute("Name", install_root[i]); } - size_t directoryCounter = 0; - size_t fileCounter = 0; - std::string fileDefinitionsFilename = cpackTopLevel + "/files.wxs"; - wixSources.push_back(fileDefinitionsFilename); + WixSources.push_back(fileDefinitionsFilename); cmWIXSourceWriter fileDefinitions(Logger, fileDefinitionsFilename); fileDefinitions.BeginElement("Fragment"); @@ -333,122 +418,109 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles() std::string featureDefinitionsFilename = cpackTopLevel +"/features.wxs"; - wixSources.push_back(featureDefinitionsFilename); + WixSources.push_back(featureDefinitionsFilename); cmWIXSourceWriter featureDefinitions(Logger, featureDefinitionsFilename); featureDefinitions.BeginElement("Fragment"); 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"); - featureDefinitions.EndElement(); - featureDefinitions.BeginElement("FeatureRef"); - featureDefinitions.AddAttribute("Id", "ProductFeature"); + if(!CreateCMakePackageRegistryEntry(featureDefinitions)) + { + return false; + } - const char *cpackPackageExecutables = GetOption("CPACK_PACKAGE_EXECUTABLES"); - std::vector<std::string> cpackPkgExecutables; - std::string regKey; - if ( cpackPackageExecutables ) + if(!CreateFeatureHierarchy(featureDefinitions)) { - cmSystemTools::ExpandListArgument(cpackPackageExecutables, - cpackPkgExecutables); - if ( cpackPkgExecutables.size() % 2 != 0 ) - { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "CPACK_PACKAGE_EXECUTABLES should contain pairs of <executable> and " - "<icon name>." << std::endl); - cpackPkgExecutables.clear(); - } + return false; + } - const char *cpackVendor = GetOption("CPACK_PACKAGE_VENDOR"); - const char *cpackPkgName = GetOption("CPACK_PACKAGE_NAME"); - if (!cpackVendor || !cpackPkgName) + featureDefinitions.EndElement("Feature"); + + bool hasShortcuts = false; + + shortcut_map_t globalShortcuts; + if(Components.empty()) + { + AddComponentsToFeature(toplevel, "ProductFeature", + directoryDefinitions, fileDefinitions, featureDefinitions, + globalShortcuts); + if(globalShortcuts.size()) { - cmCPackLogger(cmCPackLog::LOG_WARNING, "CPACK_PACKAGE_VENDOR and " - "CPACK_PACKAGE_NAME must be defined for shortcut creation" << std::endl); - cpackPkgExecutables.clear(); + hasShortcuts = true; } - else + } + else + { + for(std::map<std::string, cmCPackComponent>::const_iterator + i = Components.begin(); i != Components.end(); ++i) { - regKey = std::string("Software/") + cpackVendor + "/" + cpackPkgName; + 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()) + { + hasShortcuts = true; + } + + if(featureShortcuts.size()) + { + if(!CreateStartMenuShortcuts(component.Name, componentFeatureId, + featureShortcuts, fileDefinitions, featureDefinitions)) + { + return false; + } + } } } - std::vector<std::string> dirIdExecutables; - AddDirectoryAndFileDefinitons( - toplevel, "INSTALL_ROOT", - directoryDefinitions, fileDefinitions, featureDefinitions, - directoryCounter, fileCounter, cpackPkgExecutables, dirIdExecutables); + if(hasShortcuts) + { + if(!CreateStartMenuShortcuts(std::string(), "ProductFeature", + globalShortcuts, fileDefinitions, featureDefinitions)) + { + return false; + } + } - directoryDefinitions.EndElement(); - directoryDefinitions.EndElement(); + featureDefinitions.EndElement("Fragment"); + fileDefinitions.EndElement("Fragment"); - if (dirIdExecutables.size() > 0 && dirIdExecutables.size() % 3 == 0) + for(size_t i = 1; i < install_root.size(); ++i) { - fileDefinitions.BeginElement("DirectoryRef"); - fileDefinitions.AddAttribute("Id", "PROGRAM_MENU_FOLDER"); - fileDefinitions.BeginElement("Component"); - fileDefinitions.AddAttribute("Id", "SHORTCUT"); - fileDefinitions.AddAttribute("Guid", "*"); + directoryDefinitions.EndElement("Directory"); + } - std::vector<std::string>::iterator it; - for ( it = dirIdExecutables.begin() ; - it != dirIdExecutables.end(); - ++it) - { - std::string fileName = *it++; - std::string iconName = *it++; - std::string directoryId = *it; - - fileDefinitions.BeginElement("Shortcut"); - std::string shortcutName = fileName; // the iconName is mor likely to contain blanks early on - std::string::size_type const dotPos = shortcutName.find('.'); - if(std::string::npos == dotPos) - { shortcutName = shortcutName.substr(0, dotPos); } - fileDefinitions.AddAttribute("Id", "SHORTCUT_" + shortcutName); - fileDefinitions.AddAttribute("Name", iconName); - std::string target = "[" + directoryId + "]" + fileName; - fileDefinitions.AddAttribute("Target", target); - fileDefinitions.AddAttribute("WorkingDirectory", directoryId); - fileDefinitions.EndElement(); - } - fileDefinitions.BeginElement("Shortcut"); - fileDefinitions.AddAttribute("Id", "UNINSTALL"); - std::string pkgName = GetOption("CPACK_PACKAGE_NAME"); - fileDefinitions.AddAttribute("Name", "Uninstall " + pkgName); - fileDefinitions.AddAttribute("Description", "Uninstalls " + pkgName); - fileDefinitions.AddAttribute("Target", "[SystemFolder]msiexec.exe"); - fileDefinitions.AddAttribute("Arguments", "/x [ProductCode]"); - fileDefinitions.EndElement(); - fileDefinitions.BeginElement("RemoveFolder"); - fileDefinitions.AddAttribute("Id", "PROGRAM_MENU_FOLDER"); - fileDefinitions.AddAttribute("On", "uninstall"); - fileDefinitions.EndElement(); - fileDefinitions.BeginElement("RegistryValue"); - fileDefinitions.AddAttribute("Root", "HKCU"); - fileDefinitions.AddAttribute("Key", regKey); - fileDefinitions.AddAttribute("Name", "installed"); - fileDefinitions.AddAttribute("Type", "integer"); - fileDefinitions.AddAttribute("Value", "1"); - fileDefinitions.AddAttribute("KeyPath", "yes"); - - featureDefinitions.BeginElement("ComponentRef"); - featureDefinitions.AddAttribute("Id", "SHORTCUT"); - featureDefinitions.EndElement(); - 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"); - featureDefinitions.EndElement(); - featureDefinitions.EndElement(); - fileDefinitions.EndElement(); - directoryDefinitions.EndElement(); + if(hasShortcuts) + { + CreateStartMenuFolder(directoryDefinitions); + } + + directoryDefinitions.EndElement("Directory"); + directoryDefinitions.EndElement("Fragment"); std::string wixTemplate = FindTemplate("WIX.template.in"); if(GetOption("CPACK_WIX_TEMPLATE") != 0) @@ -473,11 +545,315 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles() return false; } - wixSources.push_back(mainSourceFilePath); + WixSources.push_back(mainSourceFilePath); + + std::string fragmentList; + for(cmWIXPatchParser::fragment_map_t::const_iterator + i = Fragments.begin(); i != Fragments.end(); ++i) + { + if(!fragmentList.empty()) + { + fragmentList += ", "; + } + + fragmentList += "'"; + fragmentList += i->first; + fragmentList += "'"; + } + + if(fragmentList.size()) + { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Some XML patch fragments did not have matching IDs: " << + fragmentList << std::endl); + return false; + } + + return true; +} + +bool cmCPackWIXGenerator::CreateCMakePackageRegistryEntry( + cmWIXSourceWriter& featureDefinitions) +{ + const char* package = GetOption("CPACK_WIX_CMAKE_PACKAGE_REGISTRY"); + if(!package) + { + return true; + } + + featureDefinitions.BeginElement("Component"); + featureDefinitions.AddAttribute("Id", "CM_PACKAGE_REGISTRY"); + featureDefinitions.AddAttribute("Directory", "TARGETDIR"); + featureDefinitions.AddAttribute("Guid", "*"); + + std::string registryKey = + std::string("Software\\Kitware\\CMake\\Packages\\") + package; + + std::string upgradeGuid = GetOption("CPACK_WIX_UPGRADE_GUID"); + + featureDefinitions.BeginElement("RegistryValue"); + featureDefinitions.AddAttribute("Root", "HKLM"); + featureDefinitions.AddAttribute("Key", registryKey); + featureDefinitions.AddAttribute("Name", upgradeGuid); + featureDefinitions.AddAttribute("Type", "string"); + featureDefinitions.AddAttribute("Value", "[INSTALL_ROOT]"); + featureDefinitions.AddAttribute("KeyPath", "yes"); + featureDefinitions.EndElement("RegistryValue"); + + featureDefinitions.EndElement("Component"); + + return true; +} + +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) +{ + featureDefinitions.BeginElement("FeatureRef"); + featureDefinitions.AddAttribute("Id", featureId); + + std::string cpackVendor; + if(!RequireOption("CPACK_PACKAGE_VENDOR", cpackVendor)) + { + return false; + } + + std::string cpackPackageName; + if(!RequireOption("CPACK_PACKAGE_NAME", cpackPackageName)) + { + 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", componentId); + fileDefinitions.AddAttribute("Guid", "*"); + + for(shortcut_map_t::const_iterator + i = shortcutMap.begin(); i != shortcutMap.end(); ++i) + { + std::string const& id = i->first; + cmWIXShortcut const& shortcut = i->second; + + std::string shortcutId = std::string("CM_S") + id; + std::string fileId = std::string("CM_F") + id; + + fileDefinitions.BeginElement("Shortcut"); + fileDefinitions.AddAttribute("Id", shortcutId); + fileDefinitions.AddAttribute("Name", shortcut.textLabel); + std::string target = "[#" + fileId + "]"; + fileDefinitions.AddAttribute("Target", target); + fileDefinitions.AddAttribute("WorkingDirectory", + shortcut.workingDirectoryId); + fileDefinitions.EndElement("Shortcut"); + } + + if(cpackComponentName.empty()) + { + CreateUninstallShortcut(cpackPackageName, fileDefinitions); + } + + fileDefinitions.BeginElement("RemoveFolder"); + fileDefinitions.AddAttribute("Id", "PROGRAM_MENU_FOLDER" + idSuffix); + fileDefinitions.AddAttribute("On", "uninstall"); + fileDefinitions.EndElement("RemoveFolder"); + + std::string registryKey = + std::string("Software\\") + cpackVendor + "\\" + cpackPackageName; + + fileDefinitions.BeginElement("RegistryValue"); + fileDefinitions.AddAttribute("Root", "HKCU"); + fileDefinitions.AddAttribute("Key", registryKey); + + 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"); + fileDefinitions.EndElement("RegistryValue"); + + fileDefinitions.EndElement("Component"); + fileDefinitions.EndElement("DirectoryRef"); + + featureDefinitions.BeginElement("ComponentRef"); + featureDefinitions.AddAttribute("Id", componentId); + featureDefinitions.EndElement("ComponentRef"); + + featureDefinitions.EndElement("FeatureRef"); return true; } +void cmCPackWIXGenerator::CreateUninstallShortcut( + std::string const& packageName, + cmWIXSourceWriter& fileDefinitions) +{ + fileDefinitions.BeginElement("Shortcut"); + fileDefinitions.AddAttribute("Id", "UNINSTALL"); + fileDefinitions.AddAttribute("Name", "Uninstall " + packageName); + fileDefinitions.AddAttribute("Description", "Uninstalls " + packageName); + fileDefinitions.AddAttribute("Target", "[SystemFolder]msiexec.exe"); + fileDefinitions.AddAttribute("Arguments", "/x [ProductCode]"); + fileDefinitions.EndElement("Shortcut"); +} + bool cmCPackWIXGenerator::CreateLicenseFile() { std::string licenseSourceFilename; @@ -504,7 +880,7 @@ bool cmCPackWIXGenerator::CreateLicenseFile() { cmWIXRichTextFormatWriter rtfWriter(licenseDestinationFilename); - std::ifstream licenseSource(licenseSourceFilename.c_str()); + cmsys::ifstream licenseSource(licenseSourceFilename.c_str()); std::string line; while(std::getline(licenseSource, line)) @@ -531,10 +907,8 @@ void cmCPackWIXGenerator::AddDirectoryAndFileDefinitons( cmWIXSourceWriter& directoryDefinitions, cmWIXSourceWriter& fileDefinitions, cmWIXSourceWriter& featureDefinitions, - size_t& directoryCounter, - size_t& fileCounter, - const std::vector<std::string>& pkgExecutables, - std::vector<std::string>& dirIdExecutables) + const std::vector<std::string>& packageExecutables, + shortcut_map_t& shortcutMap) { cmsys::Directory dir; dir.Load(topdir.c_str()); @@ -550,11 +924,14 @@ void cmCPackWIXGenerator::AddDirectoryAndFileDefinitons( std::string fullPath = topdir + "/" + fileName; + std::string relativePath = cmSystemTools::RelativePath( + toplevel.c_str(), fullPath.c_str()); + + std::string id = PathToId(relativePath); + if(cmSystemTools::FileIsDirectory(fullPath.c_str())) { - std::stringstream tmp; - tmp << "DIR_ID_" << ++directoryCounter; - std::string subDirectoryId = tmp.str(); + std::string subDirectoryId = std::string("CM_D") + id; directoryDefinitions.BeginElement("Directory"); directoryDefinitions.AddAttribute("Id", subDirectoryId); @@ -565,20 +942,16 @@ void cmCPackWIXGenerator::AddDirectoryAndFileDefinitons( directoryDefinitions, fileDefinitions, featureDefinitions, - directoryCounter, - fileCounter, - pkgExecutables, - dirIdExecutables); - directoryDefinitions.EndElement(); + packageExecutables, + shortcutMap); + + ApplyPatchFragment(subDirectoryId, directoryDefinitions); + directoryDefinitions.EndElement("Directory"); } else { - std::stringstream tmp; - tmp << "_ID_" << ++fileCounter; - std::string idSuffix = tmp.str(); - - std::string componentId = std::string("CMP") + idSuffix; - std::string fileId = std::string("FILE") + idSuffix; + std::string componentId = std::string("CM_C") + id; + std::string fileId = std::string("CM_F") + id; fileDefinitions.BeginElement("DirectoryRef"); fileDefinitions.AddAttribute("Id", directoryId); @@ -592,28 +965,36 @@ void cmCPackWIXGenerator::AddDirectoryAndFileDefinitons( fileDefinitions.AddAttribute("Source", fullPath); fileDefinitions.AddAttribute("KeyPath", "yes"); - fileDefinitions.EndElement(); - fileDefinitions.EndElement(); - fileDefinitions.EndElement(); + mode_t fileMode = 0; + cmSystemTools::GetPermissions(fullPath.c_str(), fileMode); + + if(!(fileMode & S_IWRITE)) + { + fileDefinitions.AddAttribute("ReadOnly", "yes"); + } + + ApplyPatchFragment(fileId, fileDefinitions); + fileDefinitions.EndElement("File"); + + ApplyPatchFragment(componentId, fileDefinitions); + fileDefinitions.EndElement("Component"); + fileDefinitions.EndElement("DirectoryRef"); featureDefinitions.BeginElement("ComponentRef"); featureDefinitions.AddAttribute("Id", componentId); - featureDefinitions.EndElement(); + featureDefinitions.EndElement("ComponentRef"); - std::vector<std::string>::const_iterator it; - for (it = pkgExecutables.begin() ; - it != pkgExecutables.end() ; - ++it) + for(size_t j = 0; j < packageExecutables.size(); ++j) { - std::string execName = *it++; - std::string iconName = *it; + std::string const& executableName = packageExecutables[j++]; + std::string const& textLabel = packageExecutables[j]; - if (cmSystemTools::LowerCase(fileName) == - cmSystemTools::LowerCase(execName) + ".exe") + if(cmSystemTools::LowerCase(fileName) == + cmSystemTools::LowerCase(executableName) + ".exe") { - dirIdExecutables.push_back(fileName); - dirIdExecutables.push_back(iconName); - dirIdExecutables.push_back(directoryId); + cmWIXShortcut &shortcut = shortcutMap[id]; + shortcut.textLabel= textLabel; + shortcut.workingDirectoryId = directoryId; } } } @@ -659,11 +1040,12 @@ std::string cmCPackWIXGenerator::GenerateGUID() UUID guid; UuidCreate(&guid); - unsigned char *tmp = 0; - UuidToString(&guid, &tmp); + unsigned short *tmp = 0; + UuidToStringW(&guid, &tmp); - std::string result(reinterpret_cast<char*>(tmp)); - RpcStringFree(&tmp); + std::string result = + cmsys::Encoding::ToNarrow(reinterpret_cast<wchar_t*>(tmp)); + RpcStringFreeW(&tmp); return cmSystemTools::UpperCase(result); } @@ -686,3 +1068,208 @@ std::string cmCPackWIXGenerator::GetRightmostExtension( return cmSystemTools::LowerCase(extension); } + +std::string cmCPackWIXGenerator::PathToId(const std::string& path) +{ + id_map_t::const_iterator i = PathToIdMap.find(path); + if(i != PathToIdMap.end()) return i->second; + + std::string id = CreateNewIdForPath(path); + return id; +} + +std::string cmCPackWIXGenerator::CreateNewIdForPath(const std::string& path) +{ + std::vector<std::string> components; + cmSystemTools::SplitPath(path.c_str(), components, false); + + size_t replacementCount = 0; + + std::string identifier; + std::string currentComponent; + + for(size_t i = 1; i < components.size(); ++i) + { + if(i != 1) identifier += '.'; + + currentComponent = NormalizeComponentForId( + components[i], replacementCount); + + identifier += currentComponent; + } + + std::string idPrefix = "P"; + size_t replacementPercent = replacementCount * 100 / identifier.size(); + if(replacementPercent > 33 || identifier.size() > 60) + { + identifier = CreateHashedId(path, currentComponent); + idPrefix = "H"; + } + + std::stringstream result; + result << idPrefix << "_" << identifier; + + size_t ambiguityCount = ++IdAmbiguityCounter[identifier]; + + if(ambiguityCount > 999) + { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Error while trying to generate a unique Id for '" << + path << "'" << std::endl); + + return std::string(); + } + else if(ambiguityCount > 1) + { + result << "_" << ambiguityCount; + } + + std::string resultString = result.str(); + + PathToIdMap[path] = resultString; + + return resultString; +} + +std::string cmCPackWIXGenerator::CreateHashedId( + const std::string& path, const std::string& normalizedFilename) +{ + cmsys::auto_ptr<cmCryptoHash> sha1 = cmCryptoHash::New("SHA1"); + std::string hash = sha1->HashString(path.c_str()); + + std::string identifier; + identifier += hash.substr(0, 7) + "_"; + + const size_t maxFileNameLength = 52; + if(normalizedFilename.length() > maxFileNameLength) + { + identifier += normalizedFilename.substr(0, maxFileNameLength - 3); + identifier += "..."; + } + else + { + identifier += normalizedFilename; + } + + return identifier; +} + +std::string cmCPackWIXGenerator::NormalizeComponentForId( + const std::string& component, size_t& replacementCount) +{ + std::string result; + result.resize(component.size()); + + for(size_t i = 0; i < component.size(); ++i) + { + char c = component[i]; + if(IsLegalIdCharacter(c)) + { + result[i] = c; + } + else + { + result[i] = '_'; + ++ replacementCount; + } + } + + return result; +} + +bool cmCPackWIXGenerator::IsLegalIdCharacter(char c) +{ + return (c >= '0' && c <= '9') || + (c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || + c == '_' || c == '.'; +} + +void cmCPackWIXGenerator::CollectExtensions( + const std::string& variableName, extension_set_t& extensions) +{ + const char *variableContent = GetOption(variableName.c_str()); + if(!variableContent) return; + + std::vector<std::string> list; + cmSystemTools::ExpandListArgument(variableContent, list); + + for(std::vector<std::string>::const_iterator i = list.begin(); + i != list.end(); ++i) + { + extensions.insert(*i); + } +} + +void cmCPackWIXGenerator::AddCustomFlags( + const std::string& variableName, std::ostream& stream) +{ + const char *variableContent = GetOption(variableName.c_str()); + if(!variableContent) return; + + std::vector<std::string> list; + cmSystemTools::ExpandListArgument(variableContent, list); + + for(std::vector<std::string>::const_iterator i = list.begin(); + i != list.end(); ++i) + { + 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"); +} + +void cmCPackWIXGenerator::LoadPatchFragments(const std::string& patchFilePath) +{ + cmWIXPatchParser parser(Fragments, Logger); + parser.ParseFile(patchFilePath.c_str()); +} + +void cmCPackWIXGenerator::ApplyPatchFragment( + const std::string& id, cmWIXSourceWriter& writer) +{ + cmWIXPatchParser::fragment_map_t::iterator i = Fragments.find(id); + if(i == Fragments.end()) return; + + const cmWIXPatchElement& fragment = i->second; + for(cmWIXPatchElement::child_list_t::const_iterator + j = fragment.children.begin(); j != fragment.children.end(); ++j) + { + ApplyPatchElement(**j, writer); + } + + Fragments.erase(i); +} + +void cmCPackWIXGenerator::ApplyPatchElement( + const cmWIXPatchElement& element, cmWIXSourceWriter& writer) +{ + writer.BeginElement(element.name); + + for(cmWIXPatchElement::attributes_t::const_iterator + i = element.attributes.begin(); i != element.attributes.end(); ++i) + { + writer.AddAttribute(i->first, i->second); + } + + for(cmWIXPatchElement::child_list_t::const_iterator + i = element.children.begin(); i != element.children.end(); ++i) + { + ApplyPatchElement(**i, writer); + } + + writer.EndElement(element.name); +} diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.h b/Source/CPack/WiX/cmCPackWIXGenerator.h index aaccf9d..1f4facf 100644 --- a/Source/CPack/WiX/cmCPackWIXGenerator.h +++ b/Source/CPack/WiX/cmCPackWIXGenerator.h @@ -13,11 +13,19 @@ #ifndef cmCPackWIXGenerator_h #define cmCPackWIXGenerator_h +#include "cmWIXPatchParser.h" + #include <CPack/cmCPackGenerator.h> #include <string> #include <map> +struct cmWIXShortcut +{ + std::string textLabel; + std::string workingDirectoryId; +}; + class cmWIXSourceWriter; /** \class cmCPackWIXGenerator @@ -50,10 +58,15 @@ protected: virtual bool SupportsComponentInstallation() const { - return false; + return true; } private: + typedef std::map<std::string, std::string> id_map_t; + typedef std::map<std::string, size_t> ambiguity_map_t; + typedef std::map<std::string, cmWIXShortcut> shortcut_map_t; + typedef std::set<std::string> extension_set_t; + bool InitializeWiXConfiguration(); bool PackageFilesImpl(); @@ -68,6 +81,43 @@ private: bool CreateWiXSourceFiles(); + bool CreateCMakePackageRegistryEntry( + cmWIXSourceWriter& featureDefinitions); + + 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( + std::string const& packageName, + cmWIXSourceWriter& fileDefinitions); + + void AppendUserSuppliedExtraSources(); + + void AppendUserSuppliedExtraObjects(std::ostream& stream); + bool CreateLicenseFile(); bool RunWiXCommand(const std::string& command); @@ -82,12 +132,8 @@ private: cmWIXSourceWriter& directoryDefinitions, cmWIXSourceWriter& fileDefinitions, cmWIXSourceWriter& featureDefinitions, - size_t& directoryCounter, - size_t& fileCounter, const std::vector<std::string>& pkgExecutables, - std::vector<std::string>& dirIdExecutables - ); - + shortcut_map_t& shortcutMap); bool RequireOption(const std::string& name, std::string& value) const; @@ -99,7 +145,41 @@ private: static std::string GetRightmostExtension(const std::string& filename); - std::vector<std::string> wixSources; + std::string PathToId(const std::string& path); + + std::string CreateNewIdForPath(const std::string& path); + + static std::string CreateHashedId( + const std::string& path, const std::string& normalizedFilename); + + std::string NormalizeComponentForId( + const std::string& component, size_t& replacementCount); + + static bool IsLegalIdCharacter(char c); + + void CollectExtensions( + const std::string& variableName, extension_set_t& extensions); + + void AddCustomFlags( + const std::string& variableName, std::ostream& stream); + + void CreateStartMenuFolder(cmWIXSourceWriter& directoryDefinitions); + + void LoadPatchFragments(const std::string& patchFilePath); + + void ApplyPatchFragment(const std::string& id, cmWIXSourceWriter& writer); + + void ApplyPatchElement(const cmWIXPatchElement& element, + cmWIXSourceWriter& writer); + + std::vector<std::string> WixSources; + id_map_t PathToIdMap; + ambiguity_map_t IdAmbiguityCounter; + + extension_set_t CandleExtensions; + extension_set_t LightExtensions; + + cmWIXPatchParser::fragment_map_t Fragments; }; #endif diff --git a/Source/CPack/WiX/cmWIXPatchParser.cxx b/Source/CPack/WiX/cmWIXPatchParser.cxx new file mode 100644 index 0000000..7ceaf1f --- /dev/null +++ b/Source/CPack/WiX/cmWIXPatchParser.cxx @@ -0,0 +1,145 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2013 Kitware, Inc. + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ + +#include "cmWIXPatchParser.h" + +#include <CPack/cmCPackGenerator.h> + +#include <cm_expat.h> + +cmWIXPatchElement::~cmWIXPatchElement() +{ + for(child_list_t::iterator i = children.begin(); i != children.end(); ++i) + { + delete *i; + } +} + +cmWIXPatchParser::cmWIXPatchParser( + fragment_map_t& fragments, cmCPackLog* logger): + Logger(logger), + State(BEGIN_DOCUMENT), + Valid(true), + Fragments(fragments) +{ + +} + +void cmWIXPatchParser::StartElement(const char *name, const char **atts) +{ + std::string name_str = name; + if(State == BEGIN_DOCUMENT) + { + if(name_str == "CPackWiXPatch") + { + State = BEGIN_FRAGMENTS; + } + else + { + ReportValidationError("Expected root element 'CPackWiXPatch'"); + } + } + else if(State == BEGIN_FRAGMENTS) + { + if(name_str == "CPackWiXFragment") + { + State = INSIDE_FRAGMENT; + StartFragment(atts); + } + else + { + ReportValidationError("Expected 'CPackWixFragment' element"); + } + } + else if(State == INSIDE_FRAGMENT) + { + cmWIXPatchElement &parent = *ElementStack.back(); + + parent.children.resize(parent.children.size() + 1); + cmWIXPatchElement*& currentElement = parent.children.back(); + currentElement = new cmWIXPatchElement; + currentElement->name = name; + + for(size_t i = 0; atts[i]; i += 2) + { + std::string key = atts[i]; + std::string value = atts[i+1]; + + currentElement->attributes[key] = value; + } + + ElementStack.push_back(currentElement); + } +} + +void cmWIXPatchParser::StartFragment(const char **attributes) +{ + for(size_t i = 0; attributes[i]; i += 2) + { + std::string key = attributes[i]; + std::string value = attributes[i+1]; + + if(key == "Id") + { + if(Fragments.find(value) != Fragments.end()) + { + std::stringstream tmp; + tmp << "Invalid reuse of 'CPackWixFragment' 'Id': " << value; + ReportValidationError(tmp.str()); + } + + ElementStack.push_back(&Fragments[value]); + } + else + { + ReportValidationError( + "The only allowed 'CPackWixFragment' attribute is 'Id'"); + } + } +} + +void cmWIXPatchParser::EndElement(const char *name) +{ + std::string name_str = name; + if(State == INSIDE_FRAGMENT) + { + if(name_str == "CPackWiXFragment") + { + State = BEGIN_FRAGMENTS; + ElementStack.clear(); + } + else + { + ElementStack.pop_back(); + } + } +} + +void cmWIXPatchParser::ReportError(int line, int column, const char* msg) +{ + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Error while processing XML patch file at " << line << ":" << column << + ": "<< msg << std::endl); + Valid = false; +} + +void cmWIXPatchParser::ReportValidationError(const std::string& message) +{ + ReportError(XML_GetCurrentLineNumber(Parser), + XML_GetCurrentColumnNumber(Parser), + message.c_str()); +} + +bool cmWIXPatchParser::IsValid() const +{ + return Valid; +} diff --git a/Source/CPack/WiX/cmWIXPatchParser.h b/Source/CPack/WiX/cmWIXPatchParser.h new file mode 100644 index 0000000..91b3b66 --- /dev/null +++ b/Source/CPack/WiX/cmWIXPatchParser.h @@ -0,0 +1,75 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2013 Kitware, Inc. + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ + +#ifndef cmCPackWIXPatchParser_h +#define cmCPackWIXPatchParser_h + +#include <cmXMLParser.h> + +#include <CPack/cmCPackLog.h> + +#include <map> +#include <list> + +struct cmWIXPatchElement +{ + ~cmWIXPatchElement(); + + typedef std::list<cmWIXPatchElement*> child_list_t; + typedef std::map<std::string, std::string> attributes_t; + + std::string name; + child_list_t children; + attributes_t attributes; +}; + +/** \class cmWIXPatchParser + * \brief Helper class that parses XML patch files (CPACK_WIX_PATCH_FILE) + */ +class cmWIXPatchParser : public cmXMLParser +{ +public: + typedef std::map<std::string, cmWIXPatchElement> fragment_map_t; + + cmWIXPatchParser(fragment_map_t& Fragments, cmCPackLog* logger); + +private: + virtual void StartElement(const char *name, const char **atts); + + void StartFragment(const char **attributes); + + virtual void EndElement(const char *name); + virtual void ReportError(int line, int column, const char* msg); + + void ReportValidationError(const std::string& message); + + bool IsValid() const; + + cmCPackLog* Logger; + + enum ParserState + { + BEGIN_DOCUMENT, + BEGIN_FRAGMENTS, + INSIDE_FRAGMENT + }; + + ParserState State; + + bool Valid; + + fragment_map_t& Fragments; + + std::list<cmWIXPatchElement*> ElementStack; +}; + +#endif diff --git a/Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx b/Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx index 774c22c..ddc1d71 100644 --- a/Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx +++ b/Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx @@ -16,7 +16,7 @@ cmWIXRichTextFormatWriter::cmWIXRichTextFormatWriter( const std::string& filename): - file(filename.c_str(), std::ios::binary) + File(filename.c_str(), std::ios::binary) { StartGroup(); WriteHeader(); @@ -29,8 +29,8 @@ cmWIXRichTextFormatWriter::~cmWIXRichTextFormatWriter() /* I haven't seen this in the RTF spec but * wordpad terminates its RTF like this */ - file << "\r\n"; - file.put(0); + File << "\r\n"; + File.put(0); } void cmWIXRichTextFormatWriter::AddText(const std::string& text) @@ -44,16 +44,16 @@ void cmWIXRichTextFormatWriter::AddText(const std::string& text) switch(c) { case '\\': - file << "\\\\"; + File << "\\\\"; break; case '{': - file << "\\{"; + File << "\\{"; break; case '}': - file << "\\}"; + File << "\\}"; break; case '\n': - file << "\\par\r\n"; + File << "\\par\r\n"; break; case '\r': continue; @@ -61,11 +61,45 @@ void cmWIXRichTextFormatWriter::AddText(const std::string& text) { if(c <= 0x7F) { - file << c; + File << c; } else { - file << "[NON-ASCII-" << int(c) << "]"; + if(c <= 0xC0) + { + EmitInvalidCodepoint(c); + } + else if(c < 0xE0 && i+1 < text.size()) + { + EmitUnicodeCodepoint( + (text[i+1] & 0x3F) | + ((c & 0x1F) << 6) + ); + i+= 1; + } + else if(c < 0xF0 && i+2 < text.size()) + { + EmitUnicodeCodepoint( + (text[i+2] & 0x3F) | + ((text[i+1] & 0x3F) << 6) | + ((c & 0xF) << 12) + ); + i += 2; + } + else if(c < 0xF8 && i+3 < text.size()) + { + EmitUnicodeCodepoint( + (text[i+3] & 0x3F) | + ((text[i+2] & 0x3F) << 6) | + ((text[i+1] & 0x3F) << 12) | + ((c & 0x7) << 18) + ); + i += 3; + } + else + { + EmitInvalidCodepoint(c); + } } } break; @@ -82,6 +116,7 @@ void cmWIXRichTextFormatWriter::WriteHeader() ControlWord("deflang1031"); WriteFontTable(); + WriteColorTable(); WriteGenerator(); } @@ -99,11 +134,27 @@ void cmWIXRichTextFormatWriter::WriteFontTable() EndGroup(); } +void cmWIXRichTextFormatWriter::WriteColorTable() +{ + StartGroup(); + ControlWord("colortbl ;"); + ControlWord("red255"); + ControlWord("green0"); + ControlWord("blue0;"); + ControlWord("red0"); + ControlWord("green255"); + ControlWord("blue0;"); + ControlWord("red0"); + ControlWord("green0"); + ControlWord("blue255;"); + EndGroup(); +} + void cmWIXRichTextFormatWriter::WriteGenerator() { StartGroup(); NewControlWord("generator"); - file << " CPack WiX Generator (" << cmVersion::GetCMakeVersion() << ");"; + File << " CPack WiX Generator (" << cmVersion::GetCMakeVersion() << ");"; EndGroup(); } @@ -118,20 +169,60 @@ void cmWIXRichTextFormatWriter::WriteDocumentPrefix() void cmWIXRichTextFormatWriter::ControlWord(const std::string& keyword) { - file << "\\" << keyword; + File << "\\" << keyword; } void cmWIXRichTextFormatWriter::NewControlWord(const std::string& keyword) { - file << "\\*\\" << keyword; + File << "\\*\\" << keyword; } void cmWIXRichTextFormatWriter::StartGroup() { - file.put('{'); + File.put('{'); } void cmWIXRichTextFormatWriter::EndGroup() { - file.put('}'); + File.put('}'); +} + +void cmWIXRichTextFormatWriter::EmitUnicodeCodepoint(int c) +{ + // Do not emit byte order mark (BOM) + if(c == 0xFEFF) + { + return; + } + else if(c <= 0xFFFF) + { + EmitUnicodeSurrogate(c); + } + else + { + c -= 0x10000; + EmitUnicodeSurrogate(((c >> 10) & 0x3FF) + 0xD800); + EmitUnicodeSurrogate((c & 0x3FF) + 0xDC00); + } +} + +void cmWIXRichTextFormatWriter::EmitUnicodeSurrogate(int c) +{ + ControlWord("u"); + if(c <= 32767) + { + File << c; + } + else + { + File << (c - 65536); + } + File << "?"; +} + +void cmWIXRichTextFormatWriter::EmitInvalidCodepoint(int c) +{ + ControlWord("cf1 "); + File << "[INVALID-BYTE-" << int(c) << "]"; + ControlWord("cf0 "); } diff --git a/Source/CPack/WiX/cmWIXRichTextFormatWriter.h b/Source/CPack/WiX/cmWIXRichTextFormatWriter.h index 10b67c3..2b665d4 100644 --- a/Source/CPack/WiX/cmWIXRichTextFormatWriter.h +++ b/Source/CPack/WiX/cmWIXRichTextFormatWriter.h @@ -13,7 +13,7 @@ #ifndef cmWIXRichTextFormatWriter_h #define cmWIXRichTextFormatWriter_h -#include <fstream> +#include <cmsys/FStream.hxx> /** \class cmWIXRichtTextFormatWriter * \brief Helper class to generate Rich Text Format (RTF) documents @@ -30,6 +30,7 @@ public: private: void WriteHeader(); void WriteFontTable(); + void WriteColorTable(); void WriteGenerator(); void WriteDocumentPrefix(); @@ -40,7 +41,12 @@ private: void StartGroup(); void EndGroup(); - std::ofstream file; + void EmitUnicodeCodepoint(int c); + void EmitUnicodeSurrogate(int c); + + void EmitInvalidCodepoint(int c); + + cmsys::ofstream File; }; #endif diff --git a/Source/CPack/WiX/cmWIXSourceWriter.cxx b/Source/CPack/WiX/cmWIXSourceWriter.cxx index af7ba80..e83c226 100644 --- a/Source/CPack/WiX/cmWIXSourceWriter.cxx +++ b/Source/CPack/WiX/cmWIXSourceWriter.cxx @@ -20,8 +20,9 @@ cmWIXSourceWriter::cmWIXSourceWriter(cmCPackLog* logger, const std::string& filename, bool isIncludeFile): Logger(logger), - file(filename.c_str()), - state(DEFAULT) + File(filename.c_str()), + State(DEFAULT), + SourceFilename(filename) { WriteXMLDeclaration(); @@ -39,64 +40,79 @@ cmWIXSourceWriter::cmWIXSourceWriter(cmCPackLog* logger, cmWIXSourceWriter::~cmWIXSourceWriter() { - while(elements.size()) + if(Elements.size() > 1) { - EndElement(); + cmCPackLogger(cmCPackLog::LOG_ERROR, + Elements.size() - 1 << " WiX elements were still open when closing '" << + SourceFilename << "'" << std::endl); + return; } + + EndElement(Elements.back()); } void cmWIXSourceWriter::BeginElement(const std::string& name) { - if(state == BEGIN) + if(State == BEGIN) { - file << ">"; + File << ">"; } - file << "\n"; - Indent(elements.size()); - file << "<" << name; + File << "\n"; + Indent(Elements.size()); + File << "<" << name; - elements.push_back(name); - state = BEGIN; + Elements.push_back(name); + State = BEGIN; } -void cmWIXSourceWriter::EndElement() +void cmWIXSourceWriter::EndElement(std::string const& name) { - if(elements.empty()) + if(Elements.empty()) + { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "can not end WiX element with no open elements in '" << + SourceFilename << "'" << std::endl); + return; + } + + if(Elements.back() != name) { cmCPackLogger(cmCPackLog::LOG_ERROR, - "can not end WiX element with no open elements" << std::endl); + "WiX element <" << Elements.back() << + "> can not be closed by </" << name << "> in '" << + SourceFilename << "'" << std::endl); return; } - if(state == DEFAULT) + if(State == DEFAULT) { - file << "\n"; - Indent(elements.size()-1); - file << "</" << elements.back() << ">"; + File << "\n"; + Indent(Elements.size()-1); + File << "</" << Elements.back() << ">"; } else { - file << "/>"; + File << "/>"; } - elements.pop_back(); - state = DEFAULT; + Elements.pop_back(); + State = DEFAULT; } void cmWIXSourceWriter::AddProcessingInstruction( const std::string& target, const std::string& content) { - if(state == BEGIN) + if(State == BEGIN) { - file << ">"; + File << ">"; } - file << "\n"; - Indent(elements.size()); - file << "<?" << target << " " << content << "?>"; + File << "\n"; + Indent(Elements.size()); + File << "<?" << target << " " << content << "?>"; - state = DEFAULT; + State = DEFAULT; } void cmWIXSourceWriter::AddAttribute( @@ -104,7 +120,16 @@ void cmWIXSourceWriter::AddAttribute( { std::string utf8 = WindowsCodepageToUtf8(value); - file << " " << key << "=\"" << EscapeAttributeValue(utf8) << '"'; + 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) @@ -147,14 +172,14 @@ std::string cmWIXSourceWriter::WindowsCodepageToUtf8(const std::string& value) void cmWIXSourceWriter::WriteXMLDeclaration() { - file << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl; + File << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl; } void cmWIXSourceWriter::Indent(size_t count) { for(size_t i = 0; i < count; ++i) { - file << " "; + File << " "; } } @@ -173,6 +198,9 @@ std::string cmWIXSourceWriter::EscapeAttributeValue( case '<': result += "<"; break; + case '>': + result += ">"; + break; case '&': result +="&"; break; diff --git a/Source/CPack/WiX/cmWIXSourceWriter.h b/Source/CPack/WiX/cmWIXSourceWriter.h index 1dafc1f..894ad78 100644 --- a/Source/CPack/WiX/cmWIXSourceWriter.h +++ b/Source/CPack/WiX/cmWIXSourceWriter.h @@ -15,7 +15,7 @@ #include <vector> #include <string> -#include <fstream> +#include <cmsys/FStream.hxx> #include <CPack/cmCPackLog.h> @@ -32,7 +32,7 @@ public: void BeginElement(const std::string& name); - void EndElement(); + void EndElement(const std::string& name); void AddProcessingInstruction( const std::string& target, const std::string& content); @@ -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: @@ -57,11 +60,13 @@ private: cmCPackLog* Logger; - std::ofstream file; + cmsys::ofstream File; + + State State; - State state; + std::vector<std::string> Elements; - std::vector<std::string> elements; + std::string SourceFilename; }; #endif diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx index 4494e8a..0162d55 100644 --- a/Source/CPack/cmCPackDebGenerator.cxx +++ b/Source/CPack/cmCPackDebGenerator.cxx @@ -803,7 +803,7 @@ static int put_arobj(CF *cfp, struct stat *sb) static int ar_append(const char* archive,const std::vector<std::string>& files) { int eval = 0; - FILE* aFile = fopen(archive, "wb+"); + FILE* aFile = cmSystemTools::Fopen(archive, "wb+"); if (aFile!=NULL) { fwrite(ARMAG, SARMAG, 1, aFile); if (fseek(aFile, 0, SEEK_END) != -1) { @@ -814,7 +814,7 @@ static int ar_append(const char* archive,const std::vector<std::string>& files) for(std::vector<std::string>::const_iterator fileIt = files.begin(); fileIt!=files.end(); ++fileIt) { const char* filename = fileIt->c_str(); - FILE* file = fopen(filename, "rb"); + FILE* file = cmSystemTools::Fopen(filename, "rb"); if (file == NULL) { eval = -1; continue; diff --git a/Source/CPack/cmCPackDocumentMacros.cxx b/Source/CPack/cmCPackDocumentMacros.cxx deleted file mode 100644 index ddc75a4..0000000 --- a/Source/CPack/cmCPackDocumentMacros.cxx +++ /dev/null @@ -1,16 +0,0 @@ -#include "cmCPackDocumentMacros.h" - -void cmCPackDocumentMacros::GetMacrosDocumentation( - std::vector<cmDocumentationEntry>& ) -{ - // Commented-out example of use - // - // cmDocumentationEntry e("cpack_<macro>", - // "Brief Description" - // "which may be on several lines.", - // "Long description in pre-formatted format" - // " blah\n" - // " blah\n" - //); - //v.push_back(e); -} diff --git a/Source/CPack/cmCPackDocumentMacros.h b/Source/CPack/cmCPackDocumentMacros.h deleted file mode 100644 index 544f74f..0000000 --- a/Source/CPack/cmCPackDocumentMacros.h +++ /dev/null @@ -1,21 +0,0 @@ -/*============================================================================ - CMake - Cross Platform Makefile Generator - Copyright 2000-2009 Kitware, Inc., Insight Software Consortium - - Distributed under the OSI-approved BSD License (the "License"); - see accompanying file Copyright.txt for details. - - This software is distributed WITHOUT ANY WARRANTY; without even the - implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the License for more information. -============================================================================*/ -#ifndef cmCPackDocumentMacros_h -#define cmCPackDocumentMacros_h -#include "cmStandardIncludes.h" -class cmCPackDocumentMacros -{ -public: - static void GetMacrosDocumentation(std::vector<cmDocumentationEntry>& v); -}; - -#endif diff --git a/Source/CPack/cmCPackDocumentVariables.cxx b/Source/CPack/cmCPackDocumentVariables.cxx deleted file mode 100644 index 8b16ae9..0000000 --- a/Source/CPack/cmCPackDocumentVariables.cxx +++ /dev/null @@ -1,122 +0,0 @@ -#include "cmCPackDocumentVariables.h" -#include "cmake.h" - -void cmCPackDocumentVariables::DefineVariables(cmake* cm) -{ - // Subsection: variables defined/used by cpack, - // which are common to all CPack generators - - cm->DefineProperty - ("CPACK_PACKAGING_INSTALL_PREFIX", cmProperty::VARIABLE, - "The prefix used in the built package.", - "Each CPack generator has a default value (like /usr)." - " This default value may" - " be overwritten from the CMakeLists.txt or the cpack command line" - " by setting an alternative value.\n" - "e.g. " - " set(CPACK_PACKAGING_INSTALL_PREFIX \"/opt\")\n" - "This is not the same purpose as CMAKE_INSTALL_PREFIX which" - " is used when installing from the build tree without building" - " a package." - "", false, - "Variables common to all CPack generators"); - - cm->DefineProperty - ("CPACK_INCLUDE_TOPLEVEL_DIRECTORY", cmProperty::VARIABLE, - "Boolean toggle to include/exclude top level directory.", - "When preparing a package CPack installs the item under" - " the so-called top level directory. The purpose of" - " is to include (set to 1 or ON or TRUE) the top level directory" - " in the package or not (set to 0 or OFF or FALSE).\n" - "Each CPack generator has a built-in default value for this" - " variable. E.g. Archive generators (ZIP, TGZ, ...) includes" - " the top level whereas RPM or DEB don't. The user may override" - " the default value by setting this variable.\n" - "There is a similar variable " - "CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY " - "which may be used to override the behavior for the component" - " packaging case which may have different default value for" - " historical (now backward compatibility) reason.", false, - "Variables common to all CPack generators"); - - cm->DefineProperty - ("CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY", cmProperty::VARIABLE, - "Boolean toggle to include/exclude top level directory " - "(component case).", - "Similar usage as CPACK_INCLUDE_TOPLEVEL_DIRECTORY" - " but for the component case. " - "See CPACK_INCLUDE_TOPLEVEL_DIRECTORY documentation for" - " the detail.", false, - "Variables common to all CPack generators"); - - cm->DefineProperty - ("CPACK_SET_DESTDIR", cmProperty::VARIABLE, - "Boolean toggle to make CPack use DESTDIR mechanism when" - " packaging.", "DESTDIR means DESTination DIRectory." - " It is commonly used by makefile " - "users in order to install software at non-default location. It " - "is a basic relocation mechanism that should not be used on" - " Windows (see CMAKE_INSTALL_PREFIX documentation). " - "It is usually invoked like this:\n" - " make DESTDIR=/home/john install\n" - "which will install the concerned software using the" - " installation prefix, e.g. \"/usr/local\" prepended with " - "the DESTDIR value which finally gives \"/home/john/usr/local\"." - " When preparing a package, CPack first installs the items to be " - "packaged in a local (to the build tree) directory by using the " - "same DESTDIR mechanism. Nevertheless, if " - "CPACK_SET_DESTDIR is set then CPack will set DESTDIR before" - " doing the local install. The most noticeable difference is" - " that without CPACK_SET_DESTDIR, CPack uses " - "CPACK_PACKAGING_INSTALL_PREFIX as a prefix whereas with " - "CPACK_SET_DESTDIR set, CPack will use CMAKE_INSTALL_PREFIX as" - " a prefix.\n" - "Manually setting CPACK_SET_DESTDIR may help (or simply be" - " necessary) if some install rules uses absolute " - "DESTINATION (see CMake INSTALL command)." - " However, starting with" - " CPack/CMake 2.8.3 RPM and DEB installers tries to handle DESTDIR" - " automatically so that it is seldom necessary for the user to set" - " it.", false, - "Variables common to all CPack generators"); - - cm->DefineProperty - ("CPACK_INSTALL_SCRIPT", cmProperty::VARIABLE, - "Extra CMake script provided by the user.", - "If set this CMake script will be executed by CPack " - "during its local [CPack-private] installation " - "which is done right before packaging the files." - " The script is not called by e.g.: make install.", false, - "Variables common to all CPack generators"); - - cm->DefineProperty - ("CPACK_ABSOLUTE_DESTINATION_FILES", cmProperty::VARIABLE, - "List of files which have been installed using " - " an ABSOLUTE DESTINATION path.", - "This variable is a Read-Only variable which is set internally" - " by CPack during installation and before packaging using" - " CMAKE_ABSOLUTE_DESTINATION_FILES defined in cmake_install.cmake " - "scripts. The value can be used within CPack project configuration" - " file and/or CPack<GEN>.cmake file of <GEN> generator.", false, - "Variables common to all CPack generators"); - - cm->DefineProperty - ("CPACK_WARN_ON_ABSOLUTE_INSTALL_DESTINATION", cmProperty::VARIABLE, - "Ask CPack to warn each time a file with absolute INSTALL" - " DESTINATION is encountered.", - "This variable triggers the definition of " - "CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION when CPack runs" - " cmake_install.cmake scripts.", false, - "Variables common to all CPack generators"); - - cm->DefineProperty - ("CPACK_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION", cmProperty::VARIABLE, - "Ask CPack to error out as soon as a file with absolute INSTALL" - " DESTINATION is encountered.", - "The fatal error is emitted before the installation of " - "the offending file takes place. Some CPack generators, like NSIS," - "enforce this internally. " - "This variable triggers the definition of" - "CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION when CPack runs" - "Variables common to all CPack generators"); -} diff --git a/Source/CPack/cmCPackDocumentVariables.h b/Source/CPack/cmCPackDocumentVariables.h deleted file mode 100644 index e7971be..0000000 --- a/Source/CPack/cmCPackDocumentVariables.h +++ /dev/null @@ -1,21 +0,0 @@ -/*============================================================================ - CMake - Cross Platform Makefile Generator - Copyright 2000-2009 Kitware, Inc., Insight Software Consortium - - Distributed under the OSI-approved BSD License (the "License"); - see accompanying file Copyright.txt for details. - - This software is distributed WITHOUT ANY WARRANTY; without even the - implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the License for more information. -============================================================================*/ -#ifndef cmCPackDocumentVariables_h -#define cmCPackDocumentVariables_h -class cmake; -class cmCPackDocumentVariables -{ -public: - static void DefineVariables(cmake* cm); -}; - -#endif diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx index d973c01..9f0a77e 100644 --- a/Source/CPack/cmCPackDragNDropGenerator.cxx +++ b/Source/CPack/cmCPackDragNDropGenerator.cxx @@ -16,6 +16,7 @@ #include "cmGeneratedFileStream.h" #include <cmsys/RegularExpression.hxx> +#include <cmsys/FStream.hxx> static const char* SLAHeader = "data 'LPic' (5000) {\n" @@ -422,7 +423,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, std::string sla_r = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); sla_r += "/sla.r"; - std::ifstream ifs; + cmsys::ifstream ifs; ifs.open(cpack_license_file.c_str()); if(ifs.is_open()) { @@ -474,7 +475,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, udco_image_command << this->GetOption("CPACK_COMMAND_HDIUTIL"); udco_image_command << " convert \"" << temp_image << "\""; udco_image_command << " -format UDCO"; - udco_image_command << " -o \"" << temp_udco << "\""; + udco_image_command << " -ov -o \"" << temp_udco << "\""; std::string error; if(!this->RunCommand(udco_image_command, &error)) @@ -504,6 +505,11 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, // Rez the SLA cmOStringStream embed_sla_command; embed_sla_command << this->GetOption("CPACK_COMMAND_REZ"); + const char* sysroot = this->GetOption("CPACK_OSX_SYSROOT"); + if(sysroot && sysroot[0] != '\0') + { + embed_sla_command << " -isysroot \"" << sysroot << "\""; + } embed_sla_command << " \"" << sla_r << "\""; embed_sla_command << " -a -o "; embed_sla_command << "\"" << temp_udco << "\""; diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx index 3c685bd..96491aa 100644 --- a/Source/CPack/cmCPackGenerator.cxx +++ b/Source/CPack/cmCPackGenerator.cxx @@ -23,10 +23,12 @@ #include <cmsys/SystemTools.hxx> #include <cmsys/Glob.hxx> +#include <cmsys/FStream.hxx> #include <algorithm> #if defined(__HAIKU__) -#include <StorageKit.h> +#include <FindDirectory.h> +#include <StorageDefs.h> #endif //---------------------------------------------------------------------- @@ -151,7 +153,7 @@ int cmCPackGenerator::PrepareNames() << descFileName << "]" << std::endl); return 0; } - std::ifstream ifs(descFileName); + cmsys::ifstream ifs(descFileName); if ( !ifs ) { cmCPackLogger(cmCPackLog::LOG_ERROR, @@ -579,7 +581,7 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( * (this works at CPack time too) */ if (this->SupportsComponentInstallation() & - !(this->IsSet("CPACK_MONOLITHIC_INSTALL"))) + !(this->IsOn("CPACK_MONOLITHIC_INSTALL"))) { // Determine the installation types for this project (if provided). std::string installTypesVar = "CPACK_" @@ -636,19 +638,21 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( globalGenerator->FindMakeProgram(this->MakefileMap); const char* cmakeMakeProgram = this->MakefileMap->GetDefinition("CMAKE_MAKE_PROGRAM"); - std::string buildCommand - = globalGenerator->GenerateBuildCommand(cmakeMakeProgram, - installProjectName.c_str(), 0, 0, + std::vector<std::string> buildCommand; + globalGenerator->GenerateBuildCommand(buildCommand, cmakeMakeProgram, + installProjectName.c_str(), installDirectory.c_str(), globalGenerator->GetPreinstallTargetName(), - buildConfig, false, false); + buildConfig, false); + std::string buildCommandStr = + cmSystemTools::PrintSingleCommand(buildCommand); cmCPackLogger(cmCPackLog::LOG_DEBUG, - "- Install command: " << buildCommand << std::endl); + "- Install command: " << buildCommandStr << std::endl); cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Run preinstall target for: " << installProjectName << std::endl); std::string output; int retVal = 1; bool resB = - cmSystemTools::RunSingleCommand(buildCommand.c_str(), + cmSystemTools::RunSingleCommand(buildCommand, &output, &retVal, installDirectory.c_str(), @@ -658,12 +662,12 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); tmpFile += "/PreinstallOutput.log"; cmGeneratedFileStream ofs(tmpFile.c_str()); - ofs << "# Run command: " << buildCommand.c_str() << std::endl + ofs << "# Run command: " << buildCommandStr.c_str() << std::endl << "# Directory: " << installDirectory.c_str() << std::endl << "# Output:" << std::endl << output.c_str() << std::endl; cmCPackLogger(cmCPackLog::LOG_ERROR, - "Problem running install command: " << buildCommand.c_str() + "Problem running install command: " << buildCommandStr.c_str() << std::endl << "Please check " << tmpFile.c_str() << " for errors" << std::endl); @@ -1142,12 +1146,6 @@ int cmCPackGenerator::Initialize(const char* name, cmMakefile* mf) { this->MakefileMap = mf; this->Name = name; - if ( !this->SetCMakeRoot() ) - { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Cannot initialize the generator" << std::endl); - return 0; - } // set the running generator name this->SetOption("CPACK_GENERATOR", this->Name.c_str()); // Load the project specific config file @@ -1204,32 +1202,6 @@ const char* cmCPackGenerator::GetOption(const char* op) const } //---------------------------------------------------------------------- -int cmCPackGenerator::SetCMakeRoot() -{ - // use the CMAKE_ROOT from cmake which should have been - // found by now - const char* root= - this->MakefileMap->GetDefinition("CMAKE_ROOT"); - - if(root) - { - this->CMakeRoot = root; - cmCPackLogger(cmCPackLog::LOG_DEBUG, "Looking for CMAKE_ROOT: " - << this->CMakeRoot.c_str() << std::endl); - this->SetOption("CMAKE_ROOT", this->CMakeRoot.c_str()); - return 1; - } - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Could not find CMAKE_ROOT !!!" - << std::endl - << "CMake has most likely not been installed correctly." - << std::endl - <<"Modules directory not found in" - << std::endl); - return 0; -} - -//---------------------------------------------------------------------- int cmCPackGenerator::PackageFiles() { return 0; @@ -1263,14 +1235,14 @@ const char* cmCPackGenerator::GetInstallPath() this->InstallPath += "-"; this->InstallPath += this->GetOption("CPACK_PACKAGE_VERSION"); #elif defined(__HAIKU__) - BPath dir; - if (find_directory(B_COMMON_DIRECTORY, &dir) == B_OK) + char dir[B_PATH_NAME_LENGTH]; + if (find_directory(B_SYSTEM_DIRECTORY, -1, false, dir, sizeof(dir)) == B_OK) { - this->InstallPath = dir.Path(); + this->InstallPath = dir; } else { - this->InstallPath = "/boot/common"; + this->InstallPath = "/boot/system"; } #else this->InstallPath = "/usr/local/"; @@ -1561,13 +1533,13 @@ cmCPackGenerator::GetComponent(const char *projectName, const char *name) component->DisplayName = component->Name; } component->IsHidden - = this->IsSet((macroPrefix + "_HIDDEN").c_str()); + = this->IsOn((macroPrefix + "_HIDDEN").c_str()); component->IsRequired - = this->IsSet((macroPrefix + "_REQUIRED").c_str()); + = this->IsOn((macroPrefix + "_REQUIRED").c_str()); component->IsDisabledByDefault - = this->IsSet((macroPrefix + "_DISABLED").c_str()); + = this->IsOn((macroPrefix + "_DISABLED").c_str()); component->IsDownloaded - = this->IsSet((macroPrefix + "_DOWNLOADED").c_str()) + = this->IsOn((macroPrefix + "_DOWNLOADED").c_str()) || cmSystemTools::IsOn(this->GetOption("CPACK_DOWNLOAD_ALL")); const char* archiveFile = this->GetOption((macroPrefix + @@ -1664,9 +1636,9 @@ cmCPackGenerator::GetComponentGroup(const char *projectName, const char *name) group->Description = description; } group->IsBold - = this->IsSet((macroPrefix + "_BOLD_TITLE").c_str()); + = this->IsOn((macroPrefix + "_BOLD_TITLE").c_str()); group->IsExpandedByDefault - = this->IsSet((macroPrefix + "_EXPANDED").c_str()); + = this->IsOn((macroPrefix + "_EXPANDED").c_str()); const char* parentGroupName = this->GetOption((macroPrefix + "_PARENT_GROUP").c_str()); if (parentGroupName && *parentGroupName) diff --git a/Source/CPack/cmCPackGenerator.h b/Source/CPack/cmCPackGenerator.h index 8fafef9..bb33aa0 100644 --- a/Source/CPack/cmCPackGenerator.h +++ b/Source/CPack/cmCPackGenerator.h @@ -105,9 +105,6 @@ public: bool IsSet(const char* name) const; bool IsOn(const char* name) const; - //! Set all the variables - int SetCMakeRoot(); - //! Set the logger void SetLogger(cmCPackLog* log) { this->Logger = log; } @@ -160,9 +157,10 @@ protected: * CPack specific generator may mangle CPACK_PACKAGE_FILE_NAME * with CPACK_COMPONENT_xxxx_<NAME>_DISPLAY_NAME if * CPACK_<GEN>_USE_DISPLAY_NAME_IN_FILENAME is ON. - * @param[in] initialPackageFileName - * @param[in] groupOrComponentName - * @param[in] isGroupName + * @param[in] initialPackageFileName the initial package name to be mangled + * @param[in] groupOrComponentName the name of the group/component + * @param[in] isGroupName true if previous name refers to a group, + * false otherwise */ virtual std::string GetComponentPackageFileName( const std::string& initialPackageFileName, @@ -172,7 +170,7 @@ protected: /** * Package the list of files and/or components which * has been prepared by the beginning of DoPackage. - * @pre @ref toplevel has been filled-in + * @pre the @ref toplevel has been filled-in * @pre the list of file @ref files has been populated * @pre packageFileNames contains at least 1 entry * @post packageFileNames may have been updated and contains @@ -284,10 +282,6 @@ protected: */ std::vector<std::string> files; - std::string CPackSelf; - std::string CMakeSelf; - std::string CMakeRoot; - std::map<std::string, cmCPackInstallationType> InstallationTypes; /** * The set of components. diff --git a/Source/CPack/cmCPackPackageMakerGenerator.cxx b/Source/CPack/cmCPackPackageMakerGenerator.cxx index c617a3e..c5b9c6f 100644 --- a/Source/CPack/cmCPackPackageMakerGenerator.cxx +++ b/Source/CPack/cmCPackPackageMakerGenerator.cxx @@ -22,6 +22,7 @@ #include <cmsys/SystemTools.hxx> #include <cmsys/Glob.hxx> +#include <cmsys/FStream.hxx> //---------------------------------------------------------------------- cmCPackPackageMakerGenerator::cmCPackPackageMakerGenerator() @@ -467,7 +468,7 @@ int cmCPackPackageMakerGenerator::InitializeInternal() return 0; } - std::ifstream ifs(versionFile.c_str()); + cmsys::ifstream ifs(versionFile.c_str()); if ( !ifs ) { cmCPackLogger(cmCPackLog::LOG_ERROR, @@ -716,7 +717,7 @@ GenerateComponentPackage(const char *packageFile, // X packages, which work on Mac OS X 10.3 and newer. std::string descriptionFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); descriptionFile += '/' + component.Name + "-Description.plist"; - std::ofstream out(descriptionFile.c_str()); + cmsys::ofstream out(descriptionFile.c_str()); out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl << "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\"" << "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">" << std::endl diff --git a/Source/CPack/cmCPackSTGZGenerator.cxx b/Source/CPack/cmCPackSTGZGenerator.cxx index 9b6cf14..8342fee 100644 --- a/Source/CPack/cmCPackSTGZGenerator.cxx +++ b/Source/CPack/cmCPackSTGZGenerator.cxx @@ -20,6 +20,7 @@ #include "cmCPackLog.h" #include <cmsys/ios/sstream> +#include <cmsys/FStream.hxx> #include <sys/types.h> #include <sys/stat.h> @@ -91,7 +92,7 @@ int cmCPackSTGZGenerator::GenerateHeader(std::ostream* os) std::string inLicFile = this->GetOption("CPACK_RESOURCE_FILE_LICENSE"); std::string line; - std::ifstream ilfs(inLicFile.c_str()); + cmsys::ifstream ilfs(inLicFile.c_str()); std::string licenseText; while ( cmSystemTools::GetLineFromStream(ilfs, line) ) { @@ -104,7 +105,7 @@ int cmCPackSTGZGenerator::GenerateHeader(std::ostream* os) // Create the header std::string inFile = this->GetOption("CPACK_STGZ_HEADER_FILE"); - std::ifstream ifs(inFile.c_str()); + cmsys::ifstream ifs(inFile.c_str()); std::string packageHeaderText; while ( cmSystemTools::GetLineFromStream(ifs, line) ) { diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx index b188918..a19b778 100644 --- a/Source/CPack/cpack.cxx +++ b/Source/CPack/cpack.cxx @@ -14,8 +14,6 @@ // Need these for documentation support. #include "cmake.h" #include "cmDocumentation.h" -#include "cmCPackDocumentVariables.h" -#include "cmCPackDocumentMacros.h" #include "cmCPackGeneratorFactory.h" #include "cmCPackGenerator.h" #include "cmake.h" @@ -27,114 +25,38 @@ #include <cmsys/CommandLineArguments.hxx> #include <cmsys/SystemTools.hxx> +#include <cmsys/Encoding.hxx> //---------------------------------------------------------------------------- -static const char * cmDocumentationName[][3] = +static const char * cmDocumentationName[][2] = { {0, - " cpack - Packaging driver provided by CMake.", 0}, - {0,0,0} + " cpack - Packaging driver provided by CMake."}, + {0,0} }; //---------------------------------------------------------------------------- -static const char * cmDocumentationUsage[][3] = +static const char * cmDocumentationUsage[][2] = { {0, - " cpack -G <generator> [options]", - 0}, - {0,0,0} + " cpack -G <generator> [options]"}, + {0,0} }; //---------------------------------------------------------------------------- -static const char * cmDocumentationDescription[][3] = +static const char * cmDocumentationOptions[][2] = { - {0, - "The \"cpack\" executable is the CMake packaging program. " - "CMake-generated build trees created for projects that use " - "the INSTALL_* commands have packaging support. " - "This program will generate the package.", 0}, - CMAKE_STANDARD_INTRODUCTION, - {0,0,0} -}; - -//---------------------------------------------------------------------------- -static const char * cmDocumentationOptions[][3] = -{ - {"-G <generator>", "Use the specified generator to generate package.", - "CPack may support multiple native packaging systems on certain " - "platforms. A generator is responsible for generating input files for " - "particular system and invoking that systems. Possible generator names " - "are specified in the Generators section." }, - {"-C <Configuration>", "Specify the project configuration", - "This option specifies the configuration that the project was build " - "with, for example 'Debug', 'Release'." }, - {"-D <var>=<value>", "Set a CPack variable.", \ - "Set a variable that can be used by the generator."}, \ - {"--config <config file>", "Specify the config file.", - "Specify the config file to use to create the package. By default " - "CPackConfig.cmake in the current directory will be used." }, - {"--verbose,-V","enable verbose output","Run cpack with verbose output."}, - {"--debug","enable debug output (for CPack developers)", - "Run cpack with debug output (for CPack developers)."}, - {"-P <package name>","override/define CPACK_PACKAGE_NAME", - "If the package name is not specified on cpack commmand line then" - "CPack.cmake defines it as CMAKE_PROJECT_NAME"}, - {"-R <package version>","override/define CPACK_PACKAGE_VERSION", - "If version is not specified on cpack command line then" - "CPack.cmake defines it from CPACK_PACKAGE_VERSION_[MAJOR|MINOR|PATCH]" - "look into CPack.cmake for detail"}, - {"-B <package directory>","override/define CPACK_PACKAGE_DIRECTORY", - "The directory where CPack will be doing its packaging work." - "The resulting package will be found there. Inside this directory" - "CPack creates '_CPack_Packages' sub-directory which is the" - "CPack temporary directory."}, - {"--vendor <vendor name>","override/define CPACK_PACKAGE_VENDOR", - "If vendor is not specified on cpack command line " - "(or inside CMakeLists.txt) then" - "CPack.cmake defines it with a default value"}, - {"--help-command cmd [file]", "Print help for a single command and exit.", - "Full documentation specific to the given command is displayed. " - "If a file is specified, the documentation is written into and the output " - "format is determined depending on the filename suffix. Supported are man " - "page, HTML, DocBook and plain text."}, - {"--help-command-list [file]", "List available commands and exit.", - "The list contains all commands for which help may be obtained by using " - "the --help-command argument followed by a command name. " - "If a file is specified, the documentation is written into and the output " - "format is determined depending on the filename suffix. Supported are man " - "page, HTML, DocBook and plain text."}, - {"--help-commands [file]", "Print help for all commands and exit.", - "Full documentation specific for all current command is displayed." - "If a file is specified, the documentation is written into and the output " - "format is determined depending on the filename suffix. Supported are man " - "page, HTML, DocBook and plain text."}, - {"--help-variable var [file]", - "Print help for a single variable and exit.", - "Full documentation specific to the given variable is displayed." - "If a file is specified, the documentation is written into and the output " - "format is determined depending on the filename suffix. Supported are man " - "page, HTML, DocBook and plain text."}, - {"--help-variable-list [file]", "List documented variables and exit.", - "The list contains all variables for which help may be obtained by using " - "the --help-variable argument followed by a variable name. If a file is " - "specified, the help is written into it." - "If a file is specified, the documentation is written into and the output " - "format is determined depending on the filename suffix. Supported are man " - "page, HTML, DocBook and plain text."}, - {"--help-variables [file]", "Print help for all variables and exit.", - "Full documentation for all variables is displayed." - "If a file is specified, the documentation is written into and the output " - "format is determined depending on the filename suffix. Supported are man " - "page, HTML, DocBook and plain text."}, - {0,0,0} -}; - -//---------------------------------------------------------------------------- -static const char * cmDocumentationSeeAlso[][3] = -{ - {0, "cmake", 0}, - {0, "ccmake", 0}, - {0, 0, 0} + {"-G <generator>", "Use the specified generator to generate package."}, + {"-C <Configuration>", "Specify the project configuration"}, + {"-D <var>=<value>", "Set a CPack variable."}, + {"--config <config file>", "Specify the config file."}, + {"--verbose,-V","enable verbose output"}, + {"--debug","enable debug output (for CPack developers)"}, + {"-P <package name>","override/define CPACK_PACKAGE_NAME"}, + {"-R <package version>","override/define CPACK_PACKAGE_VERSION"}, + {"-B <package directory>","override/define CPACK_PACKAGE_DIRECTORY"}, + {"--vendor <vendor name>","override/define CPACK_PACKAGE_VENDOR"}, + {0,0} }; //---------------------------------------------------------------------------- @@ -176,9 +98,14 @@ int cpackDefinitionArgument(const char* argument, const char* cValue, //---------------------------------------------------------------------------- // this is CPack. -int main (int argc, char *argv[]) +int main (int argc, char const* const* argv) { - cmSystemTools::FindExecutableDirectory(argv[0]); + cmsys::Encoding::CommandLineArguments args = + cmsys::Encoding::CommandLineArguments::Main(argc, argv); + argc = args.argc(); + argv = args.argv(); + + cmSystemTools::FindCMakeResources(argv[0]); cmCPackLog log; log.SetErrorPrefix("CPack Error: "); @@ -481,11 +408,6 @@ int main (int argc, char *argv[]) } if ( parsed ) { -#ifdef _WIN32 - std::string comspec = "cmw9xcom.exe"; - cmSystemTools::SetWindows9xComspecSubstitute(comspec.c_str()); -#endif - const char* projName = mf->GetDefinition("CPACK_PACKAGE_NAME"); cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE, "Use generator: " << cpackGenerator->GetNameOfClass() << std::endl); @@ -533,43 +455,8 @@ int main (int argc, char *argv[]) doc.SetName("cpack"); doc.SetSection("Name",cmDocumentationName); doc.SetSection("Usage",cmDocumentationUsage); - doc.SetSection("Description",cmDocumentationDescription); doc.PrependSection("Options",cmDocumentationOptions); - // statically (in C++ code) defined variables - cmCPackDocumentVariables::DefineVariables(&cminst); - - std::vector<cmDocumentationEntry> commands; - - std::string docedFile; - std::string docPath; - cmDocumentation::documentedModulesList_t docedModList; - - docedFile = globalMF->GetModulesFile("CPack.cmake"); - if (docedFile.length()!=0) - { - docPath = cmSystemTools::GetFilenamePath(docedFile.c_str()); - doc.getDocumentedModulesListInDir(docPath,"CPack*.cmake",docedModList); - } - - // parse the files for documentation. - cmDocumentation::documentedModulesList_t::iterator docedIt; - for (docedIt = docedModList.begin(); - docedIt!= docedModList.end(); ++docedIt) - { - doc.GetStructuredDocFromFile( - (docedIt->first).c_str(), - commands,&cminst); - } - - std::map<std::string,cmDocumentationSection *> propDocs; - cminst.GetPropertiesDocumentation(propDocs); - doc.SetSections(propDocs); - cminst.GetCommandDocumentation(commands,true,false); - // statically (in C++ code) defined macros/commands - cmCPackDocumentMacros::GetMacrosDocumentation(commands); - doc.SetSection("Commands",commands); - std::vector<cmDocumentationEntry> v; cmCPackGeneratorFactory::DescriptionsMap::const_iterator generatorIt; for( generatorIt = generators.GetGeneratorsList().begin(); @@ -579,12 +466,10 @@ int main (int argc, char *argv[]) cmDocumentationEntry e; e.Name = generatorIt->first.c_str(); e.Brief = generatorIt->second.c_str(); - e.Full = ""; v.push_back(e); } doc.SetSection("Generators",v); - doc.SetSeeAlsoList(cmDocumentationSeeAlso); #undef cout return doc.PrintRequestedDocumentation(std::cout)? 0:1; #define cout no_cout_use_cmCPack_Log |