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.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/strings/string_util.h"
      9 #include "base/strings/stringprintf.h"
     10 #include "tools/gn/config_values_extractors.h"
     11 #include "tools/gn/deps_iterator.h"
     12 #include "tools/gn/filesystem_utils.h"
     13 #include "tools/gn/scheduler.h"
     14 #include "tools/gn/substitution_writer.h"
     15 
     16 namespace {
     17 
     18 typedef std::set<const Config*> ConfigSet;
     19 
     20 // Merges the public configs from the given target to the given config list.
     21 void MergePublicConfigsFrom(const Target* from_target,
     22                             UniqueVector<LabelConfigPair>* dest) {
     23   const UniqueVector<LabelConfigPair>& pub = from_target->public_configs();
     24   dest->Append(pub.begin(), pub.end());
     25 }
     26 
     27 // Like MergePublicConfigsFrom above except does the "all dependent" ones. This
     28 // additionally adds all configs to the all_dependent_configs_ of the dest
     29 // target given in *all_dest.
     30 void MergeAllDependentConfigsFrom(const Target* from_target,
     31                                   UniqueVector<LabelConfigPair>* dest,
     32                                   UniqueVector<LabelConfigPair>* all_dest) {
     33   const UniqueVector<LabelConfigPair>& all =
     34       from_target->all_dependent_configs();
     35   for (size_t i = 0; i < all.size(); i++) {
     36     all_dest->push_back(all[i]);
     37     dest->push_back(all[i]);
     38   }
     39 }
     40 
     41 Err MakeTestOnlyError(const Target* from, const Target* to) {
     42   return Err(from->defined_from(), "Test-only dependency not allowed.",
     43       from->label().GetUserVisibleName(false) + "\n"
     44       "which is NOT marked testonly can't depend on\n" +
     45       to->label().GetUserVisibleName(false) + "\n"
     46       "which is marked testonly. Only targets with \"testonly = true\"\n"
     47       "can depend on other test-only targets.\n"
     48       "\n"
     49       "Either mark it test-only or don't do this dependency.");
     50 }
     51 
     52 Err MakeStaticLibDepsError(const Target* from, const Target* to) {
     53   return Err(from->defined_from(),
     54              "Complete static libraries can't depend on static libraries.",
     55              from->label().GetUserVisibleName(false) +
     56                  "\n"
     57                  "which is a complete static library can't depend on\n" +
     58                  to->label().GetUserVisibleName(false) +
     59                  "\n"
     60                  "which is a static library.\n"
     61                  "\n"
     62                  "Use source sets for intermediate targets instead.");
     63 }
     64 
     65 }  // namespace
     66 
     67 Target::Target(const Settings* settings, const Label& label)
     68     : Item(settings, label),
     69       output_type_(UNKNOWN),
     70       all_headers_public_(true),
     71       check_includes_(true),
     72       complete_static_lib_(false),
     73       testonly_(false),
     74       hard_dep_(false),
     75       toolchain_(NULL) {
     76 }
     77 
     78 Target::~Target() {
     79 }
     80 
     81 // static
     82 const char* Target::GetStringForOutputType(OutputType type) {
     83   switch (type) {
     84     case UNKNOWN:
     85       return "Unknown";
     86     case GROUP:
     87       return "Group";
     88     case EXECUTABLE:
     89       return "Executable";
     90     case SHARED_LIBRARY:
     91       return "Shared library";
     92     case STATIC_LIBRARY:
     93       return "Static library";
     94     case SOURCE_SET:
     95       return "Source set";
     96     case COPY_FILES:
     97       return "Copy";
     98     case ACTION:
     99       return "Action";
    100     case ACTION_FOREACH:
    101       return "ActionForEach";
    102     default:
    103       return "";
    104   }
    105 }
    106 
    107 Target* Target::AsTarget() {
    108   return this;
    109 }
    110 
    111 const Target* Target::AsTarget() const {
    112   return this;
    113 }
    114 
    115 bool Target::OnResolved(Err* err) {
    116   DCHECK(output_type_ != UNKNOWN);
    117   DCHECK(toolchain_) << "Toolchain should have been set before resolving.";
    118 
    119   // Copy our own dependent configs to the list of configs applying to us.
    120   configs_.Append(all_dependent_configs_.begin(), all_dependent_configs_.end());
    121   MergePublicConfigsFrom(this, &configs_);
    122 
    123   // Copy our own libs and lib_dirs to the final set. This will be from our
    124   // target and all of our configs. We do this specially since these must be
    125   // inherited through the dependency tree (other flags don't work this way).
    126   for (ConfigValuesIterator iter(this); !iter.done(); iter.Next()) {
    127     const ConfigValues& cur = iter.cur();
    128     all_lib_dirs_.append(cur.lib_dirs().begin(), cur.lib_dirs().end());
    129     all_libs_.append(cur.libs().begin(), cur.libs().end());
    130   }
    131 
    132   PullDependentTargetInfo();
    133   PullForwardedDependentConfigs();
    134   PullRecursiveHardDeps();
    135 
    136   FillOutputFiles();
    137 
    138   if (!CheckVisibility(err))
    139     return false;
    140   if (!CheckTestonly(err))
    141     return false;
    142   if (!CheckNoNestedStaticLibs(err))
    143     return false;
    144 
    145   return true;
    146 }
    147 
    148 bool Target::IsLinkable() const {
    149   return output_type_ == STATIC_LIBRARY || output_type_ == SHARED_LIBRARY;
    150 }
    151 
    152 bool Target::IsFinal() const {
    153   return output_type_ == EXECUTABLE || output_type_ == SHARED_LIBRARY ||
    154          (output_type_ == STATIC_LIBRARY && complete_static_lib_);
    155 }
    156 
    157 std::string Target::GetComputedOutputName(bool include_prefix) const {
    158   DCHECK(toolchain_)
    159       << "Toolchain must be specified before getting the computed output name.";
    160 
    161   const std::string& name = output_name_.empty() ? label().name()
    162                                                  : output_name_;
    163 
    164   std::string result;
    165   if (include_prefix) {
    166     const Tool* tool = toolchain_->GetToolForTargetFinalOutput(this);
    167     const std::string& prefix = tool->output_prefix();
    168     // Only add the prefix if the name doesn't already have it.
    169     if (!StartsWithASCII(name, prefix, true))
    170       result = prefix;
    171   }
    172 
    173   result.append(name);
    174   return result;
    175 }
    176 
    177 bool Target::SetToolchain(const Toolchain* toolchain, Err* err) {
    178   DCHECK(!toolchain_);
    179   DCHECK_NE(UNKNOWN, output_type_);
    180   toolchain_ = toolchain;
    181 
    182   const Tool* tool = toolchain->GetToolForTargetFinalOutput(this);
    183   if (tool)
    184     return true;
    185 
    186   // Tool not specified for this target type.
    187   if (err) {
    188     *err = Err(defined_from(), "This target uses an undefined tool.",
    189         base::StringPrintf(
    190             "The target %s\n"
    191             "of type \"%s\"\n"
    192             "uses toolchain %s\n"
    193             "which doesn't have the tool \"%s\" defined.\n\n"
    194             "Alas, I can not continue.",
    195             label().GetUserVisibleName(false).c_str(),
    196             GetStringForOutputType(output_type_),
    197             label().GetToolchainLabel().GetUserVisibleName(false).c_str(),
    198             Toolchain::ToolTypeToName(
    199                 toolchain->GetToolTypeForTargetFinalOutput(this)).c_str()));
    200   }
    201   return false;
    202 }
    203 
    204 void Target::PullDependentTargetInfo() {
    205   // Gather info from our dependents we need.
    206   for (DepsIterator iter(this, DepsIterator::LINKED_ONLY); !iter.done();
    207        iter.Advance()) {
    208     const Target* dep = iter.target();
    209     MergeAllDependentConfigsFrom(dep, &configs_, &all_dependent_configs_);
    210     MergePublicConfigsFrom(dep, &configs_);
    211 
    212     // Direct dependent libraries.
    213     if (dep->output_type() == STATIC_LIBRARY ||
    214         dep->output_type() == SHARED_LIBRARY ||
    215         dep->output_type() == SOURCE_SET)
    216       inherited_libraries_.push_back(dep);
    217 
    218     // Inherited libraries and flags are inherited across static library
    219     // boundaries.
    220     if (!dep->IsFinal()) {
    221       inherited_libraries_.Append(dep->inherited_libraries().begin(),
    222                                   dep->inherited_libraries().end());
    223 
    224       // Inherited library settings.
    225       all_lib_dirs_.append(dep->all_lib_dirs());
    226       all_libs_.append(dep->all_libs());
    227     }
    228   }
    229 }
    230 
    231 void Target::PullForwardedDependentConfigs() {
    232   // Pull public configs from each of our dependency's public deps.
    233   for (size_t dep = 0; dep < public_deps_.size(); dep++)
    234     PullForwardedDependentConfigsFrom(public_deps_[dep].ptr);
    235 
    236   // Forward public configs if explicitly requested.
    237   for (size_t dep = 0; dep < forward_dependent_configs_.size(); dep++) {
    238     const Target* from_target = forward_dependent_configs_[dep].ptr;
    239 
    240     // The forward_dependent_configs_ must be in the deps (public or private)
    241     // already, so we don't need to bother copying to our configs, only
    242     // forwarding.
    243     DCHECK(std::find_if(private_deps_.begin(), private_deps_.end(),
    244                         LabelPtrPtrEquals<Target>(from_target)) !=
    245                private_deps_.end() ||
    246            std::find_if(public_deps_.begin(), public_deps_.end(),
    247                         LabelPtrPtrEquals<Target>(from_target)) !=
    248                public_deps_.end());
    249 
    250     PullForwardedDependentConfigsFrom(from_target);
    251   }
    252 }
    253 
    254 void Target::PullForwardedDependentConfigsFrom(const Target* from) {
    255   public_configs_.Append(from->public_configs().begin(),
    256                          from->public_configs().end());
    257 }
    258 
    259 void Target::PullRecursiveHardDeps() {
    260   for (DepsIterator iter(this, DepsIterator::LINKED_ONLY); !iter.done();
    261        iter.Advance()) {
    262     if (iter.target()->hard_dep())
    263       recursive_hard_deps_.insert(iter.target());
    264 
    265     // Android STL doesn't like insert(begin, end) so do it manually.
    266     // TODO(brettw) this can be changed to
    267     // insert(iter.target()->begin(), iter.target()->end())
    268     // when Android uses a better STL.
    269     for (std::set<const Target*>::const_iterator cur =
    270              iter.target()->recursive_hard_deps().begin();
    271          cur != iter.target()->recursive_hard_deps().end(); ++cur)
    272       recursive_hard_deps_.insert(*cur);
    273   }
    274 }
    275 
    276 void Target::FillOutputFiles() {
    277   const Tool* tool = toolchain_->GetToolForTargetFinalOutput(this);
    278   switch (output_type_) {
    279     case GROUP:
    280     case SOURCE_SET:
    281     case COPY_FILES:
    282     case ACTION:
    283     case ACTION_FOREACH: {
    284       // These don't get linked to and use stamps which should be the first
    285       // entry in the outputs. These stamps are named
    286       // "<target_out_dir>/<targetname>.stamp".
    287       dependency_output_file_ = GetTargetOutputDirAsOutputFile(this);
    288       dependency_output_file_.value().append(GetComputedOutputName(true));
    289       dependency_output_file_.value().append(".stamp");
    290       break;
    291     }
    292     case EXECUTABLE:
    293       // Executables don't get linked to, but the first output is used for
    294       // dependency management.
    295       CHECK_GE(tool->outputs().list().size(), 1u);
    296       dependency_output_file_ =
    297           SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
    298               this, tool, tool->outputs().list()[0]);
    299       break;
    300     case STATIC_LIBRARY:
    301       // Static libraries both have dependencies and linking going off of the
    302       // first output.
    303       CHECK(tool->outputs().list().size() >= 1);
    304       link_output_file_ = dependency_output_file_ =
    305           SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
    306               this, tool, tool->outputs().list()[0]);
    307       break;
    308     case SHARED_LIBRARY:
    309       CHECK(tool->outputs().list().size() >= 1);
    310       if (tool->link_output().empty() && tool->depend_output().empty()) {
    311         // Default behavior, use the first output file for both.
    312         link_output_file_ = dependency_output_file_ =
    313             SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
    314                 this, tool, tool->outputs().list()[0]);
    315       } else {
    316         // Use the tool-specified ones.
    317         if (!tool->link_output().empty()) {
    318           link_output_file_ =
    319               SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
    320                   this, tool, tool->link_output());
    321         }
    322         if (!tool->depend_output().empty()) {
    323           dependency_output_file_ =
    324               SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
    325                   this, tool, tool->depend_output());
    326         }
    327       }
    328       break;
    329     case UNKNOWN:
    330     default:
    331       NOTREACHED();
    332   }
    333 }
    334 
    335 bool Target::CheckVisibility(Err* err) const {
    336   for (DepsIterator iter(this); !iter.done(); iter.Advance()) {
    337     if (!Visibility::CheckItemVisibility(this, iter.target(), err))
    338       return false;
    339   }
    340   return true;
    341 }
    342 
    343 bool Target::CheckTestonly(Err* err) const {
    344   // If the current target is marked testonly, it can include both testonly
    345   // and non-testonly targets, so there's nothing to check.
    346   if (testonly())
    347     return true;
    348 
    349   // Verify no deps have "testonly" set.
    350   for (DepsIterator iter(this); !iter.done(); iter.Advance()) {
    351     if (iter.target()->testonly()) {
    352       *err = MakeTestOnlyError(this, iter.target());
    353       return false;
    354     }
    355   }
    356 
    357   return true;
    358 }
    359 
    360 bool Target::CheckNoNestedStaticLibs(Err* err) const {
    361   // If the current target is not a complete static library, it can depend on
    362   // static library targets with no problem.
    363   if (!(output_type() == Target::STATIC_LIBRARY && complete_static_lib()))
    364     return true;
    365 
    366   // Verify no deps are static libraries.
    367   for (DepsIterator iter(this); !iter.done(); iter.Advance()) {
    368     if (iter.target()->output_type() == Target::STATIC_LIBRARY) {
    369       *err = MakeStaticLibDepsError(this, iter.target());
    370       return false;
    371     }
    372   }
    373 
    374   // Verify no inherited libraries are static libraries.
    375   for (size_t i = 0; i < inherited_libraries().size(); ++i) {
    376     if (inherited_libraries()[i]->output_type() == Target::STATIC_LIBRARY) {
    377       *err = MakeStaticLibDepsError(this, inherited_libraries()[i]);
    378       return false;
    379     }
    380   }
    381   return true;
    382 }
    383