16d528ed9Sopenharmony_ci// Copyright (c) 2013 The Chromium Authors. All rights reserved. 26d528ed9Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 36d528ed9Sopenharmony_ci// found in the LICENSE file. 46d528ed9Sopenharmony_ci 56d528ed9Sopenharmony_ci#ifndef TOOLS_GN_FILESYSTEM_UTILS_H_ 66d528ed9Sopenharmony_ci#define TOOLS_GN_FILESYSTEM_UTILS_H_ 76d528ed9Sopenharmony_ci 86d528ed9Sopenharmony_ci#include <stddef.h> 96d528ed9Sopenharmony_ci 106d528ed9Sopenharmony_ci#include <string> 116d528ed9Sopenharmony_ci#include <string_view> 126d528ed9Sopenharmony_ci 136d528ed9Sopenharmony_ci#include "base/files/file_path.h" 146d528ed9Sopenharmony_ci#include "gn/settings.h" 156d528ed9Sopenharmony_ci#include "gn/target.h" 166d528ed9Sopenharmony_ci 176d528ed9Sopenharmony_ciclass Err; 186d528ed9Sopenharmony_ci 196d528ed9Sopenharmony_cistd::string FilePathToUTF8(const base::FilePath::StringType& str); 206d528ed9Sopenharmony_ciinline std::string FilePathToUTF8(const base::FilePath& path) { 216d528ed9Sopenharmony_ci return FilePathToUTF8(path.value()); 226d528ed9Sopenharmony_ci} 236d528ed9Sopenharmony_cibase::FilePath UTF8ToFilePath(std::string_view sp); 246d528ed9Sopenharmony_ci 256d528ed9Sopenharmony_ci// Extensions ----------------------------------------------------------------- 266d528ed9Sopenharmony_ci 276d528ed9Sopenharmony_ci// Returns the index of the extension (character after the last dot not after a 286d528ed9Sopenharmony_ci// slash). Returns std::string::npos if not found. Returns path.size() if the 296d528ed9Sopenharmony_ci// file ends with a dot. 306d528ed9Sopenharmony_cisize_t FindExtensionOffset(const std::string& path); 316d528ed9Sopenharmony_ci 326d528ed9Sopenharmony_ci// Returns a string piece pointing into the input string identifying the 336d528ed9Sopenharmony_ci// extension. Note that the input pointer must outlive the output. 346d528ed9Sopenharmony_cistd::string_view FindExtension(const std::string* path); 356d528ed9Sopenharmony_ci 366d528ed9Sopenharmony_ci// Filename parts ------------------------------------------------------------- 376d528ed9Sopenharmony_ci 386d528ed9Sopenharmony_ci// Returns the offset of the character following the last slash, or 396d528ed9Sopenharmony_ci// 0 if no slash was found. Returns path.size() if the path ends with a slash. 406d528ed9Sopenharmony_ci// Note that the input pointer must outlive the output. 416d528ed9Sopenharmony_cisize_t FindFilenameOffset(const std::string& path); 426d528ed9Sopenharmony_ci 436d528ed9Sopenharmony_ci// Returns a string piece pointing into the input string identifying the 446d528ed9Sopenharmony_ci// file name (following the last slash, including the extension). Note that the 456d528ed9Sopenharmony_ci// input pointer must outlive the output. 466d528ed9Sopenharmony_cistd::string_view FindFilename(const std::string* path); 476d528ed9Sopenharmony_ci 486d528ed9Sopenharmony_ci// Like FindFilename but does not include the extension. 496d528ed9Sopenharmony_cistd::string_view FindFilenameNoExtension(const std::string* path); 506d528ed9Sopenharmony_ci 516d528ed9Sopenharmony_ci// Removes everything after the last slash. The last slash, if any, will be 526d528ed9Sopenharmony_ci// preserved. 536d528ed9Sopenharmony_civoid RemoveFilename(std::string* path); 546d528ed9Sopenharmony_ci 556d528ed9Sopenharmony_ci// Returns if the given character is a slash. This allows both slashes and 566d528ed9Sopenharmony_ci// backslashes for consistency between Posix and Windows (as opposed to 576d528ed9Sopenharmony_ci// FilePath::IsSeparator which is based on the current platform). 586d528ed9Sopenharmony_ciinline bool IsSlash(const char ch) { 596d528ed9Sopenharmony_ci return ch == '/' || ch == '\\'; 606d528ed9Sopenharmony_ci} 616d528ed9Sopenharmony_ci 626d528ed9Sopenharmony_ci// Returns true if the given path ends with a slash. 636d528ed9Sopenharmony_cibool EndsWithSlash(std::string_view s); 646d528ed9Sopenharmony_ci 656d528ed9Sopenharmony_ci// Path parts ----------------------------------------------------------------- 666d528ed9Sopenharmony_ci 676d528ed9Sopenharmony_ci// Returns a string piece pointing into the input string identifying the 686d528ed9Sopenharmony_ci// directory name of the given path, including the last slash. Note that the 696d528ed9Sopenharmony_ci// input pointer must outlive the output. 706d528ed9Sopenharmony_cistd::string_view FindDir(const std::string* path); 716d528ed9Sopenharmony_ci 726d528ed9Sopenharmony_ci// Returns the substring identifying the last component of the dir, or the 736d528ed9Sopenharmony_ci// empty substring if none. For example "//foo/bar/" -> "bar". 746d528ed9Sopenharmony_cistd::string_view FindLastDirComponent(const SourceDir& dir); 756d528ed9Sopenharmony_ci 766d528ed9Sopenharmony_ci// Returns true if the given string is in the given output dir. This is pretty 776d528ed9Sopenharmony_ci// stupid and doesn't handle "." and "..", etc., it is designed for a sanity 786d528ed9Sopenharmony_ci// check to keep people from writing output files to the source directory 796d528ed9Sopenharmony_ci// accidentally. 806d528ed9Sopenharmony_cibool IsStringInOutputDir(const SourceDir& output_dir, const std::string& str); 816d528ed9Sopenharmony_ci 826d528ed9Sopenharmony_ci// Verifies that the given string references a file inside of the given 836d528ed9Sopenharmony_ci// directory. This just uses IsStringInOutputDir above. 846d528ed9Sopenharmony_ci// 856d528ed9Sopenharmony_ci// The origin will be blamed in the error. 866d528ed9Sopenharmony_ci// 876d528ed9Sopenharmony_ci// If the file isn't in the dir, returns false and sets the error. Otherwise 886d528ed9Sopenharmony_ci// returns true and leaves the error untouched. 896d528ed9Sopenharmony_cibool EnsureStringIsInOutputDir(const SourceDir& output_dir, 906d528ed9Sopenharmony_ci const std::string& str, 916d528ed9Sopenharmony_ci const ParseNode* origin, 926d528ed9Sopenharmony_ci Err* err); 936d528ed9Sopenharmony_ci 946d528ed9Sopenharmony_ci// ---------------------------------------------------------------------------- 956d528ed9Sopenharmony_ci 966d528ed9Sopenharmony_ci// Returns true if the input string is absolute. Double-slashes at the 976d528ed9Sopenharmony_ci// beginning are treated as source-relative paths. On Windows, this handles 986d528ed9Sopenharmony_ci// paths of both the native format: "C:/foo" and ours "/C:/foo" 996d528ed9Sopenharmony_cibool IsPathAbsolute(std::string_view path); 1006d528ed9Sopenharmony_ci 1016d528ed9Sopenharmony_ci// Returns true if the input string is source-absolute. Source-absolute 1026d528ed9Sopenharmony_ci// paths begin with two forward slashes and resolve as if they are 1036d528ed9Sopenharmony_ci// relative to the source root. 1046d528ed9Sopenharmony_cibool IsPathSourceAbsolute(std::string_view path); 1056d528ed9Sopenharmony_ci 1066d528ed9Sopenharmony_ci// Given an absolute path, checks to see if is it is inside the source root. 1076d528ed9Sopenharmony_ci// If it is, fills a source-absolute path into the given output and returns 1086d528ed9Sopenharmony_ci// true. If it isn't, clears the dest and returns false. 1096d528ed9Sopenharmony_ci// 1106d528ed9Sopenharmony_ci// The source_root should be a base::FilePath converted to UTF-8. On Windows, 1116d528ed9Sopenharmony_ci// it should begin with a "C:/" rather than being our SourceFile's style 1126d528ed9Sopenharmony_ci// ("/C:/"). The source root can end with a slash or not. 1136d528ed9Sopenharmony_ci// 1146d528ed9Sopenharmony_ci// Note that this does not attempt to normalize slashes in the output. 1156d528ed9Sopenharmony_cibool MakeAbsolutePathRelativeIfPossible(std::string_view source_root, 1166d528ed9Sopenharmony_ci std::string_view path, 1176d528ed9Sopenharmony_ci std::string* dest); 1186d528ed9Sopenharmony_ci 1196d528ed9Sopenharmony_ci// Given two absolute paths |base| and |target|, returns a relative path to 1206d528ed9Sopenharmony_ci// |target| as if the current directory was |base|. The relative path returned 1216d528ed9Sopenharmony_ci// is minimal. For example, if "../../a/b/" and "../b" are both valid, then the 1226d528ed9Sopenharmony_ci// latter will be returned. On Windows, it's impossible to have a relative path 1236d528ed9Sopenharmony_ci// from C:\foo to D:\bar, so the absolute path |target| is returned instead for 1246d528ed9Sopenharmony_ci// this case. 1256d528ed9Sopenharmony_cibase::FilePath MakeAbsoluteFilePathRelativeIfPossible( 1266d528ed9Sopenharmony_ci const base::FilePath& base, 1276d528ed9Sopenharmony_ci const base::FilePath& target); 1286d528ed9Sopenharmony_ci 1296d528ed9Sopenharmony_ci// Collapses "." and sequential "/"s and evaluates "..". |path| may be 1306d528ed9Sopenharmony_ci// system-absolute, source-absolute, or relative. If |path| is source-absolute 1316d528ed9Sopenharmony_ci// and |source_root| is non-empty, |path| may be system absolute after this 1326d528ed9Sopenharmony_ci// function returns, if |path| references the filesystem outside of 1336d528ed9Sopenharmony_ci// |source_root| (ex. path = "//.."). In this case on Windows, |path| will have 1346d528ed9Sopenharmony_ci// a leading slash. Otherwise, |path| will retain its relativity. |source_root| 1356d528ed9Sopenharmony_ci// must not end with a slash. 1366d528ed9Sopenharmony_civoid NormalizePath(std::string* path, 1376d528ed9Sopenharmony_ci std::string_view source_root = std::string_view()); 1386d528ed9Sopenharmony_ci 1396d528ed9Sopenharmony_ci// Converts slashes to backslashes for Windows. Keeps the string unchanged 1406d528ed9Sopenharmony_ci// for other systems. 1416d528ed9Sopenharmony_civoid ConvertPathToSystem(std::string* path); 1426d528ed9Sopenharmony_ci 1436d528ed9Sopenharmony_ci// Takes a path, |input|, and makes it relative to the given directory 1446d528ed9Sopenharmony_ci// |dest_dir|. Both inputs may be source-relative (e.g. begins with 1456d528ed9Sopenharmony_ci// with "//") or may be absolute. 1466d528ed9Sopenharmony_ci// 1476d528ed9Sopenharmony_ci// If supplied, the |source_root| parameter is the absolute path to 1486d528ed9Sopenharmony_ci// the source root and not end in a slash. Unless you know that the 1496d528ed9Sopenharmony_ci// inputs are always source relative, this should be supplied. 1506d528ed9Sopenharmony_cistd::string RebasePath(const std::string& input, 1516d528ed9Sopenharmony_ci const SourceDir& dest_dir, 1526d528ed9Sopenharmony_ci std::string_view source_root = std::string_view()); 1536d528ed9Sopenharmony_ci 1546d528ed9Sopenharmony_ci// Resolves a file or dir name (parameter input) relative to 1556d528ed9Sopenharmony_ci// value directory. Will return an empty SourceDir/File on error 1566d528ed9Sopenharmony_ci// and set the give *err pointer (required). Empty input is always an error. 1576d528ed9Sopenharmony_ci// Returned value can be used to set value in either SourceFile or SourceDir 1586d528ed9Sopenharmony_ci// (based on as_file parameter). 1596d528ed9Sopenharmony_ci// 1606d528ed9Sopenharmony_ci// Parameter as_file defines whether result path will look like a file path 1616d528ed9Sopenharmony_ci// or it should be treated as a directory (contains "/" and the end 1626d528ed9Sopenharmony_ci// of the string). 1636d528ed9Sopenharmony_ci// 1646d528ed9Sopenharmony_ci// If source_root is supplied, these functions will additionally handle the 1656d528ed9Sopenharmony_ci// case where the input is a system-absolute but still inside the source 1666d528ed9Sopenharmony_ci// tree. This is the case for some external tools. 1676d528ed9Sopenharmony_cistd::string ResolveRelative(std::string_view input, 1686d528ed9Sopenharmony_ci const std::string& value, 1696d528ed9Sopenharmony_ci bool as_file, 1706d528ed9Sopenharmony_ci std::string_view source_root); 1716d528ed9Sopenharmony_ci 1726d528ed9Sopenharmony_ci// Resolves source file or directory relative to some given source root. Returns 1736d528ed9Sopenharmony_ci// an empty file path on error. 1746d528ed9Sopenharmony_cibase::FilePath ResolvePath(const std::string& value, 1756d528ed9Sopenharmony_ci bool as_file, 1766d528ed9Sopenharmony_ci const base::FilePath& source_root); 1776d528ed9Sopenharmony_ci 1786d528ed9Sopenharmony_ci// Returns the given directory with no terminating slash at the end, such that 1796d528ed9Sopenharmony_ci// appending a slash and more stuff will produce a valid path. 1806d528ed9Sopenharmony_ci// 1816d528ed9Sopenharmony_ci// If the directory refers to either the source or system root, we'll append 1826d528ed9Sopenharmony_ci// a "." so this remains valid. 1836d528ed9Sopenharmony_cistd::string DirectoryWithNoLastSlash(const SourceDir& dir); 1846d528ed9Sopenharmony_ci 1856d528ed9Sopenharmony_ci// Returns the "best" SourceDir representing the given path. If it's inside the 1866d528ed9Sopenharmony_ci// given source_root, a source-relative directory will be returned (e.g. 1876d528ed9Sopenharmony_ci// "//foo/bar.cc". If it's outside of the source root or the source root is 1886d528ed9Sopenharmony_ci// empty, a system-absolute directory will be returned. 1896d528ed9Sopenharmony_ciSourceDir SourceDirForPath(const base::FilePath& source_root, 1906d528ed9Sopenharmony_ci const base::FilePath& path); 1916d528ed9Sopenharmony_ci 1926d528ed9Sopenharmony_ci// Like SourceDirForPath but returns the SourceDir representing the current 1936d528ed9Sopenharmony_ci// directory. 1946d528ed9Sopenharmony_ciSourceDir SourceDirForCurrentDirectory(const base::FilePath& source_root); 1956d528ed9Sopenharmony_ci 1966d528ed9Sopenharmony_ci// Given the label of a toolchain and whether that toolchain is the default 1976d528ed9Sopenharmony_ci// toolchain, returns the name of the subdirectory for that toolchain's 1986d528ed9Sopenharmony_ci// output. This will be the empty string to indicate that the toolchain outputs 1996d528ed9Sopenharmony_ci// go in the root build directory. Otherwise, the result will end in a slash. 2006d528ed9Sopenharmony_cistd::string GetOutputSubdirName(const Label& toolchain_label, bool is_default); 2016d528ed9Sopenharmony_ci 2026d528ed9Sopenharmony_ci// Returns true if the contents of the file and stream given are equal, false 2036d528ed9Sopenharmony_ci// otherwise. 2046d528ed9Sopenharmony_cibool ContentsEqual(const base::FilePath& file_path, const std::string& data); 2056d528ed9Sopenharmony_ci 2066d528ed9Sopenharmony_ci// Writes given stream contents to the given file. Returns true if data was 2076d528ed9Sopenharmony_ci// successfully written, false otherwise. |err| is set on error if not nullptr. 2086d528ed9Sopenharmony_cibool WriteFile(const base::FilePath& file_path, 2096d528ed9Sopenharmony_ci const std::string& data, 2106d528ed9Sopenharmony_ci Err* err); 2116d528ed9Sopenharmony_ci 2126d528ed9Sopenharmony_ci// ----------------------------------------------------------------------------- 2136d528ed9Sopenharmony_ci 2146d528ed9Sopenharmony_cienum class BuildDirType { 2156d528ed9Sopenharmony_ci // Returns the root toolchain dir rather than the generated or output 2166d528ed9Sopenharmony_ci // subdirectories. This is valid only for the toolchain directory getters. 2176d528ed9Sopenharmony_ci // Asking for this for a target or source dir makes no sense. 2186d528ed9Sopenharmony_ci TOOLCHAIN_ROOT, 2196d528ed9Sopenharmony_ci 2206d528ed9Sopenharmony_ci // Generated file directory. 2216d528ed9Sopenharmony_ci GEN, 2226d528ed9Sopenharmony_ci 2236d528ed9Sopenharmony_ci // Output file directory. 2246d528ed9Sopenharmony_ci OBJ, 2256d528ed9Sopenharmony_ci 2266d528ed9Sopenharmony_ci // Phony file directory. As the name implies, this is not a real file 2276d528ed9Sopenharmony_ci // directory, but a path that is used for the declaration of phony targets. 2286d528ed9Sopenharmony_ci // This is done to avoid duplicate target names between real files and phony 2296d528ed9Sopenharmony_ci // aliases that point to them. 2306d528ed9Sopenharmony_ci PHONY, 2316d528ed9Sopenharmony_ci}; 2326d528ed9Sopenharmony_ci 2336d528ed9Sopenharmony_ci// In different contexts, different information is known about the toolchain in 2346d528ed9Sopenharmony_ci// question. If you have a Target or settings object, everything can be 2356d528ed9Sopenharmony_ci// extracted from there. But when querying label information on something in 2366d528ed9Sopenharmony_ci// another toolchain, for example, the only thing known (it may not even exist) 2376d528ed9Sopenharmony_ci// is the toolchain label string and whether it matches the default toolchain. 2386d528ed9Sopenharmony_ci// 2396d528ed9Sopenharmony_ci// This object extracts the relevant information from a variety of input 2406d528ed9Sopenharmony_ci// types for the convenience of the caller. 2416d528ed9Sopenharmony_ciclass BuildDirContext { 2426d528ed9Sopenharmony_ci public: 2436d528ed9Sopenharmony_ci // Extracts toolchain information associated with the given target. 2446d528ed9Sopenharmony_ci explicit BuildDirContext(const Target* target); 2456d528ed9Sopenharmony_ci 2466d528ed9Sopenharmony_ci // Extracts toolchain information associated with the given settings object. 2476d528ed9Sopenharmony_ci explicit BuildDirContext(const Settings* settings); 2486d528ed9Sopenharmony_ci 2496d528ed9Sopenharmony_ci // Extrats toolchain information from the current toolchain of the scope. 2506d528ed9Sopenharmony_ci explicit BuildDirContext(const Scope* execution_scope); 2516d528ed9Sopenharmony_ci 2526d528ed9Sopenharmony_ci // Extracts the default toolchain information from the given execution 2536d528ed9Sopenharmony_ci // scope. The toolchain you want to query must be passed in. This doesn't 2546d528ed9Sopenharmony_ci // use the settings object from the Scope so one can query other toolchains. 2556d528ed9Sopenharmony_ci // If you want to use the scope's current toolchain, use the version above. 2566d528ed9Sopenharmony_ci BuildDirContext(const Scope* execution_scope, const Label& toolchain_label); 2576d528ed9Sopenharmony_ci 2586d528ed9Sopenharmony_ci // Specify all information manually. 2596d528ed9Sopenharmony_ci BuildDirContext(const BuildSettings* build_settings, 2606d528ed9Sopenharmony_ci const Label& toolchain_label, 2616d528ed9Sopenharmony_ci bool is_default_toolchain); 2626d528ed9Sopenharmony_ci 2636d528ed9Sopenharmony_ci const BuildSettings* build_settings; 2646d528ed9Sopenharmony_ci const Label& toolchain_label; 2656d528ed9Sopenharmony_ci bool is_default_toolchain; 2666d528ed9Sopenharmony_ci}; 2676d528ed9Sopenharmony_ci 2686d528ed9Sopenharmony_ci// Returns the root, object, or generated file directory for the toolchain. 2696d528ed9Sopenharmony_ci// 2706d528ed9Sopenharmony_ci// The toolchain object file root is never exposed in GN (there is no 2716d528ed9Sopenharmony_ci// root_obj_dir variable) so BuildDirType::OBJ would normally never be passed 2726d528ed9Sopenharmony_ci// to this function except when it's called by one of the variants below that 2736d528ed9Sopenharmony_ci// append paths to it. 2746d528ed9Sopenharmony_ciSourceDir GetBuildDirAsSourceDir(const BuildDirContext& context, 2756d528ed9Sopenharmony_ci BuildDirType type); 2766d528ed9Sopenharmony_ciOutputFile GetBuildDirAsOutputFile(const BuildDirContext& context, 2776d528ed9Sopenharmony_ci BuildDirType type); 2786d528ed9Sopenharmony_ci 2796d528ed9Sopenharmony_ci// Returns the output or generated file directory corresponding to the given 2806d528ed9Sopenharmony_ci// source directory. 2816d528ed9Sopenharmony_ciSourceDir GetSubBuildDirAsSourceDir(const BuildDirContext& context, 2826d528ed9Sopenharmony_ci const SourceDir& source_dir, 2836d528ed9Sopenharmony_ci BuildDirType type); 2846d528ed9Sopenharmony_ciOutputFile GetSubBuildDirAsOutputFile(const BuildDirContext& context, 2856d528ed9Sopenharmony_ci const SourceDir& source_dir, 2866d528ed9Sopenharmony_ci BuildDirType type); 2876d528ed9Sopenharmony_ci 2886d528ed9Sopenharmony_ci// Returns the output or generated file directory corresponding to the given 2896d528ed9Sopenharmony_ci// target. 2906d528ed9Sopenharmony_ciSourceDir GetBuildDirForTargetAsSourceDir(const Target* target, 2916d528ed9Sopenharmony_ci BuildDirType type); 2926d528ed9Sopenharmony_ciOutputFile GetBuildDirForTargetAsOutputFile(const Target* target, 2936d528ed9Sopenharmony_ci BuildDirType type); 2946d528ed9Sopenharmony_ci 2956d528ed9Sopenharmony_ci// Returns the scope's current directory. 2966d528ed9Sopenharmony_ciSourceDir GetScopeCurrentBuildDirAsSourceDir(const Scope* scope, 2976d528ed9Sopenharmony_ci BuildDirType type); 2986d528ed9Sopenharmony_ci// Lack of OutputDir version is due only to it not currently being needed, 2996d528ed9Sopenharmony_ci// please add one if you need it. 3006d528ed9Sopenharmony_ci 3016d528ed9Sopenharmony_ci#endif // TOOLS_GN_FILESYSTEM_UTILS_H_ 302