1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
|
#pragma once
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#endif
//===- llvm/Support/Program.h ------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file declares the llvm::sys::Program class.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_SUPPORT_PROGRAM_H
#define LLVM_SUPPORT_PROGRAM_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/FileSystem.h"
#include <chrono>
#include <system_error>
namespace llvm {
namespace sys {
/// This is the OS-specific separator for PATH like environment variables:
// a colon on Unix or a semicolon on Windows.
#if defined(LLVM_ON_UNIX)
const char EnvPathSeparator = ':';
#elif defined (_WIN32)
const char EnvPathSeparator = ';';
#endif
#if defined(_WIN32)
typedef unsigned long procid_t; // Must match the type of DWORD on Windows.
typedef void *process_t; // Must match the type of HANDLE on Windows.
#else
typedef ::pid_t procid_t;
typedef procid_t process_t;
#endif
/// This struct encapsulates information about a process.
struct ProcessInfo {
enum : procid_t { InvalidPid = 0 };
procid_t Pid; /// The process identifier.
process_t Process; /// Platform-dependent process object.
/// The return code, set after execution.
int ReturnCode;
ProcessInfo();
};
/// This struct encapsulates information about a process execution.
struct ProcessStatistics {
std::chrono::microseconds TotalTime;
std::chrono::microseconds UserTime;
uint64_t PeakMemory = 0; ///< Maximum resident set size in KiB.
};
/// Find the first executable file \p Name in \p Paths.
///
/// This does not perform hashing as a shell would but instead stats each PATH
/// entry individually so should generally be avoided. Core LLVM library
/// functions and options should instead require fully specified paths.
///
/// \param Name name of the executable to find. If it contains any system
/// slashes, it will be returned as is.
/// \param Paths optional list of paths to search for \p Name. If empty it
/// will use the system PATH environment instead.
///
/// \returns The fully qualified path to the first \p Name in \p Paths if it
/// exists. \p Name if \p Name has slashes in it. Otherwise an error.
ErrorOr<std::string>
findProgramByName(StringRef Name, ArrayRef<StringRef> Paths = {});
// These functions change the specified standard stream (stdin or stdout) mode
// based on the Flags. They return errc::success if the specified stream was
// changed. Otherwise, a platform dependent error is returned.
std::error_code ChangeStdinMode(fs::OpenFlags Flags);
std::error_code ChangeStdoutMode(fs::OpenFlags Flags);
// These functions change the specified standard stream (stdin or stdout) to
// binary mode. They return errc::success if the specified stream
// was changed. Otherwise a platform dependent error is returned.
std::error_code ChangeStdinToBinary();
std::error_code ChangeStdoutToBinary();
/// This function executes the program using the arguments provided. The
/// invoked program will inherit the stdin, stdout, and stderr file
/// descriptors, the environment and other configuration settings of the
/// invoking program.
/// This function waits for the program to finish, so should be avoided in
/// library functions that aren't expected to block. Consider using
/// ExecuteNoWait() instead.
/// \returns an integer result code indicating the status of the program.
/// A zero or positive value indicates the result code of the program.
/// -1 indicates failure to execute
/// -2 indicates a crash during execution or timeout
int ExecuteAndWait(
StringRef Program, ///< Path of the program to be executed. It is
///< presumed this is the result of the findProgramByName method.
ArrayRef<StringRef> Args, ///< An array of strings that are passed to the
///< program. The first element should be the name of the program.
///< The array should **not** be terminated by an empty StringRef.
Optional<ArrayRef<StringRef>> Env = None, ///< An optional vector of
///< strings to use for the program's environment. If not provided, the
///< current program's environment will be used. If specified, the
///< vector should **not** be terminated by an empty StringRef.
ArrayRef<Optional<StringRef>> Redirects = {}, ///<
///< An array of optional paths. Should have a size of zero or three.
///< If the array is empty, no redirections are performed.
///< Otherwise, the inferior process's stdin(0), stdout(1), and stderr(2)
///< will be redirected to the corresponding paths, if the optional path
///< is present (not \c llvm::None).
///< When an empty path is passed in, the corresponding file descriptor
///< will be disconnected (ie, /dev/null'd) in a portable way.
unsigned SecondsToWait = 0, ///< If non-zero, this specifies the amount
///< of time to wait for the child process to exit. If the time
///< expires, the child is killed and this call returns. If zero,
///< this function will wait until the child finishes or forever if
///< it doesn't.
unsigned MemoryLimit = 0, ///< If non-zero, this specifies max. amount
///< of memory can be allocated by process. If memory usage will be
///< higher limit, the child is killed and this call returns. If zero
///< - no memory limit.
std::string *ErrMsg = nullptr, ///< If non-zero, provides a pointer to a
///< string instance in which error messages will be returned. If the
///< string is non-empty upon return an error occurred while invoking the
///< program.
bool *ExecutionFailed = nullptr,
Optional<ProcessStatistics> *ProcStat = nullptr, ///< If non-zero,
/// provides a pointer to a structure in which process execution
/// statistics will be stored.
BitVector *AffinityMask = nullptr ///< CPUs or processors the new
/// program shall run on.
);
/// Similar to ExecuteAndWait, but returns immediately.
/// @returns The \see ProcessInfo of the newly launched process.
/// \note On Microsoft Windows systems, users will need to either call
/// \see Wait until the process finished execution or win32 CloseHandle() API
/// on ProcessInfo.ProcessHandle to avoid memory leaks.
ProcessInfo ExecuteNoWait(StringRef Program, ArrayRef<StringRef> Args,
Optional<ArrayRef<StringRef>> Env,
ArrayRef<Optional<StringRef>> Redirects = {},
unsigned MemoryLimit = 0,
std::string *ErrMsg = nullptr,
bool *ExecutionFailed = nullptr,
BitVector *AffinityMask = nullptr);
/// Return true if the given arguments fit within system-specific
/// argument length limits.
bool commandLineFitsWithinSystemLimits(StringRef Program,
ArrayRef<StringRef> Args);
/// Return true if the given arguments fit within system-specific
/// argument length limits.
bool commandLineFitsWithinSystemLimits(StringRef Program,
ArrayRef<const char *> Args);
/// File encoding options when writing contents that a non-UTF8 tool will
/// read (on Windows systems). For UNIX, we always use UTF-8.
enum WindowsEncodingMethod {
/// UTF-8 is the LLVM native encoding, being the same as "do not perform
/// encoding conversion".
WEM_UTF8,
WEM_CurrentCodePage,
WEM_UTF16
};
/// Saves the UTF8-encoded \p contents string into the file \p FileName
/// using a specific encoding.
///
/// This write file function adds the possibility to choose which encoding
/// to use when writing a text file. On Windows, this is important when
/// writing files with internationalization support with an encoding that is
/// different from the one used in LLVM (UTF-8). We use this when writing
/// response files, since GCC tools on MinGW only understand legacy code
/// pages, and VisualStudio tools only understand UTF-16.
/// For UNIX, using different encodings is silently ignored, since all tools
/// work well with UTF-8.
/// This function assumes that you only use UTF-8 *text* data and will convert
/// it to your desired encoding before writing to the file.
///
/// FIXME: We use EM_CurrentCodePage to write response files for GNU tools in
/// a MinGW/MinGW-w64 environment, which has serious flaws but currently is
/// our best shot to make gcc/ld understand international characters. This
/// should be changed as soon as binutils fix this to support UTF16 on mingw.
///
/// \returns non-zero error_code if failed
std::error_code
writeFileWithEncoding(StringRef FileName, StringRef Contents,
WindowsEncodingMethod Encoding = WEM_UTF8);
/// This function waits for the process specified by \p PI to finish.
/// \returns A \see ProcessInfo struct with Pid set to:
/// \li The process id of the child process if the child process has changed
/// state.
/// \li 0 if the child process has not changed state.
/// \note Users of this function should always check the ReturnCode member of
/// the \see ProcessInfo returned from this function.
ProcessInfo Wait(
const ProcessInfo &PI, ///< The child process that should be waited on.
unsigned SecondsToWait, ///< If non-zero, this specifies the amount of
///< time to wait for the child process to exit. If the time expires, the
///< child is killed and this function returns. If zero, this function
///< will perform a non-blocking wait on the child process.
bool WaitUntilTerminates, ///< If true, ignores \p SecondsToWait and waits
///< until child has terminated.
std::string *ErrMsg = nullptr, ///< If non-zero, provides a pointer to a
///< string instance in which error messages will be returned. If the
///< string is non-empty upon return an error occurred while invoking the
///< program.
Optional<ProcessStatistics> *ProcStat = nullptr ///< If non-zero, provides
/// a pointer to a structure in which process execution statistics will be
/// stored.
);
/// Print a command argument, and optionally quote it.
void printArg(llvm::raw_ostream &OS, StringRef Arg, bool Quote);
#if defined(_WIN32)
/// Given a list of command line arguments, quote and escape them as necessary
/// to build a single flat command line appropriate for calling CreateProcess
/// on
/// Windows.
ErrorOr<std::wstring> flattenWindowsCommandLine(ArrayRef<StringRef> Args);
#endif
}
}
#endif
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
|