forked from sanyaade-mobiledev/chromium.src
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfunction_get_target_outputs.cc
183 lines (163 loc) · 6.66 KB
/
function_get_target_outputs.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
// 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/file_template.h"
#include "tools/gn/functions.h"
#include "tools/gn/ninja_helper.h"
#include "tools/gn/parse_tree.h"
#include "tools/gn/settings.h"
#include "tools/gn/target.h"
#include "tools/gn/value.h"
namespace functions {
namespace {
void GetOutputsForTarget(const Settings* settings,
const Target* target,
std::vector<std::string>* ret) {
switch (target->output_type()) {
case Target::ACTION: {
// Actions: return the outputs specified.
const std::vector<std::string>& outs = target->action_values().outputs();
ret->reserve(outs.size());
for (size_t i = 0; i < outs.size(); i++)
ret->push_back(outs[i]);
break;
}
case Target::COPY_FILES:
case Target::ACTION_FOREACH: {
// Copy/action_foreach: return the result of the template in the outputs.
FileTemplate file_template(settings, target->action_values().outputs(),
FileTemplate::OUTPUT_ABSOLUTE, SourceDir());
const std::vector<SourceFile>& sources = target->sources();
for (size_t i = 0; i < sources.size(); i++)
file_template.Apply(sources[i], ret);
break;
}
case Target::EXECUTABLE:
case Target::SHARED_LIBRARY:
case Target::STATIC_LIBRARY:
// Return the resulting binary file. Currently, fall through to the
// Ninja helper below which will compute the main output name.
//
// TODO(brettw) some targets have secondary files which should go into
// the list after the main (like shared libraries on Windows have an
// import library).
case Target::GROUP:
case Target::SOURCE_SET: {
// These return the stamp file, which is computed by the NinjaHelper.
NinjaHelper helper(settings->build_settings());
OutputFile output_file = helper.GetTargetOutputFile(target);
// The output file is relative to the build dir.
std::string absolute_output_file =
settings->build_settings()->build_dir().value();
absolute_output_file.append(output_file.value());
ret->push_back(absolute_output_file);
break;
}
default:
NOTREACHED();
}
}
} // namespace
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[] =
"get_target_outputs: [file list] Get the list of outputs from a target.\n"
"\n"
" get_target_outputs(target_label)\n"
"\n"
" Returns a list of output files for the named target. The named target\n"
" must have been previously defined in the current file before this\n"
" function is called (it can't reference targets in other files because\n"
" there isn't a defined execution order, and it obviously can't\n"
" reference targets that are defined after the function call).\n"
"\n"
"Return value\n"
"\n"
" The names in the resulting list will be absolute file paths (normally\n"
" like \"//out/Debug/bar.exe\", depending on the build directory).\n"
"\n"
" action targets: this will just return the files specified in the\n"
" \"outputs\" variable of the target.\n"
"\n"
" action_foreach targets: this will return the result of applying\n"
" the output template to the sources (see \"gn help source_expansion\").\n"
" This will be the same result (though with guaranteed absolute file\n"
" paths), as process_file_template will return for those inputs\n"
" (see \"gn help process_file_template\").\n"
"\n"
" binary targets (executables, libraries): this will return a list\n"
" of the resulting binary file(s). The \"main output\" (the actual\n"
" binary or library) will always be the 0th element in the result.\n"
" Depending on the platform and output type, there may be other output\n"
" files as well (like import libraries) which will follow.\n"
"\n"
" source sets and groups: this will return a list containing the path of\n"
" the \"stamp\" file that Ninja will produce once all outputs are\n"
" generated. This probably isn't very useful.\n"
"\n"
"Example\n"
"\n"
" # Say this action generates a bunch of C source files.\n"
" action_foreach(\"my_action\") {\n"
" sources = [ ... ]\n"
" outputs = [ ... ]\n"
" }\n"
"\n"
" # Compile the resulting source files into a source set.\n"
" source_set(\"my_lib\") {\n"
" sources = get_target_outputs(\":my_action\")\n"
" }\n";
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 = NULL;
Scope::ItemVector* collector = scope->GetItemCollector();
if (!collector) {
*err = Err(function, "No targets defined in this context.");
return Value();
}
for (size_t i = 0; i < collector->size(); i++) {
const Item* item = (*collector)[i]->get();
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();
}
std::vector<std::string> files;
GetOutputsForTarget(scope->settings(), target, &files);
Value ret(function, Value::LIST);
ret.list_value().reserve(files.size());
for (size_t i = 0; i < files.size(); i++)
ret.list_value().push_back(Value(function, files[i]));
return ret;
}
} // namespace functions