Browse Source

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
Ben Boeckel 2 months ago
parent
commit
12a225d56d

+ 7 - 0
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;
   }

+ 11 - 0
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
+")

+ 1 - 0
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)