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"
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)
31 ActionTargetGenerator::ActionTargetGenerator(
34 const FunctionCallNode* function_call,
35 Target::OutputType type,
37 : TargetGenerator(target, scope, function_call, err),
41 ActionTargetGenerator::~ActionTargetGenerator() {
44 void ActionTargetGenerator::DoRun() {
45 target_->set_output_type(output_type_);
48 if (err_->has_error())
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"
59 if (err_->has_error())
63 if (err_->has_error())
67 if (err_->has_error())
71 if (err_->has_error())
75 if (err_->has_error())
79 if (err_->has_error())
82 // Action outputs don't depend on the current toolchain so we can skip adding
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);
91 *err_ = Err(function_call_, "This target type requires a \"script\".");
94 if (!value->VerifyTypeIs(Value::STRING, err_))
97 SourceFile script_file =
98 scope_->GetSourceDir().ResolveRelativeFile(value->string_value());
99 if (script_file.value().empty()) {
100 *err_ = Err(*value, "script name is empty");
103 target_->action_values().set_script(script_file);
106 void ActionTargetGenerator::FillScriptArgs() {
107 const Value* value = scope_->GetValue(variables::kArgs, true);
111 std::vector<std::string> args;
112 if (!ExtractListOfStringValues(*value, &args, err_))
114 target_->action_values().swap_in_args(&args);
117 void ActionTargetGenerator::FillDepfile() {
118 const Value* value = scope_->GetValue(variables::kDepfile, true);
121 target_->action_values().set_depfile(
122 scope_->settings()->build_settings()->build_dir().ResolveRelativeFile(
123 value->string_value()));
126 void ActionTargetGenerator::CheckOutputs() {
127 const Target::FileList& outputs = target_->action_values().outputs();
128 if (outputs.empty()) {
129 *err_ = Err(function_call_, "Action has no outputs.",
130 "If you have no outputs, the build system can not tell when your\n"
131 "script needs to be run.");
135 if (output_type_ == Target::ACTION) {
136 // Make sure the outputs for an action have no patterns in them.
137 if (FileListHasPattern(outputs)) {
138 *err_ = Err(function_call_, "Action has patterns in the output.",
139 "An action target should have the outputs completely specified. If\n"
140 "you want to provide a mapping from source to output, use an\n"
141 "\"action_foreach\" target.");
144 } else if (output_type_ == Target::ACTION_FOREACH) {
145 // A foreach target should always have a pattern in the outputs.
146 if (!FileListHasPattern(outputs)) {
147 *err_ = Err(function_call_,
148 "action_foreach should have a pattern in the output.",
149 "An action_foreach target should have a source expansion pattern in\n"
150 "it to map source file to unique output file name. Otherwise, the\n"
151 "build system can't determine when your script needs to be run.");