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 3 // found in the LICENSE file. 4 5 #ifndef TOOLS_GN_ANALYZER_H_ 6 #define TOOLS_GN_ANALYZER_H_ 7 8 #include <set> 9 #include <string> 10 #include <vector> 11 12 #include "gn/builder.h" 13 #include "gn/item.h" 14 #include "gn/label.h" 15 #include "gn/source_file.h" 16 17 // An Analyzer can answer questions about a build graph. It is used 18 // to answer queries for the `refs` and `analyze` commands, where we 19 // need to look at the graph in ways that can't easily be determined 20 // from just a single Target. 21 class Analyzer { 22 public: 23 Analyzer(const Builder& builder, 24 const SourceFile& build_config_file, 25 const SourceFile& dot_file, 26 const SourceFileSet& build_args_dependency_files); 27 ~Analyzer(); 28 29 // Figures out from a Buider and a JSON-formatted string containing lists 30 // of files and targets, which targets would be affected by modifications 31 // to the files . See the help text for the analyze command (kAnalyze_Help) 32 // for the specification of the input and output string formats and the 33 // expected behavior of the method. 34 std::string Analyze(const std::string& input, Err* err) const; 35 36 private: 37 // Returns the set of all items that might be affected, directly or 38 // indirectly, by modifications to the given source files. 39 std::set<const Item*> GetAllAffectedItems( 40 const std::set<const SourceFile*>& source_files) const; 41 42 // Returns the set of labels that do not refer to objects in the graph. 43 std::set<Label> InvalidLabels(const std::set<Label>& labels) const; 44 45 // Returns the set of all targets that have a label in the given set. 46 // Invalid (or missing) labels will be ignored. 47 std::set<const Target*> TargetsFor(const std::set<Label>& labels) const; 48 49 // Returns a filtered set of the given targets, meaning that for each of the 50 // given targets, 51 // - if the target is not a group, add it to the set 52 // - if the target is a group, recursively filter each dependency and add 53 // its filtered results to the set. 54 // 55 // For example, if we had: 56 // 57 // group("foobar") { deps = [ ":foo", ":bar" ] } 58 // group("bar") { deps = [ ":baz", ":quux" ] } 59 // executable("foo") { ... } 60 // executable("baz") { ... } 61 // executable("quux") { ... } 62 // 63 // Then the filtered version of {"foobar"} would be {":foo", ":baz", 64 // ":quux"}. This is used by the analyze command in order to only build 65 // the affected dependencies of a group (and not also build the unaffected 66 // ones). 67 // 68 // This filtering behavior is also known as "pruning" the list of targets. 69 std::set<const Target*> Filter(const std::set<const Target*>& targets) const; 70 71 // Filter an individual target and adds the results to filtered 72 // (see Filter(), above). 73 void FilterTarget(const Target*, 74 std::set<const Target*>* seen, 75 std::set<const Target*>* filtered) const; 76 77 bool ItemRefersToFile(const Item* item, const SourceFile* file) const; 78 79 void AddItemsDirectlyReferringToFile( 80 const SourceFile* file, 81 std::set<const Item*>* affected_items) const; 82 83 void AddAllItemsReferringToItem(const Item* item, 84 std::set<const Item*>* affected_items) const; 85 86 // Main GN files stand for files whose context are used globally to execute 87 // every other build files, this list includes dot file, build config file, 88 // build args files etc. 89 bool WereMainGNFilesModified( 90 const std::set<const SourceFile*>& modified_files) const; 91 92 std::vector<const Item*> all_items_; 93 std::map<Label, const Item*> labels_to_items_; 94 Label default_toolchain_; 95 96 // Maps items to the list of items that depend on them. 97 std::multimap<const Item*, const Item*> dep_map_; 98 99 const SourceFile build_config_file_; 100 const SourceFile dot_file_; 101 const SourceFileSet build_args_dependency_files_; 102 }; 103 104 #endif // TOOLS_GN_ANALYZER_H_ 105