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 <map> |
8 #include <set> | 8 #include <set> |
9 #include <sstream> | 9 #include <sstream> |
10 | 10 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
43 const Target* source, | 43 const Target* source, |
44 RuntimeDepsVector* deps, | 44 RuntimeDepsVector* deps, |
45 std::set<OutputFile>* found_file) { | 45 std::set<OutputFile>* found_file) { |
46 OutputFile output_file(RebasePath( | 46 OutputFile output_file(RebasePath( |
47 str, | 47 str, |
48 source->settings()->build_settings()->build_dir(), | 48 source->settings()->build_settings()->build_dir(), |
49 source->settings()->build_settings()->root_path_utf8())); | 49 source->settings()->build_settings()->root_path_utf8())); |
50 AddIfNew(output_file, source, deps, found_file); | 50 AddIfNew(output_file, source, deps, found_file); |
51 } | 51 } |
52 | 52 |
53 // Returns the output file that the runtime deps considers for the given | |
54 // targets. This is weird only for shared libraries. | |
55 const OutputFile& GetMainOutput(const Target* target) { | |
56 if (target->output_type() == Target::SHARED_LIBRARY) | |
57 return target->runtime_link_output_file(); | |
58 return target->dependency_output_file(); | |
59 } | |
60 | |
61 // To avoid duplicate traversals of targets, or duplicating output files that | 53 // To avoid duplicate traversals of targets, or duplicating output files that |
62 // might be listed by more than one target, the set of targets and output files | 54 // might be listed by more than one target, the set of targets and output files |
63 // that have been found so far is passed. The "value" of the seen_targets map | 55 // that have been found so far is passed. The "value" of the seen_targets map |
64 // is a boolean indicating if the seen dep was a data dep (true = data_dep). | 56 // is a boolean indicating if the seen dep was a data dep (true = data_dep). |
65 // data deps add more stuff, so we will want to revisit a target if it's a | 57 // data deps add more stuff, so we will want to revisit a target if it's a |
66 // data dependency and we've previously only seen it as a regular dep. | 58 // data dependency and we've previously only seen it as a regular dep. |
67 void RecursiveCollectRuntimeDeps(const Target* target, | 59 void RecursiveCollectRuntimeDeps(const Target* target, |
68 bool is_target_data_dep, | 60 bool is_target_data_dep, |
69 RuntimeDepsVector* deps, | 61 RuntimeDepsVector* deps, |
70 std::map<const Target*, bool>* seen_targets, | 62 std::map<const Target*, bool>* seen_targets, |
71 std::set<OutputFile>* found_files) { | 63 std::set<OutputFile>* found_files) { |
72 const auto& found_seen_target = seen_targets->find(target); | 64 const auto& found_seen_target = seen_targets->find(target); |
73 if (found_seen_target != seen_targets->end()) { | 65 if (found_seen_target != seen_targets->end()) { |
74 // Already visited. | 66 // Already visited. |
75 if (found_seen_target->second || !is_target_data_dep) { | 67 if (found_seen_target->second || !is_target_data_dep) { |
76 // Already visited as a data dep, or the current dep is not a data | 68 // Already visited as a data dep, or the current dep is not a data |
77 // dep so visiting again will be a no-op. | 69 // dep so visiting again will be a no-op. |
78 return; | 70 return; |
79 } | 71 } |
80 // In the else case, the previously seen target was a regular dependency | 72 // In the else case, the previously seen target was a regular dependency |
81 // and we'll now process it as a data dependency. | 73 // and we'll now process it as a data dependency. |
82 } | 74 } |
83 (*seen_targets)[target] = is_target_data_dep; | 75 (*seen_targets)[target] = is_target_data_dep; |
84 | 76 |
85 // Add the main output file for executables, shared libraries, and | 77 // Add the main output file for executables, shared libraries, and |
86 // loadable modules. | 78 // loadable modules. |
87 if (target->output_type() == Target::EXECUTABLE || | 79 if (target->output_type() == Target::EXECUTABLE || |
88 target->output_type() == Target::LOADABLE_MODULE || | 80 target->output_type() == Target::LOADABLE_MODULE || |
89 target->output_type() == Target::SHARED_LIBRARY) | 81 target->output_type() == Target::SHARED_LIBRARY) { |
90 AddIfNew(GetMainOutput(target), target, deps, found_files); | 82 for (const auto& runtime_output : target->runtime_outputs()) |
| 83 AddIfNew(runtime_output, target, deps, found_files); |
| 84 } |
91 | 85 |
92 // Add all data files. | 86 // Add all data files. |
93 for (const auto& file : target->data()) | 87 for (const auto& file : target->data()) |
94 AddIfNew(file, target, deps, found_files); | 88 AddIfNew(file, target, deps, found_files); |
95 | 89 |
96 // Actions/copy have all outputs considered when the're a data dep. | 90 // Actions/copy have all outputs considered when the're a data dep. |
97 if (is_target_data_dep && | 91 if (is_target_data_dep && |
98 (target->output_type() == Target::ACTION || | 92 (target->output_type() == Target::ACTION || |
99 target->output_type() == Target::ACTION_FOREACH || | 93 target->output_type() == Target::ACTION_FOREACH || |
100 target->output_type() == Target::COPY_FILES)) { | 94 target->output_type() == Target::COPY_FILES)) { |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
166 const Target* target = item ? item->AsTarget() : nullptr; | 160 const Target* target = item ? item->AsTarget() : nullptr; |
167 if (!target) { | 161 if (!target) { |
168 *err = Err(Location(), "The label \"" + label.GetUserVisibleName(true) + | 162 *err = Err(Location(), "The label \"" + label.GetUserVisibleName(true) + |
169 "\" isn't a target.", | 163 "\" isn't a target.", |
170 "When reading the line:\n " + line + "\n" | 164 "When reading the line:\n " + line + "\n" |
171 "from the --" + switches::kRuntimeDepsListFile + "=" + | 165 "from the --" + switches::kRuntimeDepsListFile + "=" + |
172 deps_target_list_file); | 166 deps_target_list_file); |
173 return false; | 167 return false; |
174 } | 168 } |
175 | 169 |
176 OutputFile output_file = | 170 OutputFile output_file; |
177 OutputFile(GetMainOutput(target).value() + ".runtime_deps"); | 171 const char extension[] = ".runtime_deps"; |
| 172 if (target->output_type() == Target::SHARED_LIBRARY || |
| 173 target->output_type() == Target::LOADABLE_MODULE) { |
| 174 // Force the first output for shared-library-type linker outputs since |
| 175 // the dependency output files might not be the main output. |
| 176 CHECK(!target->computed_outputs().empty()); |
| 177 output_file = |
| 178 OutputFile(target->computed_outputs()[0].value() + extension); |
| 179 } else { |
| 180 output_file = |
| 181 OutputFile(target->dependency_output_file().value() + extension); |
| 182 } |
178 files_to_write->push_back(std::make_pair(output_file, target)); | 183 files_to_write->push_back(std::make_pair(output_file, target)); |
179 } | 184 } |
180 return true; | 185 return true; |
181 } | 186 } |
182 | 187 |
183 bool WriteRuntimeDepsFile(const OutputFile& output_file, | 188 bool WriteRuntimeDepsFile(const OutputFile& output_file, |
184 const Target* target, | 189 const Target* target, |
185 Err* err) { | 190 Err* err) { |
186 SourceFile output_as_source = | 191 SourceFile output_as_source = |
187 output_file.AsSourceFile(target->settings()->build_settings()); | 192 output_file.AsSourceFile(target->settings()->build_settings()); |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
255 "\n" | 260 "\n" |
256 " The results of static_library or source_set targets are not considered\n" | 261 " The results of static_library or source_set targets are not considered\n" |
257 " runtime dependencies since these are assumed to be intermediate\n" | 262 " runtime dependencies since these are assumed to be intermediate\n" |
258 " targets only. If you need to list a static library as a runtime\n" | 263 " targets only. If you need to list a static library as a runtime\n" |
259 " dependency, you can manually compute the .a/.lib file name for the\n" | 264 " dependency, you can manually compute the .a/.lib file name for the\n" |
260 " current platform and list it in the \"data\" list of a target\n" | 265 " current platform and list it in the \"data\" list of a target\n" |
261 " (possibly on the static library target itself).\n" | 266 " (possibly on the static library target itself).\n" |
262 "\n" | 267 "\n" |
263 "Multiple outputs\n" | 268 "Multiple outputs\n" |
264 "\n" | 269 "\n" |
265 " When a tool produces more than one output, only the first output\n" | 270 " Linker tools can specify which of their outputs should be considered\n" |
266 " is considered. For example, a shared library target may produce a\n" | 271 " when computing the runtime deps by setting runtime_outputs. If this\n" |
267 " .dll and a .lib file on Windows. Only the .dll file will be considered\n" | 272 " is unset on the tool, the default will be the first output only.\n"; |
268 " a runtime dependency. This applies only to linker tools. Scripts and\n" | |
269 " copy steps with multiple outputs will get all outputs listed.\n"; | |
270 | 273 |
271 RuntimeDepsVector ComputeRuntimeDeps(const Target* target) { | 274 RuntimeDepsVector ComputeRuntimeDeps(const Target* target) { |
272 RuntimeDepsVector result; | 275 RuntimeDepsVector result; |
273 std::map<const Target*, bool> seen_targets; | 276 std::map<const Target*, bool> seen_targets; |
274 std::set<OutputFile> found_files; | 277 std::set<OutputFile> found_files; |
275 | 278 |
276 // The initial target is not considered a data dependency so that actions's | 279 // The initial target is not considered a data dependency so that actions's |
277 // outputs (if the current target is an action) are not automatically | 280 // outputs (if the current target is an action) are not automatically |
278 // considered data deps. | 281 // considered data deps. |
279 RecursiveCollectRuntimeDeps(target, false, | 282 RecursiveCollectRuntimeDeps(target, false, |
(...skipping 14 matching lines...) Expand all Loading... |
294 | 297 |
295 for (const auto& entry : files_to_write) { | 298 for (const auto& entry : files_to_write) { |
296 // Currently this writes all runtime deps files sequentially. We generally | 299 // Currently this writes all runtime deps files sequentially. We generally |
297 // expect few of these. We can run this on the worker pool if it looks | 300 // expect few of these. We can run this on the worker pool if it looks |
298 // like it's talking a long time. | 301 // like it's talking a long time. |
299 if (!WriteRuntimeDepsFile(entry.first, entry.second, err)) | 302 if (!WriteRuntimeDepsFile(entry.first, entry.second, err)) |
300 return false; | 303 return false; |
301 } | 304 } |
302 return true; | 305 return true; |
303 } | 306 } |
OLD | NEW |