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 /// Response file name, if this command is set to use one, or nullptr 126 /// otherwise 127 const char *ResponseFile = nullptr; 128 129 /// The input file list in case we need to emit a file list instead of a 130 /// proper response file 131 llvm::opt::ArgStringList InputFileList; 132 133 /// String storage if we need to create a new argument to specify a response 134 /// file 135 std::string ResponseFileFlag; 136 137 /// See Command::setEnvironment 138 std::vector<const char *> Environment; 139 140 /// When a response file is needed, we try to put most arguments in an 141 /// exclusive file, while others remains as regular command line arguments. 142 /// This functions fills a vector with the regular command line arguments, 143 /// argv, excluding the ones passed in a response file. 144 void buildArgvForResponseFile(llvm::SmallVectorImpl<const char *> &Out) const; 145 146 /// Encodes an array of C strings into a single string separated by whitespace. 147 /// This function will also put in quotes arguments that have whitespaces and 148 /// will escape the regular backslashes (used in Windows paths) and quotes. 149 /// The results are the contents of a response file, written into a raw_ostream. 150 void writeResponseFile(raw_ostream &OS) const; 151 152 public: 153 /// Whether to print the input filenames when executing. 154 bool PrintInputFilenames = false; 155 156 /// Whether the command will be executed in this process or not. 157 bool InProcess = false; 158 159 Command(const Action &Source, const Tool &Creator, 160 ResponseFileSupport ResponseSupport, const char *Executable, 161 const llvm::opt::ArgStringList &Arguments, 162 ArrayRef<InputInfo> Inputs); 163 // FIXME: This really shouldn't be copyable, but is currently copied in some 164 // error handling in Driver::generateCompilationDiagnostics. 165 Command(const Command &) = default; 166 virtual ~Command() = default; 167 168 virtual void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote, 169 CrashReportInfo *CrashInfo = nullptr) const; 170 171 virtual int Execute(ArrayRef<Optional<StringRef>> Redirects, 172 std::string *ErrMsg, bool *ExecutionFailed) const; 173 174 /// getSource - Return the Action which caused the creation of this job. getSource()175 const Action &getSource() const { return Source; } 176 177 /// getCreator - Return the Tool which caused the creation of this job. getCreator()178 const Tool &getCreator() const { return Creator; } 179 180 /// Returns the kind of response file supported by the current invocation. getResponseFileSupport()181 const ResponseFileSupport &getResponseFileSupport() { 182 return ResponseSupport; 183 } 184 185 /// Set to pass arguments via a response file when launching the command 186 void setResponseFile(const char *FileName); 187 188 /// Set an input file list, necessary if you specified an RF_FileList response 189 /// file support. setInputFileList(llvm::opt::ArgStringList List)190 void setInputFileList(llvm::opt::ArgStringList List) { 191 InputFileList = std::move(List); 192 } 193 194 /// Sets the environment to be used by the new process. 195 /// \param NewEnvironment An array of environment variables. 196 /// \remark If the environment remains unset, then the environment 197 /// from the parent process will be used. 198 virtual void setEnvironment(llvm::ArrayRef<const char *> NewEnvironment); 199 getExecutable()200 const char *getExecutable() const { return Executable; } 201 getArguments()202 const llvm::opt::ArgStringList &getArguments() const { return Arguments; } 203 204 protected: 205 /// Optionally print the filenames to be compiled 206 void PrintFileNames() const; 207 }; 208 209 /// Use the CC1 tool callback when available, to avoid creating a new process 210 class CC1Command : public Command { 211 public: 212 CC1Command(const Action &Source, const Tool &Creator, 213 ResponseFileSupport ResponseSupport, const char *Executable, 214 const llvm::opt::ArgStringList &Arguments, 215 ArrayRef<InputInfo> Inputs); 216 217 void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote, 218 CrashReportInfo *CrashInfo = nullptr) const override; 219 220 int Execute(ArrayRef<Optional<StringRef>> Redirects, std::string *ErrMsg, 221 bool *ExecutionFailed) const override; 222 223 void setEnvironment(llvm::ArrayRef<const char *> NewEnvironment) override; 224 }; 225 226 /// Like Command, but with a fallback which is executed in case 227 /// the primary command crashes. 228 class FallbackCommand : public Command { 229 public: 230 FallbackCommand(const Action &Source_, const Tool &Creator_, 231 ResponseFileSupport ResponseSupport, const char *Executable_, 232 const llvm::opt::ArgStringList &Arguments_, 233 ArrayRef<InputInfo> Inputs, 234 std::unique_ptr<Command> Fallback_); 235 236 void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote, 237 CrashReportInfo *CrashInfo = nullptr) const override; 238 239 int Execute(ArrayRef<Optional<StringRef>> Redirects, std::string *ErrMsg, 240 bool *ExecutionFailed) const override; 241 242 private: 243 std::unique_ptr<Command> Fallback; 244 }; 245 246 /// Like Command, but always pretends that the wrapped command succeeded. 247 class ForceSuccessCommand : public Command { 248 public: 249 ForceSuccessCommand(const Action &Source_, const Tool &Creator_, 250 ResponseFileSupport ResponseSupport, 251 const char *Executable_, 252 const llvm::opt::ArgStringList &Arguments_, 253 ArrayRef<InputInfo> Inputs); 254 255 void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote, 256 CrashReportInfo *CrashInfo = nullptr) const override; 257 258 int Execute(ArrayRef<Optional<StringRef>> Redirects, std::string *ErrMsg, 259 bool *ExecutionFailed) const override; 260 }; 261 262 /// JobList - A sequence of jobs to perform. 263 class JobList { 264 public: 265 using list_type = SmallVector<std::unique_ptr<Command>, 4>; 266 using size_type = list_type::size_type; 267 using iterator = llvm::pointee_iterator<list_type::iterator>; 268 using const_iterator = llvm::pointee_iterator<list_type::const_iterator>; 269 270 private: 271 list_type Jobs; 272 273 public: 274 void Print(llvm::raw_ostream &OS, const char *Terminator, 275 bool Quote, CrashReportInfo *CrashInfo = nullptr) const; 276 277 /// Add a job to the list (taking ownership). addJob(std::unique_ptr<Command> J)278 void addJob(std::unique_ptr<Command> J) { Jobs.push_back(std::move(J)); } 279 280 /// Clear the job list. 281 void clear(); 282 getJobs()283 const list_type &getJobs() const { return Jobs; } 284 empty()285 bool empty() const { return Jobs.empty(); } size()286 size_type size() const { return Jobs.size(); } begin()287 iterator begin() { return Jobs.begin(); } begin()288 const_iterator begin() const { return Jobs.begin(); } end()289 iterator end() { return Jobs.end(); } end()290 const_iterator end() const { return Jobs.end(); } 291 }; 292 293 } // namespace driver 294 } // namespace clang 295 296 #endif // LLVM_CLANG_DRIVER_JOB_H 297