• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef TOOLS_GN_FILESYSTEM_UTILS_H_
6 #define TOOLS_GN_FILESYSTEM_UTILS_H_
7 
8 #include <stddef.h>
9 
10 #include <string>
11 #include <string_view>
12 
13 #include "base/files/file_path.h"
14 #include "gn/settings.h"
15 #include "gn/target.h"
16 
17 class Err;
18 
19 std::string FilePathToUTF8(const base::FilePath::StringType& str);
FilePathToUTF8(const base::FilePath & path)20 inline std::string FilePathToUTF8(const base::FilePath& path) {
21   return FilePathToUTF8(path.value());
22 }
23 base::FilePath UTF8ToFilePath(std::string_view sp);
24 
25 // Extensions -----------------------------------------------------------------
26 
27 // Returns the index of the extension (character after the last dot not after a
28 // slash). Returns std::string::npos if not found. Returns path.size() if the
29 // file ends with a dot.
30 size_t FindExtensionOffset(const std::string& path);
31 
32 // Returns a string piece pointing into the input string identifying the
33 // extension. Note that the input pointer must outlive the output.
34 std::string_view FindExtension(const std::string* path);
35 
36 // Filename parts -------------------------------------------------------------
37 
38 // Returns the offset of the character following the last slash, or
39 // 0 if no slash was found. Returns path.size() if the path ends with a slash.
40 // Note that the input pointer must outlive the output.
41 size_t FindFilenameOffset(const std::string& path);
42 
43 // Returns a string piece pointing into the input string identifying the
44 // file name (following the last slash, including the extension). Note that the
45 // input pointer must outlive the output.
46 std::string_view FindFilename(const std::string* path);
47 
48 // Like FindFilename but does not include the extension.
49 std::string_view FindFilenameNoExtension(const std::string* path);
50 
51 // Removes everything after the last slash. The last slash, if any, will be
52 // preserved.
53 void RemoveFilename(std::string* path);
54 
55 // Returns if the given character is a slash. This allows both slashes and
56 // backslashes for consistency between Posix and Windows (as opposed to
57 // FilePath::IsSeparator which is based on the current platform).
IsSlash(const char ch)58 inline bool IsSlash(const char ch) {
59   return ch == '/' || ch == '\\';
60 }
61 
62 // Returns true if the given path ends with a slash.
63 bool EndsWithSlash(std::string_view s);
64 
65 // Path parts -----------------------------------------------------------------
66 
67 // Returns a string piece pointing into the input string identifying the
68 // directory name of the given path, including the last slash. Note that the
69 // input pointer must outlive the output.
70 std::string_view FindDir(const std::string* path);
71 
72 // Returns the substring identifying the last component of the dir, or the
73 // empty substring if none. For example "//foo/bar/" -> "bar".
74 std::string_view FindLastDirComponent(const SourceDir& dir);
75 
76 // Returns true if the given string is in the given output dir. This is pretty
77 // stupid and doesn't handle "." and "..", etc., it is designed for a sanity
78 // check to keep people from writing output files to the source directory
79 // accidentally.
80 bool IsStringInOutputDir(const SourceDir& output_dir, const std::string& str);
81 
82 // Verifies that the given string references a file inside of the given
83 // directory. This just uses IsStringInOutputDir above.
84 //
85 // The origin will be blamed in the error.
86 //
87 // If the file isn't in the dir, returns false and sets the error. Otherwise
88 // returns true and leaves the error untouched.
89 bool EnsureStringIsInOutputDir(const SourceDir& output_dir,
90                                const std::string& str,
91                                const ParseNode* origin,
92                                Err* err);
93 
94 // ----------------------------------------------------------------------------
95 
96 // Returns true if the input string is absolute. Double-slashes at the
97 // beginning are treated as source-relative paths. On Windows, this handles
98 // paths of both the native format: "C:/foo" and ours "/C:/foo"
99 bool IsPathAbsolute(std::string_view path);
100 
101 // Returns true if the input string is source-absolute. Source-absolute
102 // paths begin with two forward slashes and resolve as if they are
103 // relative to the source root.
104 bool IsPathSourceAbsolute(std::string_view path);
105 
106 // Given an absolute path, checks to see if is it is inside the source root.
107 // If it is, fills a source-absolute path into the given output and returns
108 // true. If it isn't, clears the dest and returns false.
109 //
110 // The source_root should be a base::FilePath converted to UTF-8. On Windows,
111 // it should begin with a "C:/" rather than being our SourceFile's style
112 // ("/C:/"). The source root can end with a slash or not.
113 //
114 // Note that this does not attempt to normalize slashes in the output.
115 bool MakeAbsolutePathRelativeIfPossible(std::string_view source_root,
116                                         std::string_view path,
117                                         std::string* dest);
118 
119 // Given two absolute paths |base| and |target|, returns a relative path to
120 // |target| as if the current directory was |base|.  The relative path returned
121 // is minimal.  For example, if "../../a/b/" and "../b" are both valid, then the
122 // latter will be returned.  On Windows, it's impossible to have a relative path
123 // from C:\foo to D:\bar, so the absolute path |target| is returned instead for
124 // this case.
125 base::FilePath MakeAbsoluteFilePathRelativeIfPossible(
126     const base::FilePath& base,
127     const base::FilePath& target);
128 
129 // Collapses "." and sequential "/"s and evaluates "..". |path| may be
130 // system-absolute, source-absolute, or relative. If |path| is source-absolute
131 // and |source_root| is non-empty, |path| may be system absolute after this
132 // function returns, if |path| references the filesystem outside of
133 // |source_root| (ex. path = "//.."). In this case on Windows, |path| will have
134 // a leading slash. Otherwise, |path| will retain its relativity. |source_root|
135 // must not end with a slash.
136 void NormalizePath(std::string* path,
137                    std::string_view source_root = std::string_view());
138 
139 // Converts slashes to backslashes for Windows. Keeps the string unchanged
140 // for other systems.
141 void ConvertPathToSystem(std::string* path);
142 
143 // Takes a path, |input|, and makes it relative to the given directory
144 // |dest_dir|. Both inputs may be source-relative (e.g. begins with
145 // with "//") or may be absolute.
146 //
147 // If supplied, the |source_root| parameter is the absolute path to
148 // the source root and not end in a slash. Unless you know that the
149 // inputs are always source relative, this should be supplied.
150 std::string RebasePath(const std::string& input,
151                        const SourceDir& dest_dir,
152                        std::string_view source_root = std::string_view());
153 
154 // Resolves a file or dir name (parameter input) relative to
155 // value directory. Will return an empty SourceDir/File on error
156 // and set the give *err pointer (required). Empty input is always an error.
157 // Returned value can be used to set value in either SourceFile or SourceDir
158 // (based on as_file parameter).
159 //
160 // Parameter as_file defines whether result path will look like a file path
161 // or it should be treated as a directory (contains "/" and the end
162 // of the string).
163 //
164 // If source_root is supplied, these functions will additionally handle the
165 // case where the input is a system-absolute but still inside the source
166 // tree. This is the case for some external tools.
167 std::string ResolveRelative(std::string_view input,
168                             const std::string& value,
169                             bool as_file,
170                             std::string_view source_root);
171 
172 // Resolves source file or directory relative to some given source root. Returns
173 // an empty file path on error.
174 base::FilePath ResolvePath(const std::string& value,
175                            bool as_file,
176                            const base::FilePath& source_root);
177 
178 // Returns the given directory with no terminating slash at the end, such that
179 // appending a slash and more stuff will produce a valid path.
180 //
181 // If the directory refers to either the source or system root, we'll append
182 // a "." so this remains valid.
183 std::string DirectoryWithNoLastSlash(const SourceDir& dir);
184 
185 // Returns the "best" SourceDir representing the given path. If it's inside the
186 // given source_root, a source-relative directory will be returned (e.g.
187 // "//foo/bar.cc". If it's outside of the source root or the source root is
188 // empty, a system-absolute directory will be returned.
189 SourceDir SourceDirForPath(const base::FilePath& source_root,
190                            const base::FilePath& path);
191 
192 // Like SourceDirForPath but returns the SourceDir representing the current
193 // directory.
194 SourceDir SourceDirForCurrentDirectory(const base::FilePath& source_root);
195 
196 // Given the label of a toolchain and whether that toolchain is the default
197 // toolchain, returns the name of the subdirectory for that toolchain's
198 // output. This will be the empty string to indicate that the toolchain outputs
199 // go in the root build directory. Otherwise, the result will end in a slash.
200 std::string GetOutputSubdirName(const Label& toolchain_label, bool is_default);
201 
202 // Returns true if the contents of the file and stream given are equal, false
203 // otherwise.
204 bool ContentsEqual(const base::FilePath& file_path, const std::string& data);
205 
206 // Writes given stream contents to the given file. Returns true if data was
207 // successfully written, false otherwise. |err| is set on error if not nullptr.
208 bool WriteFile(const base::FilePath& file_path,
209                const std::string& data,
210                Err* err);
211 
212 // -----------------------------------------------------------------------------
213 
214 enum class BuildDirType {
215   // Returns the root toolchain dir rather than the generated or output
216   // subdirectories. This is valid only for the toolchain directory getters.
217   // Asking for this for a target or source dir makes no sense.
218   TOOLCHAIN_ROOT,
219 
220   // Generated file directory.
221   GEN,
222 
223   // Output file directory.
224   OBJ,
225 
226   // Phony file directory. As the name implies, this is not a real file
227   // directory, but a path that is used for the declaration of phony targets.
228   // This is done to avoid duplicate target names between real files and phony
229   // aliases that point to them.
230   PHONY,
231 };
232 
233 // In different contexts, different information is known about the toolchain in
234 // question. If you have a Target or settings object, everything can be
235 // extracted from there. But when querying label information on something in
236 // another toolchain, for example, the only thing known (it may not even exist)
237 // is the toolchain label string and whether it matches the default toolchain.
238 //
239 // This object extracts the relevant information from a variety of input
240 // types for the convenience of the caller.
241 class BuildDirContext {
242  public:
243   // Extracts toolchain information associated with the given target.
244   explicit BuildDirContext(const Target* target);
245 
246   // Extracts toolchain information associated with the given settings object.
247   explicit BuildDirContext(const Settings* settings);
248 
249   // Extrats toolchain information from the current toolchain of the scope.
250   explicit BuildDirContext(const Scope* execution_scope);
251 
252   // Extracts the default toolchain information from the given execution
253   // scope. The toolchain you want to query must be passed in. This doesn't
254   // use the settings object from the Scope so one can query other toolchains.
255   // If you want to use the scope's current toolchain, use the version above.
256   BuildDirContext(const Scope* execution_scope, const Label& toolchain_label);
257 
258   // Specify all information manually.
259   BuildDirContext(const BuildSettings* build_settings,
260                   const Label& toolchain_label,
261                   bool is_default_toolchain);
262 
263   const BuildSettings* build_settings;
264   const Label& toolchain_label;
265   bool is_default_toolchain;
266 };
267 
268 // Returns the root, object, or generated file directory for the toolchain.
269 //
270 // The toolchain object file root is never exposed in GN (there is no
271 // root_obj_dir variable) so BuildDirType::OBJ would normally never be passed
272 // to this function except when it's called by one of the variants below that
273 // append paths to it.
274 SourceDir GetBuildDirAsSourceDir(const BuildDirContext& context,
275                                  BuildDirType type);
276 OutputFile GetBuildDirAsOutputFile(const BuildDirContext& context,
277                                    BuildDirType type);
278 
279 // Returns the output or generated file directory corresponding to the given
280 // source directory.
281 SourceDir GetSubBuildDirAsSourceDir(const BuildDirContext& context,
282                                     const SourceDir& source_dir,
283                                     BuildDirType type);
284 OutputFile GetSubBuildDirAsOutputFile(const BuildDirContext& context,
285                                       const SourceDir& source_dir,
286                                       BuildDirType type);
287 
288 // Returns the output or generated file directory corresponding to the given
289 // target.
290 SourceDir GetBuildDirForTargetAsSourceDir(const Target* target,
291                                           BuildDirType type);
292 OutputFile GetBuildDirForTargetAsOutputFile(const Target* target,
293                                             BuildDirType type);
294 
295 // Returns the scope's current directory.
296 SourceDir GetScopeCurrentBuildDirAsSourceDir(const Scope* scope,
297                                              BuildDirType type);
298 // Lack of OutputDir version is due only to it not currently being needed,
299 // please add one if you need it.
300 
301 #endif  // TOOLS_GN_FILESYSTEM_UTILS_H_
302