Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "base/command_line.h" | |
| 6 #include "base/strings/stringprintf.h" | |
| 7 #include "tools/gn/commands.h" | |
| 8 #include "tools/gn/setup.h" | |
| 9 #include "tools/gn/standard_out.h" | |
| 10 | |
| 11 namespace commands { | |
| 12 | |
| 13 namespace { | |
| 14 | |
| 15 enum DepType { | |
| 16 DEP_NONE, | |
| 17 DEP_PUBLIC, | |
| 18 DEP_PRIVATE, | |
| 19 DEP_DATA | |
| 20 }; | |
| 21 | |
| 22 // 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 using TargetDep = std::pair<const Target*, DepType>; | |
| 25 using DepStack = std::vector<TargetDep>; | |
| 26 | |
| 27 void PrintDepStack(const DepStack& stack) { | |
| 28 // Don't print toolchains unless they differ from the first target. | |
| 29 const Label& default_toolchain = stack[0].first->label().GetToolchainLabel(); | |
| 30 | |
| 31 for (const auto& pair : stack) { | |
| 32 OutputString(pair.first->label().GetUserVisibleName(default_toolchain)); | |
| 33 switch (pair.second) { | |
| 34 case DEP_NONE: | |
| 35 break; | |
| 36 case DEP_PUBLIC: | |
| 37 OutputString(" --[public]-->", DECORATION_DIM); | |
| 38 break; | |
| 39 case DEP_PRIVATE: | |
| 40 OutputString(" --[private]-->", DECORATION_DIM); | |
| 41 break; | |
| 42 case DEP_DATA: | |
| 43 OutputString(" --[data]-->", DECORATION_DIM); | |
| 44 break; | |
| 45 } | |
| 46 OutputString("\n"); | |
| 47 } | |
| 48 OutputString("\n"); | |
| 49 } | |
| 50 | |
| 51 // Increments *found_count to reflect how many results are found. If print_all | |
| 52 // is not set, only the first result will be printed. | |
| 53 void RecursiveFindPath(const Target* current, | |
| 54 const Target* desired, | |
| 55 DepStack* stack, | |
| 56 int* found_count, | |
| 57 bool print_all) { | |
| 58 if (current == desired) { | |
| 59 (*found_count)++; | |
|
Dirk Pranke
2015/05/19 19:43:29
If I'm reading this correctly, this routine will s
brettw
2015/05/19 21:09:54
Correct. I want to find the number of items which
| |
| 60 if (print_all || *found_count == 1) { | |
| 61 stack->push_back(TargetDep(current, DEP_NONE)); | |
| 62 PrintDepStack(*stack); | |
| 63 stack->pop_back(); | |
| 64 } | |
| 65 return; | |
| 66 } | |
| 67 | |
| 68 stack->push_back(TargetDep(current, DEP_PUBLIC)); | |
| 69 for (const auto& pair : current->public_deps()) | |
| 70 RecursiveFindPath(pair.ptr, desired, stack, found_count, print_all); | |
| 71 | |
| 72 stack->back().second = DEP_PRIVATE; | |
| 73 for (const auto& pair : current->private_deps()) | |
| 74 RecursiveFindPath(pair.ptr, desired, stack, found_count, print_all); | |
| 75 | |
| 76 stack->back().second = DEP_DATA; | |
| 77 for (const auto& pair : current->data_deps()) | |
| 78 RecursiveFindPath(pair.ptr, desired, stack, found_count, print_all); | |
| 79 stack->pop_back(); | |
| 80 } | |
| 81 | |
| 82 } // namespace | |
| 83 | |
| 84 const char kPath[] = "path"; | |
| 85 const char kPath_HelpShort[] = | |
| 86 "path: Find paths between two targets."; | |
| 87 const char kPath_Help[] = | |
| 88 "gn path <out_dir> <target_one> <target_two>\n" | |
| 89 "\n" | |
| 90 " Finds paths of dependencies between two targets. Each unique path\n" | |
| 91 " will be printed in one group, and groups will be separate by newlines.\n" | |
| 92 " The two targets can appear in either order: paths will be found going\n" | |
| 93 " in either direction.\n" | |
| 94 "\n" | |
| 95 " Each dependency will be annotated with its type. By default, only the\n" | |
| 96 " first path encountered will be printed, which is not necessarily the\n" | |
| 97 " shortest path.\n" | |
| 98 "\n" | |
| 99 "Options\n" | |
| 100 "\n" | |
| 101 " --all\n" | |
| 102 " Prints all paths found rather than just the first one.\n" | |
| 103 "\n" | |
| 104 "Example\n" | |
| 105 "\n" | |
| 106 " gn path out/Default //base //tools/gn\n"; | |
| 107 | |
| 108 int RunPath(const std::vector<std::string>& args) { | |
| 109 if (args.size() != 3) { | |
| 110 Err(Location(), "You're holding it wrong.", | |
| 111 "Usage: \"gn path <out_dir> <target_one> <target_two>\"") | |
| 112 .PrintToStdout(); | |
| 113 return 1; | |
| 114 } | |
| 115 | |
| 116 Setup* setup = new Setup; | |
| 117 if (!setup->DoSetup(args[0], false)) | |
| 118 return 1; | |
| 119 if (!setup->Run()) | |
| 120 return 1; | |
| 121 | |
| 122 const Target* target1 = ResolveTargetFromCommandLineString(setup, args[1]); | |
| 123 if (!target1) | |
| 124 return 1; | |
| 125 const Target* target2 = ResolveTargetFromCommandLineString(setup, args[2]); | |
| 126 if (!target2) | |
| 127 return 1; | |
| 128 | |
| 129 bool print_all = base::CommandLine::ForCurrentProcess()->HasSwitch("all"); | |
| 130 | |
| 131 // 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 | |
| 133 // caused a run failure above. | |
| 134 DepStack stack; | |
| 135 int found = 0; | |
| 136 RecursiveFindPath(target1, target2, &stack, &found, print_all); | |
| 137 if (found == 0) | |
| 138 RecursiveFindPath(target2, target1, &stack, &found, print_all); | |
| 139 | |
| 140 if (found == 0) { | |
| 141 OutputString("No paths found between these two targets.\n", | |
| 142 DECORATION_YELLOW); | |
| 143 } else if (found == 1) { | |
| 144 OutputString("1 path found.\n", DECORATION_YELLOW); | |
| 145 } else { | |
| 146 if (print_all) { | |
| 147 OutputString(base::StringPrintf("%d unique paths found.\n", found), | |
| 148 DECORATION_YELLOW); | |
| 149 } else { | |
| 150 OutputString( | |
| 151 base::StringPrintf("Showing the first of %d unique paths. ", found), | |
| 152 DECORATION_YELLOW); | |
| 153 OutputString("Use --all to print all paths.\n"); | |
| 154 } | |
| 155 } | |
| 156 return 0; | |
| 157 } | |
| 158 | |
| 159 } // namespace commands | |
| OLD | NEW |