| 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 |