| // Copyright 2014 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "tools/gn/build_settings.h" |
| #include "tools/gn/functions.h" |
| #include "tools/gn/parse_tree.h" |
| #include "tools/gn/settings.h" |
| #include "tools/gn/substitution_writer.h" |
| #include "tools/gn/target.h" |
| #include "tools/gn/value.h" |
| |
| namespace functions { |
| |
| const char kGetTargetOutputs[] = "get_target_outputs"; |
| const char kGetTargetOutputs_HelpShort[] = |
| "get_target_outputs: [file list] Get the list of outputs from a target."; |
| const char kGetTargetOutputs_Help[] = |
| R"(get_target_outputs: [file list] Get the list of outputs from a target. |
| |
| get_target_outputs(target_label) |
| |
| Returns a list of output files for the named target. The named target must |
| have been previously defined in the current file before this function is |
| called (it can't reference targets in other files because there isn't a |
| defined execution order, and it obviously can't reference targets that are |
| defined after the function call). |
| |
| Only copy and action targets are supported. The outputs from binary targets |
| will depend on the toolchain definition which won't necessarily have been |
| loaded by the time a given line of code has run, and source sets and groups |
| have no useful output file. |
| |
| Return value |
| |
| The names in the resulting list will be absolute file paths (normally like |
| "//out/Debug/bar.exe", depending on the build directory). |
| |
| action targets: this will just return the files specified in the "outputs" |
| variable of the target. |
| |
| action_foreach targets: this will return the result of applying the output |
| template to the sources (see "gn help source_expansion"). This will be the |
| same result (though with guaranteed absolute file paths), as |
| process_file_template will return for those inputs (see "gn help |
| process_file_template"). |
| |
| binary targets (executables, libraries): this will return a list of the |
| resulting binary file(s). The "main output" (the actual binary or library) |
| will always be the 0th element in the result. Depending on the platform and |
| output type, there may be other output files as well (like import libraries) |
| which will follow. |
| |
| source sets and groups: this will return a list containing the path of the |
| "stamp" file that Ninja will produce once all outputs are generated. This |
| probably isn't very useful. |
| |
| Example |
| |
| # Say this action generates a bunch of C source files. |
| action_foreach("my_action") { |
| sources = [ ... ] |
| outputs = [ ... ] |
| } |
| |
| # Compile the resulting source files into a source set. |
| source_set("my_lib") { |
| sources = get_target_outputs(":my_action") |
| } |
| )"; |
| |
| Value RunGetTargetOutputs(Scope* scope, |
| const FunctionCallNode* function, |
| const std::vector<Value>& args, |
| Err* err) { |
| if (args.size() != 1) { |
| *err = Err(function, "Expected one argument."); |
| return Value(); |
| } |
| |
| // Resolve the requested label. |
| Label label = Label::Resolve(scope->GetSourceDir(), |
| ToolchainLabelForScope(scope), args[0], err); |
| if (label.is_null()) |
| return Value(); |
| |
| // Find the referenced target. The targets previously encountered in this |
| // scope will have been stashed in the item collector (they'll be dispatched |
| // when this file is done running) so we can look through them. |
| const Target* target = nullptr; |
| Scope::ItemVector* collector = scope->GetItemCollector(); |
| if (!collector) { |
| *err = Err(function, "No targets defined in this context."); |
| return Value(); |
| } |
| for (const auto& item : *collector) { |
| if (item->label() != label) |
| continue; |
| |
| const Target* as_target = item->AsTarget(); |
| if (!as_target) { |
| *err = Err(function, "Label does not refer to a target.", |
| label.GetUserVisibleName(false) + "\nrefers to a " + |
| item->GetItemTypeName()); |
| return Value(); |
| } |
| target = as_target; |
| break; |
| } |
| |
| if (!target) { |
| *err = Err(function, "Target not found in this context.", |
| label.GetUserVisibleName(false) + |
| "\nwas not found. get_target_outputs() can only be used for " |
| "targets\n" |
| "previously defined in the current file."); |
| return Value(); |
| } |
| |
| // Compute the output list. |
| std::vector<SourceFile> files; |
| if (target->output_type() == Target::ACTION || |
| target->output_type() == Target::COPY_FILES || |
| target->output_type() == Target::ACTION_FOREACH) { |
| target->action_values().GetOutputsAsSourceFiles(target, &files); |
| } else { |
| // Other types of targets are not supported. |
| *err = Err(args[0], "Target is not an action, action_foreach, or copy.", |
| "Only these target types are supported by get_target_outputs."); |
| return Value(); |
| } |
| |
| // Convert to Values. |
| Value ret(function, Value::LIST); |
| ret.list_value().reserve(files.size()); |
| for (const auto& file : files) |
| ret.list_value().push_back(Value(function, file.value())); |
| |
| return ret; |
| } |
| |
| } // namespace functions |