From 776a10eeea2e82e5195f08729c4ca743a788fc43 Mon Sep 17 00:00:00 2001
From: Stefan Kislinskiy <s.kislinskiy@dkfz-heidelberg.de>
Date: Mon, 21 Sep 2015 12:42:49 +0200
Subject: [PATCH 1/4] Genex: Add SHELL_PATH
To: cmake-developers@cmake.org

---
 Source/cmGeneratorExpressionNode.cxx | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx
index 31b6766..936e707 100644
--- a/Source/cmGeneratorExpressionNode.cxx
+++ b/Source/cmGeneratorExpressionNode.cxx
@@ -13,6 +13,7 @@
 #include "cmGeneratorExpressionNode.h"
 #include "cmGlobalGenerator.h"
 #include "cmAlgorithms.h"
+#include "cmOutputConverter.h"
 
 //----------------------------------------------------------------------------
 std::string cmGeneratorExpressionNode::EvaluateDependentExpression(
@@ -1792,6 +1793,22 @@ static const
 TargetFilesystemArtifactNodeGroup<ArtifactPdbTag> targetPdbNodeGroup;
 
 //----------------------------------------------------------------------------
+static const struct ShellPathNode : public cmGeneratorExpressionNode
+{
+  ShellPathNode() {}
+
+  std::string Evaluate(const std::vector<std::string> &parameters,
+                       cmGeneratorExpressionContext *context,
+                       const GeneratorExpressionContent *,
+                       cmGeneratorExpressionDAGChecker *) const
+  {
+    cmOutputConverter converter(context->Makefile->GetStateSnapshot());
+    return converter.ConvertToOutputFormat(parameters.front(),
+                                           cmOutputConverter::SHELL);
+  }
+} shellPathNode;
+
+//----------------------------------------------------------------------------
 const cmGeneratorExpressionNode*
 cmGeneratorExpressionNode::GetNode(const std::string &identifier)
 {
@@ -1846,6 +1863,7 @@ cmGeneratorExpressionNode::GetNode(const std::string &identifier)
     nodeMap["JOIN"] = &joinNode;
     nodeMap["LINK_ONLY"] = &linkOnlyNode;
     nodeMap["COMPILE_LANGUAGE"] = &languageNode;
+    nodeMap["SHELL_PATH"] = &shellPathNode;
     }
   NodeMap::const_iterator i = nodeMap.find(identifier);
   if (i == nodeMap.end())
-- 
2.5.0.windows.1


From 67cf7295eeab73d61305822f44c815587415410a Mon Sep 17 00:00:00 2001
From: Stefan Kislinskiy <s.kislinskiy@dkfz-heidelberg.de>
Date: Mon, 21 Sep 2015 12:43:11 +0200
Subject: [PATCH 2/4] Help: Document SHELL_PATH genex
To: cmake-developers@cmake.org

---
 Help/manual/cmake-generator-expressions.7.rst | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/Help/manual/cmake-generator-expressions.7.rst b/Help/manual/cmake-generator-expressions.7.rst
index 189c3ef..67c4223 100644
--- a/Help/manual/cmake-generator-expressions.7.rst
+++ b/Help/manual/cmake-generator-expressions.7.rst
@@ -278,3 +278,7 @@ Available output expressions are:
   object of type ``OBJECT_LIBRARY``.  This expression may only be used in
   the sources of :command:`add_library` and :command:`add_executable`
   commands.
+``$<SHELL_PATH:...>``
+  Content of ``...`` converted to shell path style. For example, slashes are
+  converted to backslashes in Windows shells and drive letters are converted
+  to posix paths in MSYS shells.
-- 
2.5.0.windows.1


From 01e199b0f68417b95e826d09637e7f8551e084cd Mon Sep 17 00:00:00 2001
From: Stefan Kislinskiy <s.kislinskiy@dkfz-heidelberg.de>
Date: Tue, 22 Sep 2015 17:32:23 +0200
Subject: [PATCH 3/4] Tests: Cover SHELL_PATH genex
To: cmake-developers@cmake.org

---
 Tests/GeneratorExpression/CMakeLists.txt    | 21 ++++++++++++++++++---
 Tests/GeneratorExpression/check-part4.cmake | 12 ++++++++++++
 2 files changed, 30 insertions(+), 3 deletions(-)
 create mode 100644 Tests/GeneratorExpression/check-part4.cmake

diff --git a/Tests/GeneratorExpression/CMakeLists.txt b/Tests/GeneratorExpression/CMakeLists.txt
index 758165c..f826d01 100644
--- a/Tests/GeneratorExpression/CMakeLists.txt
+++ b/Tests/GeneratorExpression/CMakeLists.txt
@@ -66,7 +66,7 @@ add_custom_target(check-part1 ALL
     -Dtest_colons_4=$<1:C:\\CMake>
     -Dtest_colons_5=$<1:C:/CMake>
     -P ${CMAKE_CURRENT_SOURCE_DIR}/check-part1.cmake
-  COMMAND ${CMAKE_COMMAND} -E echo "check done (part 1 of 3)"
+  COMMAND ${CMAKE_COMMAND} -E echo "check done (part 1 of 4)"
   VERBATIM
   )
 
@@ -137,7 +137,7 @@ add_custom_target(check-part2 ALL
     -Dtest_arbitrary_content_comma_9=$<1:a,,b,,>
     -Dtest_arbitrary_content_comma_10=$<1:,,a,,b,,>
     -P ${CMAKE_CURRENT_SOURCE_DIR}/check-part2.cmake
-  COMMAND ${CMAKE_COMMAND} -E echo "check done (part 2 of 3)"
+  COMMAND ${CMAKE_COMMAND} -E echo "check done (part 2 of 4)"
   VERBATIM
 )
 
@@ -221,7 +221,22 @@ add_custom_target(check-part3 ALL
     -Dequal22=$<EQUAL:10,-012>
     -Dequal23=$<EQUAL:-10,-012>
     -P ${CMAKE_CURRENT_SOURCE_DIR}/check-part3.cmake
-  COMMAND ${CMAKE_COMMAND} -E echo "check done (part 3 of 3)"
+  COMMAND ${CMAKE_COMMAND} -E echo "check done (part 3 of 4)"
+  VERBATIM
+  )
+
+set(path_prefix BYPASS_FURTHER_CONVERSION)
+
+add_custom_target(check-part4 ALL
+  COMMAND ${CMAKE_COMMAND}
+    # Prefix path to bypass its further conversion when being processed by
+    # CMake as command-line argument
+    -Dtest_shell_path=${path_prefix}$<SHELL_PATH:c:/shell/path>
+    -Dpath_prefix=${path_prefix}
+    -DWIN32=${WIN32}
+    -DMSYS=${MSYS}
+    -P ${CMAKE_CURRENT_SOURCE_DIR}/check-part4.cmake
+  COMMAND ${CMAKE_COMMAND} -E echo "check done (part 4 of 4)"
   VERBATIM
   )
 
diff --git a/Tests/GeneratorExpression/check-part4.cmake b/Tests/GeneratorExpression/check-part4.cmake
new file mode 100644
index 0000000..c03fbc2
--- /dev/null
+++ b/Tests/GeneratorExpression/check-part4.cmake
@@ -0,0 +1,12 @@
+
+include(${CMAKE_CURRENT_LIST_DIR}/check-common.cmake)
+
+string(REPLACE ${path_prefix} "" test_shell_path ${test_shell_path})
+
+if(MSYS)
+  check(test_shell_path "/c/shell/path")
+elseif(WIN32)
+  check(test_shell_path "c:\\\\shell\\\\path")
+else()
+  check(test_shell_path "c:/shell/path")
+endif()
\ No newline at end of file
-- 
2.5.0.windows.1


From 4d2bc1d7d83a2c974dcb4e7ef5a40877fc8d53b1 Mon Sep 17 00:00:00 2001
From: Stefan Kislinskiy <s.kislinskiy@dkfz-heidelberg.de>
Date: Wed, 23 Sep 2015 13:56:20 +0200
Subject: [PATCH 4/4] Tests: Cover invocation of native command sensitive to
 path style
To: cmake-developers@cmake.org

---
 Tests/CMakeLists.txt                               | 15 ++++++++++++
 Tests/ExternalProjectShellPathGenex/CMakeLists.txt | 28 ++++++++++++++++++++++
 .../ExternalProjectShellPathGenex/Subdir/Empty.txt |  0
 3 files changed, 43 insertions(+)
 create mode 100644 Tests/ExternalProjectShellPathGenex/CMakeLists.txt
 create mode 100644 Tests/ExternalProjectShellPathGenex/Subdir/Empty.txt

diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index 2c6a42c..fb53884 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -1448,6 +1448,21 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
     WORKING_DIRECTORY ${CMake_SOURCE_DIR}/Tests/ExternalProjectUpdate
     DEPENDS ExternalProjectUpdateSetup )
 
+  if(WIN32)
+    add_test(ExternalProjectShellPathGenex ${CMAKE_TEST_COMMAND}
+      --build-and-test
+      "${CMake_SOURCE_DIR}/Tests/ExternalProjectShellPathGenex"
+      "${CMake_BINARY_DIR}/Tests/ExternalProjectShellPathGenex"
+      ${build_generator_args}
+      --build-project ExternalProjectShellPathGenexTest
+      --force-new-ctest-process
+      --build-options ${build_options}
+      )
+    list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/ExternalProjectShellPathGenex")
+    set_tests_properties(ExternalProjectUpdateSetup PROPERTIES
+      TIMEOUT ${CMAKE_LONG_TEST_TIMEOUT})
+  endif()
+
   # do each of the tutorial steps
   foreach(STP RANGE 1 7)
     add_test(TutorialStep${STP} ${CMAKE_CTEST_COMMAND}
diff --git a/Tests/ExternalProjectShellPathGenex/CMakeLists.txt b/Tests/ExternalProjectShellPathGenex/CMakeLists.txt
new file mode 100644
index 0000000..2632a63
--- /dev/null
+++ b/Tests/ExternalProjectShellPathGenex/CMakeLists.txt
@@ -0,0 +1,28 @@
+cmake_minimum_required(VERSION 3.3.20150923)
+project(ExternalProjectShellPathGenexTest NONE)
+
+include(ExternalProject)
+
+set(base "${CMAKE_BINARY_DIR}/CMakeExternals")
+set(binary_base "${base}/Build")
+set_property(DIRECTORY PROPERTY EP_BASE ${base})
+set_property(DIRECTORY PROPERTY EP_STEP_TARGETS configure build test)
+
+set(proj UseCmdLineDirStack)
+ExternalProject_Add(${proj}
+  BUILD_COMMAND ""
+  CONFIGURE_COMMAND ""
+  DOWNLOAD_COMMAND ""
+  INSTALL_COMMAND ""
+)
+
+ExternalProject_Add_Step(${proj} pushd
+  COMMAND pushd $<SHELL_PATH:${CMAKE_CURRENT_SOURCE_DIR}/Subdir>
+  DEPENDERS download
+)
+
+ExternalProject_Add_Step(${proj} popd
+  COMMAND popd
+  DEPENDEES pushd
+  DEPENDERS download
+)
diff --git a/Tests/ExternalProjectShellPathGenex/Subdir/Empty.txt b/Tests/ExternalProjectShellPathGenex/Subdir/Empty.txt
new file mode 100644
index 0000000..e69de29
-- 
2.5.0.windows.1

