Chromium Code Reviews| 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 "tools/gn/runtime_deps.h" | 5 #include "tools/gn/runtime_deps.h" |
| 6 | 6 |
| 7 #include <map> | |
| 7 #include <set> | 8 #include <set> |
| 8 #include <sstream> | 9 #include <sstream> |
| 9 | 10 |
| 10 #include "base/command_line.h" | 11 #include "base/command_line.h" |
| 11 #include "base/files/file_util.h" | 12 #include "base/files/file_util.h" |
| 12 #include "base/strings/string_split.h" | 13 #include "base/strings/string_split.h" |
| 13 #include "tools/gn/build_settings.h" | 14 #include "tools/gn/build_settings.h" |
| 14 #include "tools/gn/builder.h" | 15 #include "tools/gn/builder.h" |
| 15 #include "tools/gn/deps_iterator.h" | 16 #include "tools/gn/deps_iterator.h" |
| 16 #include "tools/gn/filesystem_utils.h" | 17 #include "tools/gn/filesystem_utils.h" |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 51 // Returns the output file that the runtime deps considers for the given | 52 // Returns the output file that the runtime deps considers for the given |
| 52 // targets. This is weird only for shared libraries. | 53 // targets. This is weird only for shared libraries. |
| 53 const OutputFile& GetMainOutput(const Target* target) { | 54 const OutputFile& GetMainOutput(const Target* target) { |
| 54 if (target->output_type() == Target::SHARED_LIBRARY) | 55 if (target->output_type() == Target::SHARED_LIBRARY) |
| 55 return target->link_output_file(); | 56 return target->link_output_file(); |
| 56 return target->dependency_output_file(); | 57 return target->dependency_output_file(); |
| 57 } | 58 } |
| 58 | 59 |
| 59 // To avoid duplicate traversals of targets, or duplicating output files that | 60 // To avoid duplicate traversals of targets, or duplicating output files that |
| 60 // might be listed by more than one target, the set of targets and output files | 61 // might be listed by more than one target, the set of targets and output files |
| 61 // that have been found so far is passed. | 62 // that have been found so far is passed. The "value" of the seen_targets map |
| 63 // is a boolean indicating if the seen dep was a data dep (true = data_dep). | |
| 64 // data deps add more stuff, so we will want to revisit a target if it's a | |
| 65 // data dependency and we've previously only seen it as a regular dep. | |
| 62 void RecursiveCollectRuntimeDeps(const Target* target, | 66 void RecursiveCollectRuntimeDeps(const Target* target, |
| 63 bool is_target_data_dep, | 67 bool is_target_data_dep, |
| 64 RuntimeDepsVector* deps, | 68 RuntimeDepsVector* deps, |
| 65 std::set<const Target*>* seen_targets, | 69 std::map<const Target*, bool>* seen_targets, |
| 66 std::set<OutputFile>* found_files) { | 70 std::set<OutputFile>* found_files) { |
| 67 if (seen_targets->find(target) != seen_targets->end()) | 71 const auto& found_seen_target = seen_targets->find(target); |
| 68 return; // Already checked. | 72 if (found_seen_target != seen_targets->end()) { |
| 69 seen_targets->insert(target); | 73 // Already visited. |
| 74 if (found_seen_target->second || !is_target_data_dep) { | |
| 75 // Already visited as a data dep, or the current dep is not a data | |
| 76 // dep so visiting again will be a no-op. | |
| 77 return; | |
| 78 } | |
| 79 // In the else case, the previously seen target was a regular dependency | |
| 80 // and we'll now process it as a data dependency. | |
| 81 } | |
| 82 (*seen_targets)[target] = is_target_data_dep; | |
| 70 | 83 |
| 71 // Add the main output file for executables and shared libraries. | 84 // Add the main output file for executables and shared libraries. |
| 72 if (target->output_type() == Target::EXECUTABLE || | 85 if (target->output_type() == Target::EXECUTABLE || |
| 73 target->output_type() == Target::SHARED_LIBRARY) | 86 target->output_type() == Target::SHARED_LIBRARY) |
| 74 AddIfNew(GetMainOutput(target), target, deps, found_files); | 87 AddIfNew(GetMainOutput(target), target, deps, found_files); |
| 75 | 88 |
| 76 // Add all data files. | 89 // Add all data files. |
| 77 for (const auto& file : target->data()) | 90 for (const auto& file : target->data()) |
| 78 AddIfNew(file, target, deps, found_files); | 91 AddIfNew(file, target, deps, found_files); |
| 79 | 92 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 132 " Runtime dependencies of a target are exposed via the \"runtime_deps\"\n" | 145 " Runtime dependencies of a target are exposed via the \"runtime_deps\"\n" |
| 133 " category of \"gn desc\" (see \"gn help desc\") or they can be written\n" | 146 " category of \"gn desc\" (see \"gn help desc\") or they can be written\n" |
| 134 " at build generation time via \"--runtime-deps-list-file\"\n" | 147 " at build generation time via \"--runtime-deps-list-file\"\n" |
| 135 " (see \"gn help --runtime-deps-list-file\").\n" | 148 " (see \"gn help --runtime-deps-list-file\").\n" |
| 136 "\n" | 149 "\n" |
| 137 " To a first approximation, the runtime dependencies of a target are\n" | 150 " To a first approximation, the runtime dependencies of a target are\n" |
| 138 " the set of \"data\" files, data directories, and the shared libraries\n" | 151 " the set of \"data\" files, data directories, and the shared libraries\n" |
| 139 " from all transitive dependencies. Executables and shared libraries are\n" | 152 " from all transitive dependencies. Executables and shared libraries are\n" |
| 140 " considered runtime dependencies of themselves.\n" | 153 " considered runtime dependencies of themselves.\n" |
| 141 "\n" | 154 "\n" |
| 142 "Details\n" | 155 "Executables\n" |
| 143 "\n" | 156 "\n" |
| 144 " Executable targets and those executable targets' transitive\n" | 157 " Executable targets and those executable targets' transitive\n" |
| 145 " dependencies are not considered unless that executable is listed in\n" | 158 " dependencies are not considered unless that executable is listed in\n" |
| 146 " \"data_deps\". Otherwise, GN assumes that the executable (and\n" | 159 " \"data_deps\". Otherwise, GN assumes that the executable (and\n" |
| 147 " everything it requires) is a build-time dependency only.\n" | 160 " everything it requires) is a build-time dependency only.\n" |
| 148 "\n" | 161 "\n" |
| 162 "Actions and copies\n" | |
| 163 "\n" | |
| 149 " Action and copy targets that are listed as \"data_deps\" will have all\n" | 164 " Action and copy targets that are listed as \"data_deps\" will have all\n" |
| 150 " of their outputs and data files considered as runtime dependencies.\n" | 165 " of their outputs and data files considered as runtime dependencies.\n" |
| 151 " Action and copy targets that are \"deps\" or \"public_deps\" will have\n" | 166 " Action and copy targets that are \"deps\" or \"public_deps\" will have\n" |
| 152 " only their data files considered as runtime dependencies. These\n" | 167 " only their data files considered as runtime dependencies. These\n" |
| 153 " targets can list an output file in both the \"outputs\" and \"data\"\n" | 168 " targets can list an output file in both the \"outputs\" and \"data\"\n" |
| 154 " lists to force an output file as a runtime dependency in all cases.\n" | 169 " lists to force an output file as a runtime dependency in all cases.\n" |
| 155 "\n" | 170 "\n" |
| 171 " The different rules for deps and data_deps are to express build-time\n" | |
| 172 " (deps) vs. run-time (data_deps) outputs. If GN counted all build-time\n" | |
| 173 " copy steps as data dependencies, there would be a lot of extra stuff,\n" | |
| 174 " and if GN counted all run-time dependencies as regular deps, the\n" | |
| 175 " build's paralellism would be unnecessarily constrained.\n" | |
|
Dirk Pranke
2015/07/21 23:00:51
typo: parallelism
| |
| 176 "\n" | |
| 177 " This rule can sometimes lead to unintuitive results. For example,\n" | |
| 178 " given the three targets:\n" | |
| 179 " A --[data_deps]--> B --[deps]--> ACTION\n" | |
| 180 " GN would say that A does not have runtime deps on the result of the\n" | |
| 181 " ACTION, which is often correct. But the purpose of the B target might\n" | |
| 182 " be to collect many actions into one logic unit, and the \"data\"-ness\n" | |
| 183 " of A's dependency is lost. Solutions:\n" | |
| 184 "\n" | |
| 185 " - List the outputs of the action in it's data section (if the\n" | |
| 186 " results of that action are always runtime files).\n" | |
| 187 " - Have B list the action in data_deps (if the outputs of the actions\n" | |
| 188 " are always runtime files).\n" | |
| 189 " - Have B list the action in both deps and data deps (if the outputs\n" | |
| 190 " might be used in both contexts and you don't care about unnecessary\n" | |
| 191 " entries in the list of files required at runtime).\n" | |
| 192 " - Split B into run-time and build-time versions with the appropriate\n" | |
| 193 " \"deps\" for each.\n" | |
| 194 "\n" | |
| 195 "Static libraries and source sets\n" | |
| 196 "\n" | |
| 156 " The results of static_library or source_set targets are not considered\n" | 197 " The results of static_library or source_set targets are not considered\n" |
| 157 " runtime dependencies since these are assumed to be intermediate\n" | 198 " runtime dependencies since these are assumed to be intermediate\n" |
| 158 " targets only. If you need to list a static library as a runtime\n" | 199 " targets only. If you need to list a static library as a runtime\n" |
| 159 " dependency, you can manually compute the .a/.lib file name for the\n" | 200 " dependency, you can manually compute the .a/.lib file name for the\n" |
| 160 " current platform and list it in the \"data\" list of a target\n" | 201 " current platform and list it in the \"data\" list of a target\n" |
| 161 " (possibly on the static library target itself).\n" | 202 " (possibly on the static library target itself).\n" |
| 162 "\n" | 203 "\n" |
| 204 "Multiple outputs\n" | |
| 205 "\n" | |
| 163 " When a tool produces more than one output, only the first output\n" | 206 " When a tool produces more than one output, only the first output\n" |
| 164 " is considered. For example, a shared library target may produce a\n" | 207 " is considered. For example, a shared library target may produce a\n" |
| 165 " .dll and a .lib file on Windows. Only the .dll file will be considered\n" | 208 " .dll and a .lib file on Windows. Only the .dll file will be considered\n" |
| 166 " a runtime dependency.\n"; | 209 " a runtime dependency. This applies only to linker tools, scripts and\n" |
| 210 " copy steps with multiple outputs will also get all outputs listed.\n"; | |
| 167 | 211 |
| 168 RuntimeDepsVector ComputeRuntimeDeps(const Target* target) { | 212 RuntimeDepsVector ComputeRuntimeDeps(const Target* target) { |
| 169 RuntimeDepsVector result; | 213 RuntimeDepsVector result; |
| 170 std::set<const Target*> seen_targets; | 214 std::map<const Target*, bool> seen_targets; |
| 171 std::set<OutputFile> found_files; | 215 std::set<OutputFile> found_files; |
| 172 | 216 |
| 173 // The initial target is not considered a data dependency so that actions's | 217 // The initial target is not considered a data dependency so that actions's |
| 174 // outputs (if the current target is an action) are not automatically | 218 // outputs (if the current target is an action) are not automatically |
| 175 // considered data deps. | 219 // considered data deps. |
| 176 RecursiveCollectRuntimeDeps(target, false, | 220 RecursiveCollectRuntimeDeps(target, false, |
| 177 &result, &seen_targets, &found_files); | 221 &result, &seen_targets, &found_files); |
| 178 return result; | 222 return result; |
| 179 } | 223 } |
| 180 | 224 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 221 return false; | 265 return false; |
| 222 } | 266 } |
| 223 | 267 |
| 224 // Currently this writes all runtime deps files sequentially. We generally | 268 // Currently this writes all runtime deps files sequentially. We generally |
| 225 // expect few of these. We can run this on the worker pool if it looks | 269 // expect few of these. We can run this on the worker pool if it looks |
| 226 // like it's talking a long time. | 270 // like it's talking a long time. |
| 227 WriteRuntimeDepsFile(target); | 271 WriteRuntimeDepsFile(target); |
| 228 } | 272 } |
| 229 return true; | 273 return true; |
| 230 } | 274 } |
| OLD | NEW |