Job.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- Job.h - Commands to Execute ------------------------------*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #ifndef LLVM_CLANG_DRIVER_JOB_H
  14. #define LLVM_CLANG_DRIVER_JOB_H
  15. #include "clang/Basic/LLVM.h"
  16. #include "clang/Driver/InputInfo.h"
  17. #include "llvm/ADT/ArrayRef.h"
  18. #include "llvm/ADT/SmallVector.h"
  19. #include "llvm/ADT/StringRef.h"
  20. #include "llvm/ADT/iterator.h"
  21. #include "llvm/Option/Option.h"
  22. #include "llvm/Support/Program.h"
  23. #include <memory>
  24. #include <optional>
  25. #include <string>
  26. #include <utility>
  27. #include <vector>
  28. namespace clang {
  29. namespace driver {
  30. class Action;
  31. class InputInfo;
  32. class Tool;
  33. struct CrashReportInfo {
  34. StringRef Filename;
  35. StringRef VFSPath;
  36. CrashReportInfo(StringRef Filename, StringRef VFSPath)
  37. : Filename(Filename), VFSPath(VFSPath) {}
  38. };
  39. // Encodes the kind of response file supported for a command invocation.
  40. // Response files are necessary if the command line gets too large, requiring
  41. // the arguments to be transferred to a file.
  42. struct ResponseFileSupport {
  43. enum ResponseFileKind {
  44. // Provides full support for response files, which means we can transfer
  45. // all tool input arguments to a file.
  46. RF_Full,
  47. // Input file names can live in a file, but flags can't. This is a special
  48. // case for old versions of Apple's ld64.
  49. RF_FileList,
  50. // Does not support response files: all arguments must be passed via
  51. // command line.
  52. RF_None
  53. };
  54. /// The level of support for response files.
  55. ResponseFileKind ResponseKind;
  56. /// The encoding to use when writing response files on Windows. Ignored on
  57. /// other host OSes.
  58. ///
  59. /// Windows use cases: - GCC and Binutils on mingw only accept ANSI response
  60. /// files encoded with the system current code page.
  61. /// - MSVC's CL.exe and LINK.exe accept UTF16 on Windows.
  62. /// - Clang accepts both UTF8 and UTF16.
  63. ///
  64. /// FIXME: When GNU tools learn how to parse UTF16 on Windows, we should
  65. /// always use UTF16 for Windows, which is the Windows official encoding for
  66. /// international characters.
  67. llvm::sys::WindowsEncodingMethod ResponseEncoding;
  68. /// What prefix to use for the command-line argument when passing a response
  69. /// file.
  70. const char *ResponseFlag;
  71. /// Returns a ResponseFileSupport indicating that response files are not
  72. /// supported.
  73. static constexpr ResponseFileSupport None() {
  74. return {RF_None, llvm::sys::WEM_UTF8, nullptr};
  75. }
  76. /// Returns a ResponseFileSupport indicating that response files are
  77. /// supported, using the @file syntax. On windows, the file is written in the
  78. /// UTF8 encoding. On other OSes, no re-encoding occurs.
  79. static constexpr ResponseFileSupport AtFileUTF8() {
  80. return {RF_Full, llvm::sys::WEM_UTF8, "@"};
  81. }
  82. /// Returns a ResponseFileSupport indicating that response files are
  83. /// supported, using the @file syntax. On windows, the file is written in the
  84. /// current ANSI code-page encoding. On other OSes, no re-encoding occurs.
  85. static constexpr ResponseFileSupport AtFileCurCP() {
  86. return {RF_Full, llvm::sys::WEM_CurrentCodePage, "@"};
  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. /// UTF-16 encoding. On other OSes, no re-encoding occurs.
  91. static constexpr ResponseFileSupport AtFileUTF16() {
  92. return {RF_Full, llvm::sys::WEM_UTF16, "@"};
  93. }
  94. };
  95. /// Command - An executable path/name and argument vector to
  96. /// execute.
  97. class Command {
  98. /// Source - The action which caused the creation of this job.
  99. const Action &Source;
  100. /// Tool - The tool which caused the creation of this job.
  101. const Tool &Creator;
  102. /// Whether and how to generate response files if the arguments are too long.
  103. ResponseFileSupport ResponseSupport;
  104. /// The executable to run.
  105. const char *Executable;
  106. /// The list of program arguments (not including the implicit first
  107. /// argument, which will be the executable).
  108. llvm::opt::ArgStringList Arguments;
  109. /// The list of program inputs.
  110. std::vector<InputInfo> InputInfoList;
  111. /// The list of program arguments which are outputs. May be empty.
  112. std::vector<std::string> OutputFilenames;
  113. /// Response file name, if this command is set to use one, or nullptr
  114. /// otherwise
  115. const char *ResponseFile = nullptr;
  116. /// The input file list in case we need to emit a file list instead of a
  117. /// proper response file
  118. llvm::opt::ArgStringList InputFileList;
  119. /// String storage if we need to create a new argument to specify a response
  120. /// file
  121. std::string ResponseFileFlag;
  122. /// See Command::setEnvironment
  123. std::vector<const char *> Environment;
  124. /// Optional redirection for stdin, stdout, stderr.
  125. std::vector<std::optional<std::string>> RedirectFiles;
  126. /// Information on executable run provided by OS.
  127. mutable std::optional<llvm::sys::ProcessStatistics> ProcStat;
  128. /// When a response file is needed, we try to put most arguments in an
  129. /// exclusive file, while others remains as regular command line arguments.
  130. /// This functions fills a vector with the regular command line arguments,
  131. /// argv, excluding the ones passed in a response file.
  132. void buildArgvForResponseFile(llvm::SmallVectorImpl<const char *> &Out) const;
  133. /// Encodes an array of C strings into a single string separated by whitespace.
  134. /// This function will also put in quotes arguments that have whitespaces and
  135. /// will escape the regular backslashes (used in Windows paths) and quotes.
  136. /// The results are the contents of a response file, written into a raw_ostream.
  137. void writeResponseFile(raw_ostream &OS) const;
  138. public:
  139. /// Whether to print the input filenames when executing.
  140. bool PrintInputFilenames = false;
  141. /// Whether the command will be executed in this process or not.
  142. bool InProcess = false;
  143. Command(const Action &Source, const Tool &Creator,
  144. ResponseFileSupport ResponseSupport, const char *Executable,
  145. const llvm::opt::ArgStringList &Arguments, ArrayRef<InputInfo> Inputs,
  146. ArrayRef<InputInfo> Outputs = std::nullopt);
  147. // FIXME: This really shouldn't be copyable, but is currently copied in some
  148. // error handling in Driver::generateCompilationDiagnostics.
  149. Command(const Command &) = default;
  150. virtual ~Command() = default;
  151. virtual void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote,
  152. CrashReportInfo *CrashInfo = nullptr) const;
  153. virtual int Execute(ArrayRef<std::optional<StringRef>> Redirects,
  154. std::string *ErrMsg, bool *ExecutionFailed) const;
  155. /// getSource - Return the Action which caused the creation of this job.
  156. const Action &getSource() const { return Source; }
  157. /// getCreator - Return the Tool which caused the creation of this job.
  158. const Tool &getCreator() const { return Creator; }
  159. /// Returns the kind of response file supported by the current invocation.
  160. const ResponseFileSupport &getResponseFileSupport() {
  161. return ResponseSupport;
  162. }
  163. /// Set to pass arguments via a response file when launching the command
  164. void setResponseFile(const char *FileName);
  165. /// Set an input file list, necessary if you specified an RF_FileList response
  166. /// file support.
  167. void setInputFileList(llvm::opt::ArgStringList List) {
  168. InputFileList = std::move(List);
  169. }
  170. /// Sets the environment to be used by the new process.
  171. /// \param NewEnvironment An array of environment variables.
  172. /// \remark If the environment remains unset, then the environment
  173. /// from the parent process will be used.
  174. virtual void setEnvironment(llvm::ArrayRef<const char *> NewEnvironment);
  175. void
  176. setRedirectFiles(const std::vector<std::optional<std::string>> &Redirects);
  177. void replaceArguments(llvm::opt::ArgStringList List) {
  178. Arguments = std::move(List);
  179. }
  180. void replaceExecutable(const char *Exe) { Executable = Exe; }
  181. const char *getExecutable() const { return Executable; }
  182. const llvm::opt::ArgStringList &getArguments() const { return Arguments; }
  183. const std::vector<InputInfo> &getInputInfos() const { return InputInfoList; }
  184. const std::vector<std::string> &getOutputFilenames() const {
  185. return OutputFilenames;
  186. }
  187. std::optional<llvm::sys::ProcessStatistics> getProcessStatistics() const {
  188. return ProcStat;
  189. }
  190. protected:
  191. /// Optionally print the filenames to be compiled
  192. void PrintFileNames() const;
  193. };
  194. /// Use the CC1 tool callback when available, to avoid creating a new process
  195. class CC1Command : public Command {
  196. public:
  197. CC1Command(const Action &Source, const Tool &Creator,
  198. ResponseFileSupport ResponseSupport, const char *Executable,
  199. const llvm::opt::ArgStringList &Arguments,
  200. ArrayRef<InputInfo> Inputs,
  201. ArrayRef<InputInfo> Outputs = std::nullopt);
  202. void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote,
  203. CrashReportInfo *CrashInfo = nullptr) const override;
  204. int Execute(ArrayRef<std::optional<StringRef>> Redirects, std::string *ErrMsg,
  205. bool *ExecutionFailed) const override;
  206. void setEnvironment(llvm::ArrayRef<const char *> NewEnvironment) override;
  207. };
  208. /// Like Command, but always pretends that the wrapped command succeeded.
  209. class ForceSuccessCommand : public Command {
  210. public:
  211. ForceSuccessCommand(const Action &Source_, const Tool &Creator_,
  212. ResponseFileSupport ResponseSupport,
  213. const char *Executable_,
  214. const llvm::opt::ArgStringList &Arguments_,
  215. ArrayRef<InputInfo> Inputs,
  216. ArrayRef<InputInfo> Outputs = std::nullopt);
  217. void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote,
  218. CrashReportInfo *CrashInfo = nullptr) const override;
  219. int Execute(ArrayRef<std::optional<StringRef>> Redirects, std::string *ErrMsg,
  220. bool *ExecutionFailed) const override;
  221. };
  222. /// JobList - A sequence of jobs to perform.
  223. class JobList {
  224. public:
  225. using list_type = SmallVector<std::unique_ptr<Command>, 4>;
  226. using size_type = list_type::size_type;
  227. using iterator = llvm::pointee_iterator<list_type::iterator>;
  228. using const_iterator = llvm::pointee_iterator<list_type::const_iterator>;
  229. private:
  230. list_type Jobs;
  231. public:
  232. void Print(llvm::raw_ostream &OS, const char *Terminator,
  233. bool Quote, CrashReportInfo *CrashInfo = nullptr) const;
  234. /// Add a job to the list (taking ownership).
  235. void addJob(std::unique_ptr<Command> J) { Jobs.push_back(std::move(J)); }
  236. /// Clear the job list.
  237. void clear();
  238. const list_type &getJobs() const { return Jobs; }
  239. bool empty() const { return Jobs.empty(); }
  240. size_type size() const { return Jobs.size(); }
  241. iterator begin() { return Jobs.begin(); }
  242. const_iterator begin() const { return Jobs.begin(); }
  243. iterator end() { return Jobs.end(); }
  244. const_iterator end() const { return Jobs.end(); }
  245. };
  246. } // namespace driver
  247. } // namespace clang
  248. #endif // LLVM_CLANG_DRIVER_JOB_H
  249. #ifdef __GNUC__
  250. #pragma GCC diagnostic pop
  251. #endif