10b57cec5SDimitry Andric //===- Job.h - Commands to Execute ------------------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #ifndef LLVM_CLANG_DRIVER_JOB_H
100b57cec5SDimitry Andric #define LLVM_CLANG_DRIVER_JOB_H
110b57cec5SDimitry Andric 
120b57cec5SDimitry Andric #include "clang/Basic/LLVM.h"
13fe6060f1SDimitry Andric #include "clang/Driver/InputInfo.h"
140b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
150b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
160b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
170b57cec5SDimitry Andric #include "llvm/ADT/iterator.h"
180b57cec5SDimitry Andric #include "llvm/Option/Option.h"
195ffd83dbSDimitry Andric #include "llvm/Support/Program.h"
200b57cec5SDimitry Andric #include <memory>
21bdd1243dSDimitry Andric #include <optional>
220b57cec5SDimitry Andric #include <string>
230b57cec5SDimitry Andric #include <utility>
240b57cec5SDimitry Andric #include <vector>
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric namespace clang {
270b57cec5SDimitry Andric namespace driver {
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric class Action;
300b57cec5SDimitry Andric class InputInfo;
310b57cec5SDimitry Andric class Tool;
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric struct CrashReportInfo {
340b57cec5SDimitry Andric   StringRef Filename;
350b57cec5SDimitry Andric   StringRef VFSPath;
360b57cec5SDimitry Andric 
CrashReportInfoCrashReportInfo370b57cec5SDimitry Andric   CrashReportInfo(StringRef Filename, StringRef VFSPath)
380b57cec5SDimitry Andric       : Filename(Filename), VFSPath(VFSPath) {}
390b57cec5SDimitry Andric };
400b57cec5SDimitry Andric 
415ffd83dbSDimitry Andric // Encodes the kind of response file supported for a command invocation.
425ffd83dbSDimitry Andric // Response files are necessary if the command line gets too large, requiring
435ffd83dbSDimitry Andric // the arguments to be transferred to a file.
445ffd83dbSDimitry Andric struct ResponseFileSupport {
455ffd83dbSDimitry Andric   enum ResponseFileKind {
465ffd83dbSDimitry Andric     // Provides full support for response files, which means we can transfer
475ffd83dbSDimitry Andric     // all tool input arguments to a file.
485ffd83dbSDimitry Andric     RF_Full,
495ffd83dbSDimitry Andric     // Input file names can live in a file, but flags can't. This is a special
505ffd83dbSDimitry Andric     // case for old versions of Apple's ld64.
515ffd83dbSDimitry Andric     RF_FileList,
525ffd83dbSDimitry Andric     // Does not support response files: all arguments must be passed via
535ffd83dbSDimitry Andric     // command line.
545ffd83dbSDimitry Andric     RF_None
555ffd83dbSDimitry Andric   };
565ffd83dbSDimitry Andric   /// The level of support for response files.
575ffd83dbSDimitry Andric   ResponseFileKind ResponseKind;
585ffd83dbSDimitry Andric 
595ffd83dbSDimitry Andric   /// The encoding to use when writing response files on Windows. Ignored on
605ffd83dbSDimitry Andric   /// other host OSes.
615ffd83dbSDimitry Andric   ///
625ffd83dbSDimitry Andric   /// Windows use cases: - GCC and Binutils on mingw only accept ANSI response
635ffd83dbSDimitry Andric   /// files encoded with the system current code page.
645ffd83dbSDimitry Andric   /// - MSVC's CL.exe and LINK.exe accept UTF16 on Windows.
655ffd83dbSDimitry Andric   /// - Clang accepts both UTF8 and UTF16.
665ffd83dbSDimitry Andric   ///
675ffd83dbSDimitry Andric   /// FIXME: When GNU tools learn how to parse UTF16 on Windows, we should
685ffd83dbSDimitry Andric   /// always use UTF16 for Windows, which is the Windows official encoding for
695ffd83dbSDimitry Andric   /// international characters.
705ffd83dbSDimitry Andric   llvm::sys::WindowsEncodingMethod ResponseEncoding;
715ffd83dbSDimitry Andric 
725ffd83dbSDimitry Andric   /// What prefix to use for the command-line argument when passing a response
735ffd83dbSDimitry Andric   /// file.
745ffd83dbSDimitry Andric   const char *ResponseFlag;
755ffd83dbSDimitry Andric 
765ffd83dbSDimitry Andric   /// Returns a ResponseFileSupport indicating that response files are not
775ffd83dbSDimitry Andric   /// supported.
NoneResponseFileSupport785ffd83dbSDimitry Andric   static constexpr ResponseFileSupport None() {
795ffd83dbSDimitry Andric     return {RF_None, llvm::sys::WEM_UTF8, nullptr};
805ffd83dbSDimitry Andric   }
815ffd83dbSDimitry Andric 
825ffd83dbSDimitry Andric   /// Returns a ResponseFileSupport indicating that response files are
835ffd83dbSDimitry Andric   /// supported, using the @file syntax. On windows, the file is written in the
845ffd83dbSDimitry Andric   /// UTF8 encoding. On other OSes, no re-encoding occurs.
AtFileUTF8ResponseFileSupport855ffd83dbSDimitry Andric   static constexpr ResponseFileSupport AtFileUTF8() {
865ffd83dbSDimitry Andric     return {RF_Full, llvm::sys::WEM_UTF8, "@"};
875ffd83dbSDimitry Andric   }
885ffd83dbSDimitry Andric 
895ffd83dbSDimitry Andric   /// Returns a ResponseFileSupport indicating that response files are
905ffd83dbSDimitry Andric   /// supported, using the @file syntax. On windows, the file is written in the
915ffd83dbSDimitry Andric   /// current ANSI code-page encoding. On other OSes, no re-encoding occurs.
AtFileCurCPResponseFileSupport925ffd83dbSDimitry Andric   static constexpr ResponseFileSupport AtFileCurCP() {
935ffd83dbSDimitry Andric     return {RF_Full, llvm::sys::WEM_CurrentCodePage, "@"};
945ffd83dbSDimitry Andric   }
955ffd83dbSDimitry Andric 
965ffd83dbSDimitry Andric   /// Returns a ResponseFileSupport indicating that response files are
975ffd83dbSDimitry Andric   /// supported, using the @file syntax. On windows, the file is written in the
985ffd83dbSDimitry Andric   /// UTF-16 encoding. On other OSes, no re-encoding occurs.
AtFileUTF16ResponseFileSupport995ffd83dbSDimitry Andric   static constexpr ResponseFileSupport AtFileUTF16() {
1005ffd83dbSDimitry Andric     return {RF_Full, llvm::sys::WEM_UTF16, "@"};
1015ffd83dbSDimitry Andric   }
1025ffd83dbSDimitry Andric };
1035ffd83dbSDimitry Andric 
1040b57cec5SDimitry Andric /// Command - An executable path/name and argument vector to
1050b57cec5SDimitry Andric /// execute.
1060b57cec5SDimitry Andric class Command {
1070b57cec5SDimitry Andric   /// Source - The action which caused the creation of this job.
1080b57cec5SDimitry Andric   const Action &Source;
1090b57cec5SDimitry Andric 
1100b57cec5SDimitry Andric   /// Tool - The tool which caused the creation of this job.
1110b57cec5SDimitry Andric   const Tool &Creator;
1120b57cec5SDimitry Andric 
1135ffd83dbSDimitry Andric   /// Whether and how to generate response files if the arguments are too long.
1145ffd83dbSDimitry Andric   ResponseFileSupport ResponseSupport;
1155ffd83dbSDimitry Andric 
1160b57cec5SDimitry Andric   /// The executable to run.
1170b57cec5SDimitry Andric   const char *Executable;
1180b57cec5SDimitry Andric 
11906c3fb27SDimitry Andric   /// Optional argument to prepend.
12006c3fb27SDimitry Andric   const char *PrependArg;
12106c3fb27SDimitry Andric 
1220b57cec5SDimitry Andric   /// The list of program arguments (not including the implicit first
1230b57cec5SDimitry Andric   /// argument, which will be the executable).
1240b57cec5SDimitry Andric   llvm::opt::ArgStringList Arguments;
1250b57cec5SDimitry Andric 
126fe6060f1SDimitry Andric   /// The list of program inputs.
127fe6060f1SDimitry Andric   std::vector<InputInfo> InputInfoList;
1280b57cec5SDimitry Andric 
129e8d8bef9SDimitry Andric   /// The list of program arguments which are outputs. May be empty.
130e8d8bef9SDimitry Andric   std::vector<std::string> OutputFilenames;
131e8d8bef9SDimitry Andric 
1320b57cec5SDimitry Andric   /// Response file name, if this command is set to use one, or nullptr
1330b57cec5SDimitry Andric   /// otherwise
1340b57cec5SDimitry Andric   const char *ResponseFile = nullptr;
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric   /// The input file list in case we need to emit a file list instead of a
1370b57cec5SDimitry Andric   /// proper response file
1380b57cec5SDimitry Andric   llvm::opt::ArgStringList InputFileList;
1390b57cec5SDimitry Andric 
1400b57cec5SDimitry Andric   /// String storage if we need to create a new argument to specify a response
1410b57cec5SDimitry Andric   /// file
1420b57cec5SDimitry Andric   std::string ResponseFileFlag;
1430b57cec5SDimitry Andric 
1440b57cec5SDimitry Andric   /// See Command::setEnvironment
1450b57cec5SDimitry Andric   std::vector<const char *> Environment;
1460b57cec5SDimitry Andric 
147bdd1243dSDimitry Andric   /// Optional redirection for stdin, stdout, stderr.
148bdd1243dSDimitry Andric   std::vector<std::optional<std::string>> RedirectFiles;
149bdd1243dSDimitry Andric 
150e8d8bef9SDimitry Andric   /// Information on executable run provided by OS.
151bdd1243dSDimitry Andric   mutable std::optional<llvm::sys::ProcessStatistics> ProcStat;
152e8d8bef9SDimitry Andric 
1530b57cec5SDimitry Andric   /// When a response file is needed, we try to put most arguments in an
1540b57cec5SDimitry Andric   /// exclusive file, while others remains as regular command line arguments.
1550b57cec5SDimitry Andric   /// This functions fills a vector with the regular command line arguments,
1560b57cec5SDimitry Andric   /// argv, excluding the ones passed in a response file.
1570b57cec5SDimitry Andric   void buildArgvForResponseFile(llvm::SmallVectorImpl<const char *> &Out) const;
1580b57cec5SDimitry Andric 
1590b57cec5SDimitry Andric   /// Encodes an array of C strings into a single string separated by whitespace.
1600b57cec5SDimitry Andric   /// This function will also put in quotes arguments that have whitespaces and
1610b57cec5SDimitry Andric   /// will escape the regular backslashes (used in Windows paths) and quotes.
1620b57cec5SDimitry Andric   /// The results are the contents of a response file, written into a raw_ostream.
1630b57cec5SDimitry Andric   void writeResponseFile(raw_ostream &OS) const;
1640b57cec5SDimitry Andric 
1650b57cec5SDimitry Andric public:
16613138422SDimitry Andric   /// Whether to print the input filenames when executing.
16713138422SDimitry Andric   bool PrintInputFilenames = false;
16813138422SDimitry Andric 
16913138422SDimitry Andric   /// Whether the command will be executed in this process or not.
17013138422SDimitry Andric   bool InProcess = false;
17113138422SDimitry Andric 
1725ffd83dbSDimitry Andric   Command(const Action &Source, const Tool &Creator,
1735ffd83dbSDimitry Andric           ResponseFileSupport ResponseSupport, const char *Executable,
174e8d8bef9SDimitry Andric           const llvm::opt::ArgStringList &Arguments, ArrayRef<InputInfo> Inputs,
17506c3fb27SDimitry Andric           ArrayRef<InputInfo> Outputs = std::nullopt,
17606c3fb27SDimitry Andric           const char *PrependArg = nullptr);
1770b57cec5SDimitry Andric   // FIXME: This really shouldn't be copyable, but is currently copied in some
1780b57cec5SDimitry Andric   // error handling in Driver::generateCompilationDiagnostics.
1790b57cec5SDimitry Andric   Command(const Command &) = default;
1800b57cec5SDimitry Andric   virtual ~Command() = default;
1810b57cec5SDimitry Andric 
1820b57cec5SDimitry Andric   virtual void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote,
1830b57cec5SDimitry Andric                      CrashReportInfo *CrashInfo = nullptr) const;
1840b57cec5SDimitry Andric 
185bdd1243dSDimitry Andric   virtual int Execute(ArrayRef<std::optional<StringRef>> Redirects,
1860b57cec5SDimitry Andric                       std::string *ErrMsg, bool *ExecutionFailed) const;
1870b57cec5SDimitry Andric 
1880b57cec5SDimitry Andric   /// getSource - Return the Action which caused the creation of this job.
getSource()1890b57cec5SDimitry Andric   const Action &getSource() const { return Source; }
1900b57cec5SDimitry Andric 
1910b57cec5SDimitry Andric   /// getCreator - Return the Tool which caused the creation of this job.
getCreator()1920b57cec5SDimitry Andric   const Tool &getCreator() const { return Creator; }
1930b57cec5SDimitry Andric 
1945ffd83dbSDimitry Andric   /// Returns the kind of response file supported by the current invocation.
getResponseFileSupport()1955ffd83dbSDimitry Andric   const ResponseFileSupport &getResponseFileSupport() {
1965ffd83dbSDimitry Andric     return ResponseSupport;
1975ffd83dbSDimitry Andric   }
1985ffd83dbSDimitry Andric 
1990b57cec5SDimitry Andric   /// Set to pass arguments via a response file when launching the command
2000b57cec5SDimitry Andric   void setResponseFile(const char *FileName);
2010b57cec5SDimitry Andric 
2025ffd83dbSDimitry Andric   /// Set an input file list, necessary if you specified an RF_FileList response
2035ffd83dbSDimitry Andric   /// file support.
setInputFileList(llvm::opt::ArgStringList List)2040b57cec5SDimitry Andric   void setInputFileList(llvm::opt::ArgStringList List) {
2050b57cec5SDimitry Andric     InputFileList = std::move(List);
2060b57cec5SDimitry Andric   }
2070b57cec5SDimitry Andric 
2080b57cec5SDimitry Andric   /// Sets the environment to be used by the new process.
2090b57cec5SDimitry Andric   /// \param NewEnvironment An array of environment variables.
2100b57cec5SDimitry Andric   /// \remark If the environment remains unset, then the environment
2110b57cec5SDimitry Andric   ///         from the parent process will be used.
212480093f4SDimitry Andric   virtual void setEnvironment(llvm::ArrayRef<const char *> NewEnvironment);
2130b57cec5SDimitry Andric 
214bdd1243dSDimitry Andric   void
215bdd1243dSDimitry Andric   setRedirectFiles(const std::vector<std::optional<std::string>> &Redirects);
216bdd1243dSDimitry Andric 
replaceArguments(llvm::opt::ArgStringList List)2170eae32dcSDimitry Andric   void replaceArguments(llvm::opt::ArgStringList List) {
2180eae32dcSDimitry Andric     Arguments = std::move(List);
2190eae32dcSDimitry Andric   }
2200eae32dcSDimitry Andric 
replaceExecutable(const char * Exe)2211fd87a68SDimitry Andric   void replaceExecutable(const char *Exe) { Executable = Exe; }
2221fd87a68SDimitry Andric 
getExecutable()2230b57cec5SDimitry Andric   const char *getExecutable() const { return Executable; }
2240b57cec5SDimitry Andric 
getArguments()2250b57cec5SDimitry Andric   const llvm::opt::ArgStringList &getArguments() const { return Arguments; }
2260b57cec5SDimitry Andric 
getInputInfos()227fe6060f1SDimitry Andric   const std::vector<InputInfo> &getInputInfos() const { return InputInfoList; }
228e8d8bef9SDimitry Andric 
getOutputFilenames()229e8d8bef9SDimitry Andric   const std::vector<std::string> &getOutputFilenames() const {
230e8d8bef9SDimitry Andric     return OutputFilenames;
231e8d8bef9SDimitry Andric   }
232e8d8bef9SDimitry Andric 
getProcessStatistics()233bdd1243dSDimitry Andric   std::optional<llvm::sys::ProcessStatistics> getProcessStatistics() const {
234e8d8bef9SDimitry Andric     return ProcStat;
235e8d8bef9SDimitry Andric   }
236e8d8bef9SDimitry Andric 
237480093f4SDimitry Andric protected:
238480093f4SDimitry Andric   /// Optionally print the filenames to be compiled
239480093f4SDimitry Andric   void PrintFileNames() const;
240480093f4SDimitry Andric };
241480093f4SDimitry Andric 
242480093f4SDimitry Andric /// Use the CC1 tool callback when available, to avoid creating a new process
243480093f4SDimitry Andric class CC1Command : public Command {
244480093f4SDimitry Andric public:
2455ffd83dbSDimitry Andric   CC1Command(const Action &Source, const Tool &Creator,
2465ffd83dbSDimitry Andric              ResponseFileSupport ResponseSupport, const char *Executable,
24713138422SDimitry Andric              const llvm::opt::ArgStringList &Arguments,
248bdd1243dSDimitry Andric              ArrayRef<InputInfo> Inputs,
24906c3fb27SDimitry Andric              ArrayRef<InputInfo> Outputs = std::nullopt,
25006c3fb27SDimitry Andric              const char *PrependArg = nullptr);
251480093f4SDimitry Andric 
252480093f4SDimitry Andric   void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote,
253480093f4SDimitry Andric              CrashReportInfo *CrashInfo = nullptr) const override;
254480093f4SDimitry Andric 
255bdd1243dSDimitry Andric   int Execute(ArrayRef<std::optional<StringRef>> Redirects, std::string *ErrMsg,
256480093f4SDimitry Andric               bool *ExecutionFailed) const override;
257480093f4SDimitry Andric 
258480093f4SDimitry Andric   void setEnvironment(llvm::ArrayRef<const char *> NewEnvironment) override;
2590b57cec5SDimitry Andric };
2600b57cec5SDimitry Andric 
2610b57cec5SDimitry Andric /// JobList - A sequence of jobs to perform.
2620b57cec5SDimitry Andric class JobList {
2630b57cec5SDimitry Andric public:
2640b57cec5SDimitry Andric   using list_type = SmallVector<std::unique_ptr<Command>, 4>;
2650b57cec5SDimitry Andric   using size_type = list_type::size_type;
2660b57cec5SDimitry Andric   using iterator = llvm::pointee_iterator<list_type::iterator>;
2670b57cec5SDimitry Andric   using const_iterator = llvm::pointee_iterator<list_type::const_iterator>;
2680b57cec5SDimitry Andric 
2690b57cec5SDimitry Andric private:
2700b57cec5SDimitry Andric   list_type Jobs;
2710b57cec5SDimitry Andric 
2720b57cec5SDimitry Andric public:
2730b57cec5SDimitry Andric   void Print(llvm::raw_ostream &OS, const char *Terminator,
2740b57cec5SDimitry Andric              bool Quote, CrashReportInfo *CrashInfo = nullptr) const;
2750b57cec5SDimitry Andric 
2760b57cec5SDimitry Andric   /// Add a job to the list (taking ownership).
addJob(std::unique_ptr<Command> J)2770b57cec5SDimitry Andric   void addJob(std::unique_ptr<Command> J) { Jobs.push_back(std::move(J)); }
2780b57cec5SDimitry Andric 
2790b57cec5SDimitry Andric   /// Clear the job list.
2800b57cec5SDimitry Andric   void clear();
2810b57cec5SDimitry Andric 
getJobs()2820b57cec5SDimitry Andric   const list_type &getJobs() const { return Jobs; }
2830b57cec5SDimitry Andric 
empty()2840b57cec5SDimitry Andric   bool empty() const { return Jobs.empty(); }
size()2850b57cec5SDimitry Andric   size_type size() const { return Jobs.size(); }
begin()2860b57cec5SDimitry Andric   iterator begin() { return Jobs.begin(); }
begin()2870b57cec5SDimitry Andric   const_iterator begin() const { return Jobs.begin(); }
end()2880b57cec5SDimitry Andric   iterator end() { return Jobs.end(); }
end()2890b57cec5SDimitry Andric   const_iterator end() const { return Jobs.end(); }
2900b57cec5SDimitry Andric };
2910b57cec5SDimitry Andric 
2920b57cec5SDimitry Andric } // namespace driver
2930b57cec5SDimitry Andric } // namespace clang
2940b57cec5SDimitry Andric 
2950b57cec5SDimitry Andric #endif // LLVM_CLANG_DRIVER_JOB_H
296