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/binary_target_generator.h"
      8 #include "tools/gn/build_settings.h"
      9 #include "tools/gn/config.h"
     10 #include "tools/gn/copy_target_generator.h"
     11 #include "tools/gn/err.h"
     12 #include "tools/gn/filesystem_utils.h"
     13 #include "tools/gn/functions.h"
     14 #include "tools/gn/group_target_generator.h"
     15 #include "tools/gn/parse_tree.h"
     16 #include "tools/gn/scheduler.h"
     17 #include "tools/gn/scope.h"
     18 #include "tools/gn/script_target_generator.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   FillData();
     41   FillDependencies();
     42   FillGypFile();
     43 
     44   // Do type-specific generation.
     45   DoRun();
     46 }
     47 
     48 // static
     49 void TargetGenerator::GenerateTarget(Scope* scope,
     50                                      const FunctionCallNode* function_call,
     51                                      const std::vector<Value>& args,
     52                                      const std::string& output_type,
     53                                      Err* err) {
     54   // Name is the argument to the function.
     55   if (args.size() != 1u || args[0].type() != Value::STRING) {
     56     *err = Err(function_call,
     57         "Target generator requires one string argument.",
     58         "Otherwise I'm not sure what to call this target.");
     59     return;
     60   }
     61 
     62   // The location of the target is the directory name with no slash at the end.
     63   // FIXME(brettw) validate name.
     64   const Label& toolchain_label = ToolchainLabelForScope(scope);
     65   Label label(scope->GetSourceDir(), args[0].string_value(),
     66               toolchain_label.dir(), toolchain_label.name());
     67 
     68   if (g_scheduler->verbose_logging())
     69     g_scheduler->Log("Defining target", label.GetUserVisibleName(true));
     70 
     71   scoped_ptr<Target> target(new Target(scope->settings(), label));
     72   target->set_defined_from(function_call);
     73 
     74   // Create and call out to the proper generator.
     75   if (output_type == functions::kCopy) {
     76     CopyTargetGenerator generator(target.get(), scope, function_call, err);
     77     generator.Run();
     78   } else if (output_type == functions::kCustom) {
     79     ScriptTargetGenerator generator(target.get(), scope, function_call, err);
     80     generator.Run();
     81   } else if (output_type == functions::kExecutable) {
     82     BinaryTargetGenerator generator(target.get(), scope, function_call,
     83                                     Target::EXECUTABLE, err);
     84     generator.Run();
     85   } else if (output_type == functions::kGroup) {
     86     GroupTargetGenerator generator(target.get(), scope, function_call, err);
     87     generator.Run();
     88   } else if (output_type == functions::kSharedLibrary) {
     89     BinaryTargetGenerator generator(target.get(), scope, function_call,
     90                                     Target::SHARED_LIBRARY, err);
     91     generator.Run();
     92   } else if (output_type == functions::kSourceSet) {
     93     BinaryTargetGenerator generator(target.get(), scope, function_call,
     94                                     Target::SOURCE_SET, err);
     95     generator.Run();
     96   } else if (output_type == functions::kStaticLibrary) {
     97     BinaryTargetGenerator generator(target.get(), scope, function_call,
     98                                     Target::STATIC_LIBRARY, err);
     99     generator.Run();
    100   } else {
    101     *err = Err(function_call, "Not a known output type",
    102                "I am very confused.");
    103   }
    104 
    105   if (!err->has_error())
    106     scope->settings()->build_settings()->ItemDefined(target.PassAs<Item>());
    107 }
    108 
    109 const BuildSettings* TargetGenerator::GetBuildSettings() const {
    110   return scope_->settings()->build_settings();
    111 }
    112 
    113 void TargetGenerator::FillSources() {
    114   const Value* value = scope_->GetValue(variables::kSources, true);
    115   if (!value)
    116     return;
    117 
    118   Target::FileList dest_sources;
    119   if (!ExtractListOfRelativeFiles(scope_->settings()->build_settings(), *value,
    120                                   scope_->GetSourceDir(), &dest_sources, err_))
    121     return;
    122   target_->sources().swap(dest_sources);
    123 }
    124 
    125 void TargetGenerator::FillSourcePrereqs() {
    126   const Value* value = scope_->GetValue(variables::kSourcePrereqs, true);
    127   if (!value)
    128     return;
    129 
    130   Target::FileList dest_reqs;
    131   if (!ExtractListOfRelativeFiles(scope_->settings()->build_settings(), *value,
    132                                   scope_->GetSourceDir(), &dest_reqs, err_))
    133     return;
    134   target_->source_prereqs().swap(dest_reqs);
    135 }
    136 
    137 void TargetGenerator::FillConfigs() {
    138   FillGenericConfigs(variables::kConfigs, &target_->configs());
    139 }
    140 
    141 void TargetGenerator::FillDependentConfigs() {
    142   FillGenericConfigs(variables::kAllDependentConfigs,
    143                      &target_->all_dependent_configs());
    144   FillGenericConfigs(variables::kDirectDependentConfigs,
    145                      &target_->direct_dependent_configs());
    146 }
    147 
    148 void TargetGenerator::FillData() {
    149   const Value* value = scope_->GetValue(variables::kData, true);
    150   if (!value)
    151     return;
    152 
    153   Target::FileList dest_data;
    154   if (!ExtractListOfRelativeFiles(scope_->settings()->build_settings(), *value,
    155                                   scope_->GetSourceDir(), &dest_data, err_))
    156     return;
    157   target_->data().swap(dest_data);
    158 }
    159 
    160 void TargetGenerator::FillDependencies() {
    161   FillGenericDeps(variables::kDeps, &target_->deps());
    162   FillGenericDeps(variables::kDatadeps, &target_->datadeps());
    163 
    164   // This is a list of dependent targets to have their configs fowarded, so
    165   // it goes here rather than in FillConfigs.
    166   FillForwardDependentConfigs();
    167 
    168   FillHardDep();
    169 }
    170 
    171 void TargetGenerator::FillGypFile() {
    172   const Value* gyp_file_value = scope_->GetValue(variables::kGypFile, true);
    173   if (!gyp_file_value)
    174     return;
    175   if (!gyp_file_value->VerifyTypeIs(Value::STRING, err_))
    176     return;
    177 
    178   target_->set_gyp_file(scope_->GetSourceDir().ResolveRelativeFile(
    179       gyp_file_value->string_value()));
    180 }
    181 
    182 void TargetGenerator::FillHardDep() {
    183   const Value* hard_dep_value = scope_->GetValue(variables::kHardDep, true);
    184   if (!hard_dep_value)
    185     return;
    186   if (!hard_dep_value->VerifyTypeIs(Value::BOOLEAN, err_))
    187     return;
    188   target_->set_hard_dep(hard_dep_value->boolean_value());
    189 }
    190 
    191 void TargetGenerator::FillExternal() {
    192   const Value* value = scope_->GetValue(variables::kExternal, true);
    193   if (!value)
    194     return;
    195   if (!value->VerifyTypeIs(Value::BOOLEAN, err_))
    196     return;
    197   target_->set_external(value->boolean_value());
    198 }
    199 
    200 void TargetGenerator::FillOutputs() {
    201   const Value* value = scope_->GetValue(variables::kOutputs, true);
    202   if (!value)
    203     return;
    204 
    205   Target::FileList outputs;
    206   if (!ExtractListOfRelativeFiles(scope_->settings()->build_settings(), *value,
    207                                   scope_->GetSourceDir(), &outputs, err_))
    208     return;
    209 
    210   // Validate that outputs are in the output dir.
    211   CHECK(outputs.size() == value->list_value().size());
    212   for (size_t i = 0; i < outputs.size(); i++) {
    213     if (!EnsureStringIsInOutputDir(
    214             GetBuildSettings()->build_dir(),
    215             outputs[i].value(), value->list_value()[i], err_))
    216       return;
    217   }
    218   target_->script_values().outputs().swap(outputs);
    219 }
    220 
    221 void TargetGenerator::FillGenericConfigs(const char* var_name,
    222                                          LabelConfigVector* dest) {
    223   const Value* value = scope_->GetValue(var_name, true);
    224   if (value) {
    225     ExtractListOfLabels(*value, scope_->GetSourceDir(),
    226                         ToolchainLabelForScope(scope_), dest, err_);
    227   }
    228 }
    229 
    230 void TargetGenerator::FillGenericDeps(const char* var_name,
    231                                       LabelTargetVector* dest) {
    232   const Value* value = scope_->GetValue(var_name, true);
    233   if (value) {
    234     ExtractListOfLabels(*value, scope_->GetSourceDir(),
    235                         ToolchainLabelForScope(scope_), dest, err_);
    236   }
    237 }
    238 
    239 void TargetGenerator::FillForwardDependentConfigs() {
    240   const Value* value = scope_->GetValue(
    241       variables::kForwardDependentConfigsFrom, true);
    242   if (value) {
    243     ExtractListOfLabels(*value, scope_->GetSourceDir(),
    244                         ToolchainLabelForScope(scope_),
    245                         &target_->forward_dependent_configs(), err_);
    246   }
    247 }
    248