| // 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 <string_view> |
| |
| #include "base/files/file_path.h" |
| #include "gn/settings.h" |
| #include "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(std::string_view 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. |
| std::string_view 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. |
| std::string_view FindFilename(const std::string* path); |
| |
| // Like FindFilename but does not include the extension. |
| std::string_view 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(std::string_view 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. |
| std::string_view 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". |
| std::string_view 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(std::string_view 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(std::string_view 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(std::string_view source_root, |
| std::string_view path, |
| std::string* dest); |
| |
| // Given two absolute paths |base| and |target|, returns a relative path to |
| // |target| as if the current directory was |base|. The relative path returned |
| // is minimal. For example, if "../../a/b/" and "../b" are both valid, then the |
| // latter will be returned. On Windows, it's impossible to have a relative path |
| // from C:\foo to D:\bar, so the absolute path |target| is returned instead for |
| // this case. |
| base::FilePath MakeAbsoluteFilePathRelativeIfPossible( |
| const base::FilePath& base, |
| const base::FilePath& target); |
| |
| // 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, |
| std::string_view source_root = std::string_view()); |
| |
| // 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, |
| std::string_view source_root = std::string_view()); |
| |
| // Resolves a file or dir name (parameter input) relative to |
| // value directory. Will return an empty SourceDir/File on error |
| // and set the give *err pointer (required). Empty input is always an error. |
| // Returned value can be used to set value in either SourceFile or SourceDir |
| // (based on as_file parameter). |
| // |
| // Parameter as_file defines whether result path will look like a file path |
| // or it should be treated as a directory (contains "/" and the end |
| // of the string). |
| // |
| // If source_root is supplied, these functions will additionally handle the |
| // case where the input is a system-absolute but still inside the source |
| // tree. This is the case for some external tools. |
| std::string ResolveRelative(std::string_view input, |
| const std::string& value, |
| bool as_file, |
| std::string_view source_root); |
| |
| // Resolves source file or directory relative to some given source root. Returns |
| // an empty file path on error. |
| base::FilePath ResolvePath(const std::string& value, |
| bool as_file, |
| const base::FilePath& source_root); |
| |
| // 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. 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, |
| |
| // Phony file directory. As the name implies, this is not a real file |
| // directory, but a path that is used for the declaration of phony targets. |
| // This is done to avoid duplicate target names between real files and phony |
| // aliases that point to them. |
| PHONY, |
| }; |
| |
| // 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_ |