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 | llvm::append_range(C&: InputNames, R: Inputs); |
54 | llvm::sort(C&: InputNames); |
55 | |
56 | for (const auto &In : InputNames) |
57 | AddDep(DependencyInfoOpcode::InputFound, In); |
58 | |
59 | for (const std::string &F : NotFounds) |
60 | AddDep(DependencyInfoOpcode::InputMissing, F); |
61 | |
62 | AddDep(DependencyInfoOpcode::Output, Output); |
63 | } |
64 | |
65 | private: |
66 | enum DependencyInfoOpcode : uint8_t { |
67 | Tool = 0x00, |
68 | InputFound = 0x10, |
69 | InputMissing = 0x11, |
70 | Output = 0x40, |
71 | }; |
72 | |
73 | const std::string DependencyInfoPath; |
74 | std::set<std::string> NotFounds; |
75 | }; |
76 | |
77 | // Subclass to avoid any overhead when not using this feature |
78 | class DummyDependencyInfo : public DependencyInfo { |
79 | public: |
80 | DummyDependencyInfo() : DependencyInfo("" ) {} |
81 | void addMissingInput(llvm::StringRef Path) override {} |
82 | void write(llvm::Twine Version, const std::vector<std::string> &Inputs, |
83 | std::string Output) override {} |
84 | }; |
85 | |