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