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