1 //===- Job.h - Commands to Execute ------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_CLANG_DRIVER_JOB_H
10 #define LLVM_CLANG_DRIVER_JOB_H
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"
32 struct CrashReportInfo {
36 CrashReportInfo(StringRef Filename, StringRef VFSPath)
37 : Filename(Filename), VFSPath(VFSPath) {}
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.
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.
51 // Does not support response files: all arguments must be passed via
55 /// The level of support for response files.
56 ResponseFileKind ResponseKind;
58 /// The encoding to use when writing response files on Windows. Ignored on
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.
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;
71 /// What prefix to use for the command-line argument when passing a response
73 const char *ResponseFlag;
75 /// Returns a ResponseFileSupport indicating that response files are not
77 static constexpr ResponseFileSupport None() {
78 return {RF_None, llvm::sys::WEM_UTF8, nullptr};
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.
84 static constexpr ResponseFileSupport AtFileUTF8() {
85 return {RF_Full, llvm::sys::WEM_UTF8, "@"};
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.
91 static constexpr ResponseFileSupport AtFileCurCP() {
92 return {RF_Full, llvm::sys::WEM_CurrentCodePage, "@"};
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.
98 static constexpr ResponseFileSupport AtFileUTF16() {
99 return {RF_Full, llvm::sys::WEM_UTF16, "@"};
103 /// Command - An executable path/name and argument vector to
106 /// Source - The action which caused the creation of this job.
107 const Action &Source;
109 /// Tool - The tool which caused the creation of this job.
112 /// Whether and how to generate response files if the arguments are too long.
113 ResponseFileSupport ResponseSupport;
115 /// The executable to run.
116 const char *Executable;
118 /// The list of program arguments (not including the implicit first
119 /// argument, which will be the executable).
120 llvm::opt::ArgStringList Arguments;
122 /// The list of program arguments which are inputs.
123 llvm::opt::ArgStringList InputFilenames;
125 /// Response file name, if this command is set to use one, or nullptr
127 const char *ResponseFile = nullptr;
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;
133 /// String storage if we need to create a new argument to specify a response
135 std::string ResponseFileFlag;
137 /// See Command::setEnvironment
138 std::vector<const char *> Environment;
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;
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;
153 /// Whether to print the input filenames when executing.
154 bool PrintInputFilenames = false;
156 /// Whether the command will be executed in this process or not.
157 bool InProcess = false;
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;
168 virtual void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote,
169 CrashReportInfo *CrashInfo = nullptr) const;
171 virtual int Execute(ArrayRef<Optional<StringRef>> Redirects,
172 std::string *ErrMsg, bool *ExecutionFailed) const;
174 /// getSource - Return the Action which caused the creation of this job.
175 const Action &getSource() const { return Source; }
177 /// getCreator - Return the Tool which caused the creation of this job.
178 const Tool &getCreator() const { return Creator; }
180 /// Returns the kind of response file supported by the current invocation.
181 const ResponseFileSupport &getResponseFileSupport() {
182 return ResponseSupport;
185 /// Set to pass arguments via a response file when launching the command
186 void setResponseFile(const char *FileName);
188 /// Set an input file list, necessary if you specified an RF_FileList response
190 void setInputFileList(llvm::opt::ArgStringList List) {
191 InputFileList = std::move(List);
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);
200 const char *getExecutable() const { return Executable; }
202 const llvm::opt::ArgStringList &getArguments() const { return Arguments; }
205 /// Optionally print the filenames to be compiled
206 void PrintFileNames() const;
209 /// Use the CC1 tool callback when available, to avoid creating a new process
210 class CC1Command : public Command {
212 CC1Command(const Action &Source, const Tool &Creator,
213 ResponseFileSupport ResponseSupport, const char *Executable,
214 const llvm::opt::ArgStringList &Arguments,
215 ArrayRef<InputInfo> Inputs);
217 void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote,
218 CrashReportInfo *CrashInfo = nullptr) const override;
220 int Execute(ArrayRef<Optional<StringRef>> Redirects, std::string *ErrMsg,
221 bool *ExecutionFailed) const override;
223 void setEnvironment(llvm::ArrayRef<const char *> NewEnvironment) override;
226 /// Like Command, but with a fallback which is executed in case
227 /// the primary command crashes.
228 class FallbackCommand : public Command {
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_);
236 void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote,
237 CrashReportInfo *CrashInfo = nullptr) const override;
239 int Execute(ArrayRef<Optional<StringRef>> Redirects, std::string *ErrMsg,
240 bool *ExecutionFailed) const override;
243 std::unique_ptr<Command> Fallback;
246 /// Like Command, but always pretends that the wrapped command succeeded.
247 class ForceSuccessCommand : public Command {
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);
255 void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote,
256 CrashReportInfo *CrashInfo = nullptr) const override;
258 int Execute(ArrayRef<Optional<StringRef>> Redirects, std::string *ErrMsg,
259 bool *ExecutionFailed) const override;
262 /// JobList - A sequence of jobs to perform.
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>;
274 void Print(llvm::raw_ostream &OS, const char *Terminator,
275 bool Quote, CrashReportInfo *CrashInfo = nullptr) const;
277 /// Add a job to the list (taking ownership).
278 void addJob(std::unique_ptr<Command> J) { Jobs.push_back(std::move(J)); }
280 /// Clear the job list.
283 const list_type &getJobs() const { return Jobs; }
285 bool empty() const { return Jobs.empty(); }
286 size_type size() const { return Jobs.size(); }
287 iterator begin() { return Jobs.begin(); }
288 const_iterator begin() const { return Jobs.begin(); }
289 iterator end() { return Jobs.end(); }
290 const_iterator end() const { return Jobs.end(); }
293 } // namespace driver
296 #endif // LLVM_CLANG_DRIVER_JOB_H