xref: /llvm-project/llvm/tools/llvm-libtool-darwin/DependencyInfo.h (revision 10f22335f3b7c7b78b54ee6b995f6ed97e4c225d)
1 //===-- DependencyInfo.h --------------------------------------------------===//
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 #include "llvm/ADT/StringRef.h"
10 #include "llvm/Support/FileSystem.h"
11 #include "llvm/Support/WithColor.h"
12 #include "llvm/Support/raw_ostream.h"
13 
14 #include <set>
15 
16 class DependencyInfo {
17 public:
DependencyInfo(std::string DependencyInfoPath)18   explicit DependencyInfo(std::string DependencyInfoPath)
19       : DependencyInfoPath(DependencyInfoPath) {}
20 
~DependencyInfo()21   virtual ~DependencyInfo(){};
22 
addMissingInput(llvm::StringRef Path)23   virtual void addMissingInput(llvm::StringRef Path) {
24     NotFounds.insert(Path.str());
25   }
26 
27   // Writes the dependencies to specified path. The content is first sorted by
28   // OpCode and then by the filename (in alphabetical order).
write(llvm::Twine Version,const std::vector<std::string> & Inputs,std::string Output)29   virtual void write(llvm::Twine Version,
30                      const std::vector<std::string> &Inputs,
31                      std::string Output) {
32     std::error_code EC;
33     llvm::raw_fd_ostream OS(DependencyInfoPath, EC, llvm::sys::fs::OF_None);
34     if (EC) {
35       llvm::WithColor::defaultErrorHandler(llvm::createStringError(
36           EC,
37           "failed to write to " + DependencyInfoPath + ": " + EC.message()));
38       return;
39     }
40 
41     auto AddDep = [&OS](DependencyInfoOpcode Opcode,
42                         const llvm::StringRef &Path) {
43       OS << static_cast<uint8_t>(Opcode);
44       OS << Path;
45       OS << '\0';
46     };
47 
48     AddDep(DependencyInfoOpcode::Tool, Version.str());
49 
50     // Sort the input by its names.
51     std::vector<llvm::StringRef> InputNames;
52     InputNames.reserve(Inputs.size());
53     for (const auto &F : Inputs)
54       InputNames.push_back(F);
55     llvm::sort(InputNames);
56 
57     for (const auto &In : InputNames)
58       AddDep(DependencyInfoOpcode::InputFound, In);
59 
60     for (const std::string &F : NotFounds)
61       AddDep(DependencyInfoOpcode::InputMissing, F);
62 
63     AddDep(DependencyInfoOpcode::Output, Output);
64   }
65 
66 private:
67   enum DependencyInfoOpcode : uint8_t {
68     Tool = 0x00,
69     InputFound = 0x10,
70     InputMissing = 0x11,
71     Output = 0x40,
72   };
73 
74   const std::string DependencyInfoPath;
75   std::set<std::string> NotFounds;
76 };
77 
78 // Subclass to avoid any overhead when not using this feature
79 class DummyDependencyInfo : public DependencyInfo {
80 public:
DummyDependencyInfo()81   DummyDependencyInfo() : DependencyInfo("") {}
addMissingInput(llvm::StringRef Path)82   void addMissingInput(llvm::StringRef Path) override {}
write(llvm::Twine Version,const std::vector<std::string> & Inputs,std::string Output)83   void write(llvm::Twine Version, const std::vector<std::string> &Inputs,
84              std::string Output) override {}
85 };
86