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