| 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 |