1 //===-- llvm-tapi-diff.cpp - tbd comparator command-line driver --*- C++-*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines the command-line driver for the llvm-tapi difference
10 // engine.
11 //
12 //===----------------------------------------------------------------------===//
13 #include "DiffEngine.h"
14 #include "llvm/Object/TapiUniversal.h"
15 #include "llvm/Support/CommandLine.h"
16 #include "llvm/Support/Error.h"
17 #include "llvm/Support/InitLLVM.h"
18 #include "llvm/Support/WithColor.h"
19 #include "llvm/Support/raw_ostream.h"
20 #include <cstdlib>
21 
22 using namespace llvm;
23 using namespace MachO;
24 using namespace object;
25 
26 namespace {
27 cl::OptionCategory NMCat("llvm-tapi-diff Options");
28 cl::opt<std::string> InputFileNameLHS(cl::Positional, cl::desc("<first file>"),
29                                       cl::cat(NMCat));
30 cl::opt<std::string> InputFileNameRHS(cl::Positional, cl::desc("<second file>"),
31                                       cl::cat(NMCat));
32 } // anonymous namespace
33 
34 Expected<std::unique_ptr<Binary>> convertFileToBinary(std::string &Filename) {
35   ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
36       MemoryBuffer::getFileOrSTDIN(Filename);
37   if (BufferOrErr.getError())
38     return errorCodeToError(BufferOrErr.getError());
39   return createBinary(BufferOrErr.get()->getMemBufferRef());
40 }
41 
42 int main(int Argc, char **Argv) {
43   InitLLVM X(Argc, Argv);
44   cl::HideUnrelatedOptions(NMCat);
45   cl::ParseCommandLineOptions(Argc, Argv, "Text-based Stubs Comparison Tool");
46   if (InputFileNameLHS.empty() || InputFileNameRHS.empty()) {
47     cl::PrintHelpMessage();
48     return EXIT_FAILURE;
49   }
50 
51   ExitOnError ExitOnErr("error: '" + InputFileNameLHS + "' ",
52                         /*DefaultErrorExitCode=*/2);
53   auto BinLHS = ExitOnErr(convertFileToBinary(InputFileNameLHS));
54 
55   TapiUniversal *FileLHS = dyn_cast<TapiUniversal>(BinLHS.get());
56   if (!FileLHS) {
57     ExitOnErr(createStringError(std::errc::executable_format_error,
58                                 "unsupported file format"));
59   }
60 
61   ExitOnErr.setBanner("error: '" + InputFileNameRHS + "' ");
62   auto BinRHS = ExitOnErr(convertFileToBinary(InputFileNameRHS));
63 
64   TapiUniversal *FileRHS = dyn_cast<TapiUniversal>(BinRHS.get());
65   if (!FileRHS) {
66     ExitOnErr(createStringError(std::errc::executable_format_error,
67                                 "unsupported file format"));
68   }
69 
70   raw_ostream &OS = outs();
71 
72   return DiffEngine(FileLHS, FileRHS).compareFiles(OS);
73 }
74