1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "tools/gn/build_settings.h" 6 #include "tools/gn/functions.h" 7 #include "tools/gn/parse_tree.h" 8 #include "tools/gn/settings.h" 9 #include "tools/gn/substitution_writer.h" 10 #include "tools/gn/target.h" 11 #include "tools/gn/value.h" 12 13 namespace functions { 14 15 const char kGetTargetOutputs[] = "get_target_outputs"; 16 const char kGetTargetOutputs_HelpShort[] = 17 "get_target_outputs: [file list] Get the list of outputs from a target."; 18 const char kGetTargetOutputs_Help[] = 19 "get_target_outputs: [file list] Get the list of outputs from a target.\n" 20 "\n" 21 " get_target_outputs(target_label)\n" 22 "\n" 23 " Returns a list of output files for the named target. The named target\n" 24 " must have been previously defined in the current file before this\n" 25 " function is called (it can't reference targets in other files because\n" 26 " there isn't a defined execution order, and it obviously can't\n" 27 " reference targets that are defined after the function call).\n" 28 "\n" 29 " Only copy and action targets are supported. The outputs from binary\n" 30 " targets will depend on the toolchain definition which won't\n" 31 " necessarily have been loaded by the time a given line of code has run,\n" 32 " and source sets and groups have no useful output file.\n" 33 "\n" 34 "Return value\n" 35 "\n" 36 " The names in the resulting list will be absolute file paths (normally\n" 37 " like \"//out/Debug/bar.exe\", depending on the build directory).\n" 38 "\n" 39 " action targets: this will just return the files specified in the\n" 40 " \"outputs\" variable of the target.\n" 41 "\n" 42 " action_foreach targets: this will return the result of applying\n" 43 " the output template to the sources (see \"gn help source_expansion\").\n" 44 " This will be the same result (though with guaranteed absolute file\n" 45 " paths), as process_file_template will return for those inputs\n" 46 " (see \"gn help process_file_template\").\n" 47 "\n" 48 " binary targets (executables, libraries): this will return a list\n" 49 " of the resulting binary file(s). The \"main output\" (the actual\n" 50 " binary or library) will always be the 0th element in the result.\n" 51 " Depending on the platform and output type, there may be other output\n" 52 " files as well (like import libraries) which will follow.\n" 53 "\n" 54 " source sets and groups: this will return a list containing the path of\n" 55 " the \"stamp\" file that Ninja will produce once all outputs are\n" 56 " generated. This probably isn't very useful.\n" 57 "\n" 58 "Example\n" 59 "\n" 60 " # Say this action generates a bunch of C source files.\n" 61 " action_foreach(\"my_action\") {\n" 62 " sources = [ ... ]\n" 63 " outputs = [ ... ]\n" 64 " }\n" 65 "\n" 66 " # Compile the resulting source files into a source set.\n" 67 " source_set(\"my_lib\") {\n" 68 " sources = get_target_outputs(\":my_action\")\n" 69 " }\n"; 70 71 Value RunGetTargetOutputs(Scope* scope, 72 const FunctionCallNode* function, 73 const std::vector<Value>& args, 74 Err* err) { 75 if (args.size() != 1) { 76 *err = Err(function, "Expected one argument."); 77 return Value(); 78 } 79 80 // Resolve the requested label. 81 Label label = Label::Resolve(scope->GetSourceDir(), 82 ToolchainLabelForScope(scope), args[0], err); 83 if (label.is_null()) 84 return Value(); 85 86 // Find the referenced target. The targets previously encountered in this 87 // scope will have been stashed in the item collector (they'll be dispatched 88 // when this file is done running) so we can look through them. 89 const Target* target = NULL; 90 Scope::ItemVector* collector = scope->GetItemCollector(); 91 if (!collector) { 92 *err = Err(function, "No targets defined in this context."); 93 return Value(); 94 } 95 for (size_t i = 0; i < collector->size(); i++) { 96 const Item* item = (*collector)[i]->get(); 97 if (item->label() != label) 98 continue; 99 100 const Target* as_target = item->AsTarget(); 101 if (!as_target) { 102 *err = Err(function, "Label does not refer to a target.", 103 label.GetUserVisibleName(false) + 104 "\nrefers to a " + item->GetItemTypeName()); 105 return Value(); 106 } 107 target = as_target; 108 break; 109 } 110 111 if (!target) { 112 *err = Err(function, "Target not found in this context.", 113 label.GetUserVisibleName(false) + 114 "\nwas not found. get_target_outputs() can only be used for targets\n" 115 "previously defined in the current file."); 116 return Value(); 117 } 118 119 // Compute the output list. 120 std::vector<SourceFile> files; 121 if (target->output_type() == Target::ACTION || 122 target->output_type() == Target::COPY_FILES || 123 target->output_type() == Target::ACTION_FOREACH) { 124 target->action_values().GetOutputsAsSourceFiles(target, &files); 125 } else { 126 // Other types of targets are not supported. 127 *err = Err(args[0], "Target is not an action, action_foreach, or copy.", 128 "Only these target types are supported by get_target_outputs."); 129 return Value(); 130 } 131 132 // Convert to Values. 133 Value ret(function, Value::LIST); 134 ret.list_value().reserve(files.size()); 135 for (size_t i = 0; i < files.size(); i++) 136 ret.list_value().push_back(Value(function, files[i].value())); 137 138 return ret; 139 } 140 141 } // namespace functions 142