Home | History | Annotate | Download | only in gn
      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.
      4 
      5 #include "tools/gn/target_generator.h"
      6 
      7 #include "tools/gn/action_target_generator.h"
      8 #include "tools/gn/binary_target_generator.h"
      9 #include "tools/gn/build_settings.h"
     10 #include "tools/gn/config.h"
     11 #include "tools/gn/copy_target_generator.h"
     12 #include "tools/gn/err.h"
     13 #include "tools/gn/filesystem_utils.h"
     14 #include "tools/gn/functions.h"
     15 #include "tools/gn/group_target_generator.h"
     16 #include "tools/gn/parse_tree.h"
     17 #include "tools/gn/scheduler.h"
     18 #include "tools/gn/scope.h"
     19 #include "tools/gn/token.h"
     20 #include "tools/gn/value.h"
     21 #include "tools/gn/value_extractors.h"
     22 #include "tools/gn/variables.h"
     23 
     24 TargetGenerator::TargetGenerator(Target* target,
     25                                  Scope* scope,
     26                                  const FunctionCallNode* function_call,
     27                                  Err* err)
     28     : target_(target),
     29       scope_(scope),
     30       function_call_(function_call),
     31       err_(err) {
     32 }
     33 
     34 TargetGenerator::~TargetGenerator() {
     35 }
     36 
     37 void TargetGenerator::Run() {
     38   // All target types use these.
     39   FillDependentConfigs();
     40   if (err_->has_error())
     41     return;
     42 
     43   FillData();
     44   if (err_->has_error())
     45     return;
     46 
     47   FillDependencies();
     48   if (err_->has_error())
     49     return;
     50 
     51   if (!Visibility::FillItemVisibility(target_, scope_, err_))
     52     return;
     53 
     54   // Do type-specific generation.
     55   DoRun();
     56 }
     57 
     58 // static
     59 void TargetGenerator::GenerateTarget(Scope* scope,
     60                                      const FunctionCallNode* function_call,
     61                                      const std::vector<Value>& args,
     62                                      const std::string& output_type,
     63                                      Err* err) {
     64   // Name is the argument to the function.
     65   if (args.size() != 1u || args[0].type() != Value::STRING) {
     66     *err = Err(function_call,
     67         "Target generator requires one string argument.",
     68         "Otherwise I'm not sure what to call this target.");
     69     return;
     70   }
     71 
     72   // The location of the target is the directory name with no slash at the end.
     73   // FIXME(brettw) validate name.
     74   const Label& toolchain_label = ToolchainLabelForScope(scope);
     75   Label label(scope->GetSourceDir(), args[0].string_value(),
     76               toolchain_label.dir(), toolchain_label.name());
     77 
     78   if (g_scheduler->verbose_logging())
     79     g_scheduler->Log("Defining target", label.GetUserVisibleName(true));
     80 
     81   scoped_ptr<Target> target(new Target(scope->settings(), label));
     82   target->set_defined_from(function_call);
     83 
     84   // Create and call out to the proper generator.
     85   if (output_type == functions::kCopy) {
     86     CopyTargetGenerator generator(target.get(), scope, function_call, err);
     87     generator.Run();
     88   } else if (output_type == functions::kAction) {
     89     ActionTargetGenerator generator(target.get(), scope, function_call,
     90                                     Target::ACTION, err);
     91     generator.Run();
     92   } else if (output_type == functions::kActionForEach) {
     93     ActionTargetGenerator generator(target.get(), scope, function_call,
     94                                     Target::ACTION_FOREACH, err);
     95     generator.Run();
     96   } else if (output_type == functions::kExecutable) {
     97     BinaryTargetGenerator generator(target.get(), scope, function_call,
     98                                     Target::EXECUTABLE, err);
     99     generator.Run();
    100   } else if (output_type == functions::kGroup) {
    101     GroupTargetGenerator generator(target.get(), scope, function_call, err);
    102     generator.Run();
    103   } else if (output_type == functions::kSharedLibrary) {
    104     BinaryTargetGenerator generator(target.get(), scope, function_call,
    105                                     Target::SHARED_LIBRARY, err);
    106     generator.Run();
    107   } else if (output_type == functions::kSourceSet) {
    108     BinaryTargetGenerator generator(target.get(), scope, function_call,
    109                                     Target::SOURCE_SET, err);
    110     generator.Run();
    111   } else if (output_type == functions::kStaticLibrary) {
    112     BinaryTargetGenerator generator(target.get(), scope, function_call,
    113                                     Target::STATIC_LIBRARY, err);
    114     generator.Run();
    115   } else {
    116     *err = Err(function_call, "Not a known output type",
    117                "I am very confused.");
    118   }
    119 
    120   if (err->has_error())
    121     return;
    122 
    123   // Save this target for the file.
    124   Scope::ItemVector* collector = scope->GetItemCollector();
    125   if (!collector) {
    126     *err = Err(function_call, "Can't define a target in this context.");
    127     return;
    128   }
    129   collector->push_back(new scoped_ptr<Item>(target.PassAs<Item>()));
    130 }
    131 
    132 const BuildSettings* TargetGenerator::GetBuildSettings() const {
    133   return scope_->settings()->build_settings();
    134 }
    135 
    136 void TargetGenerator::FillSources() {
    137   const Value* value = scope_->GetValue(variables::kSources, true);
    138   if (!value)
    139     return;
    140 
    141   Target::FileList dest_sources;
    142   if (!ExtractListOfRelativeFiles(scope_->settings()->build_settings(), *value,
    143                                   scope_->GetSourceDir(), &dest_sources, err_))
    144     return;
    145   target_->sources().swap(dest_sources);
    146 }
    147 
    148 void TargetGenerator::FillPublic() {
    149   const Value* value = scope_->GetValue(variables::kPublic, true);
    150   if (!value)
    151     return;
    152 
    153   // If the public headers are defined, don't default to public.
    154   target_->set_all_headers_public(false);
    155 
    156   Target::FileList dest_public;
    157   if (!ExtractListOfRelativeFiles(scope_->settings()->build_settings(), *value,
    158                                   scope_->GetSourceDir(), &dest_public, err_))
    159     return;
    160   target_->public_headers().swap(dest_public);
    161 }
    162 
    163 void TargetGenerator::FillInputs() {
    164   const Value* value = scope_->GetValue(variables::kInputs, true);
    165   if (!value) {
    166     // Older versions used "source_prereqs". Allow use of this variable until
    167     // all callers are updated.
    168     // TODO(brettw) remove this eventually.
    169     value = scope_->GetValue("source_prereqs", true);
    170 
    171     if (!value)
    172       return;
    173   }
    174 
    175   Target::FileList dest_inputs;
    176   if (!ExtractListOfRelativeFiles(scope_->settings()->build_settings(), *value,
    177                                   scope_->GetSourceDir(), &dest_inputs, err_))
    178     return;
    179   target_->inputs().swap(dest_inputs);
    180 }
    181 
    182 void TargetGenerator::FillConfigs() {
    183   FillGenericConfigs(variables::kConfigs, &target_->configs());
    184 }
    185 
    186 void TargetGenerator::FillDependentConfigs() {
    187   FillGenericConfigs(variables::kAllDependentConfigs,
    188                      &target_->all_dependent_configs());
    189   FillGenericConfigs(variables::kDirectDependentConfigs,
    190                      &target_->direct_dependent_configs());
    191 }
    192 
    193 void TargetGenerator::FillData() {
    194   const Value* value = scope_->GetValue(variables::kData, true);
    195   if (!value)
    196     return;
    197 
    198   Target::FileList dest_data;
    199   if (!ExtractListOfRelativeFiles(scope_->settings()->build_settings(), *value,
    200                                   scope_->GetSourceDir(), &dest_data, err_))
    201     return;
    202   target_->data().swap(dest_data);
    203 }
    204 
    205 void TargetGenerator::FillDependencies() {
    206   FillGenericDeps(variables::kDeps, &target_->deps());
    207   if (err_->has_error())
    208     return;
    209   FillGenericDeps(variables::kDatadeps, &target_->datadeps());
    210   if (err_->has_error())
    211     return;
    212 
    213   // This is a list of dependent targets to have their configs fowarded, so
    214   // it goes here rather than in FillConfigs.
    215   FillForwardDependentConfigs();
    216   if (err_->has_error())
    217     return;
    218 }
    219 
    220 void TargetGenerator::FillOutputs() {
    221   const Value* value = scope_->GetValue(variables::kOutputs, true);
    222   if (!value)
    223     return;
    224 
    225   Target::FileList outputs;
    226   if (!ExtractListOfRelativeFiles(scope_->settings()->build_settings(), *value,
    227                                   scope_->GetSourceDir(), &outputs, err_))
    228     return;
    229 
    230   // Validate that outputs are in the output dir.
    231   CHECK(outputs.size() == value->list_value().size());
    232   for (size_t i = 0; i < outputs.size(); i++) {
    233     if (!EnsureStringIsInOutputDir(
    234             GetBuildSettings()->build_dir(),
    235             outputs[i].value(), value->list_value()[i], err_))
    236       return;
    237   }
    238   target_->action_values().outputs().swap(outputs);
    239 }
    240 
    241 void TargetGenerator::FillGenericConfigs(const char* var_name,
    242                                          LabelConfigVector* dest) {
    243   const Value* value = scope_->GetValue(var_name, true);
    244   if (value) {
    245     ExtractListOfLabels(*value, scope_->GetSourceDir(),
    246                         ToolchainLabelForScope(scope_), dest, err_);
    247   }
    248 }
    249 
    250 void TargetGenerator::FillGenericDeps(const char* var_name,
    251                                       LabelTargetVector* dest) {
    252   const Value* value = scope_->GetValue(var_name, true);
    253   if (value) {
    254     ExtractListOfLabels(*value, scope_->GetSourceDir(),
    255                         ToolchainLabelForScope(scope_), dest, err_);
    256   }
    257 }
    258 
    259 void TargetGenerator::FillForwardDependentConfigs() {
    260   const Value* value = scope_->GetValue(
    261       variables::kForwardDependentConfigsFrom, true);
    262   if (value) {
    263     ExtractListOfLabels(*value, scope_->GetSourceDir(),
    264                         ToolchainLabelForScope(scope_),
    265                         &target_->forward_dependent_configs(), err_);
    266   }
    267 }
    268