Add utility functions needed for rect-based event targeting
[chromium-blink-merge.git] / tools / gn / function_toolchain.cc
blob933d55e9beed316fae019222a3db3702a97567dc
1 // Copyright (c) 2013 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/err.h"
6 #include "tools/gn/functions.h"
7 #include "tools/gn/parse_tree.h"
8 #include "tools/gn/scheduler.h"
9 #include "tools/gn/scope.h"
10 #include "tools/gn/settings.h"
11 #include "tools/gn/toolchain.h"
13 namespace functions {
15 namespace {
17 // This is jsut a unique value to take the address of to use as the key for
18 // the toolchain property on a scope.
19 const int kToolchainPropertyKey = 0;
21 // Reads the given string from the scope (if present) and puts the result into
22 // dest. If the value is not a string, sets the error and returns false.
23 bool ReadString(Scope& scope, const char* var, std::string* dest, Err* err) {
24 const Value* v = scope.GetValue(var, true);
25 if (!v)
26 return true; // Not present is fine.
28 if (!v->VerifyTypeIs(Value::STRING, err))
29 return false;
30 *dest = v->string_value();
31 return true;
34 } // namespace
36 // toolchain -------------------------------------------------------------------
38 const char kToolchain[] = "toolchain";
39 const char kToolchain_Help[] =
40 "toolchain: Defines a toolchain.\n"
41 "\n"
42 " A toolchain is a set of commands and build flags used to compile the\n"
43 " source code. You can have more than one toolchain in use at once in\n"
44 " a build.\n"
45 "\n"
46 " A toolchain specifies the commands to run for various input file\n"
47 " types via the \"tool\" call (see \"gn help tool\") and specifies\n"
48 " arguments to be passed to the toolchain build via the\n"
49 " \"toolchain_args\" call (see \"gn help toolchain_args\").\n"
50 "\n"
51 "Invoking targets in toolchains:\n"
52 "\n"
53 " By default, when a target depends on another, there is an implicit\n"
54 " toolchain label that is inherited, so the dependee has the same one\n"
55 " as the dependant.\n"
56 "\n"
57 " You can override this and refer to any other toolchain by explicitly\n"
58 " labeling the toolchain to use. For example:\n"
59 " datadeps = [ \"//plugins:mine(//toolchains:plugin_toolchain)\" ]\n"
60 " The string \"//build/toolchains:plugin_toolchain\" is a label that\n"
61 " identifies the toolchain declaration for compiling the sources.\n"
62 "\n"
63 " To load a file in an alternate toolchain, GN does the following:\n"
64 "\n"
65 " 1. Loads the file with the toolchain definition in it (as determined\n"
66 " by the toolchain label).\n"
67 " 2. Re-runs the master build configuration file, applying the\n"
68 " arguments specified by the toolchain_args section of the toolchain\n"
69 " definition (see \"gn help toolchain_args\").\n"
70 " 3. Loads the destination build file in the context of the\n"
71 " configuration file in the previous step.\n"
72 "\n"
73 "Example:\n"
74 " toolchain(\"plugin_toolchain\") {\n"
75 " tool(\"cc\") {\n"
76 " command = \"gcc $in\""
77 " }\n"
78 "\n"
79 " toolchain_args() {\n"
80 " is_plugin = true\n"
81 " is_32bit = true\n"
82 " is_64bit = false\n"
83 " }\n"
84 " }\n";
86 Value RunToolchain(Scope* scope,
87 const FunctionCallNode* function,
88 const std::vector<Value>& args,
89 BlockNode* block,
90 Err* err) {
91 if (!EnsureNotProcessingImport(function, scope, err) ||
92 !EnsureNotProcessingBuildConfig(function, scope, err))
93 return Value();
95 // Note that we don't want to use MakeLabelForScope since that will include
96 // the toolchain name in the label, and toolchain labels don't themselves
97 // have toolchain names.
98 const SourceDir& input_dir = scope->GetSourceDir();
99 Label label(input_dir, args[0].string_value());
100 if (g_scheduler->verbose_logging())
101 g_scheduler->Log("Generating toolchain", label.GetUserVisibleName(false));
103 // This object will actually be copied into the one owned by the toolchain
104 // manager, but that has to be done in the lock.
105 Toolchain toolchain(label);
107 Scope block_scope(scope);
108 block_scope.SetProperty(&kToolchainPropertyKey, &toolchain);
109 block->ExecuteBlockInScope(&block_scope, err);
110 block_scope.SetProperty(&kToolchainPropertyKey, NULL);
111 if (err->has_error())
112 return Value();
113 if (!block_scope.CheckForUnusedVars(err))
114 return Value();
116 const BuildSettings* build_settings = scope->settings()->build_settings();
118 // Save the toolchain definition in the toolchain manager and mark the
119 // corresponding item in the dependency tree resolved so that targets
120 // that depend on this toolchain know it's ready.
121 base::AutoLock lock(build_settings->item_tree().lock());
122 build_settings->toolchain_manager().SetToolchainDefinitionLocked(
123 toolchain, function->GetRange(), err);
124 build_settings->item_tree().MarkItemDefinedLocked(build_settings, label,
125 err);
127 return Value();
130 // tool ------------------------------------------------------------------------
132 const char kTool[] = "tool";
133 const char kTool_Help[] =
134 "tool: Specify arguments to a toolchain tool.\n"
135 "\n"
136 " tool(<command type>) { <command flags> }\n"
137 "\n"
138 " Used inside a toolchain definition to define a command to run for a\n"
139 " given file type. See also \"gn help toolchain\".\n"
140 "\n"
141 "Command types:\n"
142 " The following values may be passed to the tool() function for the type\n"
143 " of the command:\n"
144 "\n"
145 " \"cc\", \"cxx\", \"objc\", \"objcxx\", \"asm\", \"alink\", \"solink\",\n"
146 " \"link\", \"stamp\", \"copy\"\n"
147 "\n"
148 "Command flags:\n"
149 "\n"
150 " These variables may be specified in the { } block after the tool call.\n"
151 " They are passed directly to Ninja. See the ninja documentation for how\n"
152 " they work. Don't forget to backslash-escape $ required by Ninja to\n"
153 " prevent GN from doing variable expansion.\n"
154 "\n"
155 " command, depfile, deps, description, pool, restat, rspfile,\n"
156 " rspfile_content\n"
157 "\n"
158 " Additionally, lib_prefix and lib_dir_prefix may be used for the link\n"
159 " tools. These strings will be prepended to the libraries and library\n"
160 " search directories, respectively, because linkers differ on how to\n"
161 " specify them.\n"
162 "\n"
163 "Example:\n"
164 " toolchain(\"my_toolchain\") {\n"
165 " # Put these at the top to apply to all tools below.\n"
166 " lib_prefix = \"-l\"\n"
167 " lib_dir_prefix = \"-L\"\n"
168 "\n"
169 " tool(\"cc\") {\n"
170 " command = \"gcc \\$in -o \\$out\"\n"
171 " description = \"GCC \\$in\"\n"
172 " }\n"
173 " tool(\"cxx\") {\n"
174 " command = \"g++ \\$in -o \\$out\"\n"
175 " description = \"G++ \\$in\"\n"
176 " }\n"
177 " }\n";
179 Value RunTool(Scope* scope,
180 const FunctionCallNode* function,
181 const std::vector<Value>& args,
182 BlockNode* block,
183 Err* err) {
184 // Find the toolchain definition we're executing inside of. The toolchain
185 // function will set a property pointing to it that we'll pick up.
186 Toolchain* toolchain = reinterpret_cast<Toolchain*>(
187 scope->GetProperty(&kToolchainPropertyKey, NULL));
188 if (!toolchain) {
189 *err = Err(function->function(), "tool() called outside of toolchain().",
190 "The tool() function can only be used inside a toolchain() "
191 "definition.");
192 return Value();
195 if (!EnsureSingleStringArg(function, args, err))
196 return Value();
197 const std::string& tool_name = args[0].string_value();
198 Toolchain::ToolType tool_type = Toolchain::ToolNameToType(tool_name);
199 if (tool_type == Toolchain::TYPE_NONE) {
200 *err = Err(args[0], "Unknown tool type");
201 return Value();
204 // Run the tool block.
205 Scope block_scope(scope);
206 block->ExecuteBlockInScope(&block_scope, err);
207 if (err->has_error())
208 return Value();
210 // Extract the stuff we need.
211 Toolchain::Tool t;
212 if (!ReadString(block_scope, "command", &t.command, err) ||
213 !ReadString(block_scope, "depfile", &t.depfile, err) ||
214 !ReadString(block_scope, "deps", &t.deps, err) ||
215 !ReadString(block_scope, "description", &t.description, err) ||
216 !ReadString(block_scope, "lib_dir_prefix", &t.lib_dir_prefix, err) ||
217 !ReadString(block_scope, "lib_prefix", &t.lib_prefix, err) ||
218 !ReadString(block_scope, "pool", &t.pool, err) ||
219 !ReadString(block_scope, "restat", &t.restat, err) ||
220 !ReadString(block_scope, "rspfile", &t.rspfile, err) ||
221 !ReadString(block_scope, "rspfile_content", &t.rspfile_content, err))
222 return Value();
224 // Make sure there weren't any vars set in this tool that were unused.
225 if (!block_scope.CheckForUnusedVars(err))
226 return Value();
228 toolchain->SetTool(tool_type, t);
229 return Value();
232 // toolchain_args --------------------------------------------------------------
234 extern const char kToolchainArgs[] = "toolchain_args";
235 extern const char kToolchainArgs_Help[] =
236 "toolchain_args: Set build arguments for toolchain build setup.\n"
237 "\n"
238 " Used inside a toolchain definition to pass arguments to an alternate\n"
239 " toolchain's invocation of the build.\n"
240 "\n"
241 " When you specify a target using an alternate toolchain, the master\n"
242 " build configuration file is re-interpreted in the context of that\n"
243 " toolchain (see \"gn help toolchain\"). The toolchain_args function\n"
244 " allows you to control the arguments passed into this alternate\n"
245 " invocation of the build.\n"
246 "\n"
247 " Any default system arguments or arguments passed in on the command-\n"
248 " line will also be passed to the alternate invocation unless explicitly\n"
249 " overridden by toolchain_args.\n"
250 "\n"
251 " The toolchain_args will be ignored when the toolchain being defined\n"
252 " is the default. In this case, it's expected you want the default\n"
253 " argument values.\n"
254 "\n"
255 " See also \"gn help buildargs\" for an overview of these arguments.\n"
256 "\n"
257 "Example:\n"
258 " toolchain(\"my_weird_toolchain\") {\n"
259 " ...\n"
260 " toolchain_args() {\n"
261 " # Override the system values for a generic Posix system.\n"
262 " is_win = false\n"
263 " is_posix = true\n"
264 "\n"
265 " # Pass this new value for specific setup for my toolchain.\n"
266 " is_my_weird_system = true\n"
267 " }\n"
268 " }\n";
270 Value RunToolchainArgs(Scope* scope,
271 const FunctionCallNode* function,
272 const std::vector<Value>& args,
273 BlockNode* block,
274 Err* err) {
275 // Find the toolchain definition we're executing inside of. The toolchain
276 // function will set a property pointing to it that we'll pick up.
277 Toolchain* toolchain = reinterpret_cast<Toolchain*>(
278 scope->GetProperty(&kToolchainPropertyKey, NULL));
279 if (!toolchain) {
280 *err = Err(function->function(),
281 "toolchain_args() called outside of toolchain().",
282 "The toolchain_args() function can only be used inside a "
283 "toolchain() definition.");
284 return Value();
287 if (!args.empty()) {
288 *err = Err(function->function(), "This function takes no arguments.");
289 return Value();
292 // This function makes a new scope with various variable sets on it, which
293 // we then save on the toolchain to use when re-invoking the build.
294 Scope block_scope(scope);
295 block->ExecuteBlockInScope(&block_scope, err);
296 if (err->has_error())
297 return Value();
299 Scope::KeyValueMap values;
300 block_scope.GetCurrentScopeValues(&values);
301 toolchain->args() = values;
303 return Value();
306 } // namespace functions