nmake: support long comments for custom commands

Fixes: #27980
This commit is contained in:
Alex Overchenko
2026-08-04 20:16:42 +03:00
committed by AJIOB
parent e2a243ba43
commit 79b807d185
5 changed files with 74 additions and 1 deletions
+43 -1
View File
@@ -1235,6 +1235,48 @@ void cmLocalUnixMakefileGenerator3::AppendDirectoryCleanCommand(
}
}
std::string cmLocalUnixMakefileGenerator3::TrimLongCommand(
std::string cmd, std::string& line) const
{
cm::static_string_view longCommandFinalizer = "..."_s;
size_t commandLineLimit = cmSystemTools::CalculateCommandLineLengthLimit();
if (commandLineLimit == 0) {
// No limit, just return the command as is.
return cmStrCat(std::move(cmd), this->EscapeForShell(line));
}
size_t usedCommandLineLength = cmd.size() + longCommandFinalizer.size();
if (usedCommandLineLength >= commandLineLimit) {
cmSystemTools::Error(cmStrCat(
"CMake command line length limit exceeded for command: ", cmd, line));
return cmd;
}
size_t remainingSpace = commandLineLimit - usedCommandLineLength;
if (remainingSpace < line.size()) {
line.erase(remainingSpace);
line.append(longCommandFinalizer.data(), longCommandFinalizer.size());
}
// re-escape the line: we cannot just trim the line, because it may contain
// characters that cannot be removed without their pairs:
// * quotes in the end of the line
// * backslash-escaped characters in the middle of the line
std::string escapedLine = this->EscapeForShell(line);
size_t overflowSize = escapedLine.size() > remainingSpace
? escapedLine.size() - remainingSpace
: 0;
if (overflowSize > 0) {
line.erase(remainingSpace - overflowSize);
line.append(longCommandFinalizer.data(), longCommandFinalizer.size());
escapedLine = this->EscapeForShell(line);
}
return cmStrCat(std::move(cmd), std::move(escapedLine));
}
void cmLocalUnixMakefileGenerator3::AppendEcho(
std::vector<std::string>& commands, std::string const& text, EchoColor color,
EchoProgress const* progress)
@@ -1288,7 +1330,7 @@ void cmLocalUnixMakefileGenerator3::AppendEcho(
progress->Dir, cmOutputConverter::SHELL),
" --progress-num=", progress->Arg, ' ');
}
cmd += this->EscapeForShell(line);
cmd = this->TrimLongCommand(std::move(cmd), line);
}
commands.emplace_back(std::move(cmd));
}
+2
View File
@@ -250,6 +250,8 @@ protected:
cmDepends::DependencyMap& validDeps);
void CheckMultipleOutputs(bool verbose);
std::string TrimLongCommand(std::string cmd, std::string& line) const;
private:
std::string MaybeConvertWatcomShellCommand(std::string const& cmd);
@@ -0,0 +1,8 @@
file(GLOB_RECURSE FILES RELATIVE "${CMAKE_ROOT}" "${CMAKE_ROOT}/Modules/*")
add_custom_command(
OUTPUT ${FILES}
COMMAND "${CMAKE_COMMAND}" -E copy_directory "${CMAKE_ROOT}/Modules" "${CMAKE_CURRENT_BINARY_DIR}/Modules"
)
add_custom_target(LongCommentAutoGenerated ALL DEPENDS ${FILES})
@@ -0,0 +1,12 @@
set(manualComment "Message X times:")
foreach(i RANGE 1 10850)
set(manualComment "${manualComment} hello")
endforeach()
add_custom_command(
OUTPUT out.txt
COMMAND "${CMAKE_COMMAND}" -E touch out.txt
COMMENT "${manualComment}"
)
add_custom_target(LongCommentUserProvided ALL DEPENDS out.txt)
@@ -24,6 +24,15 @@ run_cmake(LiteralQuotes)
if(NOT RunCMake_GENERATOR STREQUAL "Xcode")
run_configure_and_build(LotsOutputs)
endif()
# FIXME(#28019): LongCommentAutoGenerated test fails with Xcode generator on macOS 10.15 only.
# FIXME(#28013): LongCommentAutoGenerated test fails with Borland Makefiles generator.
if(NOT RunCMake_GENERATOR STREQUAL "Borland Makefiles" AND NOT RunCMake_GENERATOR STREQUAL "Xcode")
run_configure_and_build(LongCommentAutoGenerated)
endif()
# FIXME(#28013): LongCommentUserProvided test fails with Borland Makefiles generator.
if(NOT RunCMake_GENERATOR STREQUAL "Borland Makefiles")
run_configure_and_build(LongCommentUserProvided)
endif()
run_cmake(NoArguments)
run_cmake(NoOutputOrTarget)
run_cmake(OutputAndTarget)