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