1 //===- Job.h - Commands to Execute ------------------------------*- 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 #ifndef LLVM_CLANG_DRIVER_JOB_H 10 #define LLVM_CLANG_DRIVER_JOB_H 11 12 #include "clang/Basic/LLVM.h" 13 #include "llvm/ADT/ArrayRef.h" 14 #include "llvm/ADT/Optional.h" 15 #include "llvm/ADT/SmallVector.h" 16 #include "llvm/ADT/StringRef.h" 17 #include "llvm/ADT/iterator.h" 18 #include "llvm/Option/Option.h" 19 #include <memory> 20 #include <string> 21 #include <utility> 22 #include <vector> 23 24 namespace clang { 25 namespace driver { 26 27 class Action; 28 class InputInfo; 29 class Tool; 30 31 struct CrashReportInfo { 32 StringRef Filename; 33 StringRef VFSPath; 34 35 CrashReportInfo(StringRef Filename, StringRef VFSPath) 36 : Filename(Filename), VFSPath(VFSPath) {} 37 }; 38 39 /// Command - An executable path/name and argument vector to 40 /// execute. 41 class Command { 42 /// Source - The action which caused the creation of this job. 43 const Action &Source; 44 45 /// Tool - The tool which caused the creation of this job. 46 const Tool &Creator; 47 48 /// The executable to run. 49 const char *Executable; 50 51 /// The list of program arguments (not including the implicit first 52 /// argument, which will be the executable). 53 llvm::opt::ArgStringList Arguments; 54 55 /// The list of program arguments which are inputs. 56 llvm::opt::ArgStringList InputFilenames; 57 58 /// Whether to print the input filenames when executing. 59 bool PrintInputFilenames = false; 60 61 /// Response file name, if this command is set to use one, or nullptr 62 /// otherwise 63 const char *ResponseFile = nullptr; 64 65 /// The input file list in case we need to emit a file list instead of a 66 /// proper response file 67 llvm::opt::ArgStringList InputFileList; 68 69 /// String storage if we need to create a new argument to specify a response 70 /// file 71 std::string ResponseFileFlag; 72 73 /// See Command::setEnvironment 74 std::vector<const char *> Environment; 75 76 /// When a response file is needed, we try to put most arguments in an 77 /// exclusive file, while others remains as regular command line arguments. 78 /// This functions fills a vector with the regular command line arguments, 79 /// argv, excluding the ones passed in a response file. 80 void buildArgvForResponseFile(llvm::SmallVectorImpl<const char *> &Out) const; 81 82 /// Encodes an array of C strings into a single string separated by whitespace. 83 /// This function will also put in quotes arguments that have whitespaces and 84 /// will escape the regular backslashes (used in Windows paths) and quotes. 85 /// The results are the contents of a response file, written into a raw_ostream. 86 void writeResponseFile(raw_ostream &OS) const; 87 88 public: 89 Command(const Action &Source, const Tool &Creator, const char *Executable, 90 const llvm::opt::ArgStringList &Arguments, 91 ArrayRef<InputInfo> Inputs); 92 // FIXME: This really shouldn't be copyable, but is currently copied in some 93 // error handling in Driver::generateCompilationDiagnostics. 94 Command(const Command &) = default; 95 virtual ~Command() = default; 96 97 virtual void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote, 98 CrashReportInfo *CrashInfo = nullptr) const; 99 100 virtual int Execute(ArrayRef<Optional<StringRef>> Redirects, 101 std::string *ErrMsg, bool *ExecutionFailed) const; 102 103 /// getSource - Return the Action which caused the creation of this job. 104 const Action &getSource() const { return Source; } 105 106 /// getCreator - Return the Tool which caused the creation of this job. 107 const Tool &getCreator() const { return Creator; } 108 109 /// Set to pass arguments via a response file when launching the command 110 void setResponseFile(const char *FileName); 111 112 /// Set an input file list, necessary if we need to use a response file but 113 /// the tool being called only supports input files lists. 114 void setInputFileList(llvm::opt::ArgStringList List) { 115 InputFileList = std::move(List); 116 } 117 118 /// Sets the environment to be used by the new process. 119 /// \param NewEnvironment An array of environment variables. 120 /// \remark If the environment remains unset, then the environment 121 /// from the parent process will be used. 122 virtual void setEnvironment(llvm::ArrayRef<const char *> NewEnvironment); 123 124 const char *getExecutable() const { return Executable; } 125 126 const llvm::opt::ArgStringList &getArguments() const { return Arguments; } 127 128 /// Print a command argument, and optionally quote it. 129 static void printArg(llvm::raw_ostream &OS, StringRef Arg, bool Quote); 130 131 /// Set whether to print the input filenames when executing. 132 void setPrintInputFilenames(bool P) { PrintInputFilenames = P; } 133 134 protected: 135 /// Optionally print the filenames to be compiled 136 void PrintFileNames() const; 137 }; 138 139 /// Use the CC1 tool callback when available, to avoid creating a new process 140 class CC1Command : public Command { 141 public: 142 using Command::Command; 143 144 void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote, 145 CrashReportInfo *CrashInfo = nullptr) const override; 146 147 int Execute(ArrayRef<Optional<StringRef>> Redirects, std::string *ErrMsg, 148 bool *ExecutionFailed) const override; 149 150 void setEnvironment(llvm::ArrayRef<const char *> NewEnvironment) override; 151 }; 152 153 /// Like Command, but with a fallback which is executed in case 154 /// the primary command crashes. 155 class FallbackCommand : public Command { 156 public: 157 FallbackCommand(const Action &Source_, const Tool &Creator_, 158 const char *Executable_, 159 const llvm::opt::ArgStringList &Arguments_, 160 ArrayRef<InputInfo> Inputs, 161 std::unique_ptr<Command> Fallback_); 162 163 void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote, 164 CrashReportInfo *CrashInfo = nullptr) const override; 165 166 int Execute(ArrayRef<Optional<StringRef>> Redirects, std::string *ErrMsg, 167 bool *ExecutionFailed) const override; 168 169 private: 170 std::unique_ptr<Command> Fallback; 171 }; 172 173 /// Like Command, but always pretends that the wrapped command succeeded. 174 class ForceSuccessCommand : public Command { 175 public: 176 ForceSuccessCommand(const Action &Source_, const Tool &Creator_, 177 const char *Executable_, 178 const llvm::opt::ArgStringList &Arguments_, 179 ArrayRef<InputInfo> Inputs); 180 181 void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote, 182 CrashReportInfo *CrashInfo = nullptr) const override; 183 184 int Execute(ArrayRef<Optional<StringRef>> Redirects, std::string *ErrMsg, 185 bool *ExecutionFailed) const override; 186 }; 187 188 /// JobList - A sequence of jobs to perform. 189 class JobList { 190 public: 191 using list_type = SmallVector<std::unique_ptr<Command>, 4>; 192 using size_type = list_type::size_type; 193 using iterator = llvm::pointee_iterator<list_type::iterator>; 194 using const_iterator = llvm::pointee_iterator<list_type::const_iterator>; 195 196 private: 197 list_type Jobs; 198 199 public: 200 void Print(llvm::raw_ostream &OS, const char *Terminator, 201 bool Quote, CrashReportInfo *CrashInfo = nullptr) const; 202 203 /// Add a job to the list (taking ownership). 204 void addJob(std::unique_ptr<Command> J) { Jobs.push_back(std::move(J)); } 205 206 /// Clear the job list. 207 void clear(); 208 209 const list_type &getJobs() const { return Jobs; } 210 211 bool empty() const { return Jobs.empty(); } 212 size_type size() const { return Jobs.size(); } 213 iterator begin() { return Jobs.begin(); } 214 const_iterator begin() const { return Jobs.begin(); } 215 iterator end() { return Jobs.end(); } 216 const_iterator end() const { return Jobs.end(); } 217 }; 218 219 } // namespace driver 220 } // namespace clang 221 222 #endif // LLVM_CLANG_DRIVER_JOB_H 223