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.
4
5 #include <algorithm>
6 #include <limits>
7
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"
18
19 namespace functions {
20
21 namespace {
22
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;
26
ReadBool(Scope * scope,const char * var,Tool * tool,void (Tool::* set)(bool),Err * err)27 bool ReadBool(Scope* scope,
28 const char* var,
29 Tool* tool,
30 void (Tool::*set)(bool),
31 Err* err) {
32 const Value* v = scope->GetValue(var, true);
33 if (!v)
34 return true; // Not present is fine.
35 if (!v->VerifyTypeIs(Value::BOOLEAN, err))
36 return false;
37
38 (tool->*set)(v->boolean_value());
39 return true;
40 }
41
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.
ReadString(Scope * scope,const char * var,Tool * tool,void (Tool::* set)(const std::string &),Err * err)44 bool ReadString(Scope* scope,
45 const char* var,
46 Tool* tool,
47 void (Tool::*set)(const std::string&),
48 Err* err) {
49 const Value* v = scope->GetValue(var, true);
50 if (!v)
51 return true; // Not present is fine.
52 if (!v->VerifyTypeIs(Value::STRING, err))
53 return false;
54
55 (tool->*set)(v->string_value());
56 return true;
57 }
58
59 // Calls the given validate function on each type in the list. On failure,
60 // sets the error, blame the value, and return false.
ValidateSubstitutionList(const std::vector<SubstitutionType> & list,bool (* validate)(SubstitutionType),const Value * origin,Err * err)61 bool ValidateSubstitutionList(const std::vector<SubstitutionType>& list,
62 bool (*validate)(SubstitutionType),
63 const Value* origin,
64 Err* err) {
65 for (size_t i = 0; i < list.size(); i++) {
66 SubstitutionType cur_type = list[i];
67 if (!validate(cur_type)) {
68 *err = Err(*origin, "Pattern not valid here.",
69 "You used the pattern " + std::string(kSubstitutionNames[cur_type]) +
70 " which is not valid\nfor this variable.");
71 return false;
72 }
73 }
74 return true;
75 }
76
ReadPattern(Scope * scope,const char * name,bool (* validate)(SubstitutionType),Tool * tool,void (Tool::* set)(const SubstitutionPattern &),Err * err)77 bool ReadPattern(Scope* scope,
78 const char* name,
79 bool (*validate)(SubstitutionType),
80 Tool* tool,
81 void (Tool::*set)(const SubstitutionPattern&),
82 Err* err) {
83 const Value* value = scope->GetValue(name, true);
84 if (!value)
85 return true; // Not present is fine.
86 if (!value->VerifyTypeIs(Value::STRING, err))
87 return false;
88
89 SubstitutionPattern pattern;
90 if (!pattern.Parse(*value, err))
91 return false;
92 if (!ValidateSubstitutionList(pattern.required_types(), validate, value, err))
93 return false;
94
95 (tool->*set)(pattern);
96 return true;
97 }
98
ReadOutputExtension(Scope * scope,Tool * tool,Err * err)99 bool ReadOutputExtension(Scope* scope, Tool* tool, Err* err) {
100 const Value* value = scope->GetValue("default_output_extension", true);
101 if (!value)
102 return true; // Not present is fine.
103 if (!value->VerifyTypeIs(Value::STRING, err))
104 return false;
105
106 if (value->string_value().empty())
107 return true; // Accept empty string.
108
109 if (value->string_value()[0] != '.') {
110 *err = Err(*value, "default_output_extension must begin with a '.'");
111 return false;
112 }
113
114 tool->set_default_output_extension(value->string_value());
115 return true;
116 }
117
ReadDepsFormat(Scope * scope,Tool * tool,Err * err)118 bool ReadDepsFormat(Scope* scope, Tool* tool, Err* err) {
119 const Value* value = scope->GetValue("depsformat", true);
120 if (!value)
121 return true; // Not present is fine.
122 if (!value->VerifyTypeIs(Value::STRING, err))
123 return false;
124
125 if (value->string_value() == "gcc") {
126 tool->set_depsformat(Tool::DEPS_GCC);
127 } else if (value->string_value() == "msvc") {
128 tool->set_depsformat(Tool::DEPS_MSVC);
129 } else {
130 *err = Err(*value, "Deps format must be \"gcc\" or \"msvc\".");
131 return false;
132 }
133 return true;
134 }
135
ReadOutputs(Scope * scope,const FunctionCallNode * tool_function,bool (* validate)(SubstitutionType),Tool * tool,Err * err)136 bool ReadOutputs(Scope* scope,
137 const FunctionCallNode* tool_function,
138 bool (*validate)(SubstitutionType),
139 Tool* tool,
140 Err* err) {
141 const Value* value = scope->GetValue("outputs", true);
142 if (!value) {
143 *err = Err(tool_function, "\"outputs\" must be specified for this tool.");
144 return false;
145 }
146
147 SubstitutionList list;
148 if (!list.Parse(*value, err))
149 return false;
150
151 // Validate the right kinds of patterns are used.
152 if (!ValidateSubstitutionList(list.required_types(), validate, value, err))
153 return false;
154
155 // There should always be at least one output.
156 if (list.list().empty()) {
157 *err = Err(*value, "Outputs list is empty.", "I need some outputs.");
158 return false;
159 }
160
161 tool->set_outputs(list);
162 return true;
163 }
164
IsCompilerTool(Toolchain::ToolType type)165 bool IsCompilerTool(Toolchain::ToolType type) {
166 return type == Toolchain::TYPE_CC ||
167 type == Toolchain::TYPE_CXX ||
168 type == Toolchain::TYPE_OBJC ||
169 type == Toolchain::TYPE_OBJCXX ||
170 type == Toolchain::TYPE_RC ||
171 type == Toolchain::TYPE_ASM;
172 }
173
IsLinkerTool(Toolchain::ToolType type)174 bool IsLinkerTool(Toolchain::ToolType type) {
175 return type == Toolchain::TYPE_ALINK ||
176 type == Toolchain::TYPE_SOLINK ||
177 type == Toolchain::TYPE_LINK;
178 }
179
IsPatternInOutputList(const SubstitutionList & output_list,const SubstitutionPattern & pattern)180 bool IsPatternInOutputList(const SubstitutionList& output_list,
181 const SubstitutionPattern& pattern) {
182 for (size_t output_i = 0; output_i < output_list.list().size(); output_i++) {
183 const SubstitutionPattern& cur = output_list.list()[output_i];
184 if (pattern.ranges().size() == cur.ranges().size() &&
185 std::equal(pattern.ranges().begin(), pattern.ranges().end(),
186 cur.ranges().begin()))
187 return true;
188 }
189 return false;
190 }
191
192 } // namespace
193
194 // toolchain -------------------------------------------------------------------
195
196 const char kToolchain[] = "toolchain";
197 const char kToolchain_HelpShort[] =
198 "toolchain: Defines a toolchain.";
199 const char kToolchain_Help[] =
200 "toolchain: Defines a toolchain.\n"
201 "\n"
202 " A toolchain is a set of commands and build flags used to compile the\n"
203 " source code. You can have more than one toolchain in use at once in\n"
204 " a build.\n"
205 "\n"
206 "Functions and variables\n"
207 "\n"
208 " tool()\n"
209 " The tool() function call specifies the commands commands to run for\n"
210 " a given step. See \"gn help tool\".\n"
211 "\n"
212 " toolchain_args()\n"
213 " List of arguments to pass to the toolchain when invoking this\n"
214 " toolchain. This applies only to non-default toolchains. See\n"
215 " \"gn help toolchain_args\" for more.\n"
216 "\n"
217 " deps\n"
218 " Dependencies of this toolchain. These dependencies will be resolved\n"
219 " before any target in the toolchain is compiled. To avoid circular\n"
220 " dependencies these must be targets defined in another toolchain.\n"
221 "\n"
222 " This is expressed as a list of targets, and generally these targets\n"
223 " will always specify a toolchain:\n"
224 " deps = [ \"//foo/bar:baz(//build/toolchain:bootstrap)\" ]\n"
225 "\n"
226 " This concept is somewhat inefficient to express in Ninja (it\n"
227 " requires a lot of duplicate of rules) so should only be used when\n"
228 " absolutely necessary.\n"
229 "\n"
230 " concurrent_links\n"
231 " In integer expressing the number of links that Ninja will perform in\n"
232 " parallel. GN will create a pool for shared library and executable\n"
233 " link steps with this many processes. Since linking is memory- and\n"
234 " I/O-intensive, projects with many large targets may want to limit\n"
235 " the number of parallel steps to avoid overloading the computer.\n"
236 " Since creating static libraries is generally not as intensive\n"
237 " there is no limit to \"alink\" steps.\n"
238 "\n"
239 " Defaults to 0 which Ninja interprets as \"no limit\".\n"
240 "\n"
241 " The value used will be the one from the default toolchain of the\n"
242 " current build.\n"
243 "\n"
244 "Invoking targets in toolchains:\n"
245 "\n"
246 " By default, when a target depends on another, there is an implicit\n"
247 " toolchain label that is inherited, so the dependee has the same one\n"
248 " as the dependent.\n"
249 "\n"
250 " You can override this and refer to any other toolchain by explicitly\n"
251 " labeling the toolchain to use. For example:\n"
252 " data_deps = [ \"//plugins:mine(//toolchains:plugin_toolchain)\" ]\n"
253 " The string \"//build/toolchains:plugin_toolchain\" is a label that\n"
254 " identifies the toolchain declaration for compiling the sources.\n"
255 "\n"
256 " To load a file in an alternate toolchain, GN does the following:\n"
257 "\n"
258 " 1. Loads the file with the toolchain definition in it (as determined\n"
259 " by the toolchain label).\n"
260 " 2. Re-runs the master build configuration file, applying the\n"
261 " arguments specified by the toolchain_args section of the toolchain\n"
262 " definition (see \"gn help toolchain_args\").\n"
263 " 3. Loads the destination build file in the context of the\n"
264 " configuration file in the previous step.\n"
265 "\n"
266 "Example:\n"
267 " toolchain(\"plugin_toolchain\") {\n"
268 " concurrent_links = 8\n"
269 "\n"
270 " tool(\"cc\") {\n"
271 " command = \"gcc $in\"\n"
272 " ...\n"
273 " }\n"
274 "\n"
275 " toolchain_args() {\n"
276 " is_plugin = true\n"
277 " is_32bit = true\n"
278 " is_64bit = false\n"
279 " }\n"
280 " }\n";
281
RunToolchain(Scope * scope,const FunctionCallNode * function,const std::vector<Value> & args,BlockNode * block,Err * err)282 Value RunToolchain(Scope* scope,
283 const FunctionCallNode* function,
284 const std::vector<Value>& args,
285 BlockNode* block,
286 Err* err) {
287 if (!EnsureNotProcessingImport(function, scope, err) ||
288 !EnsureNotProcessingBuildConfig(function, scope, err))
289 return Value();
290
291 // Note that we don't want to use MakeLabelForScope since that will include
292 // the toolchain name in the label, and toolchain labels don't themselves
293 // have toolchain names.
294 const SourceDir& input_dir = scope->GetSourceDir();
295 Label label(input_dir, args[0].string_value());
296 if (g_scheduler->verbose_logging())
297 g_scheduler->Log("Definining toolchain", label.GetUserVisibleName(false));
298
299 // This object will actually be copied into the one owned by the toolchain
300 // manager, but that has to be done in the lock.
301 scoped_ptr<Toolchain> toolchain(new Toolchain(scope->settings(), label));
302 toolchain->set_defined_from(function);
303 toolchain->visibility().SetPublic();
304
305 Scope block_scope(scope);
306 block_scope.SetProperty(&kToolchainPropertyKey, toolchain.get());
307 block->ExecuteBlockInScope(&block_scope, err);
308 block_scope.SetProperty(&kToolchainPropertyKey, NULL);
309 if (err->has_error())
310 return Value();
311
312 // Read deps (if any).
313 const Value* deps_value = block_scope.GetValue(variables::kDeps, true);
314 if (deps_value) {
315 ExtractListOfLabels(
316 *deps_value, block_scope.GetSourceDir(),
317 ToolchainLabelForScope(&block_scope), &toolchain->deps(), err);
318 if (err->has_error())
319 return Value();
320 }
321
322 // Read concurrent_links (if any).
323 const Value* concurrent_links_value =
324 block_scope.GetValue("concurrent_links", true);
325 if (concurrent_links_value) {
326 if (!concurrent_links_value->VerifyTypeIs(Value::INTEGER, err))
327 return Value();
328 if (concurrent_links_value->int_value() < 0 ||
329 concurrent_links_value->int_value() > std::numeric_limits<int>::max()) {
330 *err = Err(*concurrent_links_value, "Value out of range.");
331 return Value();
332 }
333 toolchain->set_concurrent_links(
334 static_cast<int>(concurrent_links_value->int_value()));
335 }
336
337 if (!block_scope.CheckForUnusedVars(err))
338 return Value();
339
340 // Save this toolchain.
341 toolchain->ToolchainSetupComplete();
342 Scope::ItemVector* collector = scope->GetItemCollector();
343 if (!collector) {
344 *err = Err(function, "Can't define a toolchain in this context.");
345 return Value();
346 }
347 collector->push_back(new scoped_ptr<Item>(toolchain.PassAs<Item>()));
348 return Value();
349 }
350
351 // tool ------------------------------------------------------------------------
352
353 const char kTool[] = "tool";
354 const char kTool_HelpShort[] =
355 "tool: Specify arguments to a toolchain tool.";
356 const char kTool_Help[] =
357 "tool: Specify arguments to a toolchain tool.\n"
358 "\n"
359 "Usage:\n"
360 "\n"
361 " tool(<tool type>) {\n"
362 " <tool variables...>\n"
363 " }\n"
364 "\n"
365 "Tool types\n"
366 "\n"
367 " Compiler tools:\n"
368 " \"cc\": C compiler\n"
369 " \"cxx\": C++ compiler\n"
370 " \"objc\": Objective C compiler\n"
371 " \"objcxx\": Objective C++ compiler\n"
372 " \"rc\": Resource compiler (Windows .rc files)\n"
373 " \"asm\": Assembler\n"
374 "\n"
375 " Linker tools:\n"
376 " \"alink\": Linker for static libraries (archives)\n"
377 " \"solink\": Linker for shared libraries\n"
378 " \"link\": Linker for executables\n"
379 "\n"
380 " Other tools:\n"
381 " \"stamp\": Tool for creating stamp files\n"
382 " \"copy\": Tool to copy files.\n"
383 "\n"
384 "Tool variables\n"
385 "\n"
386 " command [string with substitutions]\n"
387 " Valid for: all tools (required)\n"
388 "\n"
389 " The command to run.\n"
390 "\n"
391 " default_output_extension [string]\n"
392 " Valid for: linker tools\n"
393 "\n"
394 " Extension for the main output of a linkable tool. It includes\n"
395 " the leading dot. This will be the default value for the\n"
396 " {{output_extension}} expansion (discussed below) but will be\n"
397 " overridden by by the \"output extension\" variable in a target,\n"
398 " if one is specified. Empty string means no extension.\n"
399 "\n"
400 " GN doesn't actually do anything with this extension other than\n"
401 " pass it along, potentially with target-specific overrides. One\n"
402 " would typically use the {{output_extension}} value in the\n"
403 " \"outputs\" to read this value.\n"
404 "\n"
405 " Example: default_output_extension = \".exe\"\n"
406 "\n"
407 " depfile [string]\n"
408 " Valid for: compiler tools (optional)\n"
409 "\n"
410 " If the tool can write \".d\" files, this specifies the name of\n"
411 " the resulting file. These files are used to list header file\n"
412 " dependencies (or other implicit input dependencies) that are\n"
413 " discovered at build time. See also \"depsformat\".\n"
414 "\n"
415 " Example: depfile = \"{{output}}.d\"\n"
416 "\n"
417 " depsformat [string]\n"
418 " Valid for: compiler tools (when depfile is specified)\n"
419 "\n"
420 " Format for the deps outputs. This is either \"gcc\" or \"msvc\".\n"
421 " See the ninja documentation for \"deps\" for more information.\n"
422 "\n"
423 " Example: depsformat = \"gcc\"\n"
424 "\n"
425 " description [string with substitutions, optional]\n"
426 " Valid for: all tools\n"
427 "\n"
428 " What to print when the command is run.\n"
429 "\n"
430 " Example: description = \"Compiling {{source}}\"\n"
431 "\n"
432 " lib_switch [string, optional, link tools only]\n"
433 " lib_dir_switch [string, optional, link tools only]\n"
434 " Valid for: Linker tools except \"alink\"\n"
435 "\n"
436 " These strings will be prepended to the libraries and library\n"
437 " search directories, respectively, because linkers differ on how\n"
438 " specify them. If you specified:\n"
439 " lib_switch = \"-l\"\n"
440 " lib_dir_switch = \"-L\"\n"
441 " then the \"{{libs}}\" expansion for [ \"freetype\", \"expat\"]\n"
442 " would be \"-lfreetype -lexpat\".\n"
443 "\n"
444 " outputs [list of strings with substitutions]\n"
445 " Valid for: Linker and compiler tools (required)\n"
446 "\n"
447 " An array of names for the output files the tool produces. These\n"
448 " are relative to the build output directory. There must always be\n"
449 " at least one output file. There can be more than one output (a\n"
450 " linker might produce a library and an import library, for\n"
451 " example).\n"
452 "\n"
453 " This array just declares to GN what files the tool will\n"
454 " produce. It is your responsibility to specify the tool command\n"
455 " that actually produces these files.\n"
456 "\n"
457 " If you specify more than one output for shared library links,\n"
458 " you should consider setting link_output and depend_output.\n"
459 " Otherwise, the first entry in the outputs list should always be\n"
460 " the main output which will be linked to.\n"
461 "\n"
462 " Example for a compiler tool that produces .obj files:\n"
463 " outputs = [\n"
464 " \"{{source_out_dir}}/{{source_name_part}}.obj\"\n"
465 " ]\n"
466 "\n"
467 " Example for a linker tool that produces a .dll and a .lib. The\n"
468 " use of {{output_extension}} rather than hardcoding \".dll\"\n"
469 " allows the extension of the library to be overridden on a\n"
470 " target-by-target basis, but in this example, it always\n"
471 " produces a \".lib\" import library:\n"
472 " outputs = [\n"
473 " \"{{root_out_dir}}/{{target_output_name}}"
474 "{{output_extension}}\",\n"
475 " \"{{root_out_dir}}/{{target_output_name}}.lib\",\n"
476 " ]\n"
477 "\n"
478 " link_output [string with substitutions]\n"
479 " depend_output [string with substitutions]\n"
480 " Valid for: \"solink\" only (optional)\n"
481 "\n"
482 " These two files specify whch of the outputs from the solink\n"
483 " tool should be used for linking and dependency tracking. These\n"
484 " should match entries in the \"outputs\". If unspecified, the\n"
485 " first item in the \"outputs\" array will be used for both. See\n"
486 " \"Separate linking and dependencies for shared libraries\"\n"
487 " below for more.\n"
488 "\n"
489 " On Windows, where the tools produce a .dll shared library and\n"
490 " a .lib import library, you will want both of these to be the\n"
491 " import library. On Linux, if you're not doing the separate\n"
492 " linking/dependency optimization, both of these should be the\n"
493 " .so output.\n"
494 "\n"
495 " output_prefix [string]\n"
496 " Valid for: Linker tools (optional)\n"
497 "\n"
498 " Prefix to use for the output name. Defaults to empty. This\n"
499 " prefix will be prepended to the name of the target (or the\n"
500 " output_name if one is manually specified for it) if the prefix\n"
501 " is not already there. The result will show up in the\n"
502 " {{output_name}} substitution pattern.\n"
503 "\n"
504 " This is typically used to prepend \"lib\" to libraries on\n"
505 " Posix systems:\n"
506 " output_prefix = \"lib\"\n"
507 "\n"
508 " restat [boolean]\n"
509 " Valid for: all tools (optional, defaults to false)\n"
510 "\n"
511 " Requests that Ninja check the file timestamp after this tool has\n"
512 " run to determine if anything changed. Set this if your tool has\n"
513 " the ability to skip writing output if the output file has not\n"
514 " changed.\n"
515 "\n"
516 " Normally, Ninja will assume that when a tool runs the output\n"
517 " be new and downstream dependents must be rebuild. When this is\n"
518 " set to trye, Ninja can skip rebuilding downstream dependents for\n"
519 " input changes that don't actually affect the output.\n"
520 "\n"
521 " Example:\n"
522 " restat = true\n"
523 "\n"
524 " rspfile [string with substitutions]\n"
525 " Valid for: all tools (optional)\n"
526 "\n"
527 " Name of the response file. If empty, no response file will be\n"
528 " used. See \"rspfile_content\".\n"
529 "\n"
530 " rspfile_content [string with substitutions]\n"
531 " Valid for: all tools (required when \"rspfile\" is specified)\n"
532 "\n"
533 " The contents to be written to the response file. This may\n"
534 " include all or part of the command to send to the tool which\n"
535 " allows you to get around OS command-line length limits.\n"
536 "\n"
537 " This example adds the inputs and libraries to a response file,\n"
538 " but passes the linker flags directly on the command line:\n"
539 " tool(\"link\") {\n"
540 " command = \"link -o {{output}} {{ldflags}} @{{output}}.rsp\"\n"
541 " rspfile = \"{{output}}.rsp\"\n"
542 " rspfile_content = \"{{inputs}} {{solibs}} {{libs}}\"\n"
543 " }\n"
544 "\n"
545 "Expansions for tool variables"
546 "\n"
547 " All paths are relative to the root build directory, which is the\n"
548 " current directory for running all tools. These expansions are\n"
549 " available to all tools:\n"
550 "\n"
551 " {{label}}\n"
552 " The label of the current target. This is typically used in the\n"
553 " \"description\" field for link tools. The toolchain will be\n"
554 " omitted from the label for targets in the default toolchain, and\n"
555 " will be included for targets in other toolchains.\n"
556 "\n"
557 " {{output}}\n"
558 " The relative path and name of the output)((s) of the current\n"
559 " build step. If there is more than one output, this will expand\n"
560 " to a list of all of them.\n"
561 " Example: \"out/base/my_file.o\"\n"
562 "\n"
563 " {{target_gen_dir}}\n"
564 " {{target_out_dir}}\n"
565 " The directory of the generated file and output directories,\n"
566 " respectively, for the current target. There is no trailing\n"
567 " slash.\n"
568 " Example: \"out/base/test\"\n"
569 "\n"
570 " {{target_output_name}}\n"
571 " The short name of the current target with no path information,\n"
572 " or the value of the \"output_name\" variable if one is specified\n"
573 " in the target. This will include the \"output_prefix\" if any.\n"
574 " Example: \"libfoo\" for the target named \"foo\" and an\n"
575 " output prefix for the linker tool of \"lib\".\n"
576 "\n"
577 " Compiler tools have the notion of a single input and a single output,\n"
578 " along with a set of compiler-specific flags. The following expansions\n"
579 " are available:\n"
580 "\n"
581 " {{cflags}}\n"
582 " {{cflags_c}}\n"
583 " {{cflags_cc}}\n"
584 " {{cflags_objc}}\n"
585 " {{cflags_objcc}}\n"
586 " {{defines}}\n"
587 " {{include_dirs}}\n"
588 " Strings correspond that to the processed flags/defines/include\n"
589 " directories specified for the target.\n"
590 " Example: \"--enable-foo --enable-bar\"\n"
591 "\n"
592 " Defines will be prefixed by \"-D\" and include directories will\n"
593 " be prefixed by \"-I\" (these work with Posix tools as well as\n"
594 " Microsoft ones).\n"
595 "\n"
596 " {{source}}\n"
597 " The relative path and name of the current input file.\n"
598 " Example: \"../../base/my_file.cc\"\n"
599 "\n"
600 " {{source_file_part}}\n"
601 " The file part of the source including the extension (with no\n"
602 " directory information).\n"
603 " Example: \"foo.cc\"\n"
604 "\n"
605 " {{source_name_part}}\n"
606 " The filename part of the source file with no directory or\n"
607 " extension.\n"
608 " Example: \"foo\"\n"
609 "\n"
610 " {{source_gen_dir}}\n"
611 " {{source_out_dir}}\n"
612 " The directory in the generated file and output directories,\n"
613 " respectively, for the current input file. If the source file\n"
614 " is in the same directory as the target is declared in, they will\n"
615 " will be the same as the \"target\" versions above.\n"
616 " Example: \"gen/base/test\"\n"
617 "\n"
618 " Linker tools have multiple inputs and (potentially) multiple outputs\n"
619 " The following expansions are available:\n"
620 "\n"
621 " {{inputs}}\n"
622 " {{inputs_newline}}\n"
623 " Expands to the inputs to the link step. This will be a list of\n"
624 " object files and static libraries.\n"
625 " Example: \"obj/foo.o obj/bar.o obj/somelibrary.a\"\n"
626 "\n"
627 " The \"_newline\" version will separate the input files with\n"
628 " newlines instead of spaces. This is useful in response files:\n"
629 " some linkers can take a \"-filelist\" flag which expects newline\n"
630 " separated files, and some Microsoft tools have a fixed-sized\n"
631 " buffer for parsing each line of a response file.\n"
632 "\n"
633 " {{ldflags}}\n"
634 " Expands to the processed set of ldflags and library search paths\n"
635 " specified for the target.\n"
636 " Example: \"-m64, -fPIC -pthread -L/usr/local/mylib\"\n"
637 "\n"
638 " {{libs}}\n"
639 " Expands to the list of system libraries to link to. Each will\n"
640 " be prefixed by the \"lib_prefix\".\n"
641 "\n"
642 " As a special case to support Mac, libraries with names ending in\n"
643 " \".framework\" will be added to the {{libs}} with \"-framework\"\n"
644 " preceeding it, and the lib prefix will be ignored.\n"
645 "\n"
646 " Example: \"-lfoo -lbar\"\n"
647 "\n"
648 " {{output_extension}}\n"
649 " The value of the \"output_extension\" variable in the target,\n"
650 " or the value of the \"default_output_extension\" value in the\n"
651 " tool if the target does not specify an output extension.\n"
652 " Example: \".so\"\n"
653 "\n"
654 " {{solibs}}\n"
655 " Extra libraries from shared library dependencide not specified\n"
656 " in the {{inputs}}. This is the list of link_output files from\n"
657 " shared libraries (if the solink tool specifies a \"link_output\"\n"
658 " variable separate from the \"depend_output\").\n"
659 "\n"
660 " These should generally be treated the same as libs by your tool.\n"
661 " Example: \"libfoo.so libbar.so\"\n"
662 "\n"
663 " The copy tool allows the common compiler/linker substitutions, plus\n"
664 " {{source}} which is the source of the copy. The stamp tool allows\n"
665 " only the common tool substitutions.\n"
666 "\n"
667 "Separate linking and dependencies for shared libraries\n"
668 "\n"
669 " Shared libraries are special in that not all changes to them require\n"
670 " that dependent targets be re-linked. If the shared library is changed\n"
671 " but no imports or exports are different, dependent code needn't be\n"
672 " relinked, which can speed up the build.\n"
673 "\n"
674 " If your link step can output a list of exports from a shared library\n"
675 " and writes the file only if the new one is different, the timestamp of\n"
676 " this file can be used for triggering re-links, while the actual shared\n"
677 " library would be used for linking.\n"
678 "\n"
679 " You will need to specify\n"
680 " restat = true\n"
681 " in the linker tool to make this work, so Ninja will detect if the\n"
682 " timestamp of the dependency file has changed after linking (otherwise\n"
683 " it will always assume that running a command updates the output):\n"
684 "\n"
685 " tool(\"solink\") {\n"
686 " command = \"...\"\n"
687 " outputs = [\n"
688 " \"{{root_out_dir}}/{{target_output_name}}{{output_extension}}\",\n"
689 " \"{{root_out_dir}}/{{target_output_name}}"
690 "{{output_extension}}.TOC\",\n"
691 " ]\n"
692 " link_output =\n"
693 " \"{{root_out_dir}}/{{target_output_name}}{{output_extension}}\",\n"
694 " depend_output =\n"
695 " \"{{root_out_dir}}/{{target_output_name}}"
696 "{{output_extension}}.TOC\",\n"
697 " restat = true\n"
698 " }\n"
699 "\n"
700 "Example\n"
701 "\n"
702 " toolchain(\"my_toolchain\") {\n"
703 " # Put these at the top to apply to all tools below.\n"
704 " lib_prefix = \"-l\"\n"
705 " lib_dir_prefix = \"-L\"\n"
706 "\n"
707 " tool(\"cc\") {\n"
708 " command = \"gcc \\$in -o \\$out\"\n"
709 " outputs = [ \"{{source_out_dir}}/{{source_name_part}}.o\"\n"
710 " description = \"GCC \\$in\"\n"
711 " }\n"
712 " tool(\"cxx\") {\n"
713 " command = \"g++ \\$in -o \\$out\"\n"
714 " outputs = [ \"{{source_out_dir}}/{{source_name_part}}.o\"\n"
715 " description = \"G++ \\$in\"\n"
716 " }\n"
717 " }\n";
718
RunTool(Scope * scope,const FunctionCallNode * function,const std::vector<Value> & args,BlockNode * block,Err * err)719 Value RunTool(Scope* scope,
720 const FunctionCallNode* function,
721 const std::vector<Value>& args,
722 BlockNode* block,
723 Err* err) {
724 // Find the toolchain definition we're executing inside of. The toolchain
725 // function will set a property pointing to it that we'll pick up.
726 Toolchain* toolchain = reinterpret_cast<Toolchain*>(
727 scope->GetProperty(&kToolchainPropertyKey, NULL));
728 if (!toolchain) {
729 *err = Err(function->function(), "tool() called outside of toolchain().",
730 "The tool() function can only be used inside a toolchain() "
731 "definition.");
732 return Value();
733 }
734
735 if (!EnsureSingleStringArg(function, args, err))
736 return Value();
737 const std::string& tool_name = args[0].string_value();
738 Toolchain::ToolType tool_type = Toolchain::ToolNameToType(tool_name);
739 if (tool_type == Toolchain::TYPE_NONE) {
740 *err = Err(args[0], "Unknown tool type");
741 return Value();
742 }
743
744 // Run the tool block.
745 Scope block_scope(scope);
746 block->ExecuteBlockInScope(&block_scope, err);
747 if (err->has_error())
748 return Value();
749
750 // Figure out which validator to use for the substitution pattern for this
751 // tool type. There are different validators for the "outputs" than for the
752 // rest of the strings.
753 bool (*subst_validator)(SubstitutionType) = NULL;
754 bool (*subst_output_validator)(SubstitutionType) = NULL;
755 if (IsCompilerTool(tool_type)) {
756 subst_validator = &IsValidCompilerSubstitution;
757 subst_output_validator = &IsValidCompilerOutputsSubstitution;
758 } else if (IsLinkerTool(tool_type)) {
759 subst_validator = &IsValidLinkerSubstitution;
760 subst_output_validator = &IsValidLinkerOutputsSubstitution;
761 } else if (tool_type == Toolchain::TYPE_COPY) {
762 subst_validator = &IsValidCopySubstitution;
763 subst_output_validator = &IsValidCopySubstitution;
764 } else {
765 subst_validator = &IsValidToolSubstutition;
766 subst_output_validator = &IsValidToolSubstutition;
767 }
768
769 scoped_ptr<Tool> tool(new Tool);
770
771 if (!ReadPattern(&block_scope, "command", subst_validator, tool.get(),
772 &Tool::set_command, err) ||
773 !ReadOutputExtension(&block_scope, tool.get(), err) ||
774 !ReadPattern(&block_scope, "depfile", subst_validator, tool.get(),
775 &Tool::set_depfile, err) ||
776 !ReadDepsFormat(&block_scope, tool.get(), err) ||
777 !ReadPattern(&block_scope, "description", subst_validator, tool.get(),
778 &Tool::set_description, err) ||
779 !ReadString(&block_scope, "lib_switch", tool.get(),
780 &Tool::set_lib_switch, err) ||
781 !ReadString(&block_scope, "lib_dir_switch", tool.get(),
782 &Tool::set_lib_dir_switch, err) ||
783 !ReadPattern(&block_scope, "link_output", subst_validator, tool.get(),
784 &Tool::set_link_output, err) ||
785 !ReadPattern(&block_scope, "depend_output", subst_validator, tool.get(),
786 &Tool::set_depend_output, err) ||
787 !ReadString(&block_scope, "output_prefix", tool.get(),
788 &Tool::set_output_prefix, err) ||
789 !ReadBool(&block_scope, "restat", tool.get(), &Tool::set_restat, err) ||
790 !ReadPattern(&block_scope, "rspfile", subst_validator, tool.get(),
791 &Tool::set_rspfile, err) ||
792 !ReadPattern(&block_scope, "rspfile_content", subst_validator, tool.get(),
793 &Tool::set_rspfile_content, err)) {
794 return Value();
795 }
796
797 if (tool_type != Toolchain::TYPE_COPY && tool_type != Toolchain::TYPE_STAMP) {
798 // All tools except the copy and stamp tools should have outputs. The copy
799 // and stamp tool's outputs are generated internally.
800 if (!ReadOutputs(&block_scope, function, subst_output_validator,
801 tool.get(), err))
802 return Value();
803 }
804
805 // Validate that the link_output and depend_output refer to items in the
806 // outputs and aren't defined for irrelevant tool types.
807 if (!tool->link_output().empty()) {
808 if (tool_type != Toolchain::TYPE_SOLINK) {
809 *err = Err(function, "This tool specifies a link_output.",
810 "This is only valid for solink tools.");
811 return Value();
812 }
813 if (!IsPatternInOutputList(tool->outputs(), tool->link_output())) {
814 *err = Err(function, "This tool's link_output is bad.",
815 "It must match one of the outputs.");
816 return Value();
817 }
818 }
819 if (!tool->depend_output().empty()) {
820 if (tool_type != Toolchain::TYPE_SOLINK) {
821 *err = Err(function, "This tool specifies a depend_output.",
822 "This is only valid for solink tools.");
823 return Value();
824 }
825 if (!IsPatternInOutputList(tool->outputs(), tool->depend_output())) {
826 *err = Err(function, "This tool's depend_output is bad.",
827 "It must match one of the outputs.");
828 return Value();
829 }
830 }
831 if ((!tool->link_output().empty() && tool->depend_output().empty()) ||
832 (tool->link_output().empty() && !tool->depend_output().empty())) {
833 *err = Err(function, "Both link_output and depend_output should either "
834 "be specified or they should both be empty.");
835 return Value();
836 }
837
838 // Make sure there weren't any vars set in this tool that were unused.
839 if (!block_scope.CheckForUnusedVars(err))
840 return Value();
841
842 toolchain->SetTool(tool_type, tool.Pass());
843 return Value();
844 }
845
846 // toolchain_args --------------------------------------------------------------
847
848 extern const char kToolchainArgs[] = "toolchain_args";
849 extern const char kToolchainArgs_HelpShort[] =
850 "toolchain_args: Set build arguments for toolchain build setup.";
851 extern const char kToolchainArgs_Help[] =
852 "toolchain_args: Set build arguments for toolchain build setup.\n"
853 "\n"
854 " Used inside a toolchain definition to pass arguments to an alternate\n"
855 " toolchain's invocation of the build.\n"
856 "\n"
857 " When you specify a target using an alternate toolchain, the master\n"
858 " build configuration file is re-interpreted in the context of that\n"
859 " toolchain (see \"gn help toolchain\"). The toolchain_args function\n"
860 " allows you to control the arguments passed into this alternate\n"
861 " invocation of the build.\n"
862 "\n"
863 " Any default system arguments or arguments passed in on the command-\n"
864 " line will also be passed to the alternate invocation unless explicitly\n"
865 " overridden by toolchain_args.\n"
866 "\n"
867 " The toolchain_args will be ignored when the toolchain being defined\n"
868 " is the default. In this case, it's expected you want the default\n"
869 " argument values.\n"
870 "\n"
871 " See also \"gn help buildargs\" for an overview of these arguments.\n"
872 "\n"
873 "Example:\n"
874 " toolchain(\"my_weird_toolchain\") {\n"
875 " ...\n"
876 " toolchain_args() {\n"
877 " # Override the system values for a generic Posix system.\n"
878 " is_win = false\n"
879 " is_posix = true\n"
880 "\n"
881 " # Pass this new value for specific setup for my toolchain.\n"
882 " is_my_weird_system = true\n"
883 " }\n"
884 " }\n";
885
RunToolchainArgs(Scope * scope,const FunctionCallNode * function,const std::vector<Value> & args,BlockNode * block,Err * err)886 Value RunToolchainArgs(Scope* scope,
887 const FunctionCallNode* function,
888 const std::vector<Value>& args,
889 BlockNode* block,
890 Err* err) {
891 // Find the toolchain definition we're executing inside of. The toolchain
892 // function will set a property pointing to it that we'll pick up.
893 Toolchain* toolchain = reinterpret_cast<Toolchain*>(
894 scope->GetProperty(&kToolchainPropertyKey, NULL));
895 if (!toolchain) {
896 *err = Err(function->function(),
897 "toolchain_args() called outside of toolchain().",
898 "The toolchain_args() function can only be used inside a "
899 "toolchain() definition.");
900 return Value();
901 }
902
903 if (!args.empty()) {
904 *err = Err(function->function(), "This function takes no arguments.");
905 return Value();
906 }
907
908 // This function makes a new scope with various variable sets on it, which
909 // we then save on the toolchain to use when re-invoking the build.
910 Scope block_scope(scope);
911 block->ExecuteBlockInScope(&block_scope, err);
912 if (err->has_error())
913 return Value();
914
915 Scope::KeyValueMap values;
916 block_scope.GetCurrentScopeValues(&values);
917 toolchain->args() = values;
918
919 return Value();
920 }
921
922 } // namespace functions
923