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: |
18 | explicit DependencyInfo(std::string DependencyInfoPath) |
19 | : DependencyInfoPath(DependencyInfoPath) {} |
20 | |
21 | virtual ~DependencyInfo(){}; |
22 | |
23 | virtual void addMissingInput(llvm::StringRef Path) { |
24 | NotFounds.insert(x: 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). |
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(Err: llvm::createStringError( |
36 | EC, |
37 | S: "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(n: Inputs.size()); |
53 | for (const auto &F : Inputs) |
54 | InputNames.push_back(x: F); |
55 | llvm::sort(C&: 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: |
81 | DummyDependencyInfo() : DependencyInfo("" ) {} |
82 | void addMissingInput(llvm::StringRef Path) override {} |
83 | void write(llvm::Twine Version, const std::vector<std::string> &Inputs, |
84 | std::string Output) override {} |
85 | }; |
86 | |