1 //===--- Job.h - Commands to Execute ----------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #ifndef LLVM_CLANG_DRIVER_JOB_H 11 #define LLVM_CLANG_DRIVER_JOB_H 12 13 #include "clang/Basic/LLVM.h" 14 #include "llvm/ADT/SmallVector.h" 15 #include "llvm/ADT/iterator.h" 16 #include "llvm/Option/Option.h" 17 #include <memory> 18 19 namespace llvm { 20 class raw_ostream; 21 } 22 23 namespace clang { 24 namespace driver { 25 class Action; 26 class Command; 27 class Tool; 28 class InputInfo; 29 30 // Re-export this as clang::driver::ArgStringList. 31 using llvm::opt::ArgStringList; 32 33 struct CrashReportInfo { 34 StringRef Filename; 35 StringRef VFSPath; 36 CrashReportInfoCrashReportInfo37 CrashReportInfo(StringRef Filename, StringRef VFSPath) 38 : Filename(Filename), VFSPath(VFSPath) {} 39 }; 40 41 /// Command - An executable path/name and argument vector to 42 /// execute. 43 class Command { 44 /// Source - The action which caused the creation of this job. 45 const Action &Source; 46 47 /// Tool - The tool which caused the creation of this job. 48 const Tool &Creator; 49 50 /// The executable to run. 51 const char *Executable; 52 53 /// The list of program arguments (not including the implicit first 54 /// argument, which will be the executable). 55 llvm::opt::ArgStringList Arguments; 56 57 /// The list of program arguments which are inputs. 58 llvm::opt::ArgStringList InputFilenames; 59 60 /// Response file name, if this command is set to use one, or nullptr 61 /// otherwise 62 const char *ResponseFile; 63 64 /// The input file list in case we need to emit a file list instead of a 65 /// proper response file 66 llvm::opt::ArgStringList InputFileList; 67 68 /// String storage if we need to create a new argument to specify a response 69 /// file 70 std::string ResponseFileFlag; 71 72 /// When a response file is needed, we try to put most arguments in an 73 /// exclusive file, while others remains as regular command line arguments. 74 /// This functions fills a vector with the regular command line arguments, 75 /// argv, excluding the ones passed in a response file. 76 void buildArgvForResponseFile(llvm::SmallVectorImpl<const char *> &Out) const; 77 78 /// Encodes an array of C strings into a single string separated by whitespace. 79 /// This function will also put in quotes arguments that have whitespaces and 80 /// will escape the regular backslashes (used in Windows paths) and quotes. 81 /// The results are the contents of a response file, written into a raw_ostream. 82 void writeResponseFile(raw_ostream &OS) const; 83 84 public: 85 Command(const Action &Source, const Tool &Creator, const char *Executable, 86 const llvm::opt::ArgStringList &Arguments, 87 ArrayRef<InputInfo> Inputs); 88 // FIXME: This really shouldn't be copyable, but is currently copied in some 89 // error handling in Driver::generateCompilationDiagnostics. 90 Command(const Command &) = default; ~Command()91 virtual ~Command() {} 92 93 virtual void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote, 94 CrashReportInfo *CrashInfo = nullptr) const; 95 96 virtual int Execute(const StringRef **Redirects, std::string *ErrMsg, 97 bool *ExecutionFailed) const; 98 99 /// getSource - Return the Action which caused the creation of this job. getSource()100 const Action &getSource() const { return Source; } 101 102 /// getCreator - Return the Tool which caused the creation of this job. getCreator()103 const Tool &getCreator() const { return Creator; } 104 105 /// Set to pass arguments via a response file when launching the command 106 void setResponseFile(const char *FileName); 107 108 /// Set an input file list, necessary if we need to use a response file but 109 /// the tool being called only supports input files lists. setInputFileList(llvm::opt::ArgStringList List)110 void setInputFileList(llvm::opt::ArgStringList List) { 111 InputFileList = std::move(List); 112 } 113 getExecutable()114 const char *getExecutable() const { return Executable; } 115 getArguments()116 const llvm::opt::ArgStringList &getArguments() const { return Arguments; } 117 118 /// Print a command argument, and optionally quote it. 119 static void printArg(llvm::raw_ostream &OS, const char *Arg, bool Quote); 120 }; 121 122 /// Like Command, but with a fallback which is executed in case 123 /// the primary command crashes. 124 class FallbackCommand : public Command { 125 public: 126 FallbackCommand(const Action &Source_, const Tool &Creator_, 127 const char *Executable_, const ArgStringList &Arguments_, 128 ArrayRef<InputInfo> Inputs, 129 std::unique_ptr<Command> Fallback_); 130 131 void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote, 132 CrashReportInfo *CrashInfo = nullptr) const override; 133 134 int Execute(const StringRef **Redirects, std::string *ErrMsg, 135 bool *ExecutionFailed) const override; 136 137 private: 138 std::unique_ptr<Command> Fallback; 139 }; 140 141 /// Like Command, but always pretends that the wrapped command succeeded. 142 class ForceSuccessCommand : public Command { 143 public: 144 ForceSuccessCommand(const Action &Source_, const Tool &Creator_, 145 const char *Executable_, const ArgStringList &Arguments_, 146 ArrayRef<InputInfo> Inputs); 147 148 void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote, 149 CrashReportInfo *CrashInfo = nullptr) const override; 150 151 int Execute(const StringRef **Redirects, std::string *ErrMsg, 152 bool *ExecutionFailed) const override; 153 }; 154 155 /// JobList - A sequence of jobs to perform. 156 class JobList { 157 public: 158 typedef SmallVector<std::unique_ptr<Command>, 4> list_type; 159 typedef list_type::size_type size_type; 160 typedef llvm::pointee_iterator<list_type::iterator> iterator; 161 typedef llvm::pointee_iterator<list_type::const_iterator> const_iterator; 162 163 private: 164 list_type Jobs; 165 166 public: 167 void Print(llvm::raw_ostream &OS, const char *Terminator, 168 bool Quote, CrashReportInfo *CrashInfo = nullptr) const; 169 170 /// Add a job to the list (taking ownership). addJob(std::unique_ptr<Command> J)171 void addJob(std::unique_ptr<Command> J) { Jobs.push_back(std::move(J)); } 172 173 /// Clear the job list. 174 void clear(); 175 getJobs()176 const list_type &getJobs() const { return Jobs; } 177 size()178 size_type size() const { return Jobs.size(); } begin()179 iterator begin() { return Jobs.begin(); } begin()180 const_iterator begin() const { return Jobs.begin(); } end()181 iterator end() { return Jobs.end(); } end()182 const_iterator end() const { return Jobs.end(); } 183 }; 184 185 } // end namespace driver 186 } // end namespace clang 187 188 #endif 189