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