1218885Sdim//===- llvm/Support/Program.h ------------------------------------*- C++ -*-===//
2218885Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6218885Sdim//
7218885Sdim//===----------------------------------------------------------------------===//
8218885Sdim//
9218885Sdim// This file declares the llvm::sys::Program class.
10218885Sdim//
11218885Sdim//===----------------------------------------------------------------------===//
12218885Sdim
13249423Sdim#ifndef LLVM_SUPPORT_PROGRAM_H
14249423Sdim#define LLVM_SUPPORT_PROGRAM_H
15218885Sdim
16251662Sdim#include "llvm/ADT/ArrayRef.h"
17327952Sdim#include "llvm/ADT/Optional.h"
18327952Sdim#include "llvm/ADT/StringRef.h"
19341825Sdim#include "llvm/Config/llvm-config.h"
20280031Sdim#include "llvm/Support/ErrorOr.h"
21276479Sdim#include <system_error>
22218885Sdim
23218885Sdimnamespace llvm {
24218885Sdimnamespace sys {
25218885Sdim
26261991Sdim  /// This is the OS-specific separator for PATH like environment variables:
27261991Sdim  // a colon on Unix or a semicolon on Windows.
28261991Sdim#if defined(LLVM_ON_UNIX)
29261991Sdim  const char EnvPathSeparator = ':';
30341825Sdim#elif defined (_WIN32)
31261991Sdim  const char EnvPathSeparator = ';';
32261991Sdim#endif
33218885Sdim
34341825Sdim#if defined(_WIN32)
35341825Sdim  typedef unsigned long procid_t; // Must match the type of DWORD on Windows.
36341825Sdim  typedef void *process_t;        // Must match the type of HANDLE on Windows.
37261991Sdim#else
38341825Sdim  typedef pid_t procid_t;
39341825Sdim  typedef procid_t process_t;
40261991Sdim#endif
41218885Sdim
42341825Sdim  /// This struct encapsulates information about a process.
43341825Sdim  struct ProcessInfo {
44341825Sdim    enum : procid_t { InvalidPid = 0 };
45309124Sdim
46341825Sdim    procid_t Pid;      /// The process identifier.
47341825Sdim    process_t Process; /// Platform-dependent process object.
48218885Sdim
49341825Sdim    /// The return code, set after execution.
50341825Sdim    int ReturnCode;
51218885Sdim
52341825Sdim    ProcessInfo();
53341825Sdim  };
54218885Sdim
55341825Sdim  /// Find the first executable file \p Name in \p Paths.
56276479Sdim  ///
57280031Sdim  /// This does not perform hashing as a shell would but instead stats each PATH
58276479Sdim  /// entry individually so should generally be avoided. Core LLVM library
59276479Sdim  /// functions and options should instead require fully specified paths.
60276479Sdim  ///
61280031Sdim  /// \param Name name of the executable to find. If it contains any system
62280031Sdim  ///   slashes, it will be returned as is.
63280031Sdim  /// \param Paths optional list of paths to search for \p Name. If empty it
64280031Sdim  ///   will use the system PATH environment instead.
65280031Sdim  ///
66280031Sdim  /// \returns The fully qualified path to the first \p Name in \p Paths if it
67280031Sdim  ///   exists. \p Name if \p Name has slashes in it. Otherwise an error.
68280031Sdim  ErrorOr<std::string>
69327952Sdim  findProgramByName(StringRef Name, ArrayRef<StringRef> Paths = {});
70261991Sdim
71276479Sdim  // These functions change the specified standard stream (stdin or stdout) to
72276479Sdim  // binary mode. They return errc::success if the specified stream
73261991Sdim  // was changed. Otherwise a platform dependent error is returned.
74276479Sdim  std::error_code ChangeStdinToBinary();
75276479Sdim  std::error_code ChangeStdoutToBinary();
76261991Sdim
77261991Sdim  /// This function executes the program using the arguments provided.  The
78261991Sdim  /// invoked program will inherit the stdin, stdout, and stderr file
79261991Sdim  /// descriptors, the environment and other configuration settings of the
80261991Sdim  /// invoking program.
81276479Sdim  /// This function waits for the program to finish, so should be avoided in
82276479Sdim  /// library functions that aren't expected to block. Consider using
83276479Sdim  /// ExecuteNoWait() instead.
84327952Sdim  /// \returns an integer result code indicating the status of the program.
85261991Sdim  /// A zero or positive value indicates the result code of the program.
86261991Sdim  /// -1 indicates failure to execute
87261991Sdim  /// -2 indicates a crash during execution or timeout
88261991Sdim  int ExecuteAndWait(
89261991Sdim      StringRef Program, ///< Path of the program to be executed. It is
90309124Sdim      ///< presumed this is the result of the findProgramByName method.
91341825Sdim      ArrayRef<StringRef> Args, ///< An array of strings that are passed to the
92218885Sdim      ///< program.  The first element should be the name of the program.
93341825Sdim      ///< The array should **not** be terminated by an empty StringRef.
94341825Sdim      Optional<ArrayRef<StringRef>> Env = None, ///< An optional vector of
95341825Sdim      ///< strings to use for the program's environment. If not provided, the
96341825Sdim      ///< current program's environment will be used.  If specified, the
97341825Sdim      ///< vector should **not** be terminated by an empty StringRef.
98327952Sdim      ArrayRef<Optional<StringRef>> Redirects = {}, ///<
99327952Sdim      ///< An array of optional paths. Should have a size of zero or three.
100327952Sdim      ///< If the array is empty, no redirections are performed.
101327952Sdim      ///< Otherwise, the inferior process's stdin(0), stdout(1), and stderr(2)
102327952Sdim      ///< will be redirected to the corresponding paths, if the optional path
103327952Sdim      ///< is present (not \c llvm::None).
104327952Sdim      ///< When an empty path is passed in, the corresponding file descriptor
105327952Sdim      ///< will be disconnected (ie, /dev/null'd) in a portable way.
106327952Sdim      unsigned SecondsToWait = 0, ///< If non-zero, this specifies the amount
107261991Sdim      ///< of time to wait for the child process to exit. If the time
108261991Sdim      ///< expires, the child is killed and this call returns. If zero,
109261991Sdim      ///< this function will wait until the child finishes or forever if
110261991Sdim      ///< it doesn't.
111327952Sdim      unsigned MemoryLimit = 0, ///< If non-zero, this specifies max. amount
112218885Sdim      ///< of memory can be allocated by process. If memory usage will be
113218885Sdim      ///< higher limit, the child is killed and this call returns. If zero
114218885Sdim      ///< - no memory limit.
115276479Sdim      std::string *ErrMsg = nullptr, ///< If non-zero, provides a pointer to a
116276479Sdim      ///< string instance in which error messages will be returned. If the
117276479Sdim      ///< string is non-empty upon return an error occurred while invoking the
118218885Sdim      ///< program.
119276479Sdim      bool *ExecutionFailed = nullptr);
120218885Sdim
121261991Sdim  /// Similar to ExecuteAndWait, but returns immediately.
122261991Sdim  /// @returns The \see ProcessInfo of the newly launced process.
123327952Sdim  /// \note On Microsoft Windows systems, users will need to either call
124327952Sdim  /// \see Wait until the process finished execution or win32 CloseHandle() API
125327952Sdim  /// on ProcessInfo.ProcessHandle to avoid memory leaks.
126341825Sdim  ProcessInfo ExecuteNoWait(StringRef Program, ArrayRef<StringRef> Args,
127341825Sdim                            Optional<ArrayRef<StringRef>> Env,
128327952Sdim                            ArrayRef<Optional<StringRef>> Redirects = {},
129327952Sdim                            unsigned MemoryLimit = 0,
130327952Sdim                            std::string *ErrMsg = nullptr,
131327952Sdim                            bool *ExecutionFailed = nullptr);
132261991Sdim
133261991Sdim  /// Return true if the given arguments fit within system-specific
134261991Sdim  /// argument length limits.
135327952Sdim  bool commandLineFitsWithinSystemLimits(StringRef Program,
136341825Sdim                                         ArrayRef<StringRef> Args);
137341825Sdim
138341825Sdim  /// Return true if the given arguments fit within system-specific
139341825Sdim  /// argument length limits.
140341825Sdim  bool commandLineFitsWithinSystemLimits(StringRef Program,
141327952Sdim                                         ArrayRef<const char *> Args);
142261991Sdim
143280031Sdim  /// File encoding options when writing contents that a non-UTF8 tool will
144280031Sdim  /// read (on Windows systems). For UNIX, we always use UTF-8.
145280031Sdim  enum WindowsEncodingMethod {
146280031Sdim    /// UTF-8 is the LLVM native encoding, being the same as "do not perform
147280031Sdim    /// encoding conversion".
148280031Sdim    WEM_UTF8,
149280031Sdim    WEM_CurrentCodePage,
150280031Sdim    WEM_UTF16
151280031Sdim  };
152280031Sdim
153280031Sdim  /// Saves the UTF8-encoded \p contents string into the file \p FileName
154280031Sdim  /// using a specific encoding.
155280031Sdim  ///
156280031Sdim  /// This write file function adds the possibility to choose which encoding
157280031Sdim  /// to use when writing a text file. On Windows, this is important when
158280031Sdim  /// writing files with internationalization support with an encoding that is
159280031Sdim  /// different from the one used in LLVM (UTF-8). We use this when writing
160280031Sdim  /// response files, since GCC tools on MinGW only understand legacy code
161280031Sdim  /// pages, and VisualStudio tools only understand UTF-16.
162280031Sdim  /// For UNIX, using different encodings is silently ignored, since all tools
163280031Sdim  /// work well with UTF-8.
164280031Sdim  /// This function assumes that you only use UTF-8 *text* data and will convert
165280031Sdim  /// it to your desired encoding before writing to the file.
166280031Sdim  ///
167280031Sdim  /// FIXME: We use EM_CurrentCodePage to write response files for GNU tools in
168280031Sdim  /// a MinGW/MinGW-w64 environment, which has serious flaws but currently is
169280031Sdim  /// our best shot to make gcc/ld understand international characters. This
170280031Sdim  /// should be changed as soon as binutils fix this to support UTF16 on mingw.
171280031Sdim  ///
172280031Sdim  /// \returns non-zero error_code if failed
173280031Sdim  std::error_code
174280031Sdim  writeFileWithEncoding(StringRef FileName, StringRef Contents,
175280031Sdim                        WindowsEncodingMethod Encoding = WEM_UTF8);
176280031Sdim
177261991Sdim  /// This function waits for the process specified by \p PI to finish.
178261991Sdim  /// \returns A \see ProcessInfo struct with Pid set to:
179261991Sdim  /// \li The process id of the child process if the child process has changed
180261991Sdim  /// state.
181261991Sdim  /// \li 0 if the child process has not changed state.
182261991Sdim  /// \note Users of this function should always check the ReturnCode member of
183261991Sdim  /// the \see ProcessInfo returned from this function.
184261991Sdim  ProcessInfo Wait(
185261991Sdim      const ProcessInfo &PI, ///< The child process that should be waited on.
186261991Sdim      unsigned SecondsToWait, ///< If non-zero, this specifies the amount of
187261991Sdim      ///< time to wait for the child process to exit. If the time expires, the
188261991Sdim      ///< child is killed and this function returns. If zero, this function
189261991Sdim      ///< will perform a non-blocking wait on the child process.
190261991Sdim      bool WaitUntilTerminates, ///< If true, ignores \p SecondsToWait and waits
191261991Sdim      ///< until child has terminated.
192276479Sdim      std::string *ErrMsg = nullptr ///< If non-zero, provides a pointer to a
193276479Sdim      ///< string instance in which error messages will be returned. If the
194276479Sdim      ///< string is non-empty upon return an error occurred while invoking the
195261991Sdim      ///< program.
196218885Sdim      );
197341825Sdim
198341825Sdim#if defined(_WIN32)
199341825Sdim  /// Given a list of command line arguments, quote and escape them as necessary
200341825Sdim  /// to build a single flat command line appropriate for calling CreateProcess
201341825Sdim  /// on
202341825Sdim  /// Windows.
203341825Sdim  std::string flattenWindowsCommandLine(ArrayRef<StringRef> Args);
204341825Sdim#endif
205261991Sdim  }
206218885Sdim}
207218885Sdim
208218885Sdim#endif
209