123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// found in the LICENSE file.
423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "tools/gn/action_target_generator.h"
623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "tools/gn/build_settings.h"
823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "tools/gn/err.h"
923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "tools/gn/filesystem_utils.h"
1023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "tools/gn/parse_tree.h"
1123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "tools/gn/scope.h"
1223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "tools/gn/value.h"
1323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "tools/gn/value_extractors.h"
1423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "tools/gn/variables.h"
1523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
1623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)ActionTargetGenerator::ActionTargetGenerator(
1723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    Target* target,
1823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    Scope* scope,
1923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    const FunctionCallNode* function_call,
2023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    Target::OutputType type,
2123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    Err* err)
2223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    : TargetGenerator(target, scope, function_call, err),
2323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      output_type_(type) {
2423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
2523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
2623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)ActionTargetGenerator::~ActionTargetGenerator() {
2723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
2823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
2923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void ActionTargetGenerator::DoRun() {
3023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  target_->set_output_type(output_type_);
3123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!FillSources())
3323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return;
3423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (output_type_ == Target::ACTION_FOREACH && target_->sources().empty()) {
3523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    // Foreach rules must always have some sources to have an effect.
3623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    *err_ = Err(function_call_, "action_foreach target has no sources.",
3723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        "If you don't specify any sources, there is nothing to run your\n"
3823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        "script over.");
3923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return;
4023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
4123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!FillInputs())
4323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return;
4423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!FillScript())
4623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return;
4723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!FillScriptArgs())
4923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return;
5023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!FillOutputs(output_type_ == Target::ACTION_FOREACH))
5223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return;
5323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!FillDepfile())
5523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return;
5623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!CheckOutputs())
5823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return;
5923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
6023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // Action outputs don't depend on the current toolchain so we can skip adding
6123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // that dependency.
6223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
6323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool ActionTargetGenerator::FillScript() {
6523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // If this gets called, the target type requires a script, so error out
6623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // if it doesn't have one.
6723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  const Value* value = scope_->GetValue(variables::kScript, true);
6823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (!value) {
6923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    *err_ = Err(function_call_, "This target type requires a \"script\".");
701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return false;
7123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
7223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (!value->VerifyTypeIs(Value::STRING, err_))
731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return false;
7423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SourceFile script_file =
76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      scope_->GetSourceDir().ResolveRelativeFile(value->string_value());
77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (script_file.value().empty()) {
78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    *err_ = Err(*value, "script name is empty");
791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return false;
80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  target_->action_values().set_script(script_file);
821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return true;
8323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
8423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool ActionTargetGenerator::FillScriptArgs() {
8623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  const Value* value = scope_->GetValue(variables::kArgs, true);
8723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (!value)
881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return true;
891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return target_->action_values().args().Parse(*value, err_);
9023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
9123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool ActionTargetGenerator::FillDepfile() {
9323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  const Value* value = scope_->GetValue(variables::kDepfile, true);
9423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (!value)
951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return true;
965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  SubstitutionPattern depfile;
985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!depfile.Parse(*value, err_))
991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return false;
1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!EnsureSubstitutionIsInOutputDir(depfile, *value))
1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return false;
1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  target_->action_values().set_depfile(depfile);
1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return true;
10523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
10623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool ActionTargetGenerator::CheckOutputs() {
1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const SubstitutionList& outputs = target_->action_values().outputs();
1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (outputs.list().empty()) {
11023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    *err_ = Err(function_call_, "Action has no outputs.",
11123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        "If you have no outputs, the build system can not tell when your\n"
11223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        "script needs to be run.");
1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return false;
11423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
11523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
11623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (output_type_ == Target::ACTION) {
1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (!outputs.required_types().empty()) {
11823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      *err_ = Err(function_call_, "Action has patterns in the output.",
11923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)          "An action target should have the outputs completely specified. If\n"
12023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)          "you want to provide a mapping from source to output, use an\n"
12123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)          "\"action_foreach\" target.");
1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return false;
12323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    }
12423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  } else if (output_type_ == Target::ACTION_FOREACH) {
12523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    // A foreach target should always have a pattern in the outputs.
1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (outputs.required_types().empty()) {
12723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      *err_ = Err(function_call_,
12823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)          "action_foreach should have a pattern in the output.",
12923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)          "An action_foreach target should have a source expansion pattern in\n"
13023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)          "it to map source file to unique output file name. Otherwise, the\n"
13123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)          "build system can't determine when your script needs to be run.");
1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return false;
13323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    }
13423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return true;
13623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
137