Ninja: Fix command concatenation on Windows

Put commands that contain `||` into brackets to avoid early abort of
execution by `cmd.exe` because `||` has higher precedence than `&&` in
`cmd.exe`.

Add test to check for command execution after `||` as part of a
parameter and as command separator.

Fixes: #16850
This commit is contained in:
Bernhard Burgermeister 2017-05-04 17:57:20 +02:00 committed by Brad King
parent a83250880a
commit 5e0e03d953
3 changed files with 31 additions and 1 deletions

View File

@ -322,7 +322,13 @@ std::string cmLocalNinjaGenerator::BuildCommandLine(
} else if (cmdLines.size() > 1) {
cmd << "cmd.exe /C \"";
}
cmd << *li;
// Put current cmdLine in brackets if it contains "||" because it has
// higher precedence than "&&" in cmd.exe
if (li->find("||") != std::string::npos) {
cmd << "( " << *li << " )";
} else {
cmd << *li;
}
}
if (cmdLines.size() > 1) {
cmd << "\"";

View File

@ -0,0 +1,14 @@
cmake_minimum_required(VERSION 3.7)
project(concat_cmd NONE)
set(output1 ${CMAKE_BINARY_DIR}/out1.txt)
set(output2 ${CMAKE_BINARY_DIR}/out2.txt)
file(REMOVE ${output1} ${output2})
# Check that second command runs if first command contains "||" which has higher precedence than "&&" on Windows
add_custom_target(concat_cmd ALL
COMMAND ${CMAKE_COMMAND} -E echo "Hello || pipe world" && ${CMAKE_COMMAND} -E touch ${output1} || exit 1
COMMAND ${CMAKE_COMMAND} -E touch ${output2})
# Check output
add_custom_target(check_output ALL
COMMAND ${CMAKE_COMMAND} -E copy ${output1} ${output1}.copy
COMMAND ${CMAKE_COMMAND} -E copy ${output2} ${output2}.copy)
add_dependencies(check_output concat_cmd)

View File

@ -40,6 +40,16 @@ run_CMP0058(NEW-by)
run_cmake(CustomCommandDepfile)
function(run_CommandConcat)
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CommandConcat-build)
set(RunCMake_TEST_NO_CLEAN 1)
file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
run_cmake(CommandConcat)
run_cmake_command(CommandConcat-build ${CMAKE_COMMAND} --build .)
endfunction()
run_CommandConcat()
function(run_SubDir)
# Use a single build tree for a few tests without cleaning.
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/SubDir-build)