filesystem_utils.cc revision 6d86b77056ed63eb6871182f42a9fd5f07550f90
1d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// Copyright (c) 2013 The Chromium Authors. All rights reserved. 2d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// Use of this source code is governed by a BSD-style license that can be 3d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// found in the LICENSE file. 4d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 5d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/filesystem_utils.h" 6d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include <algorithm> 868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 9a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/file_util.h" 10d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "base/logging.h" 11424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "base/strings/string_util.h" 12d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "base/strings/utf_string_conversions.h" 13d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "build/build_config.h" 14d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/location.h" 15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "tools/gn/settings.h" 16d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/source_dir.h" 17d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 18d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochnamespace { 19d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 20d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochenum DotDisposition { 21d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // The given dot is just part of a filename and is not special. 22d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch NOT_A_DIRECTORY, 23d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 24d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // The given dot is the current directory. 25d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch DIRECTORY_CUR, 26d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 27d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // The given dot is the first of a double dot that should take us up one. 28d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch DIRECTORY_UP 29d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}; 30d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 31d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// When we find a dot, this function is called with the character following 32d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// that dot to see what it is. The return value indicates what type this dot is 33d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// (see above). This code handles the case where the dot is at the end of the 34d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// input. 35d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// 36d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// |*consumed_len| will contain the number of characters in the input that 37d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// express what we found. 38d3868032626d59662ff73b372b5d584c1d144c53Ben MurdochDotDisposition ClassifyAfterDot(const std::string& path, 39d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch size_t after_dot, 40d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch size_t* consumed_len) { 41d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (after_dot == path.size()) { 42d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Single dot at the end. 43d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch *consumed_len = 1; 44d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return DIRECTORY_CUR; 45d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (IsSlash(path[after_dot])) { 47d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Single dot followed by a slash. 48d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch *consumed_len = 2; // Consume the slash 49d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return DIRECTORY_CUR; 50d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 51d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 52d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (path[after_dot] == '.') { 53d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Two dots. 54d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (after_dot + 1 == path.size()) { 55d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Double dot at the end. 56d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch *consumed_len = 2; 57d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return DIRECTORY_UP; 58d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (IsSlash(path[after_dot + 1])) { 60d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Double dot folowed by a slash. 61d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch *consumed_len = 3; 62d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return DIRECTORY_UP; 63d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 64d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 65d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 66d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // The dots are followed by something else, not a directory. 67d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch *consumed_len = 1; 68d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return NOT_A_DIRECTORY; 69d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 70d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 71424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#if defined(OS_WIN) 72424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)inline char NormalizeWindowsPathChar(char c) { 73424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (c == '/') 74424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return '\\'; 75424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return base::ToLowerASCII(c); 76424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 77424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 78424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// Attempts to do a case and slash-insensitive comparison of two 8-bit Windows 79424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// paths. 80424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)bool AreAbsoluteWindowsPathsEqual(const base::StringPiece& a, 81424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) const base::StringPiece& b) { 82424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (a.size() != b.size()) 83424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return false; 84424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 85424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // For now, just do a case-insensitive ASCII comparison. We could convert to 86424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // UTF-16 and use ICU if necessary. Or maybe base::strcasecmp is good enough? 87424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) for (size_t i = 0; i < a.size(); i++) { 88424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (NormalizeWindowsPathChar(a[i]) != NormalizeWindowsPathChar(b[i])) 89424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return false; 90424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 91424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return true; 92424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 93424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 94424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)bool DoesBeginWindowsDriveLetter(const base::StringPiece& path) { 95424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (path.size() < 3) 96424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return false; 97424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 98424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Check colon first, this will generally fail fastest. 99424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (path[1] != ':') 100424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return false; 101424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Check drive letter. 103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!IsAsciiAlpha(path[0])) 104424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return false; 105424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!IsSlash(path[2])) 107424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return false; 108424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return true; 109424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 110424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#endif 111424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// A wrapper around FilePath.GetComponents that works the way we need. This is 113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// not super efficient since it does some O(n) transformations on the path. If 114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// this is called a lot, we might want to optimize. 115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)std::vector<base::FilePath::StringType> GetPathComponents( 116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const base::FilePath& path) { 117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::vector<base::FilePath::StringType> result; 118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) path.GetComponents(&result); 119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (result.empty()) 121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return result; 122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // GetComponents will preserve the "/" at the beginning, which confuses us. 124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // We don't expect to have relative paths in this function. 125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Don't use IsSeparator since we always want to allow backslashes. 126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (result[0] == FILE_PATH_LITERAL("/") || 127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) result[0] == FILE_PATH_LITERAL("\\")) 128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) result.erase(result.begin()); 129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#if defined(OS_WIN) 131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // On Windows, GetComponents will give us [ "C:", "/", "foo" ], and we 132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // don't want the slash in there. This doesn't support input like "C:foo" 133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // which means foo relative to the current directory of the C drive but 134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // that's basically legacy DOS behavior we don't need to support. 135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (result.size() >= 2 && result[1].size() == 1 && IsSlash(result[1][0])) 136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) result.erase(result.begin() + 1); 137a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif 138a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 139a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return result; 140a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 141a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 142a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Provides the equivalent of == for filesystem strings, trying to do 143a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// approximately the right thing with case. 144a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool FilesystemStringsEqual(const base::FilePath::StringType& a, 145a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const base::FilePath::StringType& b) { 146a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#if defined(OS_WIN) 147a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Assume case-insensitive filesystems on Windows. We use the CompareString 148a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // function to do a case-insensitive comparison based on the current locale 149a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // (we don't want GN to depend on ICU which is large and requires data 150a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // files). This isn't perfect, but getting this perfectly right is very 151a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // difficult and requires I/O, and this comparison should cover 99.9999% of 152a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // all cases. 153a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // 154a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Note: The documentation for CompareString says it runs fastest on 155a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // null-terminated strings with -1 passed for the length, so we do that here. 156a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // There should not be embedded nulls in filesystem strings. 157a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return ::CompareString(LOCALE_USER_DEFAULT, LINGUISTIC_IGNORECASE, 158a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) a.c_str(), -1, b.c_str(), -1) == CSTR_EQUAL; 159a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#else 160a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Assume case-sensitive filesystems on non-Windows. 161a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return a == b; 162a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif 163a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 164a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 165424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} // namespace 166d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 167c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochSourceFileType GetSourceFileType(const SourceFile& file) { 168d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch base::StringPiece extension = FindExtension(&file.value()); 169d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (extension == "cc" || extension == "cpp" || extension == "cxx") 170d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return SOURCE_CC; 171d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (extension == "h") 172d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return SOURCE_H; 173d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (extension == "c") 174d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return SOURCE_C; 175c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (extension == "m") 176c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return SOURCE_M; 177c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (extension == "mm") 178c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return SOURCE_MM; 179c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (extension == "rc") 180c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return SOURCE_RC; 1810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (extension == "S" || extension == "s") 182c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return SOURCE_S; 183010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (extension == "o" || extension == "obj") 184010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return SOURCE_O; 1853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 186d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return SOURCE_UNKNOWN; 187d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 188d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 189d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochconst char* GetExtensionForOutputType(Target::OutputType type, 190d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch Settings::TargetOS os) { 191d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch switch (os) { 1922385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch case Settings::MAC: 1932385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch switch (type) { 1942385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch case Target::EXECUTABLE: 1952385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch return ""; 1962385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch case Target::SHARED_LIBRARY: 1972385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch return "dylib"; 1982385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch case Target::STATIC_LIBRARY: 1992385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch return "a"; 2002385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch default: 2012385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch NOTREACHED(); 2022385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch } 2032385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch break; 2042385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch 205d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch case Settings::WIN: 206d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch switch (type) { 207d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch case Target::EXECUTABLE: 208d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return "exe"; 209d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch case Target::SHARED_LIBRARY: 210d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return "dll.lib"; // Extension of import library. 211d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch case Target::STATIC_LIBRARY: 212d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return "lib"; 2133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) default: 2143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) NOTREACHED(); 2153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 2163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) break; 2173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) case Settings::LINUX: 2193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) switch (type) { 2203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) case Target::EXECUTABLE: 2213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return ""; 2223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) case Target::SHARED_LIBRARY: 2233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return "so"; 2243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) case Target::STATIC_LIBRARY: 2253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return "a"; 226d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch default: 227d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch NOTREACHED(); 228d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 229d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch break; 230d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 231d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch default: 232d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch NOTREACHED(); 233d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 234d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return ""; 235d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 236d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 23768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)std::string FilePathToUTF8(const base::FilePath::StringType& str) { 238d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#if defined(OS_WIN) 2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return base::WideToUTF8(str); 240d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#else 24168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return str; 242d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#endif 243d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 244d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 245d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochbase::FilePath UTF8ToFilePath(const base::StringPiece& sp) { 246d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#if defined(OS_WIN) 2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return base::FilePath(base::UTF8ToWide(sp)); 248d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#else 249d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return base::FilePath(sp.as_string()); 250d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#endif 251d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 252d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 253d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochsize_t FindExtensionOffset(const std::string& path) { 254d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch for (int i = static_cast<int>(path.size()); i >= 0; i--) { 255a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (IsSlash(path[i])) 256d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch break; 257d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (path[i] == '.') 258d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return i + 1; 259d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 260d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return std::string::npos; 261d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 262d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 263d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochbase::StringPiece FindExtension(const std::string* path) { 264d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch size_t extension_offset = FindExtensionOffset(*path); 265d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (extension_offset == std::string::npos) 266d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return base::StringPiece(); 267d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return base::StringPiece(&path->data()[extension_offset], 268d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch path->size() - extension_offset); 269d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 270d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 271d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochsize_t FindFilenameOffset(const std::string& path) { 272d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch for (int i = static_cast<int>(path.size()) - 1; i >= 0; i--) { 273a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (IsSlash(path[i])) 274d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return i + 1; 275d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 276d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return 0; // No filename found means everything was the filename. 277d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 278d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 279d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochbase::StringPiece FindFilename(const std::string* path) { 280d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch size_t filename_offset = FindFilenameOffset(*path); 281d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (filename_offset == 0) 282d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return base::StringPiece(*path); // Everything is the file name. 283d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return base::StringPiece(&(*path).data()[filename_offset], 284d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch path->size() - filename_offset); 285d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 286d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 287d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochbase::StringPiece FindFilenameNoExtension(const std::string* path) { 288d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (path->empty()) 289d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return base::StringPiece(); 290d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch size_t filename_offset = FindFilenameOffset(*path); 291d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch size_t extension_offset = FindExtensionOffset(*path); 292d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 293d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch size_t name_len; 294d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (extension_offset == std::string::npos) 295d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch name_len = path->size() - filename_offset; 296d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch else 297d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch name_len = extension_offset - filename_offset - 1; 298d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 299d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return base::StringPiece(&(*path).data()[filename_offset], name_len); 300d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 301d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 302d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochvoid RemoveFilename(std::string* path) { 303d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch path->resize(FindFilenameOffset(*path)); 304d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 305d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 306d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochbool EndsWithSlash(const std::string& s) { 307a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return !s.empty() && IsSlash(s[s.size() - 1]); 308d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 309d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 310d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochbase::StringPiece FindDir(const std::string* path) { 311d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch size_t filename_offset = FindFilenameOffset(*path); 312d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (filename_offset == 0u) 313d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return base::StringPiece(); 314d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return base::StringPiece(path->data(), filename_offset); 315d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 316d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 3175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubase::StringPiece FindLastDirComponent(const SourceDir& dir) { 3185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const std::string& dir_string = dir.value(); 3195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 3205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (dir_string.empty()) 3215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return base::StringPiece(); 3225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu int cur = static_cast<int>(dir_string.size()) - 1; 3235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu DCHECK(dir_string[cur] == '/'); 3245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu int end = cur; 3255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu cur--; // Skip before the last slash. 3265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 3275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu for (; cur >= 0; cur--) { 3285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (dir_string[cur] == '/') 3295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return base::StringPiece(&dir_string[cur + 1], end - cur - 1); 3305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 3315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return base::StringPiece(&dir_string[0], end); 3325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 3335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 334d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochbool EnsureStringIsInOutputDir(const SourceDir& dir, 335d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const std::string& str, 336d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const Value& originating, 337d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch Err* err) { 338d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // The last char of the dir will be a slash. We don't care if the input ends 339d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // in a slash or not, so just compare up until there. 340d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // 341d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // This check will be wrong for all proper prefixes "e.g. "/output" will 342d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // match "/out" but we don't really care since this is just a sanity check. 343d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const std::string& dir_str = dir.value(); 344d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (str.compare(0, dir_str.length() - 1, dir_str, 0, dir_str.length() - 1) 345d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch != 0) { 3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *err = Err(originating, "File is not inside output directory.", 347d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch "The given file should be in the output directory. Normally you would " 3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "specify\n\"$target_out_dir/foo\" or " 349d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch "\"$target_gen_dir/foo\". I interpreted this as\n\"" 350d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch + str + "\"."); 351d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return false; 352d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 353d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return true; 354d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 355d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 3563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool IsPathAbsolute(const base::StringPiece& path) { 3573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (path.empty()) 3583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return false; 3593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 360a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!IsSlash(path[0])) { 3613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#if defined(OS_WIN) 3623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Check for Windows system paths like "C:\foo". 363a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (path.size() > 2 && path[1] == ':' && IsSlash(path[2])) 3643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return true; 3653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#endif 3663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return false; // Doesn't begin with a slash, is relative. 3673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 3683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 369a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Double forward slash at the beginning means source-relative (we don't 370a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // allow backslashes for denoting this). 3713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (path.size() > 1 && path[1] == '/') 372a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return false; 3733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 3743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return true; 3753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 3763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 3773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool MakeAbsolutePathRelativeIfPossible(const base::StringPiece& source_root, 3783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const base::StringPiece& path, 3793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) std::string* dest) { 3803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DCHECK(IsPathAbsolute(source_root)); 3813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DCHECK(IsPathAbsolute(path)); 3823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 3833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) dest->clear(); 3843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 3853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (source_root.size() > path.size()) 3863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return false; // The source root is longer: the path can never be inside. 3873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 3883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#if defined(OS_WIN) 389a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Source root should be canonical on Windows. Note that the initial slash 390a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // must be forward slash, but that the other ones can be either forward or 391a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // backward. 3923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DCHECK(source_root.size() > 2 && source_root[0] != '/' && 393a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) source_root[1] == ':' && IsSlash(source_root[2])); 394424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 395424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) size_t after_common_index = std::string::npos; 396424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (DoesBeginWindowsDriveLetter(path)) { 397424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Handle "C:\foo" 398424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (AreAbsoluteWindowsPathsEqual(source_root, 399424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) path.substr(0, source_root.size()))) 400424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) after_common_index = source_root.size(); 401424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) else 402424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return false; 403424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } else if (path[0] == '/' && source_root.size() <= path.size() - 1 && 404424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) DoesBeginWindowsDriveLetter(path.substr(1))) { 405424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Handle "/C:/foo" 406424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (AreAbsoluteWindowsPathsEqual(source_root, 407424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) path.substr(1, source_root.size()))) 408424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) after_common_index = source_root.size() + 1; 409424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) else 410424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return false; 411424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } else { 412424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return false; 413424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 414424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 415424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // If we get here, there's a match and after_common_index identifies the 416424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // part after it. 417424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 418424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // The base may or may not have a trailing slash, so skip all slashes from 419424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // the path after our prefix match. 420424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) size_t first_after_slash = after_common_index; 421a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) while (first_after_slash < path.size() && IsSlash(path[first_after_slash])) 422424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) first_after_slash++; 423424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 424424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) dest->assign("//"); // Result is source root relative. 425424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) dest->append(&path.data()[first_after_slash], 426424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) path.size() - first_after_slash); 427424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return true; 428424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 4293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#else 430424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 4313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // On non-Windows this is easy. Since we know both are absolute, just do a 4323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // prefix check. 4333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (path.substr(0, source_root.size()) == source_root) { 4343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // The base may or may not have a trailing slash, so skip all slashes from 4353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // the path after our prefix match. 4363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) size_t first_after_slash = source_root.size(); 437a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) while (first_after_slash < path.size() && IsSlash(path[first_after_slash])) 4383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) first_after_slash++; 4393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 440424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) dest->assign("//"); // Result is source root relative. 4413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) dest->append(&path.data()[first_after_slash], 4423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) path.size() - first_after_slash); 4433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return true; 4443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 4453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return false; 446424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#endif 4473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 4483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 449d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochstd::string InvertDir(const SourceDir& path) { 450d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const std::string value = path.value(); 451d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (value.empty()) 452d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return std::string(); 453d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 454d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch DCHECK(value[0] == '/'); 455d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch size_t begin_index = 1; 456d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 457d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // If the input begins with two slashes, skip over both (this is a 458a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // source-relative dir). These must be forward slashes only. 459d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (value.size() > 1 && value[1] == '/') 460d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch begin_index = 2; 461d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 462d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch std::string ret; 463d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch for (size_t i = begin_index; i < value.size(); i++) { 464a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (IsSlash(value[i])) 465d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch ret.append("../"); 466d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 467d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return ret; 468d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 469d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 470d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochvoid NormalizePath(std::string* path) { 471d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch char* pathbuf = path->empty() ? NULL : &(*path)[0]; 472d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 473d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // top_index is the first character we can modify in the path. Anything 474d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // before this indicates where the path is relative to. 475d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch size_t top_index = 0; 476d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch bool is_relative = true; 477d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (!path->empty() && pathbuf[0] == '/') { 478d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch is_relative = false; 479d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 480d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (path->size() > 1 && pathbuf[1] == '/') { 481d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Two leading slashes, this is a path into the source dir. 482d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch top_index = 2; 483d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } else { 484d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // One leading slash, this is a system-absolute path. 485d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch top_index = 1; 486d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 487d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 488d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 489d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch size_t dest_i = top_index; 490d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch for (size_t src_i = top_index; src_i < path->size(); /* nothing */) { 491d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (pathbuf[src_i] == '.') { 492a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (src_i == 0 || IsSlash(pathbuf[src_i - 1])) { 493d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Slash followed by a dot, see if it's something special. 494d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch size_t consumed_len; 495d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch switch (ClassifyAfterDot(*path, src_i + 1, &consumed_len)) { 496d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch case NOT_A_DIRECTORY: 497d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Copy the dot to the output, it means nothing special. 498d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch pathbuf[dest_i++] = pathbuf[src_i++]; 499d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch break; 500d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch case DIRECTORY_CUR: 501d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Current directory, just skip the input. 502d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch src_i += consumed_len; 503d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch break; 504d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch case DIRECTORY_UP: 505d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Back up over previous directory component. If we're already 506d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // at the top, preserve the "..". 507d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (dest_i > top_index) { 508d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // The previous char was a slash, remove it. 509d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch dest_i--; 510d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 511d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 512d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (dest_i == top_index) { 513d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (is_relative) { 514d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // We're already at the beginning of a relative input, copy the 515d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // ".." and continue. We need the trailing slash if there was 516d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // one before (otherwise we're at the end of the input). 517d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch pathbuf[dest_i++] = '.'; 518d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch pathbuf[dest_i++] = '.'; 519d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (consumed_len == 3) 520d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch pathbuf[dest_i++] = '/'; 521d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 522d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // This also makes a new "root" that we can't delete by going 523d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // up more levels. Otherwise "../.." would collapse to 524d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // nothing. 525d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch top_index = dest_i; 526d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 527d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Otherwise we're at the beginning of an absolute path. Don't 528d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // allow ".." to go up another level and just eat it. 529d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } else { 530d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Just find the previous slash or the beginning of input. 531a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) while (dest_i > 0 && !IsSlash(pathbuf[dest_i - 1])) 532d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch dest_i--; 533d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 534d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch src_i += consumed_len; 535d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 536d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } else { 537d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Dot not preceeded by a slash, copy it literally. 538d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch pathbuf[dest_i++] = pathbuf[src_i++]; 539d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 540a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } else if (IsSlash(pathbuf[src_i])) { 541a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (src_i > 0 && IsSlash(pathbuf[src_i - 1])) { 542d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Two slashes in a row, skip over it. 543d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch src_i++; 544d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } else { 545a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Just one slash, copy it, normalizing to foward slash. 546a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) pathbuf[dest_i] = '/'; 547a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) dest_i++; 548a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) src_i++; 549d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 550d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } else { 551d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Input nothing special, just copy it. 552d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch pathbuf[dest_i++] = pathbuf[src_i++]; 553d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 554d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 555d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch path->resize(dest_i); 556d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 557d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 558d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochvoid ConvertPathToSystem(std::string* path) { 559d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#if defined(OS_WIN) 560d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch for (size_t i = 0; i < path->size(); i++) { 561d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if ((*path)[i] == '/') 562d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch (*path)[i] = '\\'; 563d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 564d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#endif 565d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 566d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 56768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)std::string RebaseSourceAbsolutePath(const std::string& input, 56868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const SourceDir& dest_dir) { 56968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) CHECK(input.size() >= 2 && input[0] == '/' && input[1] == '/') 57068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) << "Input to rebase isn't source-absolute: " << input; 57168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) CHECK(dest_dir.is_source_absolute()) 57268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) << "Dir to rebase to isn't source-absolute: " << dest_dir.value(); 57368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 57468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const std::string& dest = dest_dir.value(); 57568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 57668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // Skip the common prefixes of the source and dest as long as they end in 57768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // a [back]slash. 57868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) size_t common_prefix_len = 2; // The beginning two "//" are always the same. 57968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) size_t max_common_length = std::min(input.size(), dest.size()); 58068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) for (size_t i = common_prefix_len; i < max_common_length; i++) { 581a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (IsSlash(input[i]) && IsSlash(dest[i])) 58268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) common_prefix_len = i + 1; 58368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) else if (input[i] != dest[i]) 58468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) break; 58568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 58668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 58768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // Invert the dest dir starting from the end of the common prefix. 58868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) std::string ret; 58968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) for (size_t i = common_prefix_len; i < dest.size(); i++) { 590a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (IsSlash(dest[i])) 59168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ret.append("../"); 59268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 59368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 59468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // Append any remaining unique input. 59568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ret.append(&input[common_prefix_len], input.size() - common_prefix_len); 59668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 59768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // If the result is still empty, the paths are the same. 59868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (ret.empty()) 59968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ret.push_back('.'); 60068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 60168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return ret; 60268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 603f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 604f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)std::string DirectoryWithNoLastSlash(const SourceDir& dir) { 605f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::string ret; 606f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 607f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (dir.value().empty()) { 608f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Just keep input the same. 609f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } else if (dir.value() == "/") { 610f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ret.assign("/."); 611f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } else if (dir.value() == "//") { 612f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ret.assign("//."); 613f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } else { 614f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ret.assign(dir.value()); 615f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ret.resize(ret.size() - 1); 616f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 617f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return ret; 618f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 619f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 620a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)SourceDir SourceDirForPath(const base::FilePath& source_root, 621a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const base::FilePath& path) { 622a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::vector<base::FilePath::StringType> source_comp = 623a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) GetPathComponents(source_root); 624a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::vector<base::FilePath::StringType> path_comp = 625a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) GetPathComponents(path); 626a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 627a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // See if path is inside the source root by looking for each of source root's 628a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // components at the beginning of path. 629a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool is_inside_source; 630a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (path_comp.size() < source_comp.size()) { 631a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Too small to fit. 632a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) is_inside_source = false; 633a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } else { 634a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) is_inside_source = true; 635a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (size_t i = 0; i < source_comp.size(); i++) { 636a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!FilesystemStringsEqual(source_comp[i], path_comp[i])) { 637a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) is_inside_source = false; 638a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) break; 639a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 640a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 641a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 642a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 643a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::string result_str; 644a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) size_t initial_path_comp_to_use; 645a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (is_inside_source) { 646a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Construct a source-relative path beginning in // and skip all of the 647a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // shared directories. 648a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) result_str = "//"; 649a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) initial_path_comp_to_use = source_comp.size(); 650a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } else { 651a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Not inside source code, construct a system-absolute path. 652a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) result_str = "/"; 653a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) initial_path_comp_to_use = 0; 654a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 655a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 656a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (size_t i = initial_path_comp_to_use; i < path_comp.size(); i++) { 657a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) result_str.append(FilePathToUTF8(path_comp[i])); 658a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) result_str.push_back('/'); 659a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 660a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return SourceDir(result_str); 661a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 662a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 663a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)SourceDir SourceDirForCurrentDirectory(const base::FilePath& source_root) { 664a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::FilePath cd; 665a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::GetCurrentDirectory(&cd); 666a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return SourceDirForPath(source_root, cd); 667a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 668a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 669cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)std::string GetOutputSubdirName(const Label& toolchain_label, bool is_default) { 670cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // The default toolchain has no subdir. 671cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (is_default) 672cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return std::string(); 673cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 674cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // For now just assume the toolchain name is always a valid dir name. We may 675cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // want to clean up the in the future. 676cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return toolchain_label.name() + "/"; 677cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 678cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 679f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)SourceDir GetToolchainOutputDir(const Settings* settings) { 680f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const OutputFile& toolchain_subdir = settings->toolchain_output_subdir(); 681f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 682f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::string result = settings->build_settings()->build_dir().value(); 683f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!toolchain_subdir.value().empty()) 684f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) result.append(toolchain_subdir.value()); 685f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 686f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return SourceDir(SourceDir::SWAP_IN, &result); 687f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 688f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 689cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)SourceDir GetToolchainOutputDir(const BuildSettings* build_settings, 690cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const Label& toolchain_label, bool is_default) { 691cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::string result = build_settings->build_dir().value(); 692cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) result.append(GetOutputSubdirName(toolchain_label, is_default)); 693cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return SourceDir(SourceDir::SWAP_IN, &result); 694cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 695cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 696f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)SourceDir GetToolchainGenDir(const Settings* settings) { 697f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const OutputFile& toolchain_subdir = settings->toolchain_output_subdir(); 698f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 699f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::string result = settings->build_settings()->build_dir().value(); 700f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!toolchain_subdir.value().empty()) 701f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) result.append(toolchain_subdir.value()); 702f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 703f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) result.append("gen/"); 704f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return SourceDir(SourceDir::SWAP_IN, &result); 705f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 706f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 707cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)SourceDir GetToolchainGenDir(const BuildSettings* build_settings, 708cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const Label& toolchain_label, bool is_default) { 709cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::string result = GetToolchainOutputDir( 710cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) build_settings, toolchain_label, is_default).value(); 711cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) result.append("gen/"); 712cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return SourceDir(SourceDir::SWAP_IN, &result); 713cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 714cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 715f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)SourceDir GetOutputDirForSourceDir(const Settings* settings, 716f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const SourceDir& source_dir) { 717f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SourceDir toolchain = GetToolchainOutputDir(settings); 718f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 719f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::string ret; 720f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) toolchain.SwapValue(&ret); 721f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ret.append("obj/"); 722f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 7236d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (source_dir.is_source_absolute()) { 7246d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) // The source dir is source-absolute, so we trim off the two leading 7256d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) // slashes to append to the toolchain object directory. 7266d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) ret.append(&source_dir.value()[2], source_dir.value().size() - 2); 7276d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } 7286d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) // (Put system-absolute stuff in the root obj directory.) 729f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 730f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return SourceDir(SourceDir::SWAP_IN, &ret); 731f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 732f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 733f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)SourceDir GetGenDirForSourceDir(const Settings* settings, 734f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const SourceDir& source_dir) { 735f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SourceDir toolchain = GetToolchainGenDir(settings); 736f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 737f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::string ret; 738f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) toolchain.SwapValue(&ret); 739f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 7406d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (source_dir.is_source_absolute()) { 7416d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) // The source dir should be source-absolute, so we trim off the two leading 7426d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) // slashes to append to the toolchain object directory. 7436d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) DCHECK(source_dir.is_source_absolute()); 7446d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) ret.append(&source_dir.value()[2], source_dir.value().size() - 2); 7456d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } 7466d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) // (Put system-absolute stuff in the root gen directory.) 747f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 748f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return SourceDir(SourceDir::SWAP_IN, &ret); 749f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 750f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 751f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)SourceDir GetTargetOutputDir(const Target* target) { 752f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return GetOutputDirForSourceDir(target->settings(), target->label().dir()); 753f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 754f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 755f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)SourceDir GetTargetGenDir(const Target* target) { 756f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return GetGenDirForSourceDir(target->settings(), target->label().dir()); 757f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 758f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 759f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)SourceDir GetCurrentOutputDir(const Scope* scope) { 760f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return GetOutputDirForSourceDir(scope->settings(), scope->GetSourceDir()); 761f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 762f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 763f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)SourceDir GetCurrentGenDir(const Scope* scope) { 764f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return GetGenDirForSourceDir(scope->settings(), scope->GetSourceDir()); 765f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 766