OLD | NEW |
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> | 5 #include <algorithm> |
6 #include <limits> | 6 #include <limits> |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "tools/gn/err.h" | 9 #include "tools/gn/err.h" |
10 #include "tools/gn/functions.h" | 10 #include "tools/gn/functions.h" |
(...skipping 29 matching lines...) Expand all Loading... |
40 | 40 |
41 (tool->*set)(v->boolean_value()); | 41 (tool->*set)(v->boolean_value()); |
42 return true; | 42 return true; |
43 } | 43 } |
44 | 44 |
45 // Reads the given string from the scope (if present) and puts the result into | 45 // Reads the given string from the scope (if present) and puts the result into |
46 // dest. If the value is not a string, sets the error and returns false. | 46 // dest. If the value is not a string, sets the error and returns false. |
47 bool ReadString(Scope* scope, | 47 bool ReadString(Scope* scope, |
48 const char* var, | 48 const char* var, |
49 Tool* tool, | 49 Tool* tool, |
50 void (Tool::*set)(const std::string&), | 50 void (Tool::*set)(std::string), |
51 Err* err) { | 51 Err* err) { |
52 const Value* v = scope->GetValue(var, true); | 52 const Value* v = scope->GetValue(var, true); |
53 if (!v) | 53 if (!v) |
54 return true; // Not present is fine. | 54 return true; // Not present is fine. |
55 if (!v->VerifyTypeIs(Value::STRING, err)) | 55 if (!v->VerifyTypeIs(Value::STRING, err)) |
56 return false; | 56 return false; |
57 | 57 |
58 (tool->*set)(v->string_value()); | 58 (tool->*set)(v->string_value()); |
59 return true; | 59 return true; |
60 } | 60 } |
61 | 61 |
62 // Reads the given label from the scope (if present) and puts the result into | 62 // Reads the given label from the scope (if present) and puts the result into |
63 // dest. If the value is not a label, sets the error and returns false. | 63 // dest. If the value is not a label, sets the error and returns false. |
64 bool ReadLabel(Scope* scope, | 64 bool ReadLabel(Scope* scope, |
65 const char* var, | 65 const char* var, |
66 Tool* tool, | 66 Tool* tool, |
67 const ParseNode* origin, | |
68 const Label& current_toolchain, | 67 const Label& current_toolchain, |
69 void (Tool::*set)(const LabelPtrPair<Pool>&), | 68 void (Tool::*set)(LabelPtrPair<Pool>), |
70 Err* err) { | 69 Err* err) { |
71 const Value* v = scope->GetValue(var, true); | 70 const Value* v = scope->GetValue(var, true); |
72 if (!v) | 71 if (!v) |
73 return true; // Not present is fine. | 72 return true; // Not present is fine. |
74 | 73 |
75 Label label = | 74 Label label = |
76 Label::Resolve(scope->GetSourceDir(), current_toolchain, *v, err); | 75 Label::Resolve(scope->GetSourceDir(), current_toolchain, *v, err); |
77 if (err->has_error()) | 76 if (err->has_error()) |
78 return false; | 77 return false; |
79 | 78 |
80 LabelPtrPair<Pool> pair(label); | 79 LabelPtrPair<Pool> pair(label); |
81 pair.origin = origin; | 80 pair.origin = tool->defined_from(); |
82 | 81 |
83 (tool->*set)(pair); | 82 (tool->*set)(std::move(pair)); |
84 return true; | 83 return true; |
85 } | 84 } |
86 | 85 |
87 // Calls the given validate function on each type in the list. On failure, | 86 // Calls the given validate function on each type in the list. On failure, |
88 // sets the error, blame the value, and return false. | 87 // sets the error, blame the value, and return false. |
89 bool ValidateSubstitutionList(const std::vector<SubstitutionType>& list, | 88 bool ValidateSubstitutionList(const std::vector<SubstitutionType>& list, |
90 bool (*validate)(SubstitutionType), | 89 bool (*validate)(SubstitutionType), |
91 const Value* origin, | 90 const Value* origin, |
92 Err* err) { | 91 Err* err) { |
93 for (const auto& cur_type : list) { | 92 for (const auto& cur_type : list) { |
94 if (!validate(cur_type)) { | 93 if (!validate(cur_type)) { |
95 *err = Err(*origin, "Pattern not valid here.", | 94 *err = Err(*origin, "Pattern not valid here.", |
96 "You used the pattern " + std::string(kSubstitutionNames[cur_type]) + | 95 "You used the pattern " + std::string(kSubstitutionNames[cur_type]) + |
97 " which is not valid\nfor this variable."); | 96 " which is not valid\nfor this variable."); |
98 return false; | 97 return false; |
99 } | 98 } |
100 } | 99 } |
101 return true; | 100 return true; |
102 } | 101 } |
103 | 102 |
104 bool ReadPattern(Scope* scope, | 103 bool ReadPattern(Scope* scope, |
105 const char* name, | 104 const char* name, |
106 bool (*validate)(SubstitutionType), | 105 bool (*validate)(SubstitutionType), |
107 Tool* tool, | 106 Tool* tool, |
108 void (Tool::*set)(const SubstitutionPattern&), | 107 void (Tool::*set)(SubstitutionPattern), |
109 Err* err) { | 108 Err* err) { |
110 const Value* value = scope->GetValue(name, true); | 109 const Value* value = scope->GetValue(name, true); |
111 if (!value) | 110 if (!value) |
112 return true; // Not present is fine. | 111 return true; // Not present is fine. |
113 if (!value->VerifyTypeIs(Value::STRING, err)) | 112 if (!value->VerifyTypeIs(Value::STRING, err)) |
114 return false; | 113 return false; |
115 | 114 |
116 SubstitutionPattern pattern; | 115 SubstitutionPattern pattern; |
117 if (!pattern.Parse(*value, err)) | 116 if (!pattern.Parse(*value, err)) |
118 return false; | 117 return false; |
119 if (!ValidateSubstitutionList(pattern.required_types(), validate, value, err)) | 118 if (!ValidateSubstitutionList(pattern.required_types(), validate, value, err)) |
120 return false; | 119 return false; |
121 | 120 |
122 (tool->*set)(pattern); | 121 (tool->*set)(std::move(pattern)); |
123 return true; | 122 return true; |
124 } | 123 } |
125 | 124 |
| 125 bool ReadPatternList(Scope* scope, |
| 126 const char* name, |
| 127 bool (*validate)(SubstitutionType), |
| 128 Tool* tool, |
| 129 void (Tool::*set)(SubstitutionList), |
| 130 Err* err) { |
| 131 const Value* value = scope->GetValue(name, true); |
| 132 if (!value) |
| 133 return true; // Not present is fine. |
| 134 if (!value->VerifyTypeIs(Value::LIST, err)) |
| 135 return false; |
| 136 |
| 137 SubstitutionList list; |
| 138 if (!list.Parse(*value, err)) |
| 139 return false; |
| 140 |
| 141 // Validate the right kinds of patterns are used. |
| 142 if (!ValidateSubstitutionList(list.required_types(), validate, value, err)) |
| 143 return false; |
| 144 |
| 145 (tool->*set)(std::move(list)); |
| 146 return true; |
| 147 } |
| 148 |
126 bool ReadOutputExtension(Scope* scope, Tool* tool, Err* err) { | 149 bool ReadOutputExtension(Scope* scope, Tool* tool, Err* err) { |
127 const Value* value = scope->GetValue("default_output_extension", true); | 150 const Value* value = scope->GetValue("default_output_extension", true); |
128 if (!value) | 151 if (!value) |
129 return true; // Not present is fine. | 152 return true; // Not present is fine. |
130 if (!value->VerifyTypeIs(Value::STRING, err)) | 153 if (!value->VerifyTypeIs(Value::STRING, err)) |
131 return false; | 154 return false; |
132 | 155 |
133 if (value->string_value().empty()) | 156 if (value->string_value().empty()) |
134 return true; // Accept empty string. | 157 return true; // Accept empty string. |
135 | 158 |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
175 tool->set_depsformat(Tool::DEPS_GCC); | 198 tool->set_depsformat(Tool::DEPS_GCC); |
176 } else if (value->string_value() == "msvc") { | 199 } else if (value->string_value() == "msvc") { |
177 tool->set_depsformat(Tool::DEPS_MSVC); | 200 tool->set_depsformat(Tool::DEPS_MSVC); |
178 } else { | 201 } else { |
179 *err = Err(*value, "Deps format must be \"gcc\" or \"msvc\"."); | 202 *err = Err(*value, "Deps format must be \"gcc\" or \"msvc\"."); |
180 return false; | 203 return false; |
181 } | 204 } |
182 return true; | 205 return true; |
183 } | 206 } |
184 | 207 |
185 bool ReadOutputs(Scope* scope, | |
186 const FunctionCallNode* tool_function, | |
187 bool (*validate)(SubstitutionType), | |
188 Tool* tool, | |
189 Err* err) { | |
190 const Value* value = scope->GetValue("outputs", true); | |
191 if (!value) { | |
192 *err = Err(tool_function, "\"outputs\" must be specified for this tool."); | |
193 return false; | |
194 } | |
195 | |
196 SubstitutionList list; | |
197 if (!list.Parse(*value, err)) | |
198 return false; | |
199 | |
200 // Validate the right kinds of patterns are used. | |
201 if (!ValidateSubstitutionList(list.required_types(), validate, value, err)) | |
202 return false; | |
203 | |
204 // There should always be at least one output. | |
205 if (list.list().empty()) { | |
206 *err = Err(*value, "Outputs list is empty.", "I need some outputs."); | |
207 return false; | |
208 } | |
209 | |
210 tool->set_outputs(list); | |
211 return true; | |
212 } | |
213 | |
214 bool IsCompilerTool(Toolchain::ToolType type) { | 208 bool IsCompilerTool(Toolchain::ToolType type) { |
215 return type == Toolchain::TYPE_CC || | 209 return type == Toolchain::TYPE_CC || |
216 type == Toolchain::TYPE_CXX || | 210 type == Toolchain::TYPE_CXX || |
217 type == Toolchain::TYPE_OBJC || | 211 type == Toolchain::TYPE_OBJC || |
218 type == Toolchain::TYPE_OBJCXX || | 212 type == Toolchain::TYPE_OBJCXX || |
219 type == Toolchain::TYPE_RC || | 213 type == Toolchain::TYPE_RC || |
220 type == Toolchain::TYPE_ASM; | 214 type == Toolchain::TYPE_ASM; |
221 } | 215 } |
222 | 216 |
223 bool IsLinkerTool(Toolchain::ToolType type) { | 217 bool IsLinkerTool(Toolchain::ToolType type) { |
224 // "alink" is not counted as in the generic "linker" tool list. | 218 // "alink" is not counted as in the generic "linker" tool list. |
225 return type == Toolchain::TYPE_SOLINK || | 219 return type == Toolchain::TYPE_SOLINK || |
226 type == Toolchain::TYPE_SOLINK_MODULE || | 220 type == Toolchain::TYPE_SOLINK_MODULE || |
227 type == Toolchain::TYPE_LINK; | 221 type == Toolchain::TYPE_LINK; |
228 } | 222 } |
229 | 223 |
230 bool IsPatternInOutputList(const SubstitutionList& output_list, | 224 bool IsPatternInOutputList(const SubstitutionList& output_list, |
231 const SubstitutionPattern& pattern) { | 225 const SubstitutionPattern& pattern) { |
232 for (const auto& cur : output_list.list()) { | 226 for (const auto& cur : output_list.list()) { |
233 if (pattern.ranges().size() == cur.ranges().size() && | 227 if (pattern.ranges().size() == cur.ranges().size() && |
234 std::equal(pattern.ranges().begin(), pattern.ranges().end(), | 228 std::equal(pattern.ranges().begin(), pattern.ranges().end(), |
235 cur.ranges().begin())) | 229 cur.ranges().begin())) |
236 return true; | 230 return true; |
237 } | 231 } |
238 return false; | 232 return false; |
239 } | 233 } |
240 | 234 |
| 235 |
| 236 bool ValidateOutputs(const Tool* tool, Err* err) { |
| 237 if (tool->outputs().list().empty()) { |
| 238 *err = Err(tool->defined_from(), |
| 239 "\"outputs\" must be specified for this tool."); |
| 240 return false; |
| 241 } |
| 242 return true; |
| 243 } |
| 244 |
| 245 // Validates either link_output or depend_output. To generalize to either, pass |
| 246 // the associated pattern, and the variable name that should appear in error |
| 247 // messages. |
| 248 bool ValidateLinkAndDependOutput(const Tool* tool, |
| 249 Toolchain::ToolType tool_type, |
| 250 const SubstitutionPattern& pattern, |
| 251 const char* variable_name, |
| 252 Err* err) { |
| 253 if (pattern.empty()) |
| 254 return true; // Empty is always OK. |
| 255 |
| 256 // It should only be specified for certain tool types. |
| 257 if (tool_type != Toolchain::TYPE_SOLINK && |
| 258 tool_type != Toolchain::TYPE_SOLINK_MODULE) { |
| 259 *err = Err(tool->defined_from(), |
| 260 "This tool specifies a " + std::string(variable_name) + ".", |
| 261 "This is only valid for solink and solink_module tools."); |
| 262 return false; |
| 263 } |
| 264 |
| 265 if (!IsPatternInOutputList(tool->outputs(), pattern)) { |
| 266 *err = Err(tool->defined_from(), "This tool's link_output is bad.", |
| 267 "It must match one of the outputs."); |
| 268 return false; |
| 269 } |
| 270 |
| 271 return true; |
| 272 } |
| 273 |
| 274 bool ValidateRuntimeOutputs(const Tool* tool, |
| 275 Toolchain::ToolType tool_type, |
| 276 Err* err) { |
| 277 if (tool->runtime_outputs().list().empty()) |
| 278 return true; // Empty is always OK. |
| 279 |
| 280 if (!IsLinkerTool(tool_type)) { |
| 281 *err = Err(tool->defined_from(), "This tool specifies runtime_outputs.", |
| 282 "This is only valid for linker tools (alink doesn't count)."); |
| 283 return false; |
| 284 } |
| 285 |
| 286 for (const SubstitutionPattern& pattern : tool->runtime_outputs().list()) { |
| 287 if (!IsPatternInOutputList(tool->outputs(), pattern)) { |
| 288 *err = Err(tool->defined_from(), "This tool's runtime_outputs is bad.", |
| 289 "It must be a subset of the outputs. The bad one is:\n " + |
| 290 pattern.AsString()); |
| 291 return false; |
| 292 } |
| 293 } |
| 294 return true; |
| 295 } |
| 296 |
241 } // namespace | 297 } // namespace |
242 | 298 |
243 // toolchain ------------------------------------------------------------------- | 299 // toolchain ------------------------------------------------------------------- |
244 | 300 |
245 const char kToolchain[] = "toolchain"; | 301 const char kToolchain[] = "toolchain"; |
246 const char kToolchain_HelpShort[] = | 302 const char kToolchain_HelpShort[] = |
247 "toolchain: Defines a toolchain."; | 303 "toolchain: Defines a toolchain."; |
248 const char kToolchain_Help[] = | 304 const char kToolchain_Help[] = |
249 "toolchain: Defines a toolchain.\n" | 305 "toolchain: Defines a toolchain.\n" |
250 "\n" | 306 "\n" |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
520 " at least one output file. There can be more than one output (a\n" | 576 " at least one output file. There can be more than one output (a\n" |
521 " linker might produce a library and an import library, for\n" | 577 " linker might produce a library and an import library, for\n" |
522 " example).\n" | 578 " example).\n" |
523 "\n" | 579 "\n" |
524 " This array just declares to GN what files the tool will\n" | 580 " This array just declares to GN what files the tool will\n" |
525 " produce. It is your responsibility to specify the tool command\n" | 581 " produce. It is your responsibility to specify the tool command\n" |
526 " that actually produces these files.\n" | 582 " that actually produces these files.\n" |
527 "\n" | 583 "\n" |
528 " If you specify more than one output for shared library links,\n" | 584 " If you specify more than one output for shared library links,\n" |
529 " you should consider setting link_output, depend_output, and\n" | 585 " you should consider setting link_output, depend_output, and\n" |
530 " runtime_link_output. Otherwise, the first entry in the\n" | 586 " runtime_outputs.\n" |
531 " outputs list should always be the main output which will be\n" | |
532 " linked to.\n" | |
533 "\n" | 587 "\n" |
534 " Example for a compiler tool that produces .obj files:\n" | 588 " Example for a compiler tool that produces .obj files:\n" |
535 " outputs = [\n" | 589 " outputs = [\n" |
536 " \"{{source_out_dir}}/{{source_name_part}}.obj\"\n" | 590 " \"{{source_out_dir}}/{{source_name_part}}.obj\"\n" |
537 " ]\n" | 591 " ]\n" |
538 "\n" | 592 "\n" |
539 " Example for a linker tool that produces a .dll and a .lib. The\n" | 593 " Example for a linker tool that produces a .dll and a .lib. The\n" |
540 " use of {{target_output_name}}, {{output_extension}} and\n" | 594 " use of {{target_output_name}}, {{output_extension}} and\n" |
541 " {{output_dir}} allows the target to override these values.\n" | 595 " {{output_dir}} allows the target to override these values.\n" |
542 " outputs = [\n" | 596 " outputs = [\n" |
543 " \"{{output_dir}}/{{target_output_name}}" | 597 " \"{{output_dir}}/{{target_output_name}}" |
544 "{{output_extension}}\",\n" | 598 "{{output_extension}}\",\n" |
545 " \"{{output_dir}}/{{target_output_name}}.lib\",\n" | 599 " \"{{output_dir}}/{{target_output_name}}.lib\",\n" |
546 " ]\n" | 600 " ]\n" |
547 "\n" | 601 "\n" |
548 " pool [label, optional]\n" | 602 " pool [label, optional]\n" |
549 "\n" | 603 "\n" |
550 " Label of the pool to use for the tool. Pools are used to limit\n" | 604 " Label of the pool to use for the tool. Pools are used to limit\n" |
551 " the number of tasks that can execute concurrently during the\n" | 605 " the number of tasks that can execute concurrently during the\n" |
552 " build.\n" | 606 " build.\n" |
553 "\n" | 607 "\n" |
554 " See also \"gn help pool\".\n" | 608 " See also \"gn help pool\".\n" |
555 "\n" | 609 "\n" |
556 " link_output [string with substitutions]\n" | 610 " link_output [string with substitutions]\n" |
557 " depend_output [string with substitutions]\n" | 611 " depend_output [string with substitutions]\n" |
558 " runtime_link_output [string with substitutions]\n" | |
559 " Valid for: \"solink\" only (optional)\n" | 612 " Valid for: \"solink\" only (optional)\n" |
560 "\n" | 613 "\n" |
561 " These three files specify which of the outputs from the solink\n" | 614 " These two files specify which of the outputs from the solink\n" |
562 " tool should be used for linking and dependency tracking. These\n" | 615 " tool should be used for linking and dependency tracking. These\n" |
563 " should match entries in the \"outputs\". If unspecified, the\n" | 616 " should match entries in the \"outputs\". If unspecified, the\n" |
564 " first item in the \"outputs\" array will be used for all. See\n" | 617 " first item in the \"outputs\" array will be used for all. See\n" |
565 " \"Separate linking and dependencies for shared libraries\"\n" | 618 " \"Separate linking and dependencies for shared libraries\"\n" |
566 " below for more. If link_output is set but runtime_link_output\n" | 619 " below for more.\n" |
567 " is not set, runtime_link_output defaults to link_output.\n" | |
568 "\n" | 620 "\n" |
569 " On Windows, where the tools produce a .dll shared library and\n" | 621 " On Windows, where the tools produce a .dll shared library and\n" |
570 " a .lib import library, you will want the first two to be the\n" | 622 " a .lib import library, you will want the first two to be the\n" |
571 " import library and the third one to be the .dll file.\n" | 623 " import library and the third one to be the .dll file.\n" |
572 " On Linux, if you're not doing the separate linking/dependency\n" | 624 " On Linux, if you're not doing the separate linking/dependency\n" |
573 " optimization, all of these should be the .so output.\n" | 625 " optimization, all of these should be the .so output.\n" |
574 "\n" | 626 "\n" |
575 " output_prefix [string]\n" | 627 " output_prefix [string]\n" |
576 " Valid for: Linker tools (optional)\n" | 628 " Valid for: Linker tools (optional)\n" |
577 "\n" | 629 "\n" |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
635 " allows you to get around OS command-line length limits.\n" | 687 " allows you to get around OS command-line length limits.\n" |
636 "\n" | 688 "\n" |
637 " This example adds the inputs and libraries to a response file,\n" | 689 " This example adds the inputs and libraries to a response file,\n" |
638 " but passes the linker flags directly on the command line:\n" | 690 " but passes the linker flags directly on the command line:\n" |
639 " tool(\"link\") {\n" | 691 " tool(\"link\") {\n" |
640 " command = \"link -o {{output}} {{ldflags}} @{{output}}.rsp\"\n" | 692 " command = \"link -o {{output}} {{ldflags}} @{{output}}.rsp\"\n" |
641 " rspfile = \"{{output}}.rsp\"\n" | 693 " rspfile = \"{{output}}.rsp\"\n" |
642 " rspfile_content = \"{{inputs}} {{solibs}} {{libs}}\"\n" | 694 " rspfile_content = \"{{inputs}} {{solibs}} {{libs}}\"\n" |
643 " }\n" | 695 " }\n" |
644 "\n" | 696 "\n" |
| 697 " runtime_outputs [string list with substitutions]\n" |
| 698 " Valid for: linker tools\n" |
| 699 "\n" |
| 700 " If specified, this list is the subset of the outputs that should\n" |
| 701 " be added to runtime deps (see \"gn help runtime_deps\"). By\n" |
| 702 " default (if runtime_outputs is empty or unspecified), it will be\n" |
| 703 " the link_output.\n" |
| 704 "\n" |
645 "Expansions for tool variables\n" | 705 "Expansions for tool variables\n" |
646 "\n" | 706 "\n" |
647 " All paths are relative to the root build directory, which is the\n" | 707 " All paths are relative to the root build directory, which is the\n" |
648 " current directory for running all tools. These expansions are\n" | 708 " current directory for running all tools. These expansions are\n" |
649 " available to all tools:\n" | 709 " available to all tools:\n" |
650 "\n" | 710 "\n" |
651 " {{label}}\n" | 711 " {{label}}\n" |
652 " The label of the current target. This is typically used in the\n" | 712 " The label of the current target. This is typically used in the\n" |
653 " \"description\" field for link tools. The toolchain will be\n" | 713 " \"description\" field for link tools. The toolchain will be\n" |
654 " omitted from the label for targets in the default toolchain, and\n" | 714 " omitted from the label for targets in the default toolchain, and\n" |
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
908 subst_output_validator = &IsValidCopySubstitution; | 968 subst_output_validator = &IsValidCopySubstitution; |
909 } else if (tool_type == Toolchain::TYPE_COMPILE_XCASSETS) { | 969 } else if (tool_type == Toolchain::TYPE_COMPILE_XCASSETS) { |
910 subst_validator = &IsValidCompileXCassetsSubstitution; | 970 subst_validator = &IsValidCompileXCassetsSubstitution; |
911 subst_output_validator = &IsValidCompileXCassetsSubstitution; | 971 subst_output_validator = &IsValidCompileXCassetsSubstitution; |
912 } else { | 972 } else { |
913 subst_validator = &IsValidToolSubstitution; | 973 subst_validator = &IsValidToolSubstitution; |
914 subst_output_validator = &IsValidToolSubstitution; | 974 subst_output_validator = &IsValidToolSubstitution; |
915 } | 975 } |
916 | 976 |
917 std::unique_ptr<Tool> tool(new Tool); | 977 std::unique_ptr<Tool> tool(new Tool); |
| 978 tool->set_defined_from(function); |
918 | 979 |
919 if (!ReadPattern(&block_scope, "command", subst_validator, tool.get(), | 980 if (!ReadPattern(&block_scope, "command", subst_validator, tool.get(), |
920 &Tool::set_command, err) || | 981 &Tool::set_command, err) || |
921 !ReadOutputExtension(&block_scope, tool.get(), err) || | 982 !ReadOutputExtension(&block_scope, tool.get(), err) || |
922 !ReadPattern(&block_scope, "depfile", subst_validator, tool.get(), | 983 !ReadPattern(&block_scope, "depfile", subst_validator, tool.get(), |
923 &Tool::set_depfile, err) || | 984 &Tool::set_depfile, err) || |
924 !ReadDepsFormat(&block_scope, tool.get(), err) || | 985 !ReadDepsFormat(&block_scope, tool.get(), err) || |
925 !ReadPattern(&block_scope, "description", subst_validator, tool.get(), | 986 !ReadPattern(&block_scope, "description", subst_validator, tool.get(), |
926 &Tool::set_description, err) || | 987 &Tool::set_description, err) || |
927 !ReadString(&block_scope, "lib_switch", tool.get(), &Tool::set_lib_switch, | 988 !ReadString(&block_scope, "lib_switch", tool.get(), &Tool::set_lib_switch, |
928 err) || | 989 err) || |
929 !ReadString(&block_scope, "lib_dir_switch", tool.get(), | 990 !ReadString(&block_scope, "lib_dir_switch", tool.get(), |
930 &Tool::set_lib_dir_switch, err) || | 991 &Tool::set_lib_dir_switch, err) || |
931 !ReadPattern(&block_scope, "link_output", subst_validator, tool.get(), | 992 !ReadPattern(&block_scope, "link_output", subst_validator, tool.get(), |
932 &Tool::set_link_output, err) || | 993 &Tool::set_link_output, err) || |
933 !ReadPattern(&block_scope, "depend_output", subst_validator, tool.get(), | 994 !ReadPattern(&block_scope, "depend_output", subst_validator, tool.get(), |
934 &Tool::set_depend_output, err) || | 995 &Tool::set_depend_output, err) || |
935 !ReadPattern(&block_scope, "runtime_link_output", subst_validator, | 996 !ReadPatternList(&block_scope, "runtime_outputs", subst_validator, |
936 tool.get(), &Tool::set_runtime_link_output, err) || | 997 tool.get(), &Tool::set_runtime_outputs, err) || |
937 !ReadString(&block_scope, "output_prefix", tool.get(), | 998 !ReadString(&block_scope, "output_prefix", tool.get(), |
938 &Tool::set_output_prefix, err) || | 999 &Tool::set_output_prefix, err) || |
939 !ReadPattern(&block_scope, "default_output_dir", subst_validator, | 1000 !ReadPattern(&block_scope, "default_output_dir", subst_validator, |
940 tool.get(), &Tool::set_default_output_dir, err) || | 1001 tool.get(), &Tool::set_default_output_dir, err) || |
941 !ReadPrecompiledHeaderType(&block_scope, tool.get(), err) || | 1002 !ReadPrecompiledHeaderType(&block_scope, tool.get(), err) || |
942 !ReadBool(&block_scope, "restat", tool.get(), &Tool::set_restat, err) || | 1003 !ReadBool(&block_scope, "restat", tool.get(), &Tool::set_restat, err) || |
943 !ReadPattern(&block_scope, "rspfile", subst_validator, tool.get(), | 1004 !ReadPattern(&block_scope, "rspfile", subst_validator, tool.get(), |
944 &Tool::set_rspfile, err) || | 1005 &Tool::set_rspfile, err) || |
945 !ReadPattern(&block_scope, "rspfile_content", subst_validator, tool.get(), | 1006 !ReadPattern(&block_scope, "rspfile_content", subst_validator, tool.get(), |
946 &Tool::set_rspfile_content, err) || | 1007 &Tool::set_rspfile_content, err) || |
947 !ReadLabel(&block_scope, "pool", tool.get(), function, toolchain->label(), | 1008 !ReadLabel(&block_scope, "pool", tool.get(), toolchain->label(), |
948 &Tool::set_pool, err)) { | 1009 &Tool::set_pool, err)) { |
949 return Value(); | 1010 return Value(); |
950 } | 1011 } |
951 | 1012 |
952 if (tool_type != Toolchain::TYPE_COPY && | 1013 if (tool_type != Toolchain::TYPE_COPY && |
953 tool_type != Toolchain::TYPE_STAMP && | 1014 tool_type != Toolchain::TYPE_STAMP && |
954 tool_type != Toolchain::TYPE_COPY_BUNDLE_DATA && | 1015 tool_type != Toolchain::TYPE_COPY_BUNDLE_DATA && |
955 tool_type != Toolchain::TYPE_COMPILE_XCASSETS) { | 1016 tool_type != Toolchain::TYPE_COMPILE_XCASSETS) { |
956 // All tools should have outputs, except the copy, stamp, copy_bundle_data | 1017 // All tools should have outputs, except the copy, stamp, copy_bundle_data |
957 // and compile_xcassets tools that generate their outputs internally. | 1018 // and compile_xcassets tools that generate their outputs internally. |
958 if (!ReadOutputs(&block_scope, function, subst_output_validator, | 1019 if (!ReadPatternList(&block_scope, "outputs", subst_output_validator, |
959 tool.get(), err)) | 1020 tool.get(), &Tool::set_outputs, err) || |
| 1021 !ValidateOutputs(tool.get(), err)) |
960 return Value(); | 1022 return Value(); |
961 } | 1023 } |
| 1024 if (!ValidateRuntimeOutputs(tool.get(), tool_type, err)) |
| 1025 return Value(); |
962 | 1026 |
963 // Validate that the link_output, depend_output, and runtime_link_output | 1027 // Validate link_output and depend_output. |
964 // refer to items in the outputs and aren't defined for irrelevant tool | 1028 if (!ValidateLinkAndDependOutput(tool.get(), tool_type, tool->link_output(), |
965 // types. | 1029 "link_output", err)) |
966 if (!tool->link_output().empty()) { | 1030 return Value(); |
967 if (tool_type != Toolchain::TYPE_SOLINK && | 1031 if (!ValidateLinkAndDependOutput(tool.get(), tool_type, tool->depend_output(), |
968 tool_type != Toolchain::TYPE_SOLINK_MODULE) { | 1032 "depend_output", err)) |
969 *err = Err(function, "This tool specifies a link_output.", | 1033 return Value(); |
970 "This is only valid for solink and solink_module tools."); | |
971 return Value(); | |
972 } | |
973 if (!IsPatternInOutputList(tool->outputs(), tool->link_output())) { | |
974 *err = Err(function, "This tool's link_output is bad.", | |
975 "It must match one of the outputs."); | |
976 return Value(); | |
977 } | |
978 } | |
979 if (!tool->depend_output().empty()) { | |
980 if (tool_type != Toolchain::TYPE_SOLINK && | |
981 tool_type != Toolchain::TYPE_SOLINK_MODULE) { | |
982 *err = Err(function, "This tool specifies a depend_output.", | |
983 "This is only valid for solink and solink_module tools."); | |
984 return Value(); | |
985 } | |
986 if (!IsPatternInOutputList(tool->outputs(), tool->depend_output())) { | |
987 *err = Err(function, "This tool's depend_output is bad.", | |
988 "It must match one of the outputs."); | |
989 return Value(); | |
990 } | |
991 } | |
992 if ((!tool->link_output().empty() && tool->depend_output().empty()) || | 1034 if ((!tool->link_output().empty() && tool->depend_output().empty()) || |
993 (tool->link_output().empty() && !tool->depend_output().empty())) { | 1035 (tool->link_output().empty() && !tool->depend_output().empty())) { |
994 *err = Err(function, "Both link_output and depend_output should either " | 1036 *err = Err(function, "Both link_output and depend_output should either " |
995 "be specified or they should both be empty."); | 1037 "be specified or they should both be empty."); |
996 return Value(); | 1038 return Value(); |
997 } | 1039 } |
998 if (!tool->runtime_link_output().empty()) { | |
999 if (tool_type != Toolchain::TYPE_SOLINK && | |
1000 tool_type != Toolchain::TYPE_SOLINK_MODULE) { | |
1001 *err = Err(function, "This tool specifies a runtime_link_output.", | |
1002 "This is only valid for solink and solink_module tools."); | |
1003 return Value(); | |
1004 } | |
1005 if (!IsPatternInOutputList(tool->outputs(), tool->runtime_link_output())) { | |
1006 *err = Err(function, "This tool's runtime_link_output is bad.", | |
1007 "It must match one of the outputs."); | |
1008 return Value(); | |
1009 } | |
1010 } | |
1011 | 1040 |
1012 // Make sure there weren't any vars set in this tool that were unused. | 1041 // Make sure there weren't any vars set in this tool that were unused. |
1013 if (!block_scope.CheckForUnusedVars(err)) | 1042 if (!block_scope.CheckForUnusedVars(err)) |
1014 return Value(); | 1043 return Value(); |
1015 | 1044 |
1016 toolchain->SetTool(tool_type, std::move(tool)); | 1045 toolchain->SetTool(tool_type, std::move(tool)); |
1017 return Value(); | 1046 return Value(); |
1018 } | 1047 } |
1019 | 1048 |
1020 // toolchain_args -------------------------------------------------------------- | 1049 // toolchain_args -------------------------------------------------------------- |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1087 return Value(); | 1116 return Value(); |
1088 | 1117 |
1089 Scope::KeyValueMap values; | 1118 Scope::KeyValueMap values; |
1090 block_scope.GetCurrentScopeValues(&values); | 1119 block_scope.GetCurrentScopeValues(&values); |
1091 toolchain->args() = values; | 1120 toolchain->args() = values; |
1092 | 1121 |
1093 return Value(); | 1122 return Value(); |
1094 } | 1123 } |
1095 | 1124 |
1096 } // namespace functions | 1125 } // namespace functions |
OLD | NEW |