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

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

Issue 2178173002: Allow GN toolchains to specify runtime deps outputs. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix Created 4 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
« no previous file with comments | « tools/gn/BUILD.gn ('k') | tools/gn/function_toolchain_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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> 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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « tools/gn/BUILD.gn ('k') | tools/gn/function_toolchain_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698