OLD | NEW |
---|---|
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/visual_studio_writer.h" | 5 #include "tools/gn/visual_studio_writer.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <map> | 8 #include <map> |
9 #include <set> | 9 #include <set> |
10 #include <string> | 10 #include <string> |
11 | 11 |
12 #include "base/logging.h" | 12 #include "base/logging.h" |
13 #include "base/memory/scoped_ptr.h" | 13 #include "base/memory/scoped_ptr.h" |
14 #include "base/strings/string_split.h" | |
14 #include "base/strings/string_util.h" | 15 #include "base/strings/string_util.h" |
15 #include "base/strings/utf_string_conversions.h" | 16 #include "base/strings/utf_string_conversions.h" |
16 #include "tools/gn/builder.h" | 17 #include "tools/gn/builder.h" |
17 #include "tools/gn/config.h" | 18 #include "tools/gn/config.h" |
18 #include "tools/gn/config_values_extractors.h" | 19 #include "tools/gn/config_values_extractors.h" |
19 #include "tools/gn/filesystem_utils.h" | 20 #include "tools/gn/filesystem_utils.h" |
20 #include "tools/gn/parse_tree.h" | 21 #include "tools/gn/parse_tree.h" |
21 #include "tools/gn/path_output.h" | 22 #include "tools/gn/path_output.h" |
22 #include "tools/gn/source_file_type.h" | 23 #include "tools/gn/source_file_type.h" |
23 #include "tools/gn/standard_out.h" | 24 #include "tools/gn/standard_out.h" |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
207 | 208 |
208 VisualStudioWriter::~VisualStudioWriter() { | 209 VisualStudioWriter::~VisualStudioWriter() { |
209 STLDeleteContainerPointers(projects_.begin(), projects_.end()); | 210 STLDeleteContainerPointers(projects_.begin(), projects_.end()); |
210 STLDeleteContainerPointers(folders_.begin(), folders_.end()); | 211 STLDeleteContainerPointers(folders_.begin(), folders_.end()); |
211 } | 212 } |
212 | 213 |
213 // static | 214 // static |
214 bool VisualStudioWriter::RunAndWriteFiles(const BuildSettings* build_settings, | 215 bool VisualStudioWriter::RunAndWriteFiles(const BuildSettings* build_settings, |
215 Builder* builder, | 216 Builder* builder, |
216 Version version, | 217 Version version, |
218 const std::string& sln_name, | |
219 const std::string& dir_filters, | |
217 Err* err) { | 220 Err* err) { |
218 std::vector<const Target*> targets = builder->GetAllResolvedTargets(); | 221 std::vector<const Target*> targets = builder->GetAllResolvedTargets(); |
219 | 222 |
220 VisualStudioWriter writer(build_settings, version); | 223 VisualStudioWriter writer(build_settings, version); |
221 writer.projects_.reserve(targets.size()); | 224 writer.projects_.reserve(targets.size()); |
222 writer.folders_.reserve(targets.size()); | 225 writer.folders_.reserve(targets.size()); |
223 | 226 |
227 std::vector<std::string> filters; | |
228 if (!dir_filters.empty()) { | |
229 filters = base::SplitString(dir_filters, ";", base::TRIM_WHITESPACE, | |
230 base::SPLIT_WANT_NONEMPTY); | |
231 | |
232 // Git Bash and other MSYS shells convert POSIX paths before passing them to | |
233 // native Windows programs. Leading slash is trimmed in paths like | |
234 // "//chrome" or "/c:/foo" making them "/chrome" and "c:/foo". Convert such | |
235 // paths back to GN format so filters can be compared to other GN paths. | |
236 // See: http://www.mingw.org/wiki/Posix_path_conversion | |
237 for (std::string& filter : filters) { | |
238 if (filter.size() > 1 && | |
239 (filter[0] == '/' && | |
brettw
2016/02/24 22:11:26
This seems complicated and isn't something we do a
Tomasz Moniuszko
2016/02/25 13:28:20
Many thanks for this hint. I was thinking about us
| |
240 !(filter[1] == '/' || | |
241 filter.size() > 2 && base::IsAsciiAlpha(filter[1]) && | |
242 filter[2] == ':') || | |
243 base::IsAsciiAlpha(filter[0]) && filter[1] == ':')) | |
244 filter = '/' + filter; | |
245 } | |
246 } | |
247 | |
224 for (const Target* target : targets) { | 248 for (const Target* target : targets) { |
225 // Skip actions and groups. | 249 // Skip actions and groups. |
226 if (target->output_type() == Target::GROUP || | 250 if (target->output_type() == Target::GROUP || |
227 target->output_type() == Target::COPY_FILES || | 251 target->output_type() == Target::COPY_FILES || |
228 target->output_type() == Target::ACTION || | 252 target->output_type() == Target::ACTION || |
229 target->output_type() == Target::ACTION_FOREACH) { | 253 target->output_type() == Target::ACTION_FOREACH) { |
230 continue; | 254 continue; |
231 } | 255 } |
232 | 256 |
257 if (!filters.empty()) { | |
258 bool exclude = true; | |
259 for (const std::string& filter : filters) { | |
260 if (base::StartsWith(target->label().dir().value(), filter, | |
261 base::CompareCase::SENSITIVE)) { | |
262 exclude = false; | |
263 break; | |
264 } | |
265 } | |
266 if (exclude) | |
267 continue; | |
268 } | |
269 | |
233 if (!writer.WriteProjectFiles(target, err)) | 270 if (!writer.WriteProjectFiles(target, err)) |
234 return false; | 271 return false; |
235 } | 272 } |
236 | 273 |
237 if (writer.projects_.empty()) { | 274 if (writer.projects_.empty()) { |
238 *err = Err(Location(), "No Visual Studio projects generated."); | 275 *err = Err(Location(), "No Visual Studio projects generated."); |
239 return false; | 276 return false; |
240 } | 277 } |
241 | 278 |
242 // Sort projects so they appear always in the same order in solution file. | 279 // Sort projects so they appear always in the same order in solution file. |
243 // Otherwise solution file is rewritten and reloaded by Visual Studio. | 280 // Otherwise solution file is rewritten and reloaded by Visual Studio. |
244 std::sort(writer.projects_.begin(), writer.projects_.end(), | 281 std::sort(writer.projects_.begin(), writer.projects_.end(), |
245 [](const SolutionEntry* a, const SolutionEntry* b) { | 282 [](const SolutionEntry* a, const SolutionEntry* b) { |
246 return a->path < b->path; | 283 return a->path < b->path; |
247 }); | 284 }); |
248 | 285 |
249 writer.ResolveSolutionFolders(); | 286 writer.ResolveSolutionFolders(); |
250 return writer.WriteSolutionFile(err); | 287 return writer.WriteSolutionFile(sln_name, err); |
251 } | 288 } |
252 | 289 |
253 bool VisualStudioWriter::WriteProjectFiles(const Target* target, Err* err) { | 290 bool VisualStudioWriter::WriteProjectFiles(const Target* target, Err* err) { |
254 std::string project_name = target->label().name(); | 291 std::string project_name = target->label().name(); |
255 std::string project_config_platform = config_platform_; | 292 std::string project_config_platform = config_platform_; |
256 if (!target->settings()->is_default()) { | 293 if (!target->settings()->is_default()) { |
257 project_name += "_" + target->toolchain()->label().name(); | 294 project_name += "_" + target->toolchain()->label().name(); |
258 project_config_platform = target->toolchain() | 295 project_config_platform = target->toolchain() |
259 ->settings() | 296 ->settings() |
260 ->build_settings() | 297 ->build_settings() |
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
572 } | 609 } |
573 cl_item->SubElement("Filter")->Text(filter_path); | 610 cl_item->SubElement("Filter")->Text(filter_path); |
574 } | 611 } |
575 } | 612 } |
576 } | 613 } |
577 } | 614 } |
578 | 615 |
579 project.Text(files_out.str()); | 616 project.Text(files_out.str()); |
580 } | 617 } |
581 | 618 |
582 bool VisualStudioWriter::WriteSolutionFile(Err* err) { | 619 bool VisualStudioWriter::WriteSolutionFile(const std::string& sln_name, |
620 Err* err) { | |
621 std::string name = sln_name.empty() ? "all" : sln_name; | |
583 SourceFile sln_file = build_settings_->build_dir().ResolveRelativeFile( | 622 SourceFile sln_file = build_settings_->build_dir().ResolveRelativeFile( |
584 Value(nullptr, "all.sln"), err); | 623 Value(nullptr, name + ".sln"), err); |
585 if (sln_file.is_null()) | 624 if (sln_file.is_null()) |
586 return false; | 625 return false; |
587 | 626 |
588 base::FilePath sln_path = build_settings_->GetFullPath(sln_file); | 627 base::FilePath sln_path = build_settings_->GetFullPath(sln_file); |
589 | 628 |
590 std::stringstream string_out; | 629 std::stringstream string_out; |
591 WriteSolutionFileContents(string_out, sln_path.DirName()); | 630 WriteSolutionFileContents(string_out, sln_path.DirName()); |
592 | 631 |
593 // Only write the content to the file if it's different. That is | 632 // Only write the content to the file if it's different. That is |
594 // both a performance optimization and more importantly, prevents | 633 // both a performance optimization and more importantly, prevents |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
687 size_t common_prefix_len = 0; | 726 size_t common_prefix_len = 0; |
688 size_t max_common_length = | 727 size_t max_common_length = |
689 std::min(root_folder_path_.size(), folder_path.size()); | 728 std::min(root_folder_path_.size(), folder_path.size()); |
690 size_t i; | 729 size_t i; |
691 for (i = common_prefix_len; i < max_common_length; ++i) { | 730 for (i = common_prefix_len; i < max_common_length; ++i) { |
692 if (IsSlash(root_folder_path_[i]) && IsSlash(folder_path[i])) | 731 if (IsSlash(root_folder_path_[i]) && IsSlash(folder_path[i])) |
693 common_prefix_len = i + 1; | 732 common_prefix_len = i + 1; |
694 else if (root_folder_path_[i] != folder_path[i]) | 733 else if (root_folder_path_[i] != folder_path[i]) |
695 break; | 734 break; |
696 } | 735 } |
697 if (i == max_common_length) | 736 if (i == max_common_length && |
737 (i == folder_path.size() || IsSlash(folder_path[i]))) | |
698 common_prefix_len = max_common_length; | 738 common_prefix_len = max_common_length; |
699 if (common_prefix_len < root_folder_path_.size()) { | 739 if (common_prefix_len < root_folder_path_.size()) { |
700 if (IsSlash(root_folder_path_[common_prefix_len - 1])) | 740 if (IsSlash(root_folder_path_[common_prefix_len - 1])) |
701 --common_prefix_len; | 741 --common_prefix_len; |
702 root_folder_path_ = root_folder_path_.substr(0, common_prefix_len); | 742 root_folder_path_ = root_folder_path_.substr(0, common_prefix_len); |
703 } | 743 } |
704 } | 744 } |
705 } | 745 } |
706 } | 746 } |
707 | 747 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
744 base::CompareCase::SENSITIVE)) { | 784 base::CompareCase::SENSITIVE)) { |
745 folder->parent_folder = parents.back(); | 785 folder->parent_folder = parents.back(); |
746 break; | 786 break; |
747 } else { | 787 } else { |
748 parents.pop_back(); | 788 parents.pop_back(); |
749 } | 789 } |
750 } | 790 } |
751 parents.push_back(folder); | 791 parents.push_back(folder); |
752 } | 792 } |
753 } | 793 } |
OLD | NEW |