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 "llvm/Support/Program.h" 20 #include <memory> 21 #include <string> 22 #include <utility> 23 #include <vector> 24 25 namespace clang { 26 namespace driver { 27 28 class Action; 29 class InputInfo; 30 class Tool; 31 32 struct CrashReportInfo { 33 StringRef Filename; 34 StringRef VFSPath; 35 CrashReportInfoCrashReportInfo36 CrashReportInfo(StringRef Filename, StringRef VFSPath) 37 : Filename(Filename), VFSPath(VFSPath) {} 38 }; 39 40 // Encodes the kind of response file supported for a command invocation. 41 // Response files are necessary if the command line gets too large, requiring 42 // the arguments to be transferred to a file. 43 struct ResponseFileSupport { 44 enum ResponseFileKind { 45 // Provides full support for response files, which means we can transfer 46 // all tool input arguments to a file. 47 RF_Full, 48 // Input file names can live in a file, but flags can't. This is a special 49 // case for old versions of Apple's ld64. 50 RF_FileList, 51 // Does not support response files: all arguments must be passed via 52 // command line. 53 RF_None 54 }; 55 /// The level of support for response files. 56 ResponseFileKind ResponseKind; 57 58 /// The encoding to use when writing response files on Windows. Ignored on 59 /// other host OSes. 60 /// 61 /// Windows use cases: - GCC and Binutils on mingw only accept ANSI response 62 /// files encoded with the system current code page. 63 /// - MSVC's CL.exe and LINK.exe accept UTF16 on Windows. 64 /// - Clang accepts both UTF8 and UTF16. 65 /// 66 /// FIXME: When GNU tools learn how to parse UTF16 on Windows, we should 67 /// always use UTF16 for Windows, which is the Windows official encoding for 68 /// international characters. 69 llvm::sys::WindowsEncodingMethod ResponseEncoding; 70 71 /// What prefix to use for the command-line argument when passing a response 72 /// file. 73 const char *ResponseFlag; 74 75 /// Returns a ResponseFileSupport indicating that response files are not 76 /// supported. NoneResponseFileSupport77 static constexpr ResponseFileSupport None() { 78 return {RF_None, llvm::sys::WEM_UTF8, nullptr}; 79 } 80 81 /// Returns a ResponseFileSupport indicating that response files are 82 /// supported, using the @file syntax. On windows, the file is written in the 83 /// UTF8 encoding. On other OSes, no re-encoding occurs. AtFileUTF8ResponseFileSupport84 static constexpr ResponseFileSupport AtFileUTF8() { 85 return {RF_Full, llvm::sys::WEM_UTF8, "@"}; 86 } 87 88 /// Returns a ResponseFileSupport indicating that response files are 89 /// supported, using the @file syntax. On windows, the file is written in the 90 /// current ANSI code-page encoding. On other OSes, no re-encoding occurs. AtFileCurCPResponseFileSupport91 static constexpr ResponseFileSupport AtFileCurCP() { 92 return {RF_Full, llvm::sys::WEM_CurrentCodePage, "@"}; 93 } 94 95 /// Returns a ResponseFileSupport indicating that response files are 96 /// supported, using the @file syntax. On windows, the file is written in the 97 /// UTF-16 encoding. On other OSes, no re-encoding occurs. AtFileUTF16ResponseFileSupport98 static constexpr ResponseFileSupport AtFileUTF16() { 99 return {RF_Full, llvm::sys::WEM_UTF16, "@"}; 100 } 101 }; 102 103 /// Command - An executable path/name and argument vector to 104 /// execute. 105 class Command { 106 /// Source - The action which caused the creation of this job. 107 const Action &Source; 108 109 /// Tool - The tool which caused the creation of this job. 110 const Tool &Creator; 111 112 /// Whether and how to generate response files if the arguments are too long. 113 ResponseFileSupport ResponseSupport; 114 115 /// The executable to run. 116 const char *Executable; 117 118 /// The list of program arguments (not including the implicit first 119 /// argument, which will be the executable). 120 llvm::opt::ArgStringList Arguments; 121 122 /// The list of program arguments which are inputs. 123 llvm::opt::ArgStringList InputFilenames; 124 125 /// The list of program arguments which are outputs. May be empty. 126 std::vector<std::string> OutputFilenames; 127 128 /// Response file name, if this command is set to use one, or nullptr 129 /// otherwise 130 const char *ResponseFile = nullptr; 131 132 /// The input file list in case we need to emit a file list instead of a 133 /// proper response file 134 llvm::opt::ArgStringList InputFileList; 135 136 /// String storage if we need to create a new argument to specify a response 137 /// file 138 std::string ResponseFileFlag; 139 140 /// See Command::setEnvironment 141 std::vector<const char *> Environment; 142 143 /// Information on executable run provided by OS. 144 mutable Optional<llvm::sys::ProcessStatistics> ProcStat; 145 146 /// When a response file is needed, we try to put most arguments in an 147 /// exclusive file, while others remains as regular command line arguments. 148 /// This functions fills a vector with the regular command line arguments, 149 /// argv, excluding the ones passed in a response file. 150 void buildArgvForResponseFile(llvm::SmallVectorImpl<const char *> &Out) const; 151 152 /// Encodes an array of C strings into a single string separated by whitespace. 153 /// This function will also put in quotes arguments that have whitespaces and 154 /// will escape the regular backslashes (used in Windows paths) and quotes. 155 /// The results are the contents of a response file, written into a raw_ostream. 156 void writeResponseFile(raw_ostream &OS) const; 157 158 public: 159 /// Whether to print the input filenames when executing. 160 bool PrintInputFilenames = false; 161 162 /// Whether the command will be executed in this process or not. 163 bool InProcess = false; 164 165 Command(const Action &Source, const Tool &Creator, 166 ResponseFileSupport ResponseSupport, const char *Executable, 167 const llvm::opt::ArgStringList &Arguments, ArrayRef<InputInfo> Inputs, 168 ArrayRef<InputInfo> Outputs = None); 169 // FIXME: This really shouldn't be copyable, but is currently copied in some 170 // error handling in Driver::generateCompilationDiagnostics. 171 Command(const Command &) = default; 172 virtual ~Command() = default; 173 174 virtual void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote, 175 CrashReportInfo *CrashInfo = nullptr) const; 176 177 virtual int Execute(ArrayRef<Optional<StringRef>> Redirects, 178 std::string *ErrMsg, bool *ExecutionFailed) const; 179 180 /// getSource - Return the Action which caused the creation of this job. getSource()181 const Action &getSource() const { return Source; } 182 183 /// getCreator - Return the Tool which caused the creation of this job. getCreator()184 const Tool &getCreator() const { return Creator; } 185 186 /// Returns the kind of response file supported by the current invocation. getResponseFileSupport()187 const ResponseFileSupport &getResponseFileSupport() { 188 return ResponseSupport; 189 } 190 191 /// Set to pass arguments via a response file when launching the command 192 void setResponseFile(const char *FileName); 193 194 /// Set an input file list, necessary if you specified an RF_FileList response 195 /// file support. setInputFileList(llvm::opt::ArgStringList List)196 void setInputFileList(llvm::opt::ArgStringList List) { 197 InputFileList = std::move(List); 198 } 199 200 /// Sets the environment to be used by the new process. 201 /// \param NewEnvironment An array of environment variables. 202 /// \remark If the environment remains unset, then the environment 203 /// from the parent process will be used. 204 virtual void setEnvironment(llvm::ArrayRef<const char *> NewEnvironment); 205 getExecutable()206 const char *getExecutable() const { return Executable; } 207 getArguments()208 const llvm::opt::ArgStringList &getArguments() const { return Arguments; } 209 getInputFilenames()210 const llvm::opt::ArgStringList &getInputFilenames() const { 211 return InputFilenames; 212 } 213 getOutputFilenames()214 const std::vector<std::string> &getOutputFilenames() const { 215 return OutputFilenames; 216 } 217 getProcessStatistics()218 Optional<llvm::sys::ProcessStatistics> getProcessStatistics() const { 219 return ProcStat; 220 } 221 222 protected: 223 /// Optionally print the filenames to be compiled 224 void PrintFileNames() const; 225 }; 226 227 /// Use the CC1 tool callback when available, to avoid creating a new process 228 class CC1Command : public Command { 229 public: 230 CC1Command(const Action &Source, const Tool &Creator, 231 ResponseFileSupport ResponseSupport, const char *Executable, 232 const llvm::opt::ArgStringList &Arguments, 233 ArrayRef<InputInfo> Inputs, ArrayRef<InputInfo> Outputs = None); 234 235 void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote, 236 CrashReportInfo *CrashInfo = nullptr) const override; 237 238 int Execute(ArrayRef<Optional<StringRef>> Redirects, std::string *ErrMsg, 239 bool *ExecutionFailed) const override; 240 241 void setEnvironment(llvm::ArrayRef<const char *> NewEnvironment) override; 242 }; 243 244 /// Like Command, but with a fallback which is executed in case 245 /// the primary command crashes. 246 class FallbackCommand : public Command { 247 public: 248 FallbackCommand(const Action &Source_, const Tool &Creator_, 249 ResponseFileSupport ResponseSupport, const char *Executable_, 250 const llvm::opt::ArgStringList &Arguments_, 251 ArrayRef<InputInfo> Inputs, ArrayRef<InputInfo> Outputs, 252 std::unique_ptr<Command> Fallback_); 253 254 void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote, 255 CrashReportInfo *CrashInfo = nullptr) const override; 256 257 int Execute(ArrayRef<Optional<StringRef>> Redirects, std::string *ErrMsg, 258 bool *ExecutionFailed) const override; 259 260 private: 261 std::unique_ptr<Command> Fallback; 262 }; 263 264 /// Like Command, but always pretends that the wrapped command succeeded. 265 class ForceSuccessCommand : public Command { 266 public: 267 ForceSuccessCommand(const Action &Source_, const Tool &Creator_, 268 ResponseFileSupport ResponseSupport, 269 const char *Executable_, 270 const llvm::opt::ArgStringList &Arguments_, 271 ArrayRef<InputInfo> Inputs, 272 ArrayRef<InputInfo> Outputs = None); 273 274 void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote, 275 CrashReportInfo *CrashInfo = nullptr) const override; 276 277 int Execute(ArrayRef<Optional<StringRef>> Redirects, std::string *ErrMsg, 278 bool *ExecutionFailed) const override; 279 }; 280 281 /// JobList - A sequence of jobs to perform. 282 class JobList { 283 public: 284 using list_type = SmallVector<std::unique_ptr<Command>, 4>; 285 using size_type = list_type::size_type; 286 using iterator = llvm::pointee_iterator<list_type::iterator>; 287 using const_iterator = llvm::pointee_iterator<list_type::const_iterator>; 288 289 private: 290 list_type Jobs; 291 292 public: 293 void Print(llvm::raw_ostream &OS, const char *Terminator, 294 bool Quote, CrashReportInfo *CrashInfo = nullptr) const; 295 296 /// Add a job to the list (taking ownership). addJob(std::unique_ptr<Command> J)297 void addJob(std::unique_ptr<Command> J) { Jobs.push_back(std::move(J)); } 298 299 /// Clear the job list. 300 void clear(); 301 getJobs()302 const list_type &getJobs() const { return Jobs; } 303 empty()304 bool empty() const { return Jobs.empty(); } size()305 size_type size() const { return Jobs.size(); } begin()306 iterator begin() { return Jobs.begin(); } begin()307 const_iterator begin() const { return Jobs.begin(); } end()308 iterator end() { return Jobs.end(); } end()309 const_iterator end() const { return Jobs.end(); } 310 }; 311 312 } // namespace driver 313 } // namespace clang 314 315 #endif // LLVM_CLANG_DRIVER_JOB_H 316