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"
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);
26 return true; // Not present is fine.
28 if (!v
->VerifyTypeIs(Value::STRING
, err
))
30 *dest
= v
->string_value();
36 // toolchain -------------------------------------------------------------------
38 const char kToolchain
[] = "toolchain";
39 const char kToolchain_Help
[] =
40 "toolchain: Defines a toolchain.\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"
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"
51 "Invoking targets in toolchains:\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"
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"
63 " To load a file in an alternate toolchain, GN does the following:\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"
74 " toolchain(\"plugin_toolchain\") {\n"
76 " command = \"gcc $in\""
79 " toolchain_args() {\n"
86 Value
RunToolchain(Scope
* scope
,
87 const FunctionCallNode
* function
,
88 const std::vector
<Value
>& args
,
91 if (!EnsureNotProcessingImport(function
, scope
, err
) ||
92 !EnsureNotProcessingBuildConfig(function
, scope
, err
))
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())
113 if (!block_scope
.CheckForUnusedVars(err
))
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
,
130 // tool ------------------------------------------------------------------------
132 const char kTool
[] = "tool";
133 const char kTool_Help
[] =
134 "tool: Specify arguments to a toolchain tool.\n"
136 " tool(<command type>) { <command flags> }\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"
142 " The following values may be passed to the tool() function for the type\n"
145 " \"cc\", \"cxx\", \"objc\", \"objcxx\", \"asm\", \"alink\", \"solink\",\n"
146 " \"link\", \"stamp\", \"copy\"\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"
155 " command, depfile, deps, description, pool, restat, rspfile,\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"
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"
170 " command = \"gcc \\$in -o \\$out\"\n"
171 " description = \"GCC \\$in\"\n"
174 " command = \"g++ \\$in -o \\$out\"\n"
175 " description = \"G++ \\$in\"\n"
179 Value
RunTool(Scope
* scope
,
180 const FunctionCallNode
* function
,
181 const std::vector
<Value
>& args
,
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
));
189 *err
= Err(function
->function(), "tool() called outside of toolchain().",
190 "The tool() function can only be used inside a toolchain() "
195 if (!EnsureSingleStringArg(function
, args
, err
))
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");
204 // Run the tool block.
205 Scope
block_scope(scope
);
206 block
->ExecuteBlockInScope(&block_scope
, err
);
207 if (err
->has_error())
210 // Extract the stuff we need.
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
))
224 // Make sure there weren't any vars set in this tool that were unused.
225 if (!block_scope
.CheckForUnusedVars(err
))
228 toolchain
->SetTool(tool_type
, t
);
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"
238 " Used inside a toolchain definition to pass arguments to an alternate\n"
239 " toolchain's invocation of the build.\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"
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"
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"
255 " See also \"gn help buildargs\" for an overview of these arguments.\n"
258 " toolchain(\"my_weird_toolchain\") {\n"
260 " toolchain_args() {\n"
261 " # Override the system values for a generic Posix system.\n"
265 " # Pass this new value for specific setup for my toolchain.\n"
266 " is_my_weird_system = true\n"
270 Value
RunToolchainArgs(Scope
* scope
,
271 const FunctionCallNode
* function
,
272 const std::vector
<Value
>& args
,
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
));
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.");
288 *err
= Err(function
->function(), "This function takes no arguments.");
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())
299 Scope::KeyValueMap values
;
300 block_scope
.GetCurrentScopeValues(&values
);
301 toolchain
->args() = values
;
306 } // namespace functions