From 02f79c72426ec24efb597ddfdb298336f650c801 Mon Sep 17 00:00:00 2001 From: Bill Hoffman Date: Mon, 29 Oct 2007 08:11:44 -0400 Subject: [PATCH] ENH: add ability to set installer icons, links to web pages, nsis code in the icon section of the template, and ability to escape variables correctly --- CMakeCPack.cmake | 20 ++++++- Modules/CPack.cmake | 84 +++++++++++++++++++++++++-- Modules/NSIS.template.in | 5 +- Source/CPack/cmCPackNSISGenerator.cxx | 31 ++++++++-- 4 files changed, 125 insertions(+), 15 deletions(-) diff --git a/CMakeCPack.cmake b/CMakeCPack.cmake index dba3e9f91..6cb616936 100644 --- a/CMakeCPack.cmake +++ b/CMakeCPack.cmake @@ -38,11 +38,25 @@ IF(EXISTS "${CMAKE_ROOT}/Modules/CPack.cmake") ENDIF(NOT DEFINED CPACK_PACKAGE_FILE_NAME) SET(CPACK_PACKAGE_CONTACT "cmake@cmake.org") IF(WIN32 AND NOT UNIX) + # set the install/unistall icon used for the installer itself + SET(CPACK_NSIS_MUI_ICON "${CMake_SOURCE_DIR}/Utilities/Release\\CMakeLogo.ico") + SET(CPACK_NSIS_MUI_UNIICON "${CMake_SOURCE_DIR}/Utilities/Release\\CMakeLogo.ico") # There is a bug in NSI that does not handle full unix paths properly. Make # sure there is at least one set of four (4) backlasshes. - SET(CPACK_PACKAGE_ICON "${CMake_SOURCE_DIR}/Utilities/Release\\\\CMakeInstall.bmp") + SET(CPACK_PACKAGE_ICON "${CMake_SOURCE_DIR}/Utilities/Release\\CMakeInstall.bmp") # tell cpack the executables you want in the start menu as links SET(CPACK_PACKAGE_EXECUTABLES "CMakeSetup" "CMake" ) + # tell cpack to create a desktop link to CMakeSetup + SET(CPACK_CREATE_DESKTOP_LINK_CMakeSetup ON) + # These variables should have escapes preserved during the + # translation to the CPackConfig.cmake file. By default, + # CPack will require double escapes as it gets parsed by + # cmake twice + SET(CPACK_ESCAPE_VARIABLES + CPACK_PACKAGE_ICON + CPACK_NSIS_MUI_ICON + CPACK_NSIS_MUI_UNIICON + ) # tell cpack to create links to the doc files SET(CPACK_NSIS_MENU_LINKS "doc/cmake-${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}/CMakeSetup.html" "CMakeSetup Help" @@ -52,7 +66,9 @@ IF(EXISTS "${CMAKE_ROOT}/Modules/CPack.cmake") "doc/cmake-${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}/ctest.html" "CTest Help" "doc/cmake-${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}/cmake-modules.html" "CMake Modules Help" "doc/cmake-${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}/cmake-commands.html" "CMake Commands Help" - "doc/cmake-${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}/cpack.html" "CPack Help") + "doc/cmake-${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}/cpack.html" "CPack Help" + "http://www.cmake.org" "CMake Web Site" +) SET(CPACK_NSIS_INSTALLED_ICON_NAME "bin\\\\CMakeSetup.exe") SET(CPACK_NSIS_DISPLAY_NAME "${CPACK_PACKAGE_INSTALL_DIRECTORY} a cross-platform, open-source build system") SET(CPACK_NSIS_HELP_LINK "http:\\\\\\\\www.cmake.org") diff --git a/Modules/CPack.cmake b/Modules/CPack.cmake index 03e7c23c8..09ddc8043 100644 --- a/Modules/CPack.cmake +++ b/Modules/CPack.cmake @@ -19,6 +19,39 @@ MACRO(cpack_set_if_not_set name value) ENDIF(NOT DEFINED "${name}") ENDMACRO(cpack_set_if_not_set) +# create a new variable using var called +# _${var}_ESC_ where var is the name of a variable. +# the value of the new variable will have an extra +# level of escapes so that it will preserve escapes +# in the configured CPackConfig.cmake file. + +MACRO(cpack_escape_variable var) + STRING(REPLACE "\\" "\\\\" var_value "${${var}}") + STRING(REPLACE "\"" "\\\"" var_value "${var_value}") + SET(_${var}_ESC_ "${var_value}") +ENDMACRO(cpack_escape_variable) + +# do extra escapes on variables in CPACK_ESCAPE_VARIABLE +# create "special" value variables like this +# _(VARNAME)_ESC_ that store the extra escaped values for +# the varibles. This is because the original variables +# can not be used because this file gets included more +# than once and things would get double double escacped. +# (I think I want to escape...) +MACRO(cpack_escape_variables) + SET(_CPACK_OTHER_VARIABLES_) + GET_CMAKE_PROPERTY(res VARIABLES) + # first add extra escapes to the variables in CPACK_ESCAPE_VARIABLES + FOREACH(var ${res}) + IF("xxx${var}" MATCHES "xxxCPACK") + list(FIND CPACK_ESCAPE_VARIABLES "${var}" _SHOULD_BE_ESCAPED) + if(_SHOULD_BE_ESCAPED GREATER -1) + cpack_escape_variable(${var}) + endif(_SHOULD_BE_ESCAPED GREATER -1) + ENDIF("xxx${var}" MATCHES "xxxCPACK") + ENDFOREACH(var ${res}) +ENDMACRO(cpack_escape_variables) + # Macro to encode variables for the configuration file # find any varable that stars with CPACK and create a variable # _CPACK_OTHER_VARIABLES_ that contains SET commands for @@ -28,14 +61,22 @@ MACRO(cpack_encode_variables) SET(_CPACK_OTHER_VARIABLES_) GET_CMAKE_PROPERTY(res VARIABLES) FOREACH(var ${res}) - IF("xxx${var}" MATCHES "xxxCPACK") - SET(_CPACK_OTHER_VARIABLES_ - "${_CPACK_OTHER_VARIABLES_}\nSET(${var} \"${${var}}\")") - ENDIF("xxx${var}" MATCHES "xxxCPACK") + IF("xxx${var}" MATCHES "xxxCPACK") + # check for special escaped variables and use + # the escaped value instead of the actual value for + # the set. + list(FIND CPACK_ESCAPE_VARIABLES "${var}" _SHOULD_BE_ESCAPED) + if(_SHOULD_BE_ESCAPED GREATER -1) + SET(_CPACK_OTHER_VARIABLES_ + "${_CPACK_OTHER_VARIABLES_}\nSET(${var} \"${_${var}_ESC_}\")") + else(_SHOULD_BE_ESCAPED GREATER -1) + SET(_CPACK_OTHER_VARIABLES_ + "${_CPACK_OTHER_VARIABLES_}\nSET(${var} \"${${var}}\")") + endif(_SHOULD_BE_ESCAPED GREATER -1) + ENDIF("xxx${var}" MATCHES "xxxCPACK") ENDFOREACH(var ${res}) ENDMACRO(cpack_encode_variables) - # Set the package name cpack_set_if_not_set(CPACK_PACKAGE_NAME "${CMAKE_PROJECT_NAME}") cpack_set_if_not_set(CPACK_PACKAGE_VERSION_MAJOR "0") @@ -184,18 +225,48 @@ cpack_set_if_not_set(CPACK_USE_DESTDIR ON) cpack_set_if_not_set(CPACK_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") cpack_set_if_not_set(CPACK_NSIS_INSTALLER_ICON_CODE "") +cpack_set_if_not_set(CPACK_NSIS_INSTALLER_MUI_ICON_CODE "") + +# escape variables now before we do the icon define +# stuff +cpack_escape_variables() # if CPACK_PACKAGE_ICON is set, then create a # cpack variable that contains the NSIS code to define # the CPACK_PACKAGE_ICON and MUI_HEADERIMAGE_BITMAP, this is used # as an icon in the install wizard +# handle ESC_CPACK_PACKAGE_ICON version as well, that does +# not require extra escapes + if(CPACK_PACKAGE_ICON) - set(CPACK_NSIS_INSTALLER_ICON_CODE " + if(DEFINED _CPACK_PACKAGE_ICON_ESC_) + set(CPACK_NSIS_INSTALLER_ICON_CODE " +!define CPACK_PACKAGE_ICON \\\"@_CPACK_PACKAGE_ICON_ESC_@\\\" +!define MUI_HEADERIMAGE_BITMAP \\\"@_CPACK_PACKAGE_ICON_ESC_@\\\" +") + else(DEFINED _CPACK_PACKAGE_ICON_ESC_) + set(CPACK_NSIS_INSTALLER_ICON_CODE " !define CPACK_PACKAGE_ICON \\\"@CPACK_PACKAGE_ICON@\\\" !define MUI_HEADERIMAGE_BITMAP \\\"@CPACK_PACKAGE_ICON@\\\" ") + endif(DEFINED _CPACK_PACKAGE_ICON_ESC_) endif(CPACK_PACKAGE_ICON) + +if(CPACK_NSIS_MUI_ICON AND CPACK_NSIS_MUI_UNIICON) + if(DEFINED _CPACK_NSIS_MUI_ICON_ESC_) + set(CPACK_NSIS_INSTALLER_MUI_ICON_CODE " +!define MUI_ICON \\\"@_CPACK_NSIS_MUI_ICON_ESC_@\\\" +!define MUI_UNICON \\\"@_CPACK_NSIS_MUI_UNIICON_ESC_@\\\" +") + else(DEFINED _CPACK_NSIS_MUI_ICON_ESC_) + set(CPACK_NSIS_INSTALLER_MUI_ICON_CODE " +!define MUI_ICON \\\"@CPACK_NSIS_MUI_ICON@\\\" +!define MUI_UNICON \\\"@CPACK_NSIS_MUI_UNIICON@\\\" +") + endif(DEFINED _CPACK_NSIS_MUI_ICON_ESC_) +endif(CPACK_NSIS_MUI_ICON AND CPACK_NSIS_MUI_UNIICON) + cpack_encode_variables() @@ -218,6 +289,7 @@ SET(CPACK_PACKAGE_FILE_NAME "${CPACK_SOURCE_PACKAGE_FILE_NAME}") SET(CPACK_IGNORE_FILES "${CPACK_SOURCE_IGNORE_FILES}") SET(CPACK_STRIP_FILES "${CPACK_SOURCE_STRIP_FILES}") +cpack_escape_variables() cpack_encode_variables() configure_file("${cpack_source_input_file}" "${CPACK_SOURCE_OUTPUT_CONFIG_FILE}" @ONLY IMMEDIATE) diff --git a/Modules/NSIS.template.in b/Modules/NSIS.template.in index 18e1a4f97..2bdca5f28 100644 --- a/Modules/NSIS.template.in +++ b/Modules/NSIS.template.in @@ -408,6 +408,7 @@ FunctionEnd ;-------------------------------- ; Define some macro setting for the gui +@CPACK_NSIS_INSTALLER_MUI_ICON_CODE@ @CPACK_NSIS_INSTALLER_ICON_CODE@ ;-------------------------------- @@ -493,6 +494,7 @@ Section "Installer Section" InstSection ;Create shortcuts CreateDirectory "$SMPROGRAMS\$STARTMENU_FOLDER" @CPACK_NSIS_CREATE_ICONS@ +@CPACK_NSIS_CREATE_ICONS_EXTRA@ CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\Uninstall.lnk" "$INSTDIR\Uninstall.exe" ; Write special uninstall registry entries @@ -602,6 +604,7 @@ Section "Uninstall" Delete "$SMPROGRAMS\$MUI_TEMP\Uninstall.lnk" @CPACK_NSIS_DELETE_ICONS@ +@CPACK_NSIS_DELETE_ICONS_EXTRA@ ;Delete empty start menu parent diretories StrCpy $MUI_TEMP "$SMPROGRAMS\$MUI_TEMP" @@ -620,7 +623,7 @@ Section "Uninstall" ; try to fix it. StrCpy $MUI_TEMP "$START_MENU" Delete "$SMPROGRAMS\$MUI_TEMP\Uninstall.lnk" -@CPACK_NSIS_DELETE_ICONS@ +@CPACK_NSIS_DELETE_ICONS_EXTRA@ ;Delete empty start menu parent diretories StrCpy $MUI_TEMP "$SMPROGRAMS\$MUI_TEMP" diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx index f742d8e96..99618e133 100644 --- a/Source/CPack/cmCPackNSISGenerator.cxx +++ b/Source/CPack/cmCPackNSISGenerator.cxx @@ -295,15 +295,34 @@ void cmCPackNSISGenerator::CreateMenuLinks( cmOStringStream& str, ++it ) { std::string sourceName = *it; + bool url = false; + if(sourceName.find("http:") == 0) + { + url = true; + } /* convert / to \\ */ - cmSystemTools::ReplaceString(sourceName, "/", "\\"); + if(!url) + { + cmSystemTools::ReplaceString(sourceName, "/", "\\"); + } ++ it; std::string linkName = *it; - str << " CreateShortCut \"$SMPROGRAMS\\$STARTMENU_FOLDER\\" - << linkName << ".lnk\" \"$INSTDIR\\" << sourceName << "\"" - << std::endl; - deleteStr << " Delete \"$SMPROGRAMS\\$MUI_TEMP\\" << linkName - << ".lnk\"" << std::endl; + if(!url) + { + str << " CreateShortCut \"$SMPROGRAMS\\$STARTMENU_FOLDER\\" + << linkName << ".lnk\" \"$INSTDIR\\" << sourceName << "\"" + << std::endl; + deleteStr << " Delete \"$SMPROGRAMS\\$MUI_TEMP\\" << linkName + << ".lnk\"" << std::endl; + } + else + { + str << " WriteINIStr \"$SMPROGRAMS\\$STARTMENU_FOLDER\\" + << linkName << ".url\" \"InternetShortcut\" \"URL\" \"" << sourceName << "\"" + << std::endl; + deleteStr << " Delete \"$SMPROGRAMS\\$MUI_TEMP\\" << linkName + << ".url\"" << std::endl; + } // see if CPACK_CREATE_DESKTOP_LINK_ExeName is on // if so add a desktop link std::string desktop = "CPACK_CREATE_DESKTOP_LINK_";