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