diff options
author | Alex Brachet <abrachet@google.com> | 2022-03-11 03:46:46 +0000 |
---|---|---|
committer | Tom Stellard <tstellar@redhat.com> | 2022-04-25 19:07:04 -0700 |
commit | 58d5fbe2c20bbd2499675c2d7a35dc157c767fec (patch) | |
tree | 2c0ae31dae070922e26b5028ff2360270df867a8 | |
parent | 50c6ba751fa2c3ae8854ba09229bda62b3617c55 (diff) | |
download | llvm-58d5fbe2c20bbd2499675c2d7a35dc157c767fec.tar.gz |
[llvm-mt] Add support /notify_update
`/notify_update` is an undocumented feature used by CMake. From their usage, it looks like this feature just changes `mt`'s exit code if the output file was changed. See https://gitlab.kitware.com/cmake/cmake/-/blob/master/Source/cmcmd.cxx#L2300 this is also consistent with some testing I have done of the mt.exeshipped with Visual Studio. See also the comment at https://gitlab.kitware.com/cmake/cmake/-/blob/master/Source/cmcmd.cxx#L2440.
There might be a more performant way to implement this by first checking calling `llvm::sys::fs::file_size()` and if it is the same as the new output's size use `llvm::WritableMemoryBuffer` and fallback to `llvm::FileOutputBuffer` otherwise, but these don't inherit from a common ancestor so any implementation doing this would be really ugly.
Fixes https://github.com/llvm/llvm-project/issues/54329
Reviewed By: phosek
Differential Revision: https://reviews.llvm.org/D121438
(cherry picked from commit e970d2823cf2a666cb597bf06ff8e0d0b880d361)
-rw-r--r-- | llvm/test/tools/llvm-mt/notify_update.test | 16 | ||||
-rw-r--r-- | llvm/tools/llvm-mt/Opts.td | 2 | ||||
-rw-r--r-- | llvm/tools/llvm-mt/llvm-mt.cpp | 25 |
3 files changed, 41 insertions, 2 deletions
diff --git a/llvm/test/tools/llvm-mt/notify_update.test b/llvm/test/tools/llvm-mt/notify_update.test new file mode 100644 index 000000000000..f3461b3ec8fc --- /dev/null +++ b/llvm/test/tools/llvm-mt/notify_update.test @@ -0,0 +1,16 @@ +REQUIRES: libxml2 +UNSUPPORTED: system-windows + +Exits normally without /notify_update +RUN: llvm-mt /manifest %p/Inputs/test_manifest.manifest /out:%t.manifest +RUN: rm -f %t.manifest + +We can't check exit code so all we can do is see if not considered it as a failure + +File didn't exist previously so it's an update +RUN: not llvm-mt /manifest %p/Inputs/test_manifest.manifest /out:%t.manifest /notify_update +RUN: llvm-mt /manifest %p/Inputs/test_manifest.manifest /out:%t.manifest /notify_update + +New manifest, so it's an update +RUN: not llvm-mt /manifest %p/Inputs/additional.manifest /out:%t.manifest /notify_update +RUN: llvm-mt /manifest %p/Inputs/additional.manifest /out:%t.manifest /notify_update diff --git a/llvm/tools/llvm-mt/Opts.td b/llvm/tools/llvm-mt/Opts.td index da5b2c992ee3..c4f7375c6d8f 100644 --- a/llvm/tools/llvm-mt/Opts.td +++ b/llvm/tools/llvm-mt/Opts.td @@ -23,7 +23,7 @@ def validate_file_hashes : Joined<["/", "-"], "validate_file_hashes:">, HelpText def canonicalize : Flag<["/", "-"], "canonicalize:">, HelpText<"Not supported">, Group<unsupported>; def check_for_duplicates : Flag<["/", "-"], "check_for_duplicates:">, HelpText<"Not supported">, Group<unsupported>; def make_cdfs : Flag<["/", "-"], "makecdfs:">, HelpText<"Not supported">, Group<unsupported>; -def notify_update : Flag<["/", "-"], "notify_update">, HelpText<"Not supported">, Group<unsupported>; +def notify_update : Flag<["/", "-"], "notify_update">, HelpText<"Exit with a special exit code if the output file has changed">; def verbose : Flag<["/", "-"], "verbose">, HelpText<"Not supported">, Group<unsupported>; def help : Flag<["/", "-"], "?">; def help_long : Flag<["/", "-"], "help">, Alias<help>; diff --git a/llvm/tools/llvm-mt/llvm-mt.cpp b/llvm/tools/llvm-mt/llvm-mt.cpp index 60735a95efa9..74885ec28f1c 100644 --- a/llvm/tools/llvm-mt/llvm-mt.cpp +++ b/llvm/tools/llvm-mt/llvm-mt.cpp @@ -141,6 +141,29 @@ int main(int Argc, const char **Argv) { std::unique_ptr<MemoryBuffer> OutputBuffer = Merger.getMergedManifest(); if (!OutputBuffer) reportError("empty manifest not written"); + + int ExitCode = 0; + if (InputArgs.hasArg(OPT_notify_update)) { + ErrorOr<std::unique_ptr<MemoryBuffer>> OutBuffOrErr = + MemoryBuffer::getFile(OutputFile); + // Assume if we couldn't open the output file then it doesn't exist meaning + // there was a change. + bool Same = false; + if (OutBuffOrErr) { + const std::unique_ptr<MemoryBuffer> &FileBuffer = *OutBuffOrErr; + Same = std::equal(OutputBuffer->getBufferStart(), + OutputBuffer->getBufferEnd(), + FileBuffer->getBufferStart()); + } + if (!Same) { +#if LLVM_ON_UNIX + ExitCode = 0xbb; +#elif defined(_WIN32) + ExitCode = 0x41020001; +#endif + } + } + Expected<std::unique_ptr<FileOutputBuffer>> FileOrErr = FileOutputBuffer::create(OutputFile, OutputBuffer->getBufferSize()); if (!FileOrErr) @@ -149,5 +172,5 @@ int main(int Argc, const char **Argv) { std::copy(OutputBuffer->getBufferStart(), OutputBuffer->getBufferEnd(), FileBuffer->getBufferStart()); error(FileBuffer->commit()); - return 0; + return ExitCode; } |