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.
5 #include "tools/gn/build_settings.h"
6 #include "tools/gn/file_template.h"
7 #include "tools/gn/functions.h"
8 #include "tools/gn/ninja_helper.h"
9 #include "tools/gn/parse_tree.h"
10 #include "tools/gn/settings.h"
11 #include "tools/gn/target.h"
12 #include "tools/gn/value.h"
18 void GetOutputsForTarget(const Settings
* settings
,
20 std::vector
<std::string
>* ret
) {
21 switch (target
->output_type()) {
23 case Target::COPY_FILES
: {
24 // Actions and copy targets: return the outputs specified.
25 const std::vector
<SourceFile
>& outs
= target
->action_values().outputs();
26 ret
->reserve(outs
.size());
27 for (size_t i
= 0; i
< outs
.size(); i
++)
28 ret
->push_back(outs
[i
].value());
32 case Target::ACTION_FOREACH
: {
33 // Action_foreach: return the result of the template in the outputs.
34 FileTemplate
file_template(settings
, target
->action_values().outputs());
35 const std::vector
<SourceFile
>& sources
= target
->sources();
36 for (size_t i
= 0; i
< sources
.size(); i
++)
37 file_template
.Apply(sources
[i
], ret
);
41 case Target::EXECUTABLE
:
42 case Target::SHARED_LIBRARY
:
43 case Target::STATIC_LIBRARY
:
44 // Return the resulting binary file. Currently, fall through to the
45 // Ninja helper below which will compute the main output name.
47 // TODO(brettw) some targets have secondary files which should go into
48 // the list after the main (like shared libraries on Windows have an
51 case Target::SOURCE_SET
: {
52 // These return the stamp file, which is computed by the NinjaHelper.
53 NinjaHelper
helper(settings
->build_settings());
54 OutputFile output_file
= helper
.GetTargetOutputFile(target
);
56 // The output file is relative to the build dir.
57 std::string absolute_output_file
=
58 settings
->build_settings()->build_dir().value();
59 absolute_output_file
.append(output_file
.value());
61 ret
->push_back(absolute_output_file
);
72 const char kGetTargetOutputs
[] = "get_target_outputs";
73 const char kGetTargetOutputs_HelpShort
[] =
74 "get_target_outputs: [file list] Get the list of outputs from a target.";
75 const char kGetTargetOutputs_Help
[] =
76 "get_target_outputs: [file list] Get the list of outputs from a target.\n"
78 " get_target_outputs(target_label)\n"
80 " Returns a list of output files for the named target. The named target\n"
81 " must have been previously defined in the current file before this\n"
82 " function is called (it can't reference targets in other files because\n"
83 " there isn't a defined execution order, and it obviously can't\n"
84 " reference targets that are defined after the function call).\n"
88 " The names in the resulting list will be absolute file paths (normally\n"
89 " like \"//out/Debug/bar.exe\", depending on the build directory).\n"
91 " action targets: this will just return the files specified in the\n"
92 " \"outputs\" variable of the target.\n"
94 " action_foreach targets: this will return the result of applying\n"
95 " the output template to the sources (see \"gn help source_expansion\").\n"
96 " This will be the same result (though with guaranteed absolute file\n"
97 " paths), as process_file_template will return for those inputs\n"
98 " (see \"gn help process_file_template\").\n"
100 " binary targets (executables, libraries): this will return a list\n"
101 " of the resulting binary file(s). The \"main output\" (the actual\n"
102 " binary or library) will always be the 0th element in the result.\n"
103 " Depending on the platform and output type, there may be other output\n"
104 " files as well (like import libraries) which will follow.\n"
106 " source sets and groups: this will return a list containing the path of\n"
107 " the \"stamp\" file that Ninja will produce once all outputs are\n"
108 " generated. This probably isn't very useful.\n"
112 " # Say this action generates a bunch of C source files.\n"
113 " action_foreach(\"my_action\") {\n"
114 " sources = [ ... ]\n"
115 " outputs = [ ... ]\n"
118 " # Compile the resulting source files into a source set.\n"
119 " source_set(\"my_lib\") {\n"
120 " sources = get_target_outputs(\":my_action\")\n"
123 Value
RunGetTargetOutputs(Scope
* scope
,
124 const FunctionCallNode
* function
,
125 const std::vector
<Value
>& args
,
127 if (args
.size() != 1) {
128 *err
= Err(function
, "Expected one argument.");
132 // Resolve the requested label.
133 Label label
= Label::Resolve(scope
->GetSourceDir(),
134 ToolchainLabelForScope(scope
), args
[0], err
);
138 // Find the referenced target. The targets previously encountered in this
139 // scope will have been stashed in the item collector (they'll be dispatched
140 // when this file is done running) so we can look through them.
141 const Target
* target
= NULL
;
142 Scope::ItemVector
* collector
= scope
->GetItemCollector();
144 *err
= Err(function
, "No targets defined in this context.");
147 for (size_t i
= 0; i
< collector
->size(); i
++) {
148 const Item
* item
= (*collector
)[i
]->get();
149 if (item
->label() != label
)
152 const Target
* as_target
= item
->AsTarget();
154 *err
= Err(function
, "Label does not refer to a target.",
155 label
.GetUserVisibleName(false) +
156 "\nrefers to a " + item
->GetItemTypeName());
164 *err
= Err(function
, "Target not found in this context.",
165 label
.GetUserVisibleName(false) +
166 "\nwas not found. get_target_outputs() can only be used for targets\n"
167 "previously defined in the current file.");
171 std::vector
<std::string
> files
;
172 GetOutputsForTarget(scope
->settings(), target
, &files
);
174 Value
ret(function
, Value::LIST
);
175 ret
.list_value().reserve(files
.size());
176 for (size_t i
= 0; i
< files
.size(); i
++)
177 ret
.list_value().push_back(Value(function
, files
[i
]));
182 } // namespace functions