Revert 264226 "Reduce dependency of TiclInvalidationService on P..."
[chromium-blink-merge.git] / tools / gn / action_target_generator.cc
blobc51910c61b03752a7774e7dfa21627565dd95b1d
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "tools/gn/action_target_generator.h"
7 #include "tools/gn/build_settings.h"
8 #include "tools/gn/err.h"
9 #include "tools/gn/filesystem_utils.h"
10 #include "tools/gn/parse_tree.h"
11 #include "tools/gn/scope.h"
12 #include "tools/gn/value.h"
13 #include "tools/gn/value_extractors.h"
14 #include "tools/gn/variables.h"
16 namespace {
18 // Returns true if the list of files looks like it might have a {{ }} pattern
19 // in it. Used for error checking.
20 bool FileListHasPattern(const Target::FileList& files) {
21 for (size_t i = 0; i < files.size(); i++) {
22 if (files[i].value().find("{{") != std::string::npos &&
23 files[i].value().find("}}") != std::string::npos)
24 return true;
26 return false;
29 } // namespace
31 ActionTargetGenerator::ActionTargetGenerator(
32 Target* target,
33 Scope* scope,
34 const FunctionCallNode* function_call,
35 Target::OutputType type,
36 Err* err)
37 : TargetGenerator(target, scope, function_call, err),
38 output_type_(type) {
41 ActionTargetGenerator::~ActionTargetGenerator() {
44 void ActionTargetGenerator::DoRun() {
45 target_->set_output_type(output_type_);
47 FillSources();
48 if (err_->has_error())
49 return;
50 if (output_type_ == Target::ACTION_FOREACH && target_->sources().empty()) {
51 // Foreach rules must always have some sources to have an effect.
52 *err_ = Err(function_call_, "action_foreach target has no sources.",
53 "If you don't specify any sources, there is nothing to run your\n"
54 "script over.");
55 return;
58 FillSourcePrereqs();
59 if (err_->has_error())
60 return;
62 FillScript();
63 if (err_->has_error())
64 return;
66 FillScriptArgs();
67 if (err_->has_error())
68 return;
70 FillOutputs();
71 if (err_->has_error())
72 return;
74 FillDepfile();
75 if (err_->has_error())
76 return;
78 CheckOutputs();
79 if (err_->has_error())
80 return;
82 // Action outputs don't depend on the current toolchain so we can skip adding
83 // that dependency.
86 void ActionTargetGenerator::FillScript() {
87 // If this gets called, the target type requires a script, so error out
88 // if it doesn't have one.
89 const Value* value = scope_->GetValue(variables::kScript, true);
90 if (!value) {
91 *err_ = Err(function_call_, "This target type requires a \"script\".");
92 return;
94 if (!value->VerifyTypeIs(Value::STRING, err_))
95 return;
97 target_->action_values().set_script(
98 scope_->GetSourceDir().ResolveRelativeFile(value->string_value()));
101 void ActionTargetGenerator::FillScriptArgs() {
102 const Value* value = scope_->GetValue(variables::kArgs, true);
103 if (!value)
104 return;
106 std::vector<std::string> args;
107 if (!ExtractListOfStringValues(*value, &args, err_))
108 return;
109 target_->action_values().swap_in_args(&args);
112 void ActionTargetGenerator::FillDepfile() {
113 const Value* value = scope_->GetValue(variables::kDepfile, true);
114 if (!value)
115 return;
116 target_->action_values().set_depfile(
117 scope_->settings()->build_settings()->build_dir().ResolveRelativeFile(
118 value->string_value()));
121 void ActionTargetGenerator::CheckOutputs() {
122 const Target::FileList& outputs = target_->action_values().outputs();
123 if (outputs.empty()) {
124 *err_ = Err(function_call_, "Action has no outputs.",
125 "If you have no outputs, the build system can not tell when your\n"
126 "script needs to be run.");
127 return;
130 if (output_type_ == Target::ACTION) {
131 // Make sure the outputs for an action have no patterns in them.
132 if (FileListHasPattern(outputs)) {
133 *err_ = Err(function_call_, "Action has patterns in the output.",
134 "An action target should have the outputs completely specified. If\n"
135 "you want to provide a mapping from source to output, use an\n"
136 "\"action_foreach\" target.");
137 return;
139 } else if (output_type_ == Target::ACTION_FOREACH) {
140 // A foreach target should always have a pattern in the outputs.
141 if (!FileListHasPattern(outputs)) {
142 *err_ = Err(function_call_,
143 "action_foreach should have a pattern in the output.",
144 "An action_foreach target should have a source expansion pattern in\n"
145 "it to map source file to unique output file name. Otherwise, the\n"
146 "build system can't determine when your script needs to be run.");
147 return;