Home | History | Annotate | Line # | Download | only in Driver
      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 
     36   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.
     77   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.
     84   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.
     91   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.
     98   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.
    181   const Action &getSource() const { return Source; }
    182 
    183   /// getCreator - Return the Tool which caused the creation of this job.
    184   const Tool &getCreator() const { return Creator; }
    185 
    186   /// Returns the kind of response file supported by the current invocation.
    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.
    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 
    206   const char *getExecutable() const { return Executable; }
    207 
    208   const llvm::opt::ArgStringList &getArguments() const { return Arguments; }
    209 
    210   const llvm::opt::ArgStringList &getInputFilenames() const {
    211     return InputFilenames;
    212   }
    213 
    214   const std::vector<std::string> &getOutputFilenames() const {
    215     return OutputFilenames;
    216   }
    217 
    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 always pretends that the wrapped command succeeded.
    245 class ForceSuccessCommand : public Command {
    246 public:
    247   ForceSuccessCommand(const Action &Source_, const Tool &Creator_,
    248                       ResponseFileSupport ResponseSupport,
    249                       const char *Executable_,
    250                       const llvm::opt::ArgStringList &Arguments_,
    251                       ArrayRef<InputInfo> Inputs,
    252                       ArrayRef<InputInfo> Outputs = None);
    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 
    261 /// JobList - A sequence of jobs to perform.
    262 class JobList {
    263 public:
    264   using list_type = SmallVector<std::unique_ptr<Command>, 4>;
    265   using size_type = list_type::size_type;
    266   using iterator = llvm::pointee_iterator<list_type::iterator>;
    267   using const_iterator = llvm::pointee_iterator<list_type::const_iterator>;
    268 
    269 private:
    270   list_type Jobs;
    271 
    272 public:
    273   void Print(llvm::raw_ostream &OS, const char *Terminator,
    274              bool Quote, CrashReportInfo *CrashInfo = nullptr) const;
    275 
    276   /// Add a job to the list (taking ownership).
    277   void addJob(std::unique_ptr<Command> J) { Jobs.push_back(std::move(J)); }
    278 
    279   /// Clear the job list.
    280   void clear();
    281 
    282   const list_type &getJobs() const { return Jobs; }
    283 
    284   bool empty() const { return Jobs.empty(); }
    285   size_type size() const { return Jobs.size(); }
    286   iterator begin() { return Jobs.begin(); }
    287   const_iterator begin() const { return Jobs.begin(); }
    288   iterator end() { return Jobs.end(); }
    289   const_iterator end() const { return Jobs.end(); }
    290 };
    291 
    292 } // namespace driver
    293 } // namespace clang
    294 
    295 #endif // LLVM_CLANG_DRIVER_JOB_H
    296