Explorar el Código

Genex: Teach SHELL_PATH to support a list of paths

Extend the genex added by commit ca6ba3fee5 (Genex: Add a SHELL_PATH
expression, 2015-09-24, v3.4.0-rc1~37^2) to accept a `;`-list of paths,
convert them all, and generate a list separated by the native shell
`PATH``` separator.
Henri Manson hace 6 años
padre
commit
463c2fba4e

+ 5 - 0
Help/manual/cmake-generator-expressions.7.rst

@@ -455,6 +455,11 @@ Output-Related Expressions
   Content of ``...`` converted to shell path style. For example, slashes are
   Content of ``...`` converted to shell path style. For example, slashes are
   converted to backslashes in Windows shells and drive letters are converted
   converted to backslashes in Windows shells and drive letters are converted
   to posix paths in MSYS shells. The ``...`` must be an absolute path.
   to posix paths in MSYS shells. The ``...`` must be an absolute path.
+  The ``...`` may be a :ref:`semicolon-separated list <CMake Language Lists>`
+  of paths, in which case each path is converted individually and a result
+  list is generated using the shell path separator (``:`` on POSIX and
+  ``;`` on Windows).  Be sure to enclose the argument containing this genex
+  in double quotes in CMake source code so that ``;`` does not split arguments.
 
 
 Debugging
 Debugging
 =========
 =========

+ 5 - 0
Help/release/dev/shell_path.rst

@@ -0,0 +1,5 @@
+shell_path
+----------
+
+* The ``$<SHELL_PATH:...>`` :manual:`generator expression
+  <cmake-generator-expressions(7)>` gained support for a list of paths.

+ 20 - 4
Source/cmGeneratorExpressionNode.cxx

@@ -15,6 +15,8 @@
 #include "cmMessageType.h"
 #include "cmMessageType.h"
 #include "cmOutputConverter.h"
 #include "cmOutputConverter.h"
 #include "cmPolicies.h"
 #include "cmPolicies.h"
+#include "cmState.h"
+#include "cmStateSnapshot.h"
 #include "cmStateTypes.h"
 #include "cmStateTypes.h"
 #include "cmSystemTools.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
 #include "cmTarget.h"
@@ -2045,13 +2047,27 @@ static const struct ShellPathNode : public cmGeneratorExpressionNode
     const GeneratorExpressionContent* content,
     const GeneratorExpressionContent* content,
     cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
     cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
   {
   {
-    if (!cmSystemTools::FileIsFullPath(parameters.front())) {
+    std::vector<std::string> listIn;
+    cmSystemTools::ExpandListArgument(parameters.front(), listIn);
+    if (listIn.empty()) {
       reportError(context, content->GetOriginalExpression(),
       reportError(context, content->GetOriginalExpression(),
-                  "\"" + parameters.front() + "\" is not an absolute path.");
+                  "\"\" is not an absolute path.");
       return std::string();
       return std::string();
     }
     }
-    cmOutputConverter converter(context->LG->GetStateSnapshot());
-    return converter.ConvertDirectorySeparatorsForShell(parameters.front());
+    cmStateSnapshot snapshot = context->LG->GetStateSnapshot();
+    cmOutputConverter converter(snapshot);
+    const char* separator = snapshot.GetState()->UseWindowsShell() ? ";" : ":";
+    std::vector<std::string> listOut;
+    listOut.reserve(listIn.size());
+    for (auto const& in : listIn) {
+      if (!cmSystemTools::FileIsFullPath(in)) {
+        reportError(context, content->GetOriginalExpression(),
+                    "\"" + in + "\" is not an absolute path.");
+        return std::string();
+      }
+      listOut.emplace_back(converter.ConvertDirectorySeparatorsForShell(in));
+    }
+    return cmJoin(listOut, separator);
   }
   }
 } shellPathNode;
 } shellPathNode;
 
 

+ 3 - 0
Tests/GeneratorExpression/CMakeLists.txt

@@ -256,8 +256,10 @@ add_custom_target(check-part3 ALL
 
 
 if(WIN32)
 if(WIN32)
   set(test_shell_path c:/shell/path)
   set(test_shell_path c:/shell/path)
+  set(test_shell_path2 c:/shell/path d:/another/path)
 else()
 else()
   set(test_shell_path /shell/path)
   set(test_shell_path /shell/path)
+  set(test_shell_path2 /shell/path /another/path)
 endif()
 endif()
 
 
 add_custom_target(check-part4 ALL
 add_custom_target(check-part4 ALL
@@ -266,6 +268,7 @@ add_custom_target(check-part4 ALL
     # CMake as command-line argument
     # CMake as command-line argument
     -Dmsys1_prefix=${msys1_prefix}
     -Dmsys1_prefix=${msys1_prefix}
     -Dtest_shell_path=${msys1_prefix}$<SHELL_PATH:${test_shell_path}>
     -Dtest_shell_path=${msys1_prefix}$<SHELL_PATH:${test_shell_path}>
+    "-Dtest_shell_path2=$<SHELL_PATH:${test_shell_path2}>"
     -Dif_1=$<IF:1,a,b>
     -Dif_1=$<IF:1,a,b>
     -Dif_2=$<IF:0,a,b>
     -Dif_2=$<IF:0,a,b>
     -Dif_3=$<IF:$<EQUAL:10,30>,a,b>
     -Dif_3=$<IF:$<EQUAL:10,30>,a,b>

+ 11 - 0
Tests/GeneratorExpression/check-part4.cmake

@@ -15,6 +15,17 @@ if(WIN32)
 else()
 else()
   check(test_shell_path [[/shell/path]])
   check(test_shell_path [[/shell/path]])
 endif()
 endif()
+if(WIN32)
+  if(CMAKE_GENERATOR STREQUAL "MSYS Makefiles" AND NOT msys1_prefix)
+    check(test_shell_path2 [[/c/shell/path:/d/another/path]])
+  elseif(CMAKE_GENERATOR STREQUAL "Unix Makefiles")
+    check(test_shell_path2 [[c:/shell/path;d:/another/path]])
+  else()
+    check(test_shell_path2 [[c:\shell\path;d:\another\path]])
+  endif()
+else()
+  check(test_shell_path2 [[/shell/path:/another/path]])
+endif()
 
 
 check(if_1 "a")
 check(if_1 "a")
 check(if_2 "b")
 check(if_2 "b")

+ 9 - 0
Tests/RunCMake/GeneratorExpression/BadSHELL_PATH-stderr.txt

@@ -15,3 +15,12 @@ CMake Error at BadSHELL_PATH.cmake:[0-9]+ \(add_custom_target\):
   "Relative/Path" is not an absolute path.
   "Relative/Path" is not an absolute path.
 Call Stack \(most recent call first\):
 Call Stack \(most recent call first\):
   CMakeLists.txt:3 \(include\)
   CMakeLists.txt:3 \(include\)
++
+CMake Error at BadSHELL_PATH.cmake:[0-9]+ \(add_custom_target\):
+  Error evaluating generator expression:
+
+    \$<SHELL_PATH:;>
+
+  "" is not an absolute path.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)

+ 1 - 0
Tests/RunCMake/GeneratorExpression/BadSHELL_PATH.cmake

@@ -1,4 +1,5 @@
 add_custom_target(check ALL COMMAND check
 add_custom_target(check ALL COMMAND check
   $<SHELL_PATH:>
   $<SHELL_PATH:>
   $<SHELL_PATH:Relative/Path>
   $<SHELL_PATH:Relative/Path>
+  "$<SHELL_PATH:;>"
   VERBATIM)
   VERBATIM)