Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(197)

Side by Side Diff: tools/gn/function_toolchain.cc

Issue 440333002: Support more configurability in GN toolchains (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <algorithm>
6
5 #include "tools/gn/err.h" 7 #include "tools/gn/err.h"
6 #include "tools/gn/functions.h" 8 #include "tools/gn/functions.h"
7 #include "tools/gn/parse_tree.h" 9 #include "tools/gn/parse_tree.h"
8 #include "tools/gn/scheduler.h" 10 #include "tools/gn/scheduler.h"
9 #include "tools/gn/scope.h" 11 #include "tools/gn/scope.h"
10 #include "tools/gn/settings.h" 12 #include "tools/gn/settings.h"
13 #include "tools/gn/tool.h"
11 #include "tools/gn/toolchain.h" 14 #include "tools/gn/toolchain.h"
12 #include "tools/gn/value_extractors.h" 15 #include "tools/gn/value_extractors.h"
13 #include "tools/gn/variables.h" 16 #include "tools/gn/variables.h"
14 17
15 namespace functions { 18 namespace functions {
16 19
17 namespace { 20 namespace {
18 21
19 // This is jsut a unique value to take the address of to use as the key for 22 // This is jsut a unique value to take the address of to use as the key for
20 // the toolchain property on a scope. 23 // the toolchain property on a scope.
21 const int kToolchainPropertyKey = 0; 24 const int kToolchainPropertyKey = 0;
22 25
26 bool ReadBool(Scope* scope,
27 const char* var,
28 Tool* tool,
29 void (Tool::*set)(bool),
30 Err* err) {
31 const Value* v = scope->GetValue(var, true);
32 if (!v)
33 return true; // Not present is fine.
34 if (!v->VerifyTypeIs(Value::BOOLEAN, err))
35 return false;
36
37 (tool->*set)(v->boolean_value());
38 return true;
39 }
40
23 // Reads the given string from the scope (if present) and puts the result into 41 // Reads the given string from the scope (if present) and puts the result into
24 // dest. If the value is not a string, sets the error and returns false. 42 // dest. If the value is not a string, sets the error and returns false.
25 bool ReadString(Scope& scope, const char* var, std::string* dest, Err* err) { 43 bool ReadString(Scope* scope,
26 const Value* v = scope.GetValue(var, true); 44 const char* var,
45 Tool* tool,
46 void (Tool::*set)(const std::string&),
47 Err* err) {
48 const Value* v = scope->GetValue(var, true);
27 if (!v) 49 if (!v)
28 return true; // Not present is fine. 50 return true; // Not present is fine.
29
30 if (!v->VerifyTypeIs(Value::STRING, err)) 51 if (!v->VerifyTypeIs(Value::STRING, err))
31 return false; 52 return false;
32 *dest = v->string_value(); 53
54 (tool->*set)(v->string_value());
33 return true; 55 return true;
34 } 56 }
35 57
58 // Calls the given validate function on each type in the list. On failure,
59 // sets the error, blame the value, and return false.
60 bool ValidateSubstitutionList(const std::vector<SubstitutionType>& list,
61 bool (*validate)(SubstitutionType),
62 const Value* origin,
63 Err* err) {
64 for (size_t i = 0; i < list.size(); i++) {
65 SubstitutionType cur_type = list[i];
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.");
70 return false;
71 }
72 }
73 return true;
74 }
75
76 bool ReadPattern(Scope* scope,
77 const char* name,
78 bool (*validate)(SubstitutionType),
79 Tool* tool,
80 void (Tool::*set)(const SubstitutionPattern&),
81 Err* err) {
82 const Value* value = scope->GetValue(name, true);
83 if (!value)
84 return true; // Not present is fine.
85 if (!value->VerifyTypeIs(Value::STRING, err))
86 return false;
87
88 SubstitutionPattern pattern;
89 if (!pattern.Parse(*value, err))
90 return false;
91 if (!ValidateSubstitutionList(pattern.required_types(), validate, value, err))
92 return false;
93
94 (tool->*set)(pattern);
95 return true;
96 }
97
98 bool ReadOutputExtension(Scope* scope, Tool* tool, Err* err) {
99 const Value* value = scope->GetValue("default_output_extension", true);
100 if (!value)
101 return true; // Not present is fine.
102 if (!value->VerifyTypeIs(Value::STRING, err))
103 return false;
104
105 if (value->string_value().empty())
106 return true; // Accept empty string.
107
108 if (value->string_value()[0] != '.') {
109 *err = Err(*value, "default_output_extension must begin with a '.'");
110 return false;
111 }
112
113 tool->set_default_output_extension(value->string_value());
114 return true;
115 }
116
117 bool ReadDepsFormat(Scope* scope, Tool* tool, Err* err) {
118 const Value* value = scope->GetValue("depsformat", true);
119 if (!value)
120 return true; // Not present is fine.
121 if (!value->VerifyTypeIs(Value::STRING, err))
122 return false;
123
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);
128 } else {
129 *err = Err(*value, "Deps format must be \"gcc\" or \"msvc\".");
130 return false;
131 }
132 return true;
133 }
134
135 bool ReadOutputs(Scope* scope,
136 const FunctionCallNode* tool_function,
137 bool (*validate)(SubstitutionType),
138 Tool* tool,
139 Err* err) {
140 const Value* value = scope->GetValue("outputs", true);
141 if (!value) {
142 *err = Err(tool_function, "\"outputs\" must be specified for this tool.");
143 return false;
144 }
145
146 SubstitutionList list;
147 if (!list.Parse(*value, err))
148 return false;
149
150 // Validate the right kinds of patterns are used.
151 if (!ValidateSubstitutionList(list.required_types(), validate, value, err))
152 return false;
153
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.");
157 return false;
158 }
159
160 // Each output should be in the output directory.
161 /*
jamesr 2014/08/19 19:30:41 ?
brettw 2014/08/19 21:29:56 Deleted
162 for (size_t i = 0; i < list.list().size(); i++) {
163 if (!list.list()[i].IsInOutputDir(scope->settings()->build_settings(), err))
164 return false;
165 }
166 */
167
168 tool->set_outputs(list);
169 return true;
170 }
171
172 bool IsCompilerTool(Toolchain::ToolType type) {
173 return type == Toolchain::TYPE_CC ||
174 type == Toolchain::TYPE_CXX ||
175 type == Toolchain::TYPE_OBJC ||
176 type == Toolchain::TYPE_OBJCXX ||
177 type == Toolchain::TYPE_RC ||
178 type == Toolchain::TYPE_ASM;
179 }
180
181 bool IsLinkerTool(Toolchain::ToolType type) {
182 return type == Toolchain::TYPE_ALINK ||
183 type == Toolchain::TYPE_SOLINK ||
184 type == Toolchain::TYPE_LINK;
185 }
186
187 bool IsPatternInOutputList(const SubstitutionList& output_list,
188 const SubstitutionPattern& pattern) {
189 for (size_t output_i = 0; output_i < output_list.list().size(); output_i++) {
190 const SubstitutionPattern& cur = output_list.list()[output_i];
191 if (pattern.ranges().size() == cur.ranges().size() &&
192 std::equal(pattern.ranges().begin(), pattern.ranges().end(),
193 cur.ranges().begin()))
194 return true;
195 }
196 return false;
197 }
198
36 } // namespace 199 } // namespace
37 200
38 // toolchain ------------------------------------------------------------------- 201 // toolchain -------------------------------------------------------------------
39 202
40 const char kToolchain[] = "toolchain"; 203 const char kToolchain[] = "toolchain";
41 const char kToolchain_HelpShort[] = 204 const char kToolchain_HelpShort[] =
42 "toolchain: Defines a toolchain."; 205 "toolchain: Defines a toolchain.";
43 const char kToolchain_Help[] = 206 const char kToolchain_Help[] =
44 "toolchain: Defines a toolchain.\n" 207 "toolchain: Defines a toolchain.\n"
45 "\n" 208 "\n"
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
125 // Read deps (if any). 288 // Read deps (if any).
126 const Value* deps_value = block_scope.GetValue(variables::kDeps, true); 289 const Value* deps_value = block_scope.GetValue(variables::kDeps, true);
127 if (deps_value) { 290 if (deps_value) {
128 ExtractListOfLabels( 291 ExtractListOfLabels(
129 *deps_value, block_scope.GetSourceDir(), 292 *deps_value, block_scope.GetSourceDir(),
130 ToolchainLabelForScope(&block_scope), &toolchain->deps(), err); 293 ToolchainLabelForScope(&block_scope), &toolchain->deps(), err);
131 if (err->has_error()) 294 if (err->has_error())
132 return Value(); 295 return Value();
133 } 296 }
134 297
135
136 if (!block_scope.CheckForUnusedVars(err)) 298 if (!block_scope.CheckForUnusedVars(err))
137 return Value(); 299 return Value();
138 300
139 // Save this toolchain. 301 // Save this toolchain.
302 toolchain->ToolchainSetupComplete();
140 Scope::ItemVector* collector = scope->GetItemCollector(); 303 Scope::ItemVector* collector = scope->GetItemCollector();
141 if (!collector) { 304 if (!collector) {
142 *err = Err(function, "Can't define a toolchain in this context."); 305 *err = Err(function, "Can't define a toolchain in this context.");
143 return Value(); 306 return Value();
144 } 307 }
145 collector->push_back(new scoped_ptr<Item>(toolchain.PassAs<Item>())); 308 collector->push_back(new scoped_ptr<Item>(toolchain.PassAs<Item>()));
146 return Value(); 309 return Value();
147 } 310 }
148 311
149 // tool ------------------------------------------------------------------------ 312 // tool ------------------------------------------------------------------------
150 313
151 const char kTool[] = "tool"; 314 const char kTool[] = "tool";
152 const char kTool_HelpShort[] = 315 const char kTool_HelpShort[] =
153 "tool: Specify arguments to a toolchain tool."; 316 "tool: Specify arguments to a toolchain tool.";
154 const char kTool_Help[] = 317 const char kTool_Help[] =
155 "tool: Specify arguments to a toolchain tool.\n" 318 "tool: Specify arguments to a toolchain tool.\n"
156 "\n" 319 "\n"
157 " tool(<command type>) { <command flags> }\n" 320 "Usage:\n"
158 "\n" 321 "\n"
159 " Used inside a toolchain definition to define a command to run for a\n" 322 " tool(<tool type>) {\n"
160 " given file type. See also \"gn help toolchain\".\n" 323 " <tool variables...>\n"
161 "\n" 324 " }\n"
162 "Command types\n" 325 "\n"
163 "\n" 326 "Tool types\n"
164 " The following values may be passed to the tool() function for the type\n" 327 "\n"
165 " of the command:\n" 328 " Compiler tools:\n"
166 "\n" 329 " \"cc\": C compiler\n"
167 " \"cc\", \"cxx\", \"objc\", \"objcxx\", \"asm\", \"alink\", \"solink\",\n" 330 " \"cxx\": C++ compiler\n"
168 " \"link\", \"stamp\", \"copy\"\n" 331 " \"objc\": Objective C compiler\n"
169 "\n" 332 " \"objcxx\": Objective C++ compiler\n"
170 "Tool-specific notes\n" 333 " \"rc\": Resource compiler (Windows .rc files)\n"
171 "\n" 334 " \"asm\": Assembler\n"
172 " copy\n" 335 "\n"
173 " The copy command should be a native OS command since it does not\n" 336 " Linker tools:\n"
174 " implement toolchain dependencies (which would enable a copy tool to\n" 337 " \"alink\": Linker for static libraries (archives)\n"
175 " be compiled by a previous step).\n" 338 " \"solink\": Linker for shared libraries\n"
176 "\n" 339 " \"link\": Linker for executables\n"
177 " It is legal for the copy to not update the timestamp of the output\n" 340 "\n"
178 " file (as long as it's greater than or equal to the input file). This\n" 341 " Other tools:\n"
179 " allows the copy command to be implemented as a hard link which can\n" 342 " \"stamp\": Tool for creating stamp files\n"
180 " be more efficient.\n" 343 " \"copy\": Tool to copy files.\n"
181 "\n" 344 "\n"
182 "Command flags\n" 345 "Tool variables\n"
183 "\n" 346 "\n"
184 " These variables may be specified in the { } block after the tool call.\n" 347 " command [string with substitutions]\n"
185 " They are passed directly to Ninja. See the ninja documentation for how\n" 348 " Valid for: all tools (required)\n"
186 " they work. Don't forget to backslash-escape $ required by Ninja to\n" 349 "\n"
187 " prevent GN from doing variable expansion.\n" 350 " The command to run.\n"
188 "\n" 351 "\n"
189 " command, depfile, depsformat, description, pool, restat, rspfile,\n" 352 " default_output_extension [string]\n"
190 " rspfile_content\n" 353 " Valid for: linker tools (required)\n"
jamesr 2014/08/19 19:30:41 this says 'required' but the code allows it to be
191 "\n" 354 "\n"
192 " (Note that GN uses \"depsformat\" for Ninja's \"deps\" variable to\n" 355 " Extension for the main output of a linkable tool. It includes\n"
193 " avoid confusion with dependency lists.)\n" 356 " the leading dot. This will be the default value for the\n"
194 "\n" 357 " {{output_extension}} expansion (discussed below) but will be\n"
195 " Additionally, lib_prefix and lib_dir_prefix may be used for the link\n" 358 " overridden by by the \"output extension\" variable in a target,\n"
196 " tools. These strings will be prepended to the libraries and library\n" 359 " if one is specified. Empty string means no extension.\n"
197 " search directories, respectively, because linkers differ on how to\n" 360 "\n"
198 " specify them.\n" 361 " GN doesn't actually do anything with this extension other than\n"
199 "\n" 362 " pass it along, potentially with target-specific overrides. One\n"
200 " Note: On Mac libraries with names ending in \".framework\" will be\n" 363 " would typically use the {{output_extension}} value in the\n"
201 " added to the link like with a \"-framework\" switch and the lib prefix\n" 364 " \"outputs\" to read this value.\n"
202 " will be ignored.\n" 365 "\n"
203 "\n" 366 " Example: default_output_extension = \".exe\"\n"
204 "Ninja variables available to tool invocations\n" 367 "\n"
205 "\n" 368 " depfile [string]\n"
206 " When writing tool commands, you use the various built-in Ninja\n" 369 " Valid for: compiler tools (optional)\n"
207 " variables like \"$in\" and \"$out\" (note that the $ must be escaped\n" 370 "\n"
208 " for it to be passed to Ninja, so write \"\\$in\" in the command\n" 371 " If the tool can write \".d\" files, this specifies the name of\n"
209 " string).\n" 372 " the resulting file. These files are used to list header file\n"
210 "\n" 373 " dependencies (or other implicit input dependencies) that are\n"
211 " GN defines the following variables for binary targets to access the\n" 374 " discovered at build time. See also \"depsformat\".\n"
212 " various computed information needed for compiling:\n" 375 "\n"
213 "\n" 376 " Example: depfile = \"{{output}}.d\"\n"
214 " - Compiler flags: \"cflags\", \"cflags_c\", \"cflags_cc\",\n" 377 "\n"
215 " \"cflags_objc\", \"cflags_objcc\"\n" 378 " depsformat [string]\n"
216 "\n" 379 " Valid for: compiler tools (when depfile is specified)\n"
217 " - Linker flags: \"ldflags\", \"libs\"\n" 380 "\n"
218 "\n" 381 " Format for the deps outputs. This is either \"gcc\" or \"msvc\".\n"
219 " GN sets these other variables with target information that can be\n" 382 " See the ninja documentation for \"deps\" for more information.\n"
220 " used for computing names for supplimetary files:\n" 383 "\n"
221 "\n" 384 " Example: depsformat = \"gcc\"\n"
222 " - \"target_name\": The name of the current target with no\n" 385 "\n"
223 " path information. For example \"mylib\".\n" 386 " description [string with substitutions, optional]\n"
224 "\n" 387 " Valid for: all tools\n"
225 " - \"target_out_dir\": The value of \"target_out_dir\" from the BUILD\n" 388 "\n"
226 " file for this target (see \"gn help target_out_dir\"), relative\n" 389 " What to print when the command is run.\n"
227 " to the root build directory with no trailing slash.\n" 390 "\n"
228 "\n" 391 " Example: description = \"Compiling {{source}}\"\n"
229 " - \"root_out_dir\": The value of \"root_out_dir\" from the BUILD\n" 392 "\n"
230 " file for this target (see \"gn help root_out_dir\"), relative\n" 393 " lib_switch [string, optional, link tools only]\n"
231 " to the root build directory with no trailing slash.\n" 394 " lib_dir_switch [string, optional, link tools only]\n"
395 " Valid for: Linker tools except \"alink\"\n"
396 "\n"
397 " These strings will be prepended to the libraries and library\n"
398 " search directories, respectively, because linkers differ on how\n"
399 " specify them. If you specified:\n"
400 " lib_switch = \"-l\"\n"
401 " lib_dir_switch = \"-L\"\n"
402 " then the \"{{libs}}\" expansion for [ \"freetype\", \"expat\"]\n"
403 " would be \"-lfreetype -lexpat\".\n"
404 "\n"
405 " outputs [list of strings with substitutions]\n"
406 " Valid for: Linker and compiler tools (required)\n"
407 "\n"
408 " An array of names for the output files the tool produces. These\n"
409 " are relative to the build output directory. There must always be\n"
410 " at least one output file. There can be more than one output (a\n"
411 " linker might produce a library and an import library, for\n"
412 " example).\n"
413 "\n"
414 " This array just declares to GN what files the tool will\n"
415 " produce. It is your responsibility to specify the tool command\n"
416 " that actually produces these files.\n"
417 "\n"
418 " If you specify more than one output for shared library links,\n"
419 " you should consider setting link_output and depend_output.\n"
420 " Otherwise, the first entry in the outputs list should always be\n"
421 " the main output which will be linked to.\n"
422 "\n"
423 " Example for a compiler tool that produces .obj files:\n"
424 " outputs = [\n"
425 " \"{{source_out_dir}}/{{source_name_part}}.obj\"\n"
426 " ]\n"
427 "\n"
428 " Example for a linker tool that produces a .dll and a .lib. The\n"
429 " use of {{output_extension}} rather than hardcoding \".dll\"\n"
430 " allows the extension of the library to be overridden on a\n"
431 " target-by-target basis, but in this example, it always\n"
432 " produces a \".lib\" import library:\n"
433 " outputs = [\n"
434 " \"{{root_out_dir}}/{{target_output_name}}"
435 "{{output_extension}}\",\n"
436 " \"{{root_out_dir}}/{{target_output_name}}.lib\",\n"
437 " ]\n"
438 "\n"
439 " link_output [string with substitutions]\n"
440 " depend_output [string with substitutions]\n"
441 " Valid for: \"solink\" only (optional)\n"
442 "\n"
443 " These two files specify whch of the outputs from the solink\n"
444 " tool should be used for linking and dependency tracking. These\n"
445 " should match entries in the \"outputs\". If unspecified, the\n"
446 " first item in the \"outputs\" array will be used for both. See\n"
447 " \"Separate linking and dependencies for shared libraries\"\n"
448 " below for more.\n"
449 "\n"
450 " On Windows, where the tools produce a .dll shared library and\n"
451 " a .lib import library, you will want both of these to be the\n"
452 " import library. On Linux, if you're not doing the separate\n"
453 " linking/dependency optimization, both of these should be the\n"
454 " .so output.\n"
455 "\n"
456 " output_prefix [string]\n"
457 " Valid for: Linker tools (optional)\n"
458 "\n"
459 " Prefix to use for the output name. Defaults to empty. This\n"
460 " prefix will be prepended to the name of the target (or the\n"
461 " output_name if one is manually specified for it) if the prefix\n"
462 " is not already there. The result will show up in the\n"
463 " {{output_name}} substitution pattern.\n"
464 "\n"
465 " This is typically used to prepend \"lib\" to libraries on\n"
466 " Posix systems:\n"
467 " output_prefix = \"lib\"\n"
468 "\n"
469 " pool [string, optional]\n"
470 " See the Ninja documentation.\n"
471 " TODO(brettw) write this. Probably doesn't work yet.\n"
jamesr 2014/08/19 19:30:41 should we just leave this out?
472 "\n"
473 " restat [boolean]\n"
474 " Valid for: all tools (optional, defaults to false)\n"
475 "\n"
476 " Requests that Ninja check the file timestamp after this tool has\n"
477 " run to determine if anything changed. Set this if your tool has\n"
478 " the ability to skip writing output if the output file has not\n"
479 " changed.\n"
480 "\n"
481 " Normally, Ninja will assume that when a tool runs the output\n"
482 " be new and downstream dependents must be rebuild. When this is\n"
483 " set to trye, Ninja can skip rebuilding downstream dependents for\n"
484 " input changes that don't actually affect the output.\n"
485 "\n"
486 " Example:\n"
487 " restat = true\n"
488 "\n"
489 " rspfile [string with substitutions]\n"
490 " Valid for: all tools (optional)\n"
491 "\n"
492 " Name of the response file. If empty, no response file will be\n"
493 " used. See \"rspfile_content\".\n"
494 "\n"
495 " rspfile_content [string with substitutions]\n"
496 " Valid for: all tools (required when \"rspfile\" is specified)\n"
497 "\n"
498 " The contents to be written to the response file. This may\n"
499 " include all or part of the command to send to the tool which\n"
500 " allows you to get around OS command-line length limits.\n"
501 "\n"
502 " This example adds the inputs and libraries to a response file,\n"
503 " but passes the linker flags directly on the command line:\n"
504 " tool(\"link\") {\n"
505 " command = \"link -o {{output}} {{ldflags}} @{{output}}.rsp\"\n"
506 " rspfile = \"{{output}}.rsp\"\n"
507 " rspfile_content = \"{{inputs}} {{solibs}} {{libs}}\"\n"
508 " }\n"
509 "\n"
510 "Expansions for tool variables"
511 "\n"
512 " All paths are relative to the root build directory, which is the\n"
513 " current directory for running all tools. These expansions are\n"
514 " available to all tools:\n"
515 "\n"
516 " {{label}}\n"
517 " The label of the current target. This is typically used in the\n"
518 " \"description\" field for link tools. The toolchain will be\n"
519 " omitted from the label for targets in the default toolchain, and\n"
520 " will be included for targets in other toolchains.\n"
521 "\n"
522 " {{output}}\n"
523 " The relative path and name of the output)((s) of the current\n"
524 " build step. If there is more than one output, this will expand\n"
525 " to a list of all of them.\n"
526 " Example: \"out/base/my_file.o\"\n"
527 "\n"
528 " {{target_gen_dir}}\n"
529 " {{target_out_dir}}\n"
530 " The directory of the generated file and output directories,\n"
531 " respectively, for the current target. There is no trailing\n"
532 " slash.\n"
533 " Example: \"out/base/test\"\n"
534 "\n"
535 " {{target_output_name}}\n"
536 " The short name of the current target with no path information,\n"
537 " or the value of the \"output_name\" variable if one is specified\n"
538 " in the target. This will include the \"output_prefix\" if any.\n"
539 " Example: \"libfoo\" for the target named \"foo\" and an\n"
540 " output prefix for the linker tool of \"lib\".\n"
541 "\n"
542 " Compiler tools have the notion of a single input and a single output,\n"
543 " along with a set of compiler-specific flags. The following expansions\n"
544 " are available:\n"
545 "\n"
546 " {{cflags}}\n"
547 " {{cflags_c}}\n"
548 " {{cflags_cc}}\n"
549 " {{cflags_objc}}\n"
550 " {{cflags_objcc}}\n"
551 " {{defines}}\n"
jamesr 2014/08/19 19:30:41 does this have /Dxxx or -Dxxx or is it just xxx? e
552 " {{include_dirs}}\n"
553 " Strings correspond that to the processed flags/defines/include\n"
554 " directories specified for the target.\n"
555 " Example: \"--enable-foo --enable-bar\"\n"
556 "\n"
557 " {{source}}\n"
558 " The relative path and name of the current input file.\n"
559 " Example: \"../../base/my_file.cc\"\n"
560 "\n"
561 " {{source_file_part}}\n"
562 " The file part of the source including the extension (with no\n"
563 " directory information).\n"
564 " Example: \"foo.cc\"\n"
565 "\n"
566 " {{source_name_part}}\n"
567 " The filename part of the source file with no directory or\n"
568 " extension.\n"
569 " Example: \"foo\"\n"
570 "\n"
571 " {{source_gen_dir}}\n"
572 " {{source_out_dir}}\n"
573 " The directory in the generated file and output directories,\n"
574 " respectively, for the current input file. If the source file\n"
575 " is in the same directory as the target is declared in, they will\n"
576 " will be the same as the \"target\" versions above.\n"
577 " Example: \"gen/base/test\"\n"
578 "\n"
579 " Linker tools have multiple inputs and (potentially) multiple outputs\n"
580 " The following expansions are available:\n"
581 "\n"
582 " {{inputs}}\n"
583 " Expands to the inputs to the link step. This will be a list of\n"
584 " object files and static libraries.\n"
585 " Example: \"obj/foo.o obj/bar.o obj/somelibrary.a\"\n"
586 "\n"
587 " {{ldflags}}\n"
588 " Expands to the processed set of ldflags and library search paths\n"
589 " specified for the target.\n"
590 " Example: \"-m64, -fPIC -pthread -L/usr/local/mylib\"\n"
591 "\n"
592 " {{libs}}\n"
593 " Expands to the list of system libraries to link to. Each will\n"
594 " be prefixed by the \"lib_prefix\".\n"
595 "\n"
596 " As a special case to support Mac, libraries with names ending in\n"
597 " \".framework\" will be added to the {{libs}} with \"-framework\"\n"
598 " preceeding it, and the lib prefix will be ignored.\n"
599 "\n"
600 " Example: \"-lfoo -lbar\"\n"
601 "\n"
602 " {{output_extension}}\n"
603 " The value of the \"output_extension\" variable in the target,\n"
604 " or the value of the \"default_output_extension\" value in the\n"
605 " tool if the target does not specify an output extension.\n"
606 " Example: \".so\"\n"
607 "\n"
608 " {{solibs}}\n"
609 " Extra libraries from shared library dependncies not specified\n"
jamesr 2014/08/19 19:30:41 typo 'dependncies' -> 'dependencies'
610 " in the {{inputs}}. This is the list of link_output files from\n"
611 " shared libraries (if the solink tool specifies a \"link_output\"\n"
612 " variable separate from the \"depend_output\").\n"
613 "\n"
614 " These should basically be treated by sources by your tool.\n"
jamesr 2014/08/19 19:30:41 dunno what 'by sources' means - do you mean 'treat
615 " Example: \"libfoo.so libbar.so\"\n"
616 "\n"
617 " The copy tool allows the common compiler/linker substitutions, plus\n"
618 " {{source}} which is the source of the copy. The stamp tool allows\n"
619 " only the common tool substitutions.\n"
620 "\n"
621 "Separate linking and dependencies for shared libraries\n"
622 "\n"
623 " Shared libraries are special in that not all changes to them require\n"
624 " that dependent targets be re-linked. If the shared library is changed\n"
625 " but no imports or exports are different, dependent code needn't be\n"
626 " relinked, which can speed up the build.\n"
627 "\n"
628 " If your link step can output a list of exports from a shared library\n"
629 " and writes the file only if the new one is different, the timestamp of\n"
630 " this file can be used for triggering re-links, while the actual shared\n"
631 " library would be used for linking.\n"
632 "\n"
633 " You will need to specify\n"
634 " restat = true\n"
635 " in the linker tool to make this work, so Ninja will detect if the\n"
636 " timestamp of the dependency file has changed after linking (otherwise\n"
637 " it will always assume that running a command updates the output):\n"
638 "\n"
639 " tool(\"solink\") {\n"
640 " command = \"...\"\n"
641 " outputs = [\n"
642 " \"{{root_out_dir}}/{{target_output_name}}{{output_extension}}\",\n"
643 " \"{{root_out_dir}}/{{target_output_name}}"
644 "{{output_extension}}.TOC\",\n"
645 " ]\n"
646 " link_output =\n"
647 " \"{{root_out_dir}}/{{target_output_name}}{{output_extension}}\",\n"
648 " depend_output =\n"
649 " \"{{root_out_dir}}/{{target_output_name}}"
650 "{{output_extension}}.TOC\",\n"
651 " restat = true\n"
652 " }\n"
232 "\n" 653 "\n"
233 "Example\n" 654 "Example\n"
234 "\n" 655 "\n"
235 " toolchain(\"my_toolchain\") {\n" 656 " toolchain(\"my_toolchain\") {\n"
236 " # Put these at the top to apply to all tools below.\n" 657 " # Put these at the top to apply to all tools below.\n"
237 " lib_prefix = \"-l\"\n" 658 " lib_prefix = \"-l\"\n"
238 " lib_dir_prefix = \"-L\"\n" 659 " lib_dir_prefix = \"-L\"\n"
239 "\n" 660 "\n"
240 " tool(\"cc\") {\n" 661 " tool(\"cc\") {\n"
241 " command = \"gcc \\$in -o \\$out\"\n" 662 " command = \"gcc \\$in -o \\$out\"\n"
663 " outputs = [ \"{{source_out_dir}}/{{source_name_part}}.o\"\n"
242 " description = \"GCC \\$in\"\n" 664 " description = \"GCC \\$in\"\n"
243 " }\n" 665 " }\n"
244 " tool(\"cxx\") {\n" 666 " tool(\"cxx\") {\n"
245 " command = \"g++ \\$in -o \\$out\"\n" 667 " command = \"g++ \\$in -o \\$out\"\n"
668 " outputs = [ \"{{source_out_dir}}/{{source_name_part}}.o\"\n"
246 " description = \"G++ \\$in\"\n" 669 " description = \"G++ \\$in\"\n"
247 " }\n" 670 " }\n"
248 " }\n"; 671 " }\n";
249 672
250 Value RunTool(Scope* scope, 673 Value RunTool(Scope* scope,
251 const FunctionCallNode* function, 674 const FunctionCallNode* function,
252 const std::vector<Value>& args, 675 const std::vector<Value>& args,
253 BlockNode* block, 676 BlockNode* block,
254 Err* err) { 677 Err* err) {
255 // Find the toolchain definition we're executing inside of. The toolchain 678 // Find the toolchain definition we're executing inside of. The toolchain
(...skipping 15 matching lines...) Expand all
271 *err = Err(args[0], "Unknown tool type"); 694 *err = Err(args[0], "Unknown tool type");
272 return Value(); 695 return Value();
273 } 696 }
274 697
275 // Run the tool block. 698 // Run the tool block.
276 Scope block_scope(scope); 699 Scope block_scope(scope);
277 block->ExecuteBlockInScope(&block_scope, err); 700 block->ExecuteBlockInScope(&block_scope, err);
278 if (err->has_error()) 701 if (err->has_error())
279 return Value(); 702 return Value();
280 703
281 // Extract the stuff we need. 704 // Figure out which validator to use for the substitution pattern for this
282 Toolchain::Tool t; 705 // tool type. There are different validators for the "outputs" than for the
283 if (!ReadString(block_scope, "command", &t.command, err) || 706 // rest of the strings.
284 !ReadString(block_scope, "depfile", &t.depfile, err) || 707 bool (*subst_validator)(SubstitutionType) = NULL;
285 // TODO(brettw) delete this once we rename "deps" -> "depsformat" in 708 bool (*subst_output_validator)(SubstitutionType) = NULL;
286 // the toolchain definitions. This will avoid colliding with the 709 if (IsCompilerTool(tool_type)) {
287 // toolchain's "deps" list. For now, accept either. 710 subst_validator = &IsValidCompilerSubstitution;
288 !ReadString(block_scope, "deps", &t.depsformat, err) || 711 subst_output_validator = &IsValidCompilerOutputsSubstitution;
289 !ReadString(block_scope, "depsformat", &t.depsformat, err) || 712 } else if (IsLinkerTool(tool_type)) {
290 !ReadString(block_scope, "description", &t.description, err) || 713 subst_validator = &IsValidLinkerSubstitution;
291 !ReadString(block_scope, "lib_dir_prefix", &t.lib_dir_prefix, err) || 714 subst_output_validator = &IsValidLinkerOutputsSubstitution;
292 !ReadString(block_scope, "lib_prefix", &t.lib_prefix, err) || 715 } else if (tool_type == Toolchain::TYPE_COPY) {
293 !ReadString(block_scope, "pool", &t.pool, err) || 716 subst_validator = &IsValidCopySubstitution;
294 !ReadString(block_scope, "restat", &t.restat, err) || 717 subst_output_validator = &IsValidCopySubstitution;
295 !ReadString(block_scope, "rspfile", &t.rspfile, err) || 718 } else {
296 !ReadString(block_scope, "rspfile_content", &t.rspfile_content, err)) 719 subst_validator = &IsValidToolSubstutition;
720 subst_output_validator = &IsValidToolSubstutition;
721 }
722
723 scoped_ptr<Tool> tool(new Tool);
724
725 if (!ReadPattern(&block_scope, "command", subst_validator, tool.get(),
726 &Tool::set_command, err) ||
727 !ReadOutputExtension(&block_scope, tool.get(), err) ||
728 !ReadPattern(&block_scope, "depfile", subst_validator, tool.get(),
729 &Tool::set_depfile, err) ||
730 !ReadDepsFormat(&block_scope, tool.get(), err) ||
731 !ReadPattern(&block_scope, "description", subst_validator, tool.get(),
732 &Tool::set_description, err) ||
733 !ReadString(&block_scope, "lib_switch", tool.get(),
734 &Tool::set_lib_switch, err) ||
735 !ReadString(&block_scope, "lib_dir_switch", tool.get(),
736 &Tool::set_lib_dir_switch, err) ||
737 !ReadPattern(&block_scope, "link_output", subst_validator, tool.get(),
738 &Tool::set_link_output, err) ||
739 !ReadPattern(&block_scope, "depend_output", subst_validator, tool.get(),
740 &Tool::set_depend_output, err) ||
741 !ReadString(&block_scope, "output_prefix", tool.get(),
742 &Tool::set_output_prefix, err) ||
743 !ReadString(&block_scope, "pool", tool.get(), &Tool::set_pool, err) ||
744 !ReadBool(&block_scope, "restat", tool.get(), &Tool::set_restat, err) ||
745 !ReadPattern(&block_scope, "rspfile", subst_validator, tool.get(),
746 &Tool::set_rspfile, err) ||
747 !ReadPattern(&block_scope, "rspfile_content", subst_validator, tool.get(),
748 &Tool::set_rspfile_content, err)) {
297 return Value(); 749 return Value();
750 }
751
752 if (tool_type != Toolchain::TYPE_COPY && tool_type != Toolchain::TYPE_STAMP) {
753 // All tools except the copy and stamp tools should have outputs. The copy
754 // and stamp tool's outputs are generated internally.
755 if (!ReadOutputs(&block_scope, function, subst_output_validator,
756 tool.get(), err))
757 return Value();
758 }
759
760 // Validate that the link_output and depend_output refer to items in the
761 // outputs and aren't defined for irrelevant tool types.
762 if (!tool->link_output().empty()) {
763 if (tool_type != Toolchain::TYPE_SOLINK) {
764 *err = Err(function, "This tool specifies a link_output.",
765 "This is only valid for solink tools.");
766 return Value();
767 }
768 if (!IsPatternInOutputList(tool->outputs(), tool->link_output())) {
769 *err = Err(function, "This tool's link_output is bad.",
770 "It must match one of the outputs.");
771 return Value();
772 }
773 }
774 if (!tool->depend_output().empty()) {
775 if (tool_type != Toolchain::TYPE_SOLINK) {
776 *err = Err(function, "This tool specifies a depend_output.",
777 "This is only valid for solink tools.");
778 return Value();
779 }
780 if (!IsPatternInOutputList(tool->outputs(), tool->depend_output())) {
781 *err = Err(function, "This tool's depend_output is bad.",
782 "It must match one of the outputs.");
783 return Value();
784 }
785 }
786 if ((!tool->link_output().empty() && tool->depend_output().empty()) ||
787 (tool->link_output().empty() && !tool->depend_output().empty())) {
788 *err = Err(function, "Both link_output and depend_output should either "
789 "be specified or they should both be empty.");
790 return Value();
791 }
298 792
299 // Make sure there weren't any vars set in this tool that were unused. 793 // Make sure there weren't any vars set in this tool that were unused.
300 if (!block_scope.CheckForUnusedVars(err)) 794 if (!block_scope.CheckForUnusedVars(err))
301 return Value(); 795 return Value();
302 796
303 toolchain->SetTool(tool_type, t); 797 toolchain->SetTool(tool_type, tool.Pass());
304 return Value(); 798 return Value();
305 } 799 }
306 800
307 // toolchain_args -------------------------------------------------------------- 801 // toolchain_args --------------------------------------------------------------
308 802
309 extern const char kToolchainArgs[] = "toolchain_args"; 803 extern const char kToolchainArgs[] = "toolchain_args";
310 extern const char kToolchainArgs_HelpShort[] = 804 extern const char kToolchainArgs_HelpShort[] =
311 "toolchain_args: Set build arguments for toolchain build setup."; 805 "toolchain_args: Set build arguments for toolchain build setup.";
312 extern const char kToolchainArgs_Help[] = 806 extern const char kToolchainArgs_Help[] =
313 "toolchain_args: Set build arguments for toolchain build setup.\n" 807 "toolchain_args: Set build arguments for toolchain build setup.\n"
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
374 return Value(); 868 return Value();
375 869
376 Scope::KeyValueMap values; 870 Scope::KeyValueMap values;
377 block_scope.GetCurrentScopeValues(&values); 871 block_scope.GetCurrentScopeValues(&values);
378 toolchain->args() = values; 872 toolchain->args() = values;
379 873
380 return Value(); 874 return Value();
381 } 875 }
382 876
383 } // namespace functions 877 } // namespace functions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698