From 12a225d56d0e3220f1c55235c59600e7e895d735 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Mon, 6 Oct 2025 09:51:55 -0400 Subject: [PATCH] Ninja: handle trailing newlines in variable stanzas When a variable ends with a newline, the Ninja generator escapes it as expected with `$\n`. However, when writing it out, whitespace is trimmed. This leaves a trailing `$` instead which consumes the newline and masks the following stanza. In a custom command, this hides the `restat = 1` setting. Detect this case and restore the newline as necessary. See: #25983 --- Source/cmGlobalNinjaGenerator.cxx | 7 +++++++ .../RunCMake/Ninja/CommentsWithTrailingNewlines.cmake | 11 +++++++++++ Tests/RunCMake/Ninja/RunCMakeTest.cmake | 1 + 3 files changed, 19 insertions(+) create mode 100644 Tests/RunCMake/Ninja/CommentsWithTrailingNewlines.cmake diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 8527f4fcdf..b443d26069 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -521,6 +521,13 @@ void cmGlobalNinjaGenerator::WriteVariable(std::ostream& os, if (variablesShouldNotBeTrimmed.find(name) == variablesShouldNotBeTrimmed.end()) { val = cmTrimWhitespace(value); + // If the value ends with `\n` and a `$` was left at the end of the trimmed + // value, put the newline back. Otherwise the next stanza is hidden by the + // trailing `$` escaping the newline. + if (cmSystemTools::StringEndsWith(value, "\n") && + cmSystemTools::StringEndsWith(val, "$")) { + val += '\n'; + } } else { val = value; } diff --git a/Tests/RunCMake/Ninja/CommentsWithTrailingNewlines.cmake b/Tests/RunCMake/Ninja/CommentsWithTrailingNewlines.cmake new file mode 100644 index 0000000000..f4c7e6afdb --- /dev/null +++ b/Tests/RunCMake/Ninja/CommentsWithTrailingNewlines.cmake @@ -0,0 +1,11 @@ +enable_language(C) + +add_executable(comments_with_newlines hello.c) +add_custom_command(TARGET comments_with_newlines PRE_LINK + COMMAND "${CMAKE_COMMAND}" -E echo prelink + COMMENT "prelink with trailing newline +") +add_custom_command(TARGET comments_with_newlines POST_BUILD + COMMAND "${CMAKE_COMMAND}" -E echo postbuild + COMMENT "postbuild with trailing newline +") diff --git a/Tests/RunCMake/Ninja/RunCMakeTest.cmake b/Tests/RunCMake/Ninja/RunCMakeTest.cmake index 9e9caf11f5..737bcdb478 100644 --- a/Tests/RunCMake/Ninja/RunCMakeTest.cmake +++ b/Tests/RunCMake/Ninja/RunCMakeTest.cmake @@ -81,6 +81,7 @@ function(run_WithBuild name) endfunction() run_WithBuild(CommentsWithDollars) run_WithBuild(CommentsWithNewlines) +run_WithBuild(CommentsWithTrailingNewlines) function(run_VerboseBuild) run_cmake(VerboseBuild)