Limit the set of Visual Studio projects generated by GN BUG=589099 Review URL: https://codereview.chromium.org/1718093006 Cr-Original-Commit-Position: refs/heads/master@{#377871} Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src Cr-Mirrored-Commit: 014e81d144453d840e09eb9695b0dee262bc3507
diff --git a/tools/gn/command_gen.cc b/tools/gn/command_gen.cc index b5ffc14..fee3f1a 100644 --- a/tools/gn/command_gen.cc +++ b/tools/gn/command_gen.cc
@@ -26,11 +26,13 @@ namespace { const char kSwitchCheck[] = "check"; +const char kSwitchFilters[] = "filters"; const char kSwitchIde[] = "ide"; const char kSwitchIdeValueEclipse[] = "eclipse"; const char kSwitchIdeValueVs[] = "vs"; const char kSwitchIdeValueVs2013[] = "vs2013"; const char kSwitchIdeValueVs2015[] = "vs2015"; +const char kSwitchSln[] = "sln"; // Called on worker thread to write the ninja file. void BackgroundDoWrite(const Target* target) { @@ -155,11 +157,13 @@ const BuildSettings* build_settings, Builder* builder, Err* err) { + const base::CommandLine* command_line = + base::CommandLine::ForCurrentProcess(); base::ElapsedTimer timer; + if (ide == kSwitchIdeValueEclipse) { bool res = EclipseWriter::RunAndWriteFile(build_settings, builder, err); - if (res && - !base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kQuiet)) { + if (res && !command_line->HasSwitch(switches::kQuiet)) { OutputString("Generating Eclipse settings took " + base::Int64ToString(timer.Elapsed().InMilliseconds()) + "ms\n"); @@ -170,10 +174,15 @@ VisualStudioWriter::Version version = ide == kSwitchIdeValueVs2013 ? VisualStudioWriter::Version::Vs2013 : VisualStudioWriter::Version::Vs2015; - bool res = VisualStudioWriter::RunAndWriteFiles(build_settings, builder, - version, err); - if (res && - !base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kQuiet)) { + std::string sln_name; + if (command_line->HasSwitch(kSwitchSln)) + sln_name = command_line->GetSwitchValueASCII(kSwitchSln); + std::string filters; + if (command_line->HasSwitch(kSwitchFilters)) + filters = command_line->GetSwitchValueASCII(kSwitchFilters); + bool res = VisualStudioWriter::RunAndWriteFiles( + build_settings, builder, version, sln_name, filters, err); + if (res && !command_line->HasSwitch(switches::kQuiet)) { OutputString("Generating Visual Studio projects took " + base::Int64ToString(timer.Elapsed().InMilliseconds()) + "ms\n"); @@ -193,7 +202,7 @@ const char kGen_Help[] = "gn gen: Generate ninja files.\n" "\n" - " gn gen [--ide=<ide_name>] <out_dir>\n" + " gn gen [<ide options>] <out_dir>\n" "\n" " Generates ninja files from the current tree and puts them in the given\n" " output directory.\n" @@ -203,15 +212,29 @@ " Or it can be a directory relative to the current directory such as:\n" " out/foo\n" "\n" + " See \"gn help switches\" for the common command-line switches.\n" + "\n" + "IDE options\n" + "\n" + " GN optionally generates files for IDE. Possibilities for <ide options>\n" + "\n" " --ide=<ide_name>\n" - " Also generate files for an IDE. Currently supported values:\n" + " Generate files for an IDE. Currently supported values:\n" " \"eclipse\" - Eclipse CDT settings file.\n" " \"vs\" - Visual Studio project/solution files.\n" " (default Visual Studio version: 2015)\n" " \"vs2013\" - Visual Studio 2013 project/solution files.\n" " \"vs2015\" - Visual Studio 2015 project/solution files.\n" "\n" - " See \"gn help switches\" for the common command-line switches.\n" + " --sln=<file_name>\n" + " Override default sln file name (\"all\"). Solution file is written\n" + " to the root build directory. Only for Visual Studio.\n" + "\n" + " --filters=<path_prefixes>\n" + " Semicolon-separated list of label patterns used to limit the set\n" + " of generated projects (see \"gn help label_pattern\"). Only\n" + " matching targets will be included to the solution. Only for Visual\n" + " Studio.\n" "\n" "Eclipse IDE Support\n" "\n"
diff --git a/tools/gn/visual_studio_writer.cc b/tools/gn/visual_studio_writer.cc index 6c364b3..54a7bf2 100644 --- a/tools/gn/visual_studio_writer.cc +++ b/tools/gn/visual_studio_writer.cc
@@ -11,12 +11,15 @@ #include "base/logging.h" #include "base/memory/scoped_ptr.h" +#include "base/strings/string_split.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "tools/gn/builder.h" +#include "tools/gn/commands.h" #include "tools/gn/config.h" #include "tools/gn/config_values_extractors.h" #include "tools/gn/filesystem_utils.h" +#include "tools/gn/label_pattern.h" #include "tools/gn/parse_tree.h" #include "tools/gn/path_output.h" #include "tools/gn/source_file_type.h" @@ -214,8 +217,30 @@ bool VisualStudioWriter::RunAndWriteFiles(const BuildSettings* build_settings, Builder* builder, Version version, + const std::string& sln_name, + const std::string& dir_filters, Err* err) { - std::vector<const Target*> targets = builder->GetAllResolvedTargets(); + std::vector<const Target*> targets; + if (dir_filters.empty()) { + targets = builder->GetAllResolvedTargets(); + } else { + std::vector<std::string> tokens = base::SplitString( + dir_filters, ";", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); + SourceDir root_dir = + SourceDirForCurrentDirectory(build_settings->root_path()); + + std::vector<LabelPattern> filters; + for (const std::string& token : tokens) { + LabelPattern pattern = + LabelPattern::GetPattern(root_dir, Value(nullptr, token), err); + if (err->has_error()) + return false; + filters.push_back(pattern); + } + + commands::FilterTargetsByPatterns(builder->GetAllResolvedTargets(), filters, + &targets); + } const char* config_platform = "Win32"; @@ -259,7 +284,7 @@ }); writer.ResolveSolutionFolders(); - return writer.WriteSolutionFile(err); + return writer.WriteSolutionFile(sln_name, err); } bool VisualStudioWriter::WriteProjectFiles(const Target* target, Err* err) { @@ -590,9 +615,11 @@ project.Text(files_out.str()); } -bool VisualStudioWriter::WriteSolutionFile(Err* err) { +bool VisualStudioWriter::WriteSolutionFile(const std::string& sln_name, + Err* err) { + std::string name = sln_name.empty() ? "all" : sln_name; SourceFile sln_file = build_settings_->build_dir().ResolveRelativeFile( - Value(nullptr, "all.sln"), err); + Value(nullptr, name + ".sln"), err); if (sln_file.is_null()) return false; @@ -704,7 +731,8 @@ else if (root_folder_path_[i] != folder_path[i]) break; } - if (i == max_common_length) + if (i == max_common_length && + (i == folder_path.size() || IsSlash(folder_path[i]))) common_prefix_len = max_common_length; if (common_prefix_len < root_folder_path_.size()) { if (IsSlash(root_folder_path_[common_prefix_len - 1]))
diff --git a/tools/gn/visual_studio_writer.h b/tools/gn/visual_studio_writer.h index 6950dd6..5b578ed 100644 --- a/tools/gn/visual_studio_writer.h +++ b/tools/gn/visual_studio_writer.h
@@ -29,10 +29,16 @@ Vs2015 // Visual Studio 2015 }; - // On failure will populate |err| and will return false. + // Writes Visual Studio project and solution files. |sln_name| is the optional + // solution file name ("all" is used if not specified). |dir_filters| is + // optional semicolon-separated list of label patterns used to limit the set + // of generated projects. Only matching targets will be included to the + // solution. On failure will populate |err| and will return false. static bool RunAndWriteFiles(const BuildSettings* build_settings, Builder* builder, Version version, + const std::string& sln_name, + const std::string& dir_filters, Err* err); private: @@ -74,9 +80,9 @@ using SolutionProjects = std::vector<SolutionProject*>; using SolutionFolders = std::vector<SolutionEntry*>; - explicit VisualStudioWriter(const BuildSettings* build_settings, - const char* config_platform, - Version version); + VisualStudioWriter(const BuildSettings* build_settings, + const char* config_platform, + Version version); ~VisualStudioWriter(); bool WriteProjectFiles(const Target* target, Err* err); @@ -85,7 +91,7 @@ const Target* target, Err* err); void WriteFiltersFileContents(std::ostream& out, const Target* target); - bool WriteSolutionFile(Err* err); + bool WriteSolutionFile(const std::string& sln_name, Err* err); void WriteSolutionFileContents(std::ostream& out, const base::FilePath& solution_dir_path);