Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(113)

Side by Side Diff: tools/gn/filesystem_utils.cc

Issue 165823003: GN: Change gen command syntax, support relative dirs. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Change in build file writing Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698