Skip to content

Commit 58d5fbe

Browse files
abrachettstellar
authored andcommitted
[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 llvm#54329 Reviewed By: phosek Differential Revision: https://reviews.llvm.org/D121438 (cherry picked from commit e970d28)
1 parent 50c6ba7 commit 58d5fbe

File tree

3 files changed

+41
-2
lines changed

3 files changed

+41
-2
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
REQUIRES: libxml2
2+
UNSUPPORTED: system-windows
3+
4+
Exits normally without /notify_update
5+
RUN: llvm-mt /manifest %p/Inputs/test_manifest.manifest /out:%t.manifest
6+
RUN: rm -f %t.manifest
7+
8+
We can't check exit code so all we can do is see if not considered it as a failure
9+
10+
File didn't exist previously so it's an update
11+
RUN: not llvm-mt /manifest %p/Inputs/test_manifest.manifest /out:%t.manifest /notify_update
12+
RUN: llvm-mt /manifest %p/Inputs/test_manifest.manifest /out:%t.manifest /notify_update
13+
14+
New manifest, so it's an update
15+
RUN: not llvm-mt /manifest %p/Inputs/additional.manifest /out:%t.manifest /notify_update
16+
RUN: llvm-mt /manifest %p/Inputs/additional.manifest /out:%t.manifest /notify_update

llvm/tools/llvm-mt/Opts.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ def validate_file_hashes : Joined<["/", "-"], "validate_file_hashes:">, HelpText
2323
def canonicalize : Flag<["/", "-"], "canonicalize:">, HelpText<"Not supported">, Group<unsupported>;
2424
def check_for_duplicates : Flag<["/", "-"], "check_for_duplicates:">, HelpText<"Not supported">, Group<unsupported>;
2525
def make_cdfs : Flag<["/", "-"], "makecdfs:">, HelpText<"Not supported">, Group<unsupported>;
26-
def notify_update : Flag<["/", "-"], "notify_update">, HelpText<"Not supported">, Group<unsupported>;
26+
def notify_update : Flag<["/", "-"], "notify_update">, HelpText<"Exit with a special exit code if the output file has changed">;
2727
def verbose : Flag<["/", "-"], "verbose">, HelpText<"Not supported">, Group<unsupported>;
2828
def help : Flag<["/", "-"], "?">;
2929
def help_long : Flag<["/", "-"], "help">, Alias<help>;

llvm/tools/llvm-mt/llvm-mt.cpp

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,29 @@ int main(int Argc, const char **Argv) {
141141
std::unique_ptr<MemoryBuffer> OutputBuffer = Merger.getMergedManifest();
142142
if (!OutputBuffer)
143143
reportError("empty manifest not written");
144+
145+
int ExitCode = 0;
146+
if (InputArgs.hasArg(OPT_notify_update)) {
147+
ErrorOr<std::unique_ptr<MemoryBuffer>> OutBuffOrErr =
148+
MemoryBuffer::getFile(OutputFile);
149+
// Assume if we couldn't open the output file then it doesn't exist meaning
150+
// there was a change.
151+
bool Same = false;
152+
if (OutBuffOrErr) {
153+
const std::unique_ptr<MemoryBuffer> &FileBuffer = *OutBuffOrErr;
154+
Same = std::equal(OutputBuffer->getBufferStart(),
155+
OutputBuffer->getBufferEnd(),
156+
FileBuffer->getBufferStart());
157+
}
158+
if (!Same) {
159+
#if LLVM_ON_UNIX
160+
ExitCode = 0xbb;
161+
#elif defined(_WIN32)
162+
ExitCode = 0x41020001;
163+
#endif
164+
}
165+
}
166+
144167
Expected<std::unique_ptr<FileOutputBuffer>> FileOrErr =
145168
FileOutputBuffer::create(OutputFile, OutputBuffer->getBufferSize());
146169
if (!FileOrErr)
@@ -149,5 +172,5 @@ int main(int Argc, const char **Argv) {
149172
std::copy(OutputBuffer->getBufferStart(), OutputBuffer->getBufferEnd(),
150173
FileBuffer->getBufferStart());
151174
error(FileBuffer->commit());
152-
return 0;
175+
return ExitCode;
153176
}

0 commit comments

Comments
 (0)