[llvm] e970d28 - [llvm-mt] Add support /notify_update

Alex Brachet via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 10 19:48:00 PST 2022


Author: Alex Brachet
Date: 2022-03-11T03:46:46Z
New Revision: e970d2823cf2a666cb597bf06ff8e0d0b880d361

URL: https://github.com/llvm/llvm-project/commit/e970d2823cf2a666cb597bf06ff8e0d0b880d361
DIFF: https://github.com/llvm/llvm-project/commit/e970d2823cf2a666cb597bf06ff8e0d0b880d361.diff

LOG: [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

Added: 
    llvm/test/tools/llvm-mt/notify_update.test

Modified: 
    llvm/tools/llvm-mt/Opts.td
    llvm/tools/llvm-mt/llvm-mt.cpp

Removed: 
    


################################################################################
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 0000000000000..f3461b3ec8fc5
--- /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 da5b2c992ee35..c4f7375c6d8fa 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 60735a95efa97..74885ec28f1c3 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;
 }


        


More information about the llvm-commits mailing list