diff --git a/Modules/CPackNSIS.cmake b/Modules/CPackNSIS.cmake index db5984a66..4693ce5ac 100644 --- a/Modules/CPackNSIS.cmake +++ b/Modules/CPackNSIS.cmake @@ -96,6 +96,11 @@ # Contact information for questions and comments about the installation # process. # +# .. variable:: CPACK_NSIS__INSTALL_DIRECTORY +# +# Custom install directory for the specified component instead +# of $INSTDIR. +# # .. variable:: CPACK_NSIS_CREATE_ICONS_EXTRA # # Additional NSIS commands for creating start menu shortcuts. diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx index 2db94f118..b49da7f18 100644 --- a/Source/CPack/cmCPackNSISGenerator.cxx +++ b/Source/CPack/cmCPackNSISGenerator.cxx @@ -71,14 +71,26 @@ int cmCPackNSISGenerator::PackageFiles() std::ostringstream str; std::vector::const_iterator it; for (it = files.begin(); it != files.end(); ++it) { + std::string outputDir = "$INSTDIR"; std::string fileN = cmSystemTools::RelativePath(toplevel.c_str(), it->c_str()); if (!this->Components.empty()) { + const std::string::size_type pos = fileN.find('/'); + + // Use the custom component install directory if we have one + if (pos != std::string::npos) { + const std::string componentName = fileN.substr(0, pos); + outputDir = CustomComponentInstallDirectory(componentName); + } else { + outputDir = CustomComponentInstallDirectory(fileN); + } + // Strip off the component part of the path. - fileN = fileN.substr(fileN.find('/') + 1, std::string::npos); + fileN = fileN.substr(pos + 1, std::string::npos); } std::replace(fileN.begin(), fileN.end(), '/', '\\'); - str << " Delete \"$INSTDIR\\" << fileN << "\"" << std::endl; + + str << " Delete \"" << outputDir << "\\" << fileN << "\"" << std::endl; } cmCPackLogger(cmCPackLog::LOG_DEBUG, "Uninstall Files: " << str.str() << std::endl); @@ -108,7 +120,12 @@ int cmCPackNSISGenerator::PackageFiles() } } std::replace(fileN.begin(), fileN.end(), '/', '\\'); - dstr << " RMDir \"$INSTDIR\\" << fileN << "\"" << std::endl; + + const std::string componentOutputDir = + CustomComponentInstallDirectory(componentName); + + dstr << " RMDir \"" << componentOutputDir << "\\" << fileN << "\"" + << std::endl; if (!componentName.empty()) { this->Components[componentName].Directories.push_back(fileN); } @@ -650,7 +667,10 @@ std::string cmCPackNSISGenerator::CreateComponentDescription( } componentCode += " SectionIn" + out.str() + "\n"; } - componentCode += " SetOutPath \"$INSTDIR\"\n"; + + const std::string componentOutputDir = + CustomComponentInstallDirectory(component->Name); + componentCode += " SetOutPath \"" + componentOutputDir + "\"\n"; // Create the actual installation commands if (component->IsDownloaded) { @@ -796,13 +816,13 @@ std::string cmCPackNSISGenerator::CreateComponentDescription( ++pathIt) { path = *pathIt; std::replace(path.begin(), path.end(), '/', '\\'); - macrosOut << " Delete \"$INSTDIR\\" << path << "\"\n"; + macrosOut << " Delete \"" << componentOutputDir << "\\" << path << "\"\n"; } for (pathIt = component->Directories.begin(); pathIt != component->Directories.end(); ++pathIt) { path = *pathIt; std::replace(path.begin(), path.end(), '/', '\\'); - macrosOut << " RMDir \"$INSTDIR\\" << path << "\"\n"; + macrosOut << " RMDir \"" << componentOutputDir << "\\" << path << "\"\n"; } macrosOut << " noremove_" << component->Name << ":\n"; macrosOut << "!macroend\n"; @@ -914,6 +934,15 @@ std::string cmCPackNSISGenerator::CreateComponentGroupDescription( return code; } +std::string cmCPackNSISGenerator::CustomComponentInstallDirectory( + const std::string& componentName) +{ + const char* outputDir = + this->GetOption("CPACK_NSIS_" + componentName + "_INSTALL_DIRECTORY"); + const std::string componentOutputDir = (outputDir ? outputDir : "$INSTDIR"); + return componentOutputDir; +} + std::string cmCPackNSISGenerator::TranslateNewlines(std::string str) { cmSystemTools::ReplaceString(str, "\n", "$\\r$\\n"); diff --git a/Source/CPack/cmCPackNSISGenerator.h b/Source/CPack/cmCPackNSISGenerator.h index ae03e6b5d..bd7d752ee 100644 --- a/Source/CPack/cmCPackNSISGenerator.h +++ b/Source/CPack/cmCPackNSISGenerator.h @@ -84,6 +84,11 @@ protected: std::string CreateComponentGroupDescription(cmCPackComponentGroup* group, std::ostream& macrosOut); + /// Returns the custom install directory if available for the specified + /// component, otherwise $INSTDIR is returned. + std::string CustomComponentInstallDirectory( + const std::string& componentName); + /// Translations any newlines found in the string into \\r\\n, so that the /// resulting string can be used within NSIS. static std::string TranslateNewlines(std::string str);