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
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
|
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef TOOLS_GN_FILESYSTEM_UTILS_H_
#define TOOLS_GN_FILESYSTEM_UTILS_H_
#include <stddef.h>
#include <string>
#include "base/files/file_path.h"
#include "base/strings/string_piece.h"
#include "tools/gn/settings.h"
#include "tools/gn/target.h"
class Err;
std::string FilePathToUTF8(const base::FilePath::StringType& str);
inline std::string FilePathToUTF8(const base::FilePath& path) {
return FilePathToUTF8(path.value());
}
base::FilePath UTF8ToFilePath(const base::StringPiece& sp);
// Extensions -----------------------------------------------------------------
// Returns the index of the extension (character after the last dot not after a
// slash). Returns std::string::npos if not found. Returns path.size() if the
// file ends with a dot.
size_t FindExtensionOffset(const std::string& path);
// Returns a string piece pointing into the input string identifying the
// extension. Note that the input pointer must outlive the output.
base::StringPiece FindExtension(const std::string* path);
// Filename parts -------------------------------------------------------------
// Returns the offset of the character following the last slash, or
// 0 if no slash was found. Returns path.size() if the path ends with a slash.
// Note that the input pointer must outlive the output.
size_t FindFilenameOffset(const std::string& path);
// Returns a string piece pointing into the input string identifying the
// file name (following the last slash, including the extension). Note that the
// input pointer must outlive the output.
base::StringPiece FindFilename(const std::string* path);
// Like FindFilename but does not include the extension.
base::StringPiece FindFilenameNoExtension(const std::string* path);
// Removes everything after the last slash. The last slash, if any, will be
// preserved.
void RemoveFilename(std::string* path);
// Returns if the given character is a slash. This allows both slashes and
// backslashes for consistency between Posix and Windows (as opposed to
// FilePath::IsSeparator which is based on the current platform).
inline bool IsSlash(const char ch) {
return ch == '/' || ch == '\\';
}
// Returns true if the given path ends with a slash.
bool EndsWithSlash(const std::string& s);
// Path parts -----------------------------------------------------------------
// Returns a string piece pointing into the input string identifying the
// directory name of the given path, including the last slash. Note that the
// input pointer must outlive the output.
base::StringPiece FindDir(const std::string* path);
// Returns the substring identifying the last component of the dir, or the
// empty substring if none. For example "//foo/bar/" -> "bar".
base::StringPiece FindLastDirComponent(const SourceDir& dir);
// Returns true if the given string is in the given output dir. This is pretty
// stupid and doesn't handle "." and "..", etc., it is designed for a sanity
// check to keep people from writing output files to the source directory
// accidentally.
bool IsStringInOutputDir(const SourceDir& output_dir, const std::string& str);
// Verifies that the given string references a file inside of the given
// directory. This just uses IsStringInOutputDir above.
//
// The origin will be blamed in the error.
//
// If the file isn't in the dir, returns false and sets the error. Otherwise
// returns true and leaves the error untouched.
bool EnsureStringIsInOutputDir(const SourceDir& output_dir,
const std::string& str,
const ParseNode* origin,
Err* err);
// ----------------------------------------------------------------------------
// Returns true if the input string is absolute. Double-slashes at the
// beginning are treated as source-relative paths. On Windows, this handles
// paths of both the native format: "C:/foo" and ours "/C:/foo"
bool IsPathAbsolute(const base::StringPiece& path);
// Returns true if the input string is source-absolute. Source-absolute
// paths begin with two forward slashes and resolve as if they are
// relative to the source root.
bool IsPathSourceAbsolute(const base::StringPiece& path);
// Given an absolute path, checks to see if is it is inside the source root.
// If it is, fills a source-absolute path into the given output and returns
// true. If it isn't, clears the dest and returns false.
//
// The source_root should be a base::FilePath converted to UTF-8. On Windows,
// it should begin with a "C:/" rather than being our SourceFile's style
// ("/C:/"). The source root can end with a slash or not.
//
// Note that this does not attempt to normalize slashes in the output.
bool MakeAbsolutePathRelativeIfPossible(const base::StringPiece& source_root,
const base::StringPiece& path,
std::string* dest);
// Collapses "." and sequential "/"s and evaluates "..". |path| may be
// system-absolute, source-absolute, or relative. If |path| is source-absolute
// and |source_root| is non-empty, |path| may be system absolute after this
// function returns, if |path| references the filesystem outside of
// |source_root| (ex. path = "//.."). In this case on Windows, |path| will have
// a leading slash. Otherwise, |path| will retain its relativity. |source_root|
// must not end with a slash.
void NormalizePath(std::string* path,
const base::StringPiece& source_root = base::StringPiece());
// Converts slashes to backslashes for Windows. Keeps the string unchanged
// for other systems.
void ConvertPathToSystem(std::string* path);
// Takes a path, |input|, and makes it relative to the given directory
// |dest_dir|. Both inputs may be source-relative (e.g. begins with
// with "//") or may be absolute.
//
// If supplied, the |source_root| parameter is the absolute path to
// the source root and not end in a slash. Unless you know that the
// inputs are always source relative, this should be supplied.
std::string RebasePath(
const std::string& input,
const SourceDir& dest_dir,
const base::StringPiece& source_root = base::StringPiece());
// Returns the given directory with no terminating slash at the end, such that
// appending a slash and more stuff will produce a valid path.
//
// If the directory refers to either the source or system root, we'll append
// a "." so this remains valid.
std::string DirectoryWithNoLastSlash(const SourceDir& dir);
// Returns the "best" SourceDir representing the given path. If it's inside the
// given source_root, a source-relative directory will be returned (e.g.
// "//foo/bar.cc". If it's outside of the source root or the source root is
// empty, a system-absolute directory will be returned.
SourceDir SourceDirForPath(const base::FilePath& source_root,
const base::FilePath& path);
// Like SourceDirForPath but returns the SourceDir representing the current
// directory.
SourceDir SourceDirForCurrentDirectory(const base::FilePath& source_root);
// Given the label of a toolchain and whether that toolchain is the default
// toolchain, returns the name of the subdirectory for that toolchain's
// output. This will be the empty string to indicate that the toolchain outputs
// go in the root build directory. Otherwise, the result will end in a slash.
std::string GetOutputSubdirName(const Label& toolchain_label, bool is_default);
// Returns true if the contents of the file and stream given are equal, false
// otherwise.
bool ContentsEqual(const base::FilePath& file_path, const std::string& data);
// Writes given stream contents to the given file if it differs from existing
// file contents. Returns true if new contents was successfully written or
// existing file contents doesn't need updating, false on write error. |err| is
// set on write error if not nullptr.
bool WriteFileIfChanged(const base::FilePath& file_path,
const std::string& data,
Err* err);
// Writes given stream contents to the given file. Returns true if data was
// successfully written, false otherwise. |err| is set on error if not nullptr.
bool WriteFile(const base::FilePath& file_path, const std::string& data,
Err* err);
// -----------------------------------------------------------------------------
enum class BuildDirType {
// Returns the root toolchain dir rather than the generated or output
// subdirectories. This is valid only for the toolchain directory getters.
// Asking for this for a target or source dir makes no sense.
TOOLCHAIN_ROOT,
// Generated file directory.
GEN,
// Output file directory.
OBJ,
};
// In different contexts, different information is known about the toolchain in
// question. If you have a Target or settings object, everything can be
// extracted from there. But when querying label information on something in
// another toolchain, for example, the only thing known (it may not even exist)
// is the toolchain label string and whether it matches the default toolchain.
//
// This object extracts the relevant information from a variety of input
// types for the convenience of the caller.
class BuildDirContext {
public:
// Extracts toolchain information associated with the given target.
explicit BuildDirContext(const Target* target);
// Extracts toolchain information associated with the given settings object.
explicit BuildDirContext(const Settings* settings);
// Extrats toolchain information from the current toolchain of the scope.
explicit BuildDirContext(const Scope* execution_scope);
// Extracts the default toolchain information from the given execution
// scope. The toolchain you want to query must be passed in. This doesn't
// use the settings object from the Scope so one can query other toolchains.
// If you want to use the scope's current toolchain, use the version above.
BuildDirContext(const Scope* execution_scope, const Label& toolchain_label);
// Specify all information manually.
BuildDirContext(const BuildSettings* build_settings,
const Label& toolchain_label,
bool is_default_toolchain);
const BuildSettings* build_settings;
const Label& toolchain_label;
bool is_default_toolchain;
};
// Returns the root, object, or generated file directory for the toolchain.
//
// The toolchain object file root is never exposed in GN (there is no
// root_obj_dir variable) so BuildDirType::OBJ would normally never be passed
// to this function except when it's called by one of the variants below that
// append paths to it.
SourceDir GetBuildDirAsSourceDir(const BuildDirContext& context,
BuildDirType type);
OutputFile GetBuildDirAsOutputFile(const BuildDirContext& context,
BuildDirType type);
// Returns the output or generated file directory corresponding to the given
// source directory.
SourceDir GetSubBuildDirAsSourceDir(const BuildDirContext& context,
const SourceDir& source_dir,
BuildDirType type);
OutputFile GetSubBuildDirAsOutputFile(const BuildDirContext& context,
const SourceDir& source_dir,
BuildDirType type);
// Returns the output or generated file directory corresponding to the given
// target.
SourceDir GetBuildDirForTargetAsSourceDir(const Target* target,
BuildDirType type);
OutputFile GetBuildDirForTargetAsOutputFile(const Target* target,
BuildDirType type);
// Returns the scope's current directory.
SourceDir GetScopeCurrentBuildDirAsSourceDir(const Scope* scope,
BuildDirType type);
// Lack of OutputDir version is due only to it not currently being needed,
// please add one if you need it.
#endif // TOOLS_GN_FILESYSTEM_UTILS_H_
|