| // 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(std::string_view 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 GetSourceDir(const BuildDirContext& context, BuildDirType type); | |
| std::string GetBuildDir(const BuildDirContext& context, BuildDirType type); | |
| // Returns the output or generated file directory corresponding to the given | |
| // source directory. | |
| SourceDir GetSourceDir(const BuildDirContext& context, | |
| const SourceDir& source_dir, | |
| BuildDirType type); | |
| std::string GetBuildDir(const BuildDirContext& context, | |
| const SourceDir& source_dir, | |
| BuildDirType type); | |
| // Returns the output or generated file directory corresponding to the given | |
| // target. | |
| SourceDir GetSourceDir(const Target& target, BuildDirType type); | |
| std::string GetBuildDir(const Target& target, BuildDirType type); | |
| // Returns the scope's current directory. | |
| SourceDir GetSourceDir(const Scope& scope, BuildDirType type); | |
| // Lack of GetBuildDir version is due only to it not currently being needed, | |
| // please add one if you need it. | |
| template <typename... Args> | |
| OutputFile GetOutputFile(const BuildDirContext& context, | |
| BuildDirType type, | |
| Args&&... args) { | |
| std::string path = GetBuildDir(context, type); | |
| (path.append(std::forward<Args>(args)), ...); | |
| return OutputFile(path); | |
| } | |
| template <typename... Args> | |
| OutputFile GetOutputFile(const BuildDirContext& context, | |
| const SourceDir& source_dir, | |
| BuildDirType type, | |
| Args&&... args) { | |
| std::string path = GetBuildDir(context, source_dir, type); | |
| (path.append(std::forward<Args>(args)), ...); | |
| return OutputFile(path); | |
| } | |
| template <typename... Args> | |
| OutputFile GetOutputFile(const Target& target, | |
| BuildDirType type, | |
| Args&&... args) { | |
| std::string path = GetBuildDir(target, type); | |
| (path.append(std::forward<Args>(args)), ...); | |
| return OutputFile(path); | |
| } | |
| #endif // TOOLS_GN_FILESYSTEM_UTILS_H_ |