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.
8 #include "tools/gn/err.h"
9 #include "tools/gn/functions.h"
10 #include "tools/gn/parse_tree.h"
11 #include "tools/gn/scheduler.h"
12 #include "tools/gn/scope.h"
13 #include "tools/gn/settings.h"
14 #include "tools/gn/tool.h"
15 #include "tools/gn/toolchain.h"
16 #include "tools/gn/value_extractors.h"
17 #include "tools/gn/variables.h"
23 // This is jsut a unique value to take the address of to use as the key for
24 // the toolchain property on a scope.
25 const int kToolchainPropertyKey
= 0;
27 bool ReadBool(Scope
* scope
,
30 void (Tool::*set
)(bool),
32 const Value
* v
= scope
->GetValue(var
, true);
34 return true; // Not present is fine.
35 if (!v
->VerifyTypeIs(Value::BOOLEAN
, err
))
38 (tool
->*set
)(v
->boolean_value());
42 // Reads the given string from the scope (if present) and puts the result into
43 // dest. If the value is not a string, sets the error and returns false.
44 bool ReadString(Scope
* scope
,
47 void (Tool::*set
)(const std::string
&),
49 const Value
* v
= scope
->GetValue(var
, true);
51 return true; // Not present is fine.
52 if (!v
->VerifyTypeIs(Value::STRING
, err
))
55 (tool
->*set
)(v
->string_value());
59 // Calls the given validate function on each type in the list. On failure,
60 // sets the error, blame the value, and return false.
61 bool ValidateSubstitutionList(const std::vector
<SubstitutionType
>& list
,
62 bool (*validate
)(SubstitutionType
),
65 for (const auto& cur_type
: list
) {
66 if (!validate(cur_type
)) {
67 *err
= Err(*origin
, "Pattern not valid here.",
68 "You used the pattern " + std::string(kSubstitutionNames
[cur_type
]) +
69 " which is not valid\nfor this variable.");
76 bool ReadPattern(Scope
* scope
,
78 bool (*validate
)(SubstitutionType
),
80 void (Tool::*set
)(const SubstitutionPattern
&),
82 const Value
* value
= scope
->GetValue(name
, true);
84 return true; // Not present is fine.
85 if (!value
->VerifyTypeIs(Value::STRING
, err
))
88 SubstitutionPattern pattern
;
89 if (!pattern
.Parse(*value
, err
))
91 if (!ValidateSubstitutionList(pattern
.required_types(), validate
, value
, err
))
94 (tool
->*set
)(pattern
);
98 bool ReadOutputExtension(Scope
* scope
, Tool
* tool
, Err
* err
) {
99 const Value
* value
= scope
->GetValue("default_output_extension", true);
101 return true; // Not present is fine.
102 if (!value
->VerifyTypeIs(Value::STRING
, err
))
105 if (value
->string_value().empty())
106 return true; // Accept empty string.
108 if (value
->string_value()[0] != '.') {
109 *err
= Err(*value
, "default_output_extension must begin with a '.'");
113 tool
->set_default_output_extension(value
->string_value());
117 bool ReadDepsFormat(Scope
* scope
, Tool
* tool
, Err
* err
) {
118 const Value
* value
= scope
->GetValue("depsformat", true);
120 return true; // Not present is fine.
121 if (!value
->VerifyTypeIs(Value::STRING
, err
))
124 if (value
->string_value() == "gcc") {
125 tool
->set_depsformat(Tool::DEPS_GCC
);
126 } else if (value
->string_value() == "msvc") {
127 tool
->set_depsformat(Tool::DEPS_MSVC
);
129 *err
= Err(*value
, "Deps format must be \"gcc\" or \"msvc\".");
135 bool ReadOutputs(Scope
* scope
,
136 const FunctionCallNode
* tool_function
,
137 bool (*validate
)(SubstitutionType
),
140 const Value
* value
= scope
->GetValue("outputs", true);
142 *err
= Err(tool_function
, "\"outputs\" must be specified for this tool.");
146 SubstitutionList list
;
147 if (!list
.Parse(*value
, err
))
150 // Validate the right kinds of patterns are used.
151 if (!ValidateSubstitutionList(list
.required_types(), validate
, value
, err
))
154 // There should always be at least one output.
155 if (list
.list().empty()) {
156 *err
= Err(*value
, "Outputs list is empty.", "I need some outputs.");
160 tool
->set_outputs(list
);
164 bool IsCompilerTool(Toolchain::ToolType type
) {
165 return type
== Toolchain::TYPE_CC
||
166 type
== Toolchain::TYPE_CXX
||
167 type
== Toolchain::TYPE_OBJC
||
168 type
== Toolchain::TYPE_OBJCXX
||
169 type
== Toolchain::TYPE_RC
||
170 type
== Toolchain::TYPE_ASM
;
173 bool IsLinkerTool(Toolchain::ToolType type
) {
174 return type
== Toolchain::TYPE_ALINK
||
175 type
== Toolchain::TYPE_SOLINK
||
176 type
== Toolchain::TYPE_LINK
;
179 bool IsPatternInOutputList(const SubstitutionList
& output_list
,
180 const SubstitutionPattern
& pattern
) {
181 for (const auto& cur
: output_list
.list()) {
182 if (pattern
.ranges().size() == cur
.ranges().size() &&
183 std::equal(pattern
.ranges().begin(), pattern
.ranges().end(),
184 cur
.ranges().begin()))
192 // toolchain -------------------------------------------------------------------
194 const char kToolchain
[] = "toolchain";
195 const char kToolchain_HelpShort
[] =
196 "toolchain: Defines a toolchain.";
197 const char kToolchain_Help
[] =
198 "toolchain: Defines a toolchain.\n"
200 " A toolchain is a set of commands and build flags used to compile the\n"
201 " source code. You can have more than one toolchain in use at once in\n"
204 "Functions and variables\n"
207 " The tool() function call specifies the commands commands to run for\n"
208 " a given step. See \"gn help tool\".\n"
210 " toolchain_args()\n"
211 " List of arguments to pass to the toolchain when invoking this\n"
212 " toolchain. This applies only to non-default toolchains. See\n"
213 " \"gn help toolchain_args\" for more.\n"
216 " Dependencies of this toolchain. These dependencies will be resolved\n"
217 " before any target in the toolchain is compiled. To avoid circular\n"
218 " dependencies these must be targets defined in another toolchain.\n"
220 " This is expressed as a list of targets, and generally these targets\n"
221 " will always specify a toolchain:\n"
222 " deps = [ \"//foo/bar:baz(//build/toolchain:bootstrap)\" ]\n"
224 " This concept is somewhat inefficient to express in Ninja (it\n"
225 " requires a lot of duplicate of rules) so should only be used when\n"
226 " absolutely necessary.\n"
228 " concurrent_links\n"
229 " In integer expressing the number of links that Ninja will perform in\n"
230 " parallel. GN will create a pool for shared library and executable\n"
231 " link steps with this many processes. Since linking is memory- and\n"
232 " I/O-intensive, projects with many large targets may want to limit\n"
233 " the number of parallel steps to avoid overloading the computer.\n"
234 " Since creating static libraries is generally not as intensive\n"
235 " there is no limit to \"alink\" steps.\n"
237 " Defaults to 0 which Ninja interprets as \"no limit\".\n"
239 " The value used will be the one from the default toolchain of the\n"
242 "Invoking targets in toolchains:\n"
244 " By default, when a target depends on another, there is an implicit\n"
245 " toolchain label that is inherited, so the dependee has the same one\n"
246 " as the dependent.\n"
248 " You can override this and refer to any other toolchain by explicitly\n"
249 " labeling the toolchain to use. For example:\n"
250 " data_deps = [ \"//plugins:mine(//toolchains:plugin_toolchain)\" ]\n"
251 " The string \"//build/toolchains:plugin_toolchain\" is a label that\n"
252 " identifies the toolchain declaration for compiling the sources.\n"
254 " To load a file in an alternate toolchain, GN does the following:\n"
256 " 1. Loads the file with the toolchain definition in it (as determined\n"
257 " by the toolchain label).\n"
258 " 2. Re-runs the master build configuration file, applying the\n"
259 " arguments specified by the toolchain_args section of the toolchain\n"
260 " definition (see \"gn help toolchain_args\").\n"
261 " 3. Loads the destination build file in the context of the\n"
262 " configuration file in the previous step.\n"
265 " toolchain(\"plugin_toolchain\") {\n"
266 " concurrent_links = 8\n"
269 " command = \"gcc {{source}}\"\n"
273 " toolchain_args() {\n"
274 " is_plugin = true\n"
276 " is_64bit = false\n"
280 Value
RunToolchain(Scope
* scope
,
281 const FunctionCallNode
* function
,
282 const std::vector
<Value
>& args
,
285 if (!EnsureNotProcessingImport(function
, scope
, err
) ||
286 !EnsureNotProcessingBuildConfig(function
, scope
, err
))
289 // Note that we don't want to use MakeLabelForScope since that will include
290 // the toolchain name in the label, and toolchain labels don't themselves
291 // have toolchain names.
292 const SourceDir
& input_dir
= scope
->GetSourceDir();
293 Label
label(input_dir
, args
[0].string_value());
294 if (g_scheduler
->verbose_logging())
295 g_scheduler
->Log("Defining toolchain", label
.GetUserVisibleName(false));
297 // This object will actually be copied into the one owned by the toolchain
298 // manager, but that has to be done in the lock.
299 scoped_ptr
<Toolchain
> toolchain(new Toolchain(scope
->settings(), label
));
300 toolchain
->set_defined_from(function
);
301 toolchain
->visibility().SetPublic();
303 Scope
block_scope(scope
);
304 block_scope
.SetProperty(&kToolchainPropertyKey
, toolchain
.get());
305 block
->Execute(&block_scope
, err
);
306 block_scope
.SetProperty(&kToolchainPropertyKey
, nullptr);
307 if (err
->has_error())
310 // Read deps (if any).
311 const Value
* deps_value
= block_scope
.GetValue(variables::kDeps
, true);
314 *deps_value
, block_scope
.GetSourceDir(),
315 ToolchainLabelForScope(&block_scope
), &toolchain
->deps(), err
);
316 if (err
->has_error())
320 // Read concurrent_links (if any).
321 const Value
* concurrent_links_value
=
322 block_scope
.GetValue("concurrent_links", true);
323 if (concurrent_links_value
) {
324 if (!concurrent_links_value
->VerifyTypeIs(Value::INTEGER
, err
))
326 if (concurrent_links_value
->int_value() < 0 ||
327 concurrent_links_value
->int_value() > std::numeric_limits
<int>::max()) {
328 *err
= Err(*concurrent_links_value
, "Value out of range.");
331 toolchain
->set_concurrent_links(
332 static_cast<int>(concurrent_links_value
->int_value()));
335 if (!block_scope
.CheckForUnusedVars(err
))
338 // Save this toolchain.
339 toolchain
->ToolchainSetupComplete();
340 Scope::ItemVector
* collector
= scope
->GetItemCollector();
342 *err
= Err(function
, "Can't define a toolchain in this context.");
345 collector
->push_back(toolchain
.release());
349 // tool ------------------------------------------------------------------------
351 const char kTool
[] = "tool";
352 const char kTool_HelpShort
[] =
353 "tool: Specify arguments to a toolchain tool.";
354 const char kTool_Help
[] =
355 "tool: Specify arguments to a toolchain tool.\n"
359 " tool(<tool type>) {\n"
360 " <tool variables...>\n"
366 " \"cc\": C compiler\n"
367 " \"cxx\": C++ compiler\n"
368 " \"objc\": Objective C compiler\n"
369 " \"objcxx\": Objective C++ compiler\n"
370 " \"rc\": Resource compiler (Windows .rc files)\n"
371 " \"asm\": Assembler\n"
374 " \"alink\": Linker for static libraries (archives)\n"
375 " \"solink\": Linker for shared libraries\n"
376 " \"link\": Linker for executables\n"
379 " \"stamp\": Tool for creating stamp files\n"
380 " \"copy\": Tool to copy files.\n"
384 " command [string with substitutions]\n"
385 " Valid for: all tools (required)\n"
387 " The command to run.\n"
389 " default_output_extension [string]\n"
390 " Valid for: linker tools\n"
392 " Extension for the main output of a linkable tool. It includes\n"
393 " the leading dot. This will be the default value for the\n"
394 " {{output_extension}} expansion (discussed below) but will be\n"
395 " overridden by by the \"output extension\" variable in a target,\n"
396 " if one is specified. Empty string means no extension.\n"
398 " GN doesn't actually do anything with this extension other than\n"
399 " pass it along, potentially with target-specific overrides. One\n"
400 " would typically use the {{output_extension}} value in the\n"
401 " \"outputs\" to read this value.\n"
403 " Example: default_output_extension = \".exe\"\n"
405 " depfile [string]\n"
406 " Valid for: compiler tools (optional)\n"
408 " If the tool can write \".d\" files, this specifies the name of\n"
409 " the resulting file. These files are used to list header file\n"
410 " dependencies (or other implicit input dependencies) that are\n"
411 " discovered at build time. See also \"depsformat\".\n"
413 " Example: depfile = \"{{output}}.d\"\n"
415 " depsformat [string]\n"
416 " Valid for: compiler tools (when depfile is specified)\n"
418 " Format for the deps outputs. This is either \"gcc\" or \"msvc\".\n"
419 " See the ninja documentation for \"deps\" for more information.\n"
421 " Example: depsformat = \"gcc\"\n"
423 " description [string with substitutions, optional]\n"
424 " Valid for: all tools\n"
426 " What to print when the command is run.\n"
428 " Example: description = \"Compiling {{source}}\"\n"
430 " lib_switch [string, optional, link tools only]\n"
431 " lib_dir_switch [string, optional, link tools only]\n"
432 " Valid for: Linker tools except \"alink\"\n"
434 " These strings will be prepended to the libraries and library\n"
435 " search directories, respectively, because linkers differ on how\n"
436 " specify them. If you specified:\n"
437 " lib_switch = \"-l\"\n"
438 " lib_dir_switch = \"-L\"\n"
439 " then the \"{{libs}}\" expansion for [ \"freetype\", \"expat\"]\n"
440 " would be \"-lfreetype -lexpat\".\n"
442 " outputs [list of strings with substitutions]\n"
443 " Valid for: Linker and compiler tools (required)\n"
445 " An array of names for the output files the tool produces. These\n"
446 " are relative to the build output directory. There must always be\n"
447 " at least one output file. There can be more than one output (a\n"
448 " linker might produce a library and an import library, for\n"
451 " This array just declares to GN what files the tool will\n"
452 " produce. It is your responsibility to specify the tool command\n"
453 " that actually produces these files.\n"
455 " If you specify more than one output for shared library links,\n"
456 " you should consider setting link_output and depend_output.\n"
457 " Otherwise, the first entry in the outputs list should always be\n"
458 " the main output which will be linked to.\n"
460 " Example for a compiler tool that produces .obj files:\n"
462 " \"{{source_out_dir}}/{{source_name_part}}.obj\"\n"
465 " Example for a linker tool that produces a .dll and a .lib. The\n"
466 " use of {{output_extension}} rather than hardcoding \".dll\"\n"
467 " allows the extension of the library to be overridden on a\n"
468 " target-by-target basis, but in this example, it always\n"
469 " produces a \".lib\" import library:\n"
471 " \"{{root_out_dir}}/{{target_output_name}}"
472 "{{output_extension}}\",\n"
473 " \"{{root_out_dir}}/{{target_output_name}}.lib\",\n"
476 " link_output [string with substitutions]\n"
477 " depend_output [string with substitutions]\n"
478 " Valid for: \"solink\" only (optional)\n"
480 " These two files specify whch of the outputs from the solink\n"
481 " tool should be used for linking and dependency tracking. These\n"
482 " should match entries in the \"outputs\". If unspecified, the\n"
483 " first item in the \"outputs\" array will be used for both. See\n"
484 " \"Separate linking and dependencies for shared libraries\"\n"
487 " On Windows, where the tools produce a .dll shared library and\n"
488 " a .lib import library, you will want both of these to be the\n"
489 " import library. On Linux, if you're not doing the separate\n"
490 " linking/dependency optimization, both of these should be the\n"
493 " output_prefix [string]\n"
494 " Valid for: Linker tools (optional)\n"
496 " Prefix to use for the output name. Defaults to empty. This\n"
497 " prefix will be prepended to the name of the target (or the\n"
498 " output_name if one is manually specified for it) if the prefix\n"
499 " is not already there. The result will show up in the\n"
500 " {{output_name}} substitution pattern.\n"
502 " This is typically used to prepend \"lib\" to libraries on\n"
504 " output_prefix = \"lib\"\n"
506 " restat [boolean]\n"
507 " Valid for: all tools (optional, defaults to false)\n"
509 " Requests that Ninja check the file timestamp after this tool has\n"
510 " run to determine if anything changed. Set this if your tool has\n"
511 " the ability to skip writing output if the output file has not\n"
514 " Normally, Ninja will assume that when a tool runs the output\n"
515 " be new and downstream dependents must be rebuild. When this is\n"
516 " set to trye, Ninja can skip rebuilding downstream dependents for\n"
517 " input changes that don't actually affect the output.\n"
522 " rspfile [string with substitutions]\n"
523 " Valid for: all tools (optional)\n"
525 " Name of the response file. If empty, no response file will be\n"
526 " used. See \"rspfile_content\".\n"
528 " rspfile_content [string with substitutions]\n"
529 " Valid for: all tools (required when \"rspfile\" is specified)\n"
531 " The contents to be written to the response file. This may\n"
532 " include all or part of the command to send to the tool which\n"
533 " allows you to get around OS command-line length limits.\n"
535 " This example adds the inputs and libraries to a response file,\n"
536 " but passes the linker flags directly on the command line:\n"
537 " tool(\"link\") {\n"
538 " command = \"link -o {{output}} {{ldflags}} @{{output}}.rsp\"\n"
539 " rspfile = \"{{output}}.rsp\"\n"
540 " rspfile_content = \"{{inputs}} {{solibs}} {{libs}}\"\n"
543 "Expansions for tool variables"
545 " All paths are relative to the root build directory, which is the\n"
546 " current directory for running all tools. These expansions are\n"
547 " available to all tools:\n"
550 " The label of the current target. This is typically used in the\n"
551 " \"description\" field for link tools. The toolchain will be\n"
552 " omitted from the label for targets in the default toolchain, and\n"
553 " will be included for targets in other toolchains.\n"
556 " The relative path and name of the output(s) of the current\n"
557 " build step. If there is more than one output, this will expand\n"
558 " to a list of all of them.\n"
559 " Example: \"out/base/my_file.o\"\n"
561 " {{target_gen_dir}}\n"
562 " {{target_out_dir}}\n"
563 " The directory of the generated file and output directories,\n"
564 " respectively, for the current target. There is no trailing\n"
566 " Example: \"out/base/test\"\n"
568 " {{target_output_name}}\n"
569 " The short name of the current target with no path information,\n"
570 " or the value of the \"output_name\" variable if one is specified\n"
571 " in the target. This will include the \"output_prefix\" if any.\n"
572 " Example: \"libfoo\" for the target named \"foo\" and an\n"
573 " output prefix for the linker tool of \"lib\".\n"
575 " Compiler tools have the notion of a single input and a single output,\n"
576 " along with a set of compiler-specific flags. The following expansions\n"
583 " {{cflags_objcc}}\n"
585 " {{include_dirs}}\n"
586 " Strings correspond that to the processed flags/defines/include\n"
587 " directories specified for the target.\n"
588 " Example: \"--enable-foo --enable-bar\"\n"
590 " Defines will be prefixed by \"-D\" and include directories will\n"
591 " be prefixed by \"-I\" (these work with Posix tools as well as\n"
592 " Microsoft ones).\n"
595 " The relative path and name of the current input file.\n"
596 " Example: \"../../base/my_file.cc\"\n"
598 " {{source_file_part}}\n"
599 " The file part of the source including the extension (with no\n"
600 " directory information).\n"
601 " Example: \"foo.cc\"\n"
603 " {{source_name_part}}\n"
604 " The filename part of the source file with no directory or\n"
606 " Example: \"foo\"\n"
608 " {{source_gen_dir}}\n"
609 " {{source_out_dir}}\n"
610 " The directory in the generated file and output directories,\n"
611 " respectively, for the current input file. If the source file\n"
612 " is in the same directory as the target is declared in, they will\n"
613 " will be the same as the \"target\" versions above.\n"
614 " Example: \"gen/base/test\"\n"
616 " Linker tools have multiple inputs and (potentially) multiple outputs\n"
617 " The following expansions are available:\n"
620 " {{inputs_newline}}\n"
621 " Expands to the inputs to the link step. This will be a list of\n"
622 " object files and static libraries.\n"
623 " Example: \"obj/foo.o obj/bar.o obj/somelibrary.a\"\n"
625 " The \"_newline\" version will separate the input files with\n"
626 " newlines instead of spaces. This is useful in response files:\n"
627 " some linkers can take a \"-filelist\" flag which expects newline\n"
628 " separated files, and some Microsoft tools have a fixed-sized\n"
629 " buffer for parsing each line of a response file.\n"
632 " Expands to the processed set of ldflags and library search paths\n"
633 " specified for the target.\n"
634 " Example: \"-m64 -fPIC -pthread -L/usr/local/mylib\"\n"
637 " Expands to the list of system libraries to link to. Each will\n"
638 " be prefixed by the \"lib_prefix\".\n"
640 " As a special case to support Mac, libraries with names ending in\n"
641 " \".framework\" will be added to the {{libs}} with \"-framework\"\n"
642 " preceeding it, and the lib prefix will be ignored.\n"
644 " Example: \"-lfoo -lbar\"\n"
646 " {{output_extension}}\n"
647 " The value of the \"output_extension\" variable in the target,\n"
648 " or the value of the \"default_output_extension\" value in the\n"
649 " tool if the target does not specify an output extension.\n"
650 " Example: \".so\"\n"
653 " Extra libraries from shared library dependencide not specified\n"
654 " in the {{inputs}}. This is the list of link_output files from\n"
655 " shared libraries (if the solink tool specifies a \"link_output\"\n"
656 " variable separate from the \"depend_output\").\n"
658 " These should generally be treated the same as libs by your tool.\n"
659 " Example: \"libfoo.so libbar.so\"\n"
661 " The copy tool allows the common compiler/linker substitutions, plus\n"
662 " {{source}} which is the source of the copy. The stamp tool allows\n"
663 " only the common tool substitutions.\n"
665 "Separate linking and dependencies for shared libraries\n"
667 " Shared libraries are special in that not all changes to them require\n"
668 " that dependent targets be re-linked. If the shared library is changed\n"
669 " but no imports or exports are different, dependent code needn't be\n"
670 " relinked, which can speed up the build.\n"
672 " If your link step can output a list of exports from a shared library\n"
673 " and writes the file only if the new one is different, the timestamp of\n"
674 " this file can be used for triggering re-links, while the actual shared\n"
675 " library would be used for linking.\n"
677 " You will need to specify\n"
679 " in the linker tool to make this work, so Ninja will detect if the\n"
680 " timestamp of the dependency file has changed after linking (otherwise\n"
681 " it will always assume that running a command updates the output):\n"
683 " tool(\"solink\") {\n"
684 " command = \"...\"\n"
686 " \"{{root_out_dir}}/{{target_output_name}}{{output_extension}}\",\n"
687 " \"{{root_out_dir}}/{{target_output_name}}"
688 "{{output_extension}}.TOC\",\n"
691 " \"{{root_out_dir}}/{{target_output_name}}{{output_extension}}\"\n"
693 " \"{{root_out_dir}}/{{target_output_name}}"
694 "{{output_extension}}.TOC\"\n"
700 " toolchain(\"my_toolchain\") {\n"
701 " # Put these at the top to apply to all tools below.\n"
702 " lib_prefix = \"-l\"\n"
703 " lib_dir_prefix = \"-L\"\n"
706 " command = \"gcc {{source}} -o {{output}}\"\n"
707 " outputs = [ \"{{source_out_dir}}/{{source_name_part}}.o\" ]\n"
708 " description = \"GCC {{source}}\"\n"
711 " command = \"g++ {{source}} -o {{output}}\"\n"
712 " outputs = [ \"{{source_out_dir}}/{{source_name_part}}.o\" ]\n"
713 " description = \"G++ {{source}}\"\n"
717 Value
RunTool(Scope
* scope
,
718 const FunctionCallNode
* function
,
719 const std::vector
<Value
>& args
,
722 // Find the toolchain definition we're executing inside of. The toolchain
723 // function will set a property pointing to it that we'll pick up.
724 Toolchain
* toolchain
= reinterpret_cast<Toolchain
*>(
725 scope
->GetProperty(&kToolchainPropertyKey
, nullptr));
727 *err
= Err(function
->function(), "tool() called outside of toolchain().",
728 "The tool() function can only be used inside a toolchain() "
733 if (!EnsureSingleStringArg(function
, args
, err
))
735 const std::string
& tool_name
= args
[0].string_value();
736 Toolchain::ToolType tool_type
= Toolchain::ToolNameToType(tool_name
);
737 if (tool_type
== Toolchain::TYPE_NONE
) {
738 *err
= Err(args
[0], "Unknown tool type");
742 // Run the tool block.
743 Scope
block_scope(scope
);
744 block
->Execute(&block_scope
, err
);
745 if (err
->has_error())
748 // Figure out which validator to use for the substitution pattern for this
749 // tool type. There are different validators for the "outputs" than for the
750 // rest of the strings.
751 bool (*subst_validator
)(SubstitutionType
) = nullptr;
752 bool (*subst_output_validator
)(SubstitutionType
) = nullptr;
753 if (IsCompilerTool(tool_type
)) {
754 subst_validator
= &IsValidCompilerSubstitution
;
755 subst_output_validator
= &IsValidCompilerOutputsSubstitution
;
756 } else if (IsLinkerTool(tool_type
)) {
757 subst_validator
= &IsValidLinkerSubstitution
;
758 subst_output_validator
= &IsValidLinkerOutputsSubstitution
;
759 } else if (tool_type
== Toolchain::TYPE_COPY
) {
760 subst_validator
= &IsValidCopySubstitution
;
761 subst_output_validator
= &IsValidCopySubstitution
;
763 subst_validator
= &IsValidToolSubstutition
;
764 subst_output_validator
= &IsValidToolSubstutition
;
767 scoped_ptr
<Tool
> tool(new Tool
);
769 if (!ReadPattern(&block_scope
, "command", subst_validator
, tool
.get(),
770 &Tool::set_command
, err
) ||
771 !ReadOutputExtension(&block_scope
, tool
.get(), err
) ||
772 !ReadPattern(&block_scope
, "depfile", subst_validator
, tool
.get(),
773 &Tool::set_depfile
, err
) ||
774 !ReadDepsFormat(&block_scope
, tool
.get(), err
) ||
775 !ReadPattern(&block_scope
, "description", subst_validator
, tool
.get(),
776 &Tool::set_description
, err
) ||
777 !ReadString(&block_scope
, "lib_switch", tool
.get(),
778 &Tool::set_lib_switch
, err
) ||
779 !ReadString(&block_scope
, "lib_dir_switch", tool
.get(),
780 &Tool::set_lib_dir_switch
, err
) ||
781 !ReadPattern(&block_scope
, "link_output", subst_validator
, tool
.get(),
782 &Tool::set_link_output
, err
) ||
783 !ReadPattern(&block_scope
, "depend_output", subst_validator
, tool
.get(),
784 &Tool::set_depend_output
, err
) ||
785 !ReadString(&block_scope
, "output_prefix", tool
.get(),
786 &Tool::set_output_prefix
, err
) ||
787 !ReadBool(&block_scope
, "restat", tool
.get(), &Tool::set_restat
, err
) ||
788 !ReadPattern(&block_scope
, "rspfile", subst_validator
, tool
.get(),
789 &Tool::set_rspfile
, err
) ||
790 !ReadPattern(&block_scope
, "rspfile_content", subst_validator
, tool
.get(),
791 &Tool::set_rspfile_content
, err
)) {
795 if (tool_type
!= Toolchain::TYPE_COPY
&& tool_type
!= Toolchain::TYPE_STAMP
) {
796 // All tools except the copy and stamp tools should have outputs. The copy
797 // and stamp tool's outputs are generated internally.
798 if (!ReadOutputs(&block_scope
, function
, subst_output_validator
,
803 // Validate that the link_output and depend_output refer to items in the
804 // outputs and aren't defined for irrelevant tool types.
805 if (!tool
->link_output().empty()) {
806 if (tool_type
!= Toolchain::TYPE_SOLINK
) {
807 *err
= Err(function
, "This tool specifies a link_output.",
808 "This is only valid for solink tools.");
811 if (!IsPatternInOutputList(tool
->outputs(), tool
->link_output())) {
812 *err
= Err(function
, "This tool's link_output is bad.",
813 "It must match one of the outputs.");
817 if (!tool
->depend_output().empty()) {
818 if (tool_type
!= Toolchain::TYPE_SOLINK
) {
819 *err
= Err(function
, "This tool specifies a depend_output.",
820 "This is only valid for solink tools.");
823 if (!IsPatternInOutputList(tool
->outputs(), tool
->depend_output())) {
824 *err
= Err(function
, "This tool's depend_output is bad.",
825 "It must match one of the outputs.");
829 if ((!tool
->link_output().empty() && tool
->depend_output().empty()) ||
830 (tool
->link_output().empty() && !tool
->depend_output().empty())) {
831 *err
= Err(function
, "Both link_output and depend_output should either "
832 "be specified or they should both be empty.");
836 // Make sure there weren't any vars set in this tool that were unused.
837 if (!block_scope
.CheckForUnusedVars(err
))
840 toolchain
->SetTool(tool_type
, tool
.Pass());
844 // toolchain_args --------------------------------------------------------------
846 extern const char kToolchainArgs
[] = "toolchain_args";
847 extern const char kToolchainArgs_HelpShort
[] =
848 "toolchain_args: Set build arguments for toolchain build setup.";
849 extern const char kToolchainArgs_Help
[] =
850 "toolchain_args: Set build arguments for toolchain build setup.\n"
852 " Used inside a toolchain definition to pass arguments to an alternate\n"
853 " toolchain's invocation of the build.\n"
855 " When you specify a target using an alternate toolchain, the master\n"
856 " build configuration file is re-interpreted in the context of that\n"
857 " toolchain (see \"gn help toolchain\"). The toolchain_args function\n"
858 " allows you to control the arguments passed into this alternate\n"
859 " invocation of the build.\n"
861 " Any default system arguments or arguments passed in on the command-\n"
862 " line will also be passed to the alternate invocation unless explicitly\n"
863 " overridden by toolchain_args.\n"
865 " The toolchain_args will be ignored when the toolchain being defined\n"
866 " is the default. In this case, it's expected you want the default\n"
867 " argument values.\n"
869 " See also \"gn help buildargs\" for an overview of these arguments.\n"
872 " toolchain(\"my_weird_toolchain\") {\n"
874 " toolchain_args() {\n"
875 " # Override the system values for a generic Posix system.\n"
879 " # Pass this new value for specific setup for my toolchain.\n"
880 " is_my_weird_system = true\n"
884 Value
RunToolchainArgs(Scope
* scope
,
885 const FunctionCallNode
* function
,
886 const std::vector
<Value
>& args
,
889 // Find the toolchain definition we're executing inside of. The toolchain
890 // function will set a property pointing to it that we'll pick up.
891 Toolchain
* toolchain
= reinterpret_cast<Toolchain
*>(
892 scope
->GetProperty(&kToolchainPropertyKey
, nullptr));
894 *err
= Err(function
->function(),
895 "toolchain_args() called outside of toolchain().",
896 "The toolchain_args() function can only be used inside a "
897 "toolchain() definition.");
902 *err
= Err(function
->function(), "This function takes no arguments.");
906 // This function makes a new scope with various variable sets on it, which
907 // we then save on the toolchain to use when re-invoking the build.
908 Scope
block_scope(scope
);
909 block
->Execute(&block_scope
, err
);
910 if (err
->has_error())
913 Scope::KeyValueMap values
;
914 block_scope
.GetCurrentScopeValues(&values
);
915 toolchain
->args() = values
;
920 } // namespace functions