OLD | NEW |
---|---|
(Empty) | |
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/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" | |
13 | |
14 namespace functions { | |
15 | |
16 namespace { | |
17 | |
18 void GetOutputsForTarget(const BuildSettings* build_settings, | |
19 const Target* target, | |
20 std::vector<std::string>* ret) { | |
21 switch (target->output_type()) { | |
22 case Target::ACTION: | |
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()); | |
29 return; | |
scottmg
2014/05/05 16:31:15
these |return|s rather than break are a bit odd
| |
30 } | |
31 | |
32 case Target::ACTION_FOREACH: { | |
33 // Action_foreach: return the result of the template in the outputs. | |
34 FileTemplate file_template(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.ApplyString(sources[i].value(), ret); | |
38 return; | |
39 } | |
40 | |
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. | |
46 // | |
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 | |
49 // import library). | |
50 case Target::GROUP: | |
51 case Target::SOURCE_SET: { | |
52 // These return the stamp file, which is computed by the NinjaHelper. | |
53 NinjaHelper helper(build_settings); | |
54 OutputFile output_file = helper.GetTargetOutputFile(target); | |
55 | |
56 // The output file is relative to the build dir. | |
57 std::string absolute_output_file = build_settings->build_dir().value(); | |
58 absolute_output_file.append(output_file.value()); | |
59 | |
60 ret->push_back(absolute_output_file); | |
61 return; | |
62 } | |
63 | |
64 default: | |
65 NOTREACHED(); | |
66 } | |
67 } | |
68 | |
69 } // namespace | |
70 | |
71 const char kGetTargetOutputs[] = "get_target_outputs"; | |
72 const char kGetTargetOutputs_HelpShort[] = | |
73 "get_target_outputs: [file list] Get the list of outputs from a target."; | |
74 const char kGetTargetOutputs_Help[] = | |
75 "get_target_outputs: [file list] Get the list of outputs from a target.\n" | |
76 "\n" | |
77 " get_target_outputs(target_label)\n" | |
78 "\n" | |
79 " Returns a list of output files for the named target. The named target\n" | |
80 " must have been previously defined in the current file before this\n" | |
81 " function is called (it can't reference targets in other files because\n" | |
82 " there isn't a defined execution order, and it obviously can't\n" | |
83 " reference targets that are defined after the function call).\n" | |
84 "\n" | |
85 "Return value\n" | |
86 "\n" | |
87 " The names in the resulting list will be absolute file paths (normally\n" | |
88 " like \"//out/Debug/bar.exe\", depending on the build directory).\n" | |
89 "\n" | |
90 " action targets: this will just return the files specified in the\n" | |
91 " \"outputs\" variable of the target.\n" | |
92 "\n" | |
93 " action_foreach targets: this will return the result of applying\n" | |
94 " the output template to the sources (see \"gn help source_expansion\").\n" | |
95 " This will be the same result (though with guaranteed absolute file\n" | |
96 " paths), as process_file_template will return for those inputs\n" | |
97 " (see \"gn help process_file_template\").\n" | |
98 "\n" | |
99 " binary targets (executables, libraries): this will return a list\n" | |
100 " of the resulting binary file(s). The \"main output\" (the actual\n" | |
101 " binary or library) will always be the 0th element in the result.\n" | |
102 " Depending on the platform and output type, there may be other output\n" | |
103 " files as well (like import libraries) which will follow.\n" | |
104 "\n" | |
105 " source sets and groups: this will return a list containing the path of\n" | |
106 " the \"stamp\" file that Ninja will produce once all outputs are\n" | |
107 " generated. This probably isn't very useful.\n" | |
108 "\n" | |
109 "Example\n" | |
110 "\n" | |
111 " # Say this action generates a bunch of C source files.\n" | |
112 " action_foreach(\"my_action\") {\n" | |
113 " sources = [ ... ]\n" | |
114 " outputs = [ ... ]\n" | |
115 " }\n" | |
116 "\n" | |
117 " # Compile the resulting source files into a source set.\n" | |
118 " source_set(\"my_lib\") {\n" | |
119 " sources = get_target_outputs(\":my_action\")\n" | |
120 " }\n"; | |
121 | |
122 Value RunGetTargetOutputs(Scope* scope, | |
123 const FunctionCallNode* function, | |
124 const std::vector<Value>& args, | |
125 Err* err) { | |
126 if (args.size() != 1) { | |
127 *err = Err(function, "Expected one argument."); | |
128 return Value(); | |
129 } | |
130 | |
131 // Resolve the requested label. | |
132 Label label = Label::Resolve(scope->GetSourceDir(), | |
133 ToolchainLabelForScope(scope), args[0], err); | |
134 if (label.is_null()) | |
135 return Value(); | |
136 | |
137 // Find the referenced target. The targets previously encountered in this | |
138 // scope will have been stashed in the item collector (they'll be dispatched | |
139 // when this file is done running) so we can look through them. | |
140 const Target* target = NULL; | |
141 Scope::ItemVector* collector = scope->GetItemCollector(); | |
142 if (!collector) { | |
143 *err = Err(function, "No targets defined in this context."); | |
144 return Value(); | |
145 } | |
146 for (size_t i = 0; i < collector->size(); i++) { | |
147 const Item* item = (*collector)[i]->get(); | |
148 if (item->label() != label) | |
149 continue; | |
150 | |
151 const Target* as_target = item->AsTarget(); | |
152 if (!as_target) { | |
153 *err = Err(function, "Label does not refer to a target.", | |
154 label.GetUserVisibleName(false) + | |
155 "\nrefers to a " + item->GetItemTypeName()); | |
156 return Value(); | |
157 } | |
158 target = as_target; | |
159 break; | |
160 } | |
161 | |
162 if (!target) { | |
163 *err = Err(function, "Target not found in this context.", | |
164 label.GetUserVisibleName(false) + | |
165 "\nwas not found. get_target_outputs() can only be used for targets\n" | |
166 "previously defined in the current file."); | |
167 return Value(); | |
168 } | |
169 | |
170 std::vector<std::string> files; | |
171 GetOutputsForTarget(scope->settings()->build_settings(), target, &files); | |
172 | |
173 Value ret(function, Value::LIST); | |
174 ret.list_value().reserve(files.size()); | |
175 for (size_t i = 0; i < files.size(); i++) | |
176 ret.list_value().push_back(Value(function, files[i])); | |
177 | |
178 return ret; | |
179 } | |
180 | |
181 } // namespace function | |
scottmg
2014/05/05 16:31:15
functions
| |
OLD | NEW |