[cmake-developers] [PATCH] CPack: add a new setting, CPACK_VERBATIM_VARIABLES

Роман Донченко dpb at corrigendum.ru
Sun Sep 20 14:03:59 EDT 2015


If it's set to a true value, CPack will escape all variables for the CMake
parser when writing them out to configuration files. This parallels the
VERBATIM argument to add_custom_command.

The cpack_encode_variables macro is changed into a function to remove
scope pollution. There should be no other effects.
---
 Help/release/dev/CPack-updates.rst              |  5 +++
 Modules/CPack.cmake                             | 43 ++++++++++++++++++++-----
 Tests/RunCMake/CPackConfig/RunCMakeTest.cmake   |  2 ++
 Tests/RunCMake/CPackConfig/Special-check.cmake  |  5 +++
 Tests/RunCMake/CPackConfig/Special.cmake        |  3 ++
 Tests/RunCMake/CPackConfig/Verbatim-check.cmake | 10 ++++++
 Tests/RunCMake/CPackConfig/Verbatim.cmake       |  5 +++
 7 files changed, 65 insertions(+), 8 deletions(-)
 create mode 100644 Tests/RunCMake/CPackConfig/Special-check.cmake
 create mode 100644 Tests/RunCMake/CPackConfig/Special.cmake
 create mode 100644 Tests/RunCMake/CPackConfig/Verbatim-check.cmake
 create mode 100644 Tests/RunCMake/CPackConfig/Verbatim.cmake

diff --git a/Help/release/dev/CPack-updates.rst b/Help/release/dev/CPack-updates.rst
index 7ac1ed7..ea0780f 100644
--- a/Help/release/dev/CPack-updates.rst
+++ b/Help/release/dev/CPack-updates.rst
@@ -4,3 +4,8 @@ CPack-updates
 * The :module:`CPack` module no longer mangles settings with CMake-special
   characters when they're used as defaults for other settings. The macro
   ``cpack_set_if_not_set``, which was responsible for this, is now deprecated.
+
+* The :module:`CPack` module gained a new setting, ``CPACK_VERBATIM_VARIABLES``,
+  which can be used to ensure the cpack program receives the settings' values
+  exactly as they were set, even if they contain CMake-special characters.
+  For compatibility, it's off by default.
diff --git a/Modules/CPack.cmake b/Modules/CPack.cmake
index 7d6d54c..ea5283c 100644
--- a/Modules/CPack.cmake
+++ b/Modules/CPack.cmake
@@ -182,6 +182,14 @@
 #  will be a boolean variable which enables stripping of all files (a list
 #  of files evaluates to TRUE in CMake, so this change is compatible).
 #
+# .. variable:: CPACK_VERBATIM_VARIABLES
+#
+#  If set to a true value, the other variables' values will be escaped before
+#  being written to the configuration files, so that the cpack program receives
+#  them exactly as they were specified. If not, characters like quotes and
+#  backslashes can cause parsing errors or alter the value received by the
+#  cpack program. Defaults to FALSE for backwards compatibility.
+#
 # The following CPack variables are specific to source packages, and
 # will not affect binary packages:
 #
@@ -305,21 +313,28 @@ macro(cpack_set_if_not_set name value)
   _cpack_set_default("${name}" "${value}")
 endmacro()
 
-# cpack_encode_variables - Macro to encode variables for the configuration file
+# cpack_encode_variables - Function to encode variables for the configuration file
 # find any variable that starts with CPACK and create a variable
 # _CPACK_OTHER_VARIABLES_ that contains SET commands for
 # each cpack variable.  _CPACK_OTHER_VARIABLES_ is then
 # used as an @ replacment in configure_file for the CPackConfig.
-macro(cpack_encode_variables)
-  set(_CPACK_OTHER_VARIABLES_)
+function(cpack_encode_variables)
+  set(commands "")
   get_cmake_property(res VARIABLES)
   foreach(var ${res})
     if(var MATCHES "^CPACK")
-      set(_CPACK_OTHER_VARIABLES_
-        "${_CPACK_OTHER_VARIABLES_}\nSET(${var} \"${${var}}\")")
+      if(CPACK_VERBATIM_VARIABLES)
+        _cpack_escape_for_cmake(value "${${var}}")
+      else()
+        set(value "${${var}}")
       endif()
+
+      set(commands "${commands}\nSET(${var} \"${value}\")")
+    endif()
   endforeach()
-endmacro()
+
+  set(_CPACK_OTHER_VARIABLES_ "${commands}" PARENT_SCOPE)
+endfunction()
 
 # Internal use functions
 function(_cpack_set_default name value)
@@ -328,6 +343,11 @@ function(_cpack_set_default name value)
   endif()
 endfunction()
 
+function(_cpack_escape_for_cmake var value)
+  string(REGEX REPLACE "([\\\$\"])" "\\\\\\1" escaped "${value}")
+  set("${var}" "${escaped}" PARENT_SCOPE)
+endfunction()
+
 # Set the package name
 _cpack_set_default(CPACK_PACKAGE_NAME "${CMAKE_PROJECT_NAME}")
 _cpack_set_default(CPACK_PACKAGE_VERSION_MAJOR "0")
@@ -608,8 +628,15 @@ _cpack_set_default(CPACK_SOURCE_INSTALLED_DIRECTORIES
 _cpack_set_default(CPACK_SOURCE_TOPLEVEL_TAG "${CPACK_SYSTEM_NAME}-Source")
 _cpack_set_default(CPACK_SOURCE_PACKAGE_FILE_NAME
   "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-Source")
-_cpack_set_default(CPACK_SOURCE_IGNORE_FILES
-  "/CVS/;/\\\\.svn/;/\\\\.bzr/;/\\\\.hg/;/\\\\.git/;\\\\.swp$;\\\\.#;/#")
+
+set(__cpack_source_ignore_files_default
+  "/CVS/;/\\.svn/;/\\.bzr/;/\\.hg/;/\\.git/;\\.swp$;\\.#;/#")
+if(NOT CPACK_VERBATIM_VARIABLES)
+  _cpack_escape_for_cmake(__cpack_source_ignore_files_default
+    "${__cpack_source_ignore_files_default}")
+endif()
+_cpack_set_default(CPACK_SOURCE_IGNORE_FILES "${__cpack_source_ignore_files_default}")
+
 set(CPACK_INSTALL_CMAKE_PROJECTS "${CPACK_SOURCE_INSTALL_CMAKE_PROJECTS}")
 set(CPACK_INSTALLED_DIRECTORIES "${CPACK_SOURCE_INSTALLED_DIRECTORIES}")
 set(CPACK_GENERATOR "${CPACK_SOURCE_GENERATOR}")
diff --git a/Tests/RunCMake/CPackConfig/RunCMakeTest.cmake b/Tests/RunCMake/CPackConfig/RunCMakeTest.cmake
index ef018b5..16d2cf3 100644
--- a/Tests/RunCMake/CPackConfig/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CPackConfig/RunCMakeTest.cmake
@@ -2,3 +2,5 @@ include(RunCMake)
 
 run_cmake(Simple)
 run_cmake(Default)
+run_cmake(Special)
+run_cmake(Verbatim)
diff --git a/Tests/RunCMake/CPackConfig/Special-check.cmake b/Tests/RunCMake/CPackConfig/Special-check.cmake
new file mode 100644
index 0000000..0624b79
--- /dev/null
+++ b/Tests/RunCMake/CPackConfig/Special-check.cmake
@@ -0,0 +1,5 @@
+include(${RunCMake_SOURCE_DIR}/check.cmake)
+
+test_variable(CPACK_BACKSLASH "\\")
+test_variable(CPACK_QUOTE "a;b;c")
+test_variable(CPACK_DOLLAR "ab")
diff --git a/Tests/RunCMake/CPackConfig/Special.cmake b/Tests/RunCMake/CPackConfig/Special.cmake
new file mode 100644
index 0000000..9442c93
--- /dev/null
+++ b/Tests/RunCMake/CPackConfig/Special.cmake
@@ -0,0 +1,3 @@
+set(CPACK_BACKSLASH "\\\\")
+set(CPACK_QUOTE "a\" b \"c")
+set(CPACK_DOLLAR "a\${NOTHING}b")
diff --git a/Tests/RunCMake/CPackConfig/Verbatim-check.cmake b/Tests/RunCMake/CPackConfig/Verbatim-check.cmake
new file mode 100644
index 0000000..958547d
--- /dev/null
+++ b/Tests/RunCMake/CPackConfig/Verbatim-check.cmake
@@ -0,0 +1,10 @@
+include(${RunCMake_SOURCE_DIR}/check.cmake)
+
+test_variable(CPACK_BACKSLASH "\\\\")
+test_variable(CPACK_QUOTE "a\" b \"c")
+test_variable(CPACK_DOLLAR "a\${NOTHING}b")
+
+# make sure the default for this is still set correctly with
+# CPACK_VERBATIM_VARIABLES on
+test_variable(CPACK_SOURCE_IGNORE_FILES
+  "/CVS/;/\\.svn/;/\\.bzr/;/\\.hg/;/\\.git/;\\.swp$;\\.#;/#")
diff --git a/Tests/RunCMake/CPackConfig/Verbatim.cmake b/Tests/RunCMake/CPackConfig/Verbatim.cmake
new file mode 100644
index 0000000..4d271c3
--- /dev/null
+++ b/Tests/RunCMake/CPackConfig/Verbatim.cmake
@@ -0,0 +1,5 @@
+set(CPACK_VERBATIM_VARIABLES YES)
+
+set(CPACK_BACKSLASH "\\\\")
+set(CPACK_QUOTE "a\" b \"c")
+set(CPACK_DOLLAR "a\${NOTHING}b")
-- 
1.9.5.msysgit.0



More information about the cmake-developers mailing list