From 21da25d2a878cfccf9496ef7b227de2c98601ef2 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 11 Mar 2019 10:43:38 -0400 Subject: Tests: Generalize GeneratorExpression MSYS path conversion workaround Use MSYS2's `MSYS2_ARG_CONV_EXCL` environment variable to prevent path conversion where possible. --- Tests/GeneratorExpression/CMakeLists.txt | 28 +++++++++++++++++++++------- Tests/GeneratorExpression/check-part4.cmake | 4 +++- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/Tests/GeneratorExpression/CMakeLists.txt b/Tests/GeneratorExpression/CMakeLists.txt index 3d08704..ab6016b 100644 --- a/Tests/GeneratorExpression/CMakeLists.txt +++ b/Tests/GeneratorExpression/CMakeLists.txt @@ -3,11 +3,26 @@ project(GeneratorExpression) include(CTest) +# Real projects normally want the MSYS shell path conversion, but for this test +# we need to verify that the command line is constructed with the proper string. +set(msys1_prefix "") +set(msys2_no_conv "") +if(CMAKE_GENERATOR STREQUAL "MSYS Makefiles") + execute_process(COMMAND "uname" OUTPUT_VARIABLE uname) + if("${uname}" MATCHES "^MINGW32") + # MinGW.org MSYS 1.0 does not support generic path conversion suppression + set(msys1_prefix MSYS1_PREFIX) + else() + # msys2 supports generic path conversion suppression + set(msys2_no_conv env MSYS2_ARG_CONV_EXCL=-D) + endif() +endif() + # This test is split into multiple parts as needed to avoid NMake command # length limits. add_custom_target(check-part1 ALL - COMMAND ${CMAKE_COMMAND} + COMMAND ${msys2_no_conv} ${CMAKE_COMMAND} -Dtest_0=$<0:nothing> -Dtest_0_with_comma=$<0:-Wl,--no-undefined> -Dtest_1=$<1:content> @@ -97,7 +112,7 @@ add_library(empty5 empty.cpp) target_include_directories(empty5 PRIVATE /empty5/private1 /empty5/private2) add_custom_target(check-part2 ALL - COMMAND ${CMAKE_COMMAND} + COMMAND ${msys2_no_conv} ${CMAKE_COMMAND} -Dtest_incomplete_1=$< -Dtest_incomplete_2=$ -Dtest_version_greater_2=$ -Dtest_version_less_1=$ @@ -244,14 +259,13 @@ if(WIN32) else() set(test_shell_path /shell/path) endif() -set(path_prefix BYPASS_FURTHER_CONVERSION) add_custom_target(check-part4 ALL - COMMAND ${CMAKE_COMMAND} + COMMAND ${msys2_no_conv} ${CMAKE_COMMAND} # Prefix path to bypass its further conversion when being processed by # CMake as command-line argument - -Dtest_shell_path=${path_prefix}$ - -Dpath_prefix=${path_prefix} + -Dmsys1_prefix=${msys1_prefix} + -Dtest_shell_path=${msys1_prefix}$ -Dif_1=$ -Dif_2=$ -Dif_3=$,a,b> diff --git a/Tests/GeneratorExpression/check-part4.cmake b/Tests/GeneratorExpression/check-part4.cmake index f5d14dd..b6966de 100644 --- a/Tests/GeneratorExpression/check-part4.cmake +++ b/Tests/GeneratorExpression/check-part4.cmake @@ -1,6 +1,8 @@ include(${CMAKE_CURRENT_LIST_DIR}/check-common.cmake) -string(REPLACE ${path_prefix} "" test_shell_path ${test_shell_path}) +if(msys1_prefix) + string(REPLACE "${msys1_prefix}" "" test_shell_path ${test_shell_path}) +endif() if(WIN32) if(CMAKE_GENERATOR STREQUAL "MSYS Makefiles") -- cgit v0.12 From 463c2fba4eec7f364689a11b7c36afe966b1f151 Mon Sep 17 00:00:00 2001 From: Henri Manson Date: Mon, 4 Mar 2019 12:40:24 +0100 Subject: 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. --- Help/manual/cmake-generator-expressions.7.rst | 5 +++++ Help/release/dev/shell_path.rst | 5 +++++ Source/cmGeneratorExpressionNode.cxx | 24 ++++++++++++++++++---- Tests/GeneratorExpression/CMakeLists.txt | 3 +++ Tests/GeneratorExpression/check-part4.cmake | 11 ++++++++++ .../GeneratorExpression/BadSHELL_PATH-stderr.txt | 9 ++++++++ .../GeneratorExpression/BadSHELL_PATH.cmake | 1 + 7 files changed, 54 insertions(+), 4 deletions(-) create mode 100644 Help/release/dev/shell_path.rst diff --git a/Help/manual/cmake-generator-expressions.7.rst b/Help/manual/cmake-generator-expressions.7.rst index 7f484a4..614358a 100644 --- a/Help/manual/cmake-generator-expressions.7.rst +++ b/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 converted to backslashes in Windows shells and drive letters are converted to posix paths in MSYS shells. The ``...`` must be an absolute path. + The ``...`` may be a :ref:`semicolon-separated list ` + 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 ========= diff --git a/Help/release/dev/shell_path.rst b/Help/release/dev/shell_path.rst new file mode 100644 index 0000000..e8ebfb5 --- /dev/null +++ b/Help/release/dev/shell_path.rst @@ -0,0 +1,5 @@ +shell_path +---------- + +* The ``$`` :manual:`generator expression + ` gained support for a list of paths. diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index ce308cc..50fd16e 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -15,6 +15,8 @@ #include "cmMessageType.h" #include "cmOutputConverter.h" #include "cmPolicies.h" +#include "cmState.h" +#include "cmStateSnapshot.h" #include "cmStateTypes.h" #include "cmSystemTools.h" #include "cmTarget.h" @@ -2045,13 +2047,27 @@ static const struct ShellPathNode : public cmGeneratorExpressionNode const GeneratorExpressionContent* content, cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override { - if (!cmSystemTools::FileIsFullPath(parameters.front())) { + std::vector listIn; + cmSystemTools::ExpandListArgument(parameters.front(), listIn); + if (listIn.empty()) { reportError(context, content->GetOriginalExpression(), - "\"" + parameters.front() + "\" is not an absolute path."); + "\"\" is not an absolute path."); 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 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; diff --git a/Tests/GeneratorExpression/CMakeLists.txt b/Tests/GeneratorExpression/CMakeLists.txt index ab6016b..df0c78d 100644 --- a/Tests/GeneratorExpression/CMakeLists.txt +++ b/Tests/GeneratorExpression/CMakeLists.txt @@ -256,8 +256,10 @@ add_custom_target(check-part3 ALL if(WIN32) set(test_shell_path c:/shell/path) + set(test_shell_path2 c:/shell/path d:/another/path) else() set(test_shell_path /shell/path) + set(test_shell_path2 /shell/path /another/path) endif() add_custom_target(check-part4 ALL @@ -266,6 +268,7 @@ add_custom_target(check-part4 ALL # CMake as command-line argument -Dmsys1_prefix=${msys1_prefix} -Dtest_shell_path=${msys1_prefix}$ + "-Dtest_shell_path2=$" -Dif_1=$ -Dif_2=$ -Dif_3=$,a,b> diff --git a/Tests/GeneratorExpression/check-part4.cmake b/Tests/GeneratorExpression/check-part4.cmake index b6966de..a7e0944 100644 --- a/Tests/GeneratorExpression/check-part4.cmake +++ b/Tests/GeneratorExpression/check-part4.cmake @@ -15,6 +15,17 @@ if(WIN32) else() check(test_shell_path [[/shell/path]]) 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_2 "b") diff --git a/Tests/RunCMake/GeneratorExpression/BadSHELL_PATH-stderr.txt b/Tests/RunCMake/GeneratorExpression/BadSHELL_PATH-stderr.txt index 8d3c4cc..a08e7b2 100644 --- a/Tests/RunCMake/GeneratorExpression/BadSHELL_PATH-stderr.txt +++ b/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. Call Stack \(most recent call first\): CMakeLists.txt:3 \(include\) ++ +CMake Error at BadSHELL_PATH.cmake:[0-9]+ \(add_custom_target\): + Error evaluating generator expression: + + \$ + + "" is not an absolute path. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/GeneratorExpression/BadSHELL_PATH.cmake b/Tests/RunCMake/GeneratorExpression/BadSHELL_PATH.cmake index 5eff7bc..0e7c342 100644 --- a/Tests/RunCMake/GeneratorExpression/BadSHELL_PATH.cmake +++ b/Tests/RunCMake/GeneratorExpression/BadSHELL_PATH.cmake @@ -1,4 +1,5 @@ add_custom_target(check ALL COMMAND check $ $ + "$" VERBATIM) -- cgit v0.12