Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "tools/gn/filesystem_utils.h" | 5 #include "tools/gn/filesystem_utils.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/file_util.h" | |
| 9 #include "base/logging.h" | 10 #include "base/logging.h" |
| 10 #include "base/strings/string_util.h" | 11 #include "base/strings/string_util.h" |
| 11 #include "base/strings/utf_string_conversions.h" | 12 #include "base/strings/utf_string_conversions.h" |
| 12 #include "build/build_config.h" | 13 #include "build/build_config.h" |
| 13 #include "tools/gn/location.h" | 14 #include "tools/gn/location.h" |
| 14 #include "tools/gn/settings.h" | 15 #include "tools/gn/settings.h" |
| 15 #include "tools/gn/source_dir.h" | 16 #include "tools/gn/source_dir.h" |
| 16 | 17 |
| 17 namespace { | 18 namespace { |
| 18 | 19 |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 102 if (!((path[0] >= 'A' && path[0] <= 'Z') || | 103 if (!((path[0] >= 'A' && path[0] <= 'Z') || |
| 103 path[0] >= 'a' && path[0] <= 'z')) | 104 path[0] >= 'a' && path[0] <= 'z')) |
| 104 return false; | 105 return false; |
| 105 | 106 |
| 106 if (path[2] != '/' && path[2] != '\\') | 107 if (path[2] != '/' && path[2] != '\\') |
| 107 return false; | 108 return false; |
| 108 return true; | 109 return true; |
| 109 } | 110 } |
| 110 #endif | 111 #endif |
| 111 | 112 |
| 113 // A wrapper around FilePath.GetComponents that works the way we need. This is | |
| 114 // not super efficient since it does some O9n) transformations on the path. If | |
|
Dirk Pranke
2014/02/18 19:22:35
typo: O9n) -> O(n)
| |
| 115 // this is called a lot, we might want to optimize. | |
| 116 std::vector<base::FilePath::StringType> GetPathComponents( | |
| 117 const base::FilePath& path) { | |
| 118 std::vector<base::FilePath::StringType> result; | |
| 119 path.GetComponents(&result); | |
| 120 | |
| 121 if (result.empty()) | |
| 122 return result; | |
| 123 | |
| 124 // GetComponents will preserve the "/" at the beginning, which confuses us. | |
| 125 // We don't expect to have relative paths in this function. | |
| 126 // Don't use IsSeparator since we always want to allow backslashes. | |
| 127 if (result[0] == FILE_PATH_LITERAL("/") || | |
| 128 result[0] == FILE_PATH_LITERAL("\\")) | |
| 129 result.erase(result.begin()); | |
| 130 | |
| 131 #if defined(OS_WIN) | |
| 132 // On Windows, GetComponents will give us [ "C:", "/", "foo" ], and we | |
| 133 // don't want the slash in there. This doesn't support input like "C:foo" | |
| 134 // which means foo relative to the current directory of the C drive but | |
| 135 // that's basically legacy DOS behavior we don't need to support. | |
| 136 if (result.size() >= 2 && result[1] == L"/" || result[1] == L"\\") | |
| 137 result.erase(result.begin() + 1); | |
| 138 #endif | |
| 139 | |
| 140 return result; | |
| 141 } | |
| 142 | |
| 143 // Provides the equivalent of == for filesystem strings, trying to do | |
| 144 // approximately the right thing with case. | |
| 145 bool FilesystemStringsEqual(const base::FilePath::StringType& a, | |
| 146 const base::FilePath::StringType& b) { | |
| 147 #if defined(OS_WIN) | |
| 148 // Assume case-insesitive filesystems on Windows. We use the CompareString | |
|
Dirk Pranke
2014/02/18 19:22:35
typo: case-insesitive -> case-insensitive.
| |
| 149 // function to do a case-insensitive comparison based on the current locale | |
| 150 // (we don't want GN to depend on ICU which is large and requires data | |
| 151 // files). This isn't perfect, but getting this perfectly right is very | |
| 152 // difficult and requires I/O, and this comparison should cover 99.9999% of | |
| 153 // all cases. | |
| 154 // | |
| 155 // Note: The documentation for CompareString says it runs fastest on | |
| 156 // null-terminated strings with -1 passed for the length, so we do that here. | |
| 157 // There should not be embedded nulls in filesystem strings. | |
| 158 return ::CompareString(LOCALE_USER_DEFAULT, LINGUISTIC_IGNORECASE, | |
| 159 a.c_str(), -1, b.c_str(), -1) == CSTR_EQUAL; | |
| 160 #else | |
| 161 // Assume case-sensitive filesystems on non-Windows. | |
| 162 return a == b; | |
|
Dirk Pranke
2014/02/18 19:22:35
isn't Mac also case-insensitive by default? (thoug
brettw
2014/02/18 20:22:46
Hey, I didn't even know that. Let's see if we can
| |
| 163 #endif | |
| 164 } | |
| 165 | |
| 112 } // namespace | 166 } // namespace |
| 113 | 167 |
| 114 SourceFileType GetSourceFileType(const SourceFile& file, | 168 SourceFileType GetSourceFileType(const SourceFile& file, |
| 115 Settings::TargetOS os) { | 169 Settings::TargetOS os) { |
| 116 base::StringPiece extension = FindExtension(&file.value()); | 170 base::StringPiece extension = FindExtension(&file.value()); |
| 117 if (extension == "cc" || extension == "cpp" || extension == "cxx") | 171 if (extension == "cc" || extension == "cpp" || extension == "cxx") |
| 118 return SOURCE_CC; | 172 return SOURCE_CC; |
| 119 if (extension == "h") | 173 if (extension == "h") |
| 120 return SOURCE_H; | 174 return SOURCE_H; |
| 121 if (extension == "c") | 175 if (extension == "c") |
| (...skipping 435 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 557 ret.assign("/."); | 611 ret.assign("/."); |
| 558 } else if (dir.value() == "//") { | 612 } else if (dir.value() == "//") { |
| 559 ret.assign("//."); | 613 ret.assign("//."); |
| 560 } else { | 614 } else { |
| 561 ret.assign(dir.value()); | 615 ret.assign(dir.value()); |
| 562 ret.resize(ret.size() - 1); | 616 ret.resize(ret.size() - 1); |
| 563 } | 617 } |
| 564 return ret; | 618 return ret; |
| 565 } | 619 } |
| 566 | 620 |
| 621 SourceDir SourceDirForPath(const base::FilePath& source_root, | |
| 622 const base::FilePath& path) { | |
| 623 std::vector<base::FilePath::StringType> source_comp = | |
| 624 GetPathComponents(source_root); | |
| 625 std::vector<base::FilePath::StringType> path_comp = | |
| 626 GetPathComponents(path); | |
| 627 | |
| 628 // See if path is inside the source root by looking for each of source root's | |
| 629 // components at the beginning of path. | |
| 630 bool is_inside_source; | |
| 631 if (path_comp.size() < source_comp.size()) { | |
| 632 // Too small to fit. | |
| 633 is_inside_source = false; | |
| 634 } else { | |
| 635 is_inside_source = true; | |
| 636 for (size_t i = 0; i < source_comp.size(); i++) { | |
| 637 if (!FilesystemStringsEqual(source_comp[i], path_comp[i])) { | |
| 638 is_inside_source = false; | |
| 639 break; | |
| 640 } | |
| 641 } | |
| 642 } | |
| 643 | |
| 644 std::string result_str; | |
| 645 size_t initial_path_comp_to_use; | |
| 646 if (is_inside_source) { | |
| 647 // Construct a source-relative path beginning in // and skip all of the | |
| 648 // shared directories. | |
| 649 result_str = "//"; | |
| 650 initial_path_comp_to_use = source_comp.size(); | |
| 651 } else { | |
| 652 // Not inside source code, construct a system-absolute path. | |
| 653 result_str = "/"; | |
| 654 initial_path_comp_to_use = 0; | |
| 655 } | |
| 656 | |
| 657 for (size_t i = initial_path_comp_to_use; i < path_comp.size(); i++) { | |
| 658 result_str.append(FilePathToUTF8(path_comp[i])); | |
| 659 result_str.push_back('/'); | |
| 660 } | |
| 661 return SourceDir(result_str); | |
| 662 } | |
| 663 | |
| 664 SourceDir SourceDirForCurrentDirectory(const base::FilePath& source_root) { | |
| 665 base::FilePath cd; | |
| 666 file_util::GetCurrentDirectory(&cd); | |
| 667 return SourceDirForPath(source_root, cd); | |
| 668 } | |
| 669 | |
| 567 SourceDir GetToolchainOutputDir(const Settings* settings) { | 670 SourceDir GetToolchainOutputDir(const Settings* settings) { |
| 568 const OutputFile& toolchain_subdir = settings->toolchain_output_subdir(); | 671 const OutputFile& toolchain_subdir = settings->toolchain_output_subdir(); |
| 569 | 672 |
| 570 std::string result = settings->build_settings()->build_dir().value(); | 673 std::string result = settings->build_settings()->build_dir().value(); |
| 571 if (!toolchain_subdir.value().empty()) | 674 if (!toolchain_subdir.value().empty()) |
| 572 result.append(toolchain_subdir.value()); | 675 result.append(toolchain_subdir.value()); |
| 573 | 676 |
| 574 return SourceDir(SourceDir::SWAP_IN, &result); | 677 return SourceDir(SourceDir::SWAP_IN, &result); |
| 575 } | 678 } |
| 576 | 679 |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 624 return GetGenDirForSourceDir(target->settings(), target->label().dir()); | 727 return GetGenDirForSourceDir(target->settings(), target->label().dir()); |
| 625 } | 728 } |
| 626 | 729 |
| 627 SourceDir GetCurrentOutputDir(const Scope* scope) { | 730 SourceDir GetCurrentOutputDir(const Scope* scope) { |
| 628 return GetOutputDirForSourceDir(scope->settings(), scope->GetSourceDir()); | 731 return GetOutputDirForSourceDir(scope->settings(), scope->GetSourceDir()); |
| 629 } | 732 } |
| 630 | 733 |
| 631 SourceDir GetCurrentGenDir(const Scope* scope) { | 734 SourceDir GetCurrentGenDir(const Scope* scope) { |
| 632 return GetGenDirForSourceDir(scope->settings(), scope->GetSourceDir()); | 735 return GetGenDirForSourceDir(scope->settings(), scope->GetSourceDir()); |
| 633 } | 736 } |
| OLD | NEW |