| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "base/command_line.h" | 5 #include "base/command_line.h" |
| 6 #include "base/containers/hash_tables.h" |
| 6 #include "base/strings/stringprintf.h" | 7 #include "base/strings/stringprintf.h" |
| 7 #include "tools/gn/commands.h" | 8 #include "tools/gn/commands.h" |
| 8 #include "tools/gn/setup.h" | 9 #include "tools/gn/setup.h" |
| 9 #include "tools/gn/standard_out.h" | 10 #include "tools/gn/standard_out.h" |
| 10 | 11 |
| 11 namespace commands { | 12 namespace commands { |
| 12 | 13 |
| 13 namespace { | 14 namespace { |
| 14 | 15 |
| 15 enum DepType { | 16 enum DepType { |
| 16 DEP_NONE, | 17 DEP_NONE, |
| 17 DEP_PUBLIC, | 18 DEP_PUBLIC, |
| 18 DEP_PRIVATE, | 19 DEP_PRIVATE, |
| 19 DEP_DATA | 20 DEP_DATA |
| 20 }; | 21 }; |
| 21 | 22 |
| 22 // As we do a depth-first search, this vector will store the current path | 23 // As we do a depth-first search, this vector will store the current path |
| 23 // the current target for printing when a match is found. | 24 // the current target for printing when a match is found. |
| 24 using TargetDep = std::pair<const Target*, DepType>; | 25 using TargetDep = std::pair<const Target*, DepType>; |
| 25 using DepStack = std::vector<TargetDep>; | 26 using DepStack = std::vector<TargetDep>; |
| 26 | 27 |
| 28 using DepSet = base::hash_set<const Target*>; |
| 29 |
| 27 void PrintDepStack(const DepStack& stack) { | 30 void PrintDepStack(const DepStack& stack) { |
| 28 // Don't print toolchains unless they differ from the first target. | 31 // Don't print toolchains unless they differ from the first target. |
| 29 const Label& default_toolchain = stack[0].first->label().GetToolchainLabel(); | 32 const Label& default_toolchain = stack[0].first->label().GetToolchainLabel(); |
| 30 | 33 |
| 31 for (const auto& pair : stack) { | 34 for (const auto& pair : stack) { |
| 32 OutputString(pair.first->label().GetUserVisibleName(default_toolchain)); | 35 OutputString(pair.first->label().GetUserVisibleName(default_toolchain)); |
| 33 switch (pair.second) { | 36 switch (pair.second) { |
| 34 case DEP_NONE: | 37 case DEP_NONE: |
| 35 break; | 38 break; |
| 36 case DEP_PUBLIC: | 39 case DEP_PUBLIC: |
| 37 OutputString(" --[public]-->", DECORATION_DIM); | 40 OutputString(" --[public]-->", DECORATION_DIM); |
| 38 break; | 41 break; |
| 39 case DEP_PRIVATE: | 42 case DEP_PRIVATE: |
| 40 OutputString(" --[private]-->", DECORATION_DIM); | 43 OutputString(" --[private]-->", DECORATION_DIM); |
| 41 break; | 44 break; |
| 42 case DEP_DATA: | 45 case DEP_DATA: |
| 43 OutputString(" --[data]-->", DECORATION_DIM); | 46 OutputString(" --[data]-->", DECORATION_DIM); |
| 44 break; | 47 break; |
| 45 } | 48 } |
| 46 OutputString("\n"); | 49 OutputString("\n"); |
| 47 } | 50 } |
| 48 OutputString("\n"); | 51 OutputString("\n"); |
| 49 } | 52 } |
| 50 | 53 |
| 51 // Increments *found_count to reflect how many results are found. If print_all | 54 // Increments *found_count to reflect how many results are found. If print_all |
| 52 // is not set, only the first result will be printed. | 55 // is not set, only the first result will be printed. |
| 56 // |
| 57 // As an optimization, targets that do not have any paths are added to |
| 58 // *reject so this function doesn't waste time revisiting them. |
| 53 void RecursiveFindPath(const Target* current, | 59 void RecursiveFindPath(const Target* current, |
| 54 const Target* desired, | 60 const Target* desired, |
| 55 DepStack* stack, | 61 DepStack* stack, |
| 62 DepSet* reject, |
| 56 int* found_count, | 63 int* found_count, |
| 57 bool print_all) { | 64 bool print_all) { |
| 65 if (reject->find(current) != reject->end()) |
| 66 return; |
| 67 int initial_found_count = *found_count; |
| 68 |
| 58 if (current == desired) { | 69 if (current == desired) { |
| 59 (*found_count)++; | 70 (*found_count)++; |
| 60 if (print_all || *found_count == 1) { | 71 if (print_all || *found_count == 1) { |
| 61 stack->push_back(TargetDep(current, DEP_NONE)); | 72 stack->push_back(TargetDep(current, DEP_NONE)); |
| 62 PrintDepStack(*stack); | 73 PrintDepStack(*stack); |
| 63 stack->pop_back(); | 74 stack->pop_back(); |
| 64 } | 75 } |
| 65 return; | 76 return; |
| 66 } | 77 } |
| 67 | 78 |
| 68 stack->push_back(TargetDep(current, DEP_PUBLIC)); | 79 stack->push_back(TargetDep(current, DEP_PUBLIC)); |
| 69 for (const auto& pair : current->public_deps()) | 80 for (const auto& pair : current->public_deps()) |
| 70 RecursiveFindPath(pair.ptr, desired, stack, found_count, print_all); | 81 RecursiveFindPath(pair.ptr, desired, stack, reject, found_count, print_all); |
| 71 | 82 |
| 72 stack->back().second = DEP_PRIVATE; | 83 stack->back().second = DEP_PRIVATE; |
| 73 for (const auto& pair : current->private_deps()) | 84 for (const auto& pair : current->private_deps()) |
| 74 RecursiveFindPath(pair.ptr, desired, stack, found_count, print_all); | 85 RecursiveFindPath(pair.ptr, desired, stack, reject, found_count, print_all); |
| 75 | 86 |
| 76 stack->back().second = DEP_DATA; | 87 stack->back().second = DEP_DATA; |
| 77 for (const auto& pair : current->data_deps()) | 88 for (const auto& pair : current->data_deps()) |
| 78 RecursiveFindPath(pair.ptr, desired, stack, found_count, print_all); | 89 RecursiveFindPath(pair.ptr, desired, stack, reject, found_count, print_all); |
| 79 stack->pop_back(); | 90 stack->pop_back(); |
| 91 |
| 92 if (*found_count == initial_found_count) |
| 93 reject->insert(current); // Eliminated this target. |
| 80 } | 94 } |
| 81 | 95 |
| 82 } // namespace | 96 } // namespace |
| 83 | 97 |
| 84 const char kPath[] = "path"; | 98 const char kPath[] = "path"; |
| 85 const char kPath_HelpShort[] = | 99 const char kPath_HelpShort[] = |
| 86 "path: Find paths between two targets."; | 100 "path: Find paths between two targets."; |
| 87 const char kPath_Help[] = | 101 const char kPath_Help[] = |
| 88 "gn path <out_dir> <target_one> <target_two>\n" | 102 "gn path <out_dir> <target_one> <target_two>\n" |
| 89 "\n" | 103 "\n" |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 125 const Target* target2 = ResolveTargetFromCommandLineString(setup, args[2]); | 139 const Target* target2 = ResolveTargetFromCommandLineString(setup, args[2]); |
| 126 if (!target2) | 140 if (!target2) |
| 127 return 1; | 141 return 1; |
| 128 | 142 |
| 129 bool print_all = base::CommandLine::ForCurrentProcess()->HasSwitch("all"); | 143 bool print_all = base::CommandLine::ForCurrentProcess()->HasSwitch("all"); |
| 130 | 144 |
| 131 // If we don't find a path going "forwards", try the reverse direction. Deps | 145 // If we don't find a path going "forwards", try the reverse direction. Deps |
| 132 // can only go in one direction without having a cycle, which will have | 146 // can only go in one direction without having a cycle, which will have |
| 133 // caused a run failure above. | 147 // caused a run failure above. |
| 134 DepStack stack; | 148 DepStack stack; |
| 149 DepSet rejected; |
| 135 int found = 0; | 150 int found = 0; |
| 136 RecursiveFindPath(target1, target2, &stack, &found, print_all); | 151 RecursiveFindPath(target1, target2, &stack, &rejected, &found, print_all); |
| 137 if (found == 0) | 152 if (found == 0) { |
| 138 RecursiveFindPath(target2, target1, &stack, &found, print_all); | 153 // Need to reset the rejected set for a new invocation since the reverse |
| 154 // search will revisit the same targets looking for something else. |
| 155 rejected.clear(); |
| 156 RecursiveFindPath(target2, target1, &stack, &rejected, &found, print_all); |
| 157 } |
| 139 | 158 |
| 140 if (found == 0) { | 159 if (found == 0) { |
| 141 OutputString("No paths found between these two targets.\n", | 160 OutputString("No paths found between these two targets.\n", |
| 142 DECORATION_YELLOW); | 161 DECORATION_YELLOW); |
| 143 } else if (found == 1) { | 162 } else if (found == 1) { |
| 144 OutputString("1 path found.\n", DECORATION_YELLOW); | 163 OutputString("1 path found.\n", DECORATION_YELLOW); |
| 145 } else { | 164 } else { |
| 146 if (print_all) { | 165 if (print_all) { |
| 147 OutputString(base::StringPrintf("%d unique paths found.\n", found), | 166 OutputString(base::StringPrintf("%d unique paths found.\n", found), |
| 148 DECORATION_YELLOW); | 167 DECORATION_YELLOW); |
| 149 } else { | 168 } else { |
| 150 OutputString( | 169 OutputString( |
| 151 base::StringPrintf("Showing the first of %d unique paths. ", found), | 170 base::StringPrintf("Showing the first of %d unique paths. ", found), |
| 152 DECORATION_YELLOW); | 171 DECORATION_YELLOW); |
| 153 OutputString("Use --all to print all paths.\n"); | 172 OutputString("Use --all to print all paths.\n"); |
| 154 } | 173 } |
| 155 } | 174 } |
| 156 return 0; | 175 return 0; |
| 157 } | 176 } |
| 158 | 177 |
| 159 } // namespace commands | 178 } // namespace commands |
| OLD | NEW |