• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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