Home | History | Annotate | Download | only in gn
      1 // Copyright 2014 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/build_settings.h"
      6 #include "tools/gn/file_template.h"
      7 #include "tools/gn/functions.h"
      8 #include "tools/gn/ninja_helper.h"
      9 #include "tools/gn/parse_tree.h"
     10 #include "tools/gn/settings.h"
     11 #include "tools/gn/target.h"
     12 #include "tools/gn/value.h"
     13 
     14 namespace functions {
     15 
     16 namespace {
     17 
     18 void GetOutputsForTarget(const Settings* settings,
     19                          const Target* target,
     20                          std::vector<std::string>* ret) {
     21   switch (target->output_type()) {
     22     case Target::ACTION:
     23     case Target::COPY_FILES: {
     24       // Actions and copy targets: return the outputs specified.
     25       const std::vector<SourceFile>& outs = target->action_values().outputs();
     26       ret->reserve(outs.size());
     27       for (size_t i = 0; i < outs.size(); i++)
     28         ret->push_back(outs[i].value());
     29       break;
     30     }
     31 
     32     case Target::ACTION_FOREACH: {
     33       // Action_foreach: return the result of the template in the outputs.
     34       FileTemplate file_template(settings, target->action_values().outputs());
     35       const std::vector<SourceFile>& sources = target->sources();
     36       for (size_t i = 0; i < sources.size(); i++)
     37         file_template.Apply(sources[i], ret);
     38       break;
     39     }
     40 
     41     case Target::EXECUTABLE:
     42     case Target::SHARED_LIBRARY:
     43     case Target::STATIC_LIBRARY:
     44       // Return the resulting binary file. Currently, fall through to the
     45       // Ninja helper below which will compute the main output name.
     46       //
     47       // TODO(brettw) some targets have secondary files which should go into
     48       // the list after the main (like shared libraries on Windows have an
     49       // import library).
     50     case Target::GROUP:
     51     case Target::SOURCE_SET: {
     52       // These return the stamp file, which is computed by the NinjaHelper.
     53       NinjaHelper helper(settings->build_settings());
     54       OutputFile output_file = helper.GetTargetOutputFile(target);
     55 
     56       // The output file is relative to the build dir.
     57       std::string absolute_output_file =
     58           settings->build_settings()->build_dir().value();
     59       absolute_output_file.append(output_file.value());
     60 
     61       ret->push_back(absolute_output_file);
     62       break;
     63     }
     64 
     65     default:
     66       NOTREACHED();
     67   }
     68 }
     69 
     70 }  // namespace
     71 
     72 const char kGetTargetOutputs[] = "get_target_outputs";
     73 const char kGetTargetOutputs_HelpShort[] =
     74     "get_target_outputs: [file list] Get the list of outputs from a target.";
     75 const char kGetTargetOutputs_Help[] =
     76     "get_target_outputs: [file list] Get the list of outputs from a target.\n"
     77     "\n"
     78     "  get_target_outputs(target_label)\n"
     79     "\n"
     80     "  Returns a list of output files for the named target. The named target\n"
     81     "  must have been previously defined in the current file before this\n"
     82     "  function is called (it can't reference targets in other files because\n"
     83     "  there isn't a defined execution order, and it obviously can't\n"
     84     "  reference targets that are defined after the function call).\n"
     85     "\n"
     86     "Return value\n"
     87     "\n"
     88     "  The names in the resulting list will be absolute file paths (normally\n"
     89     "  like \"//out/Debug/bar.exe\", depending on the build directory).\n"
     90     "\n"
     91     "  action targets: this will just return the files specified in the\n"
     92     "  \"outputs\" variable of the target.\n"
     93     "\n"
     94     "  action_foreach targets: this will return the result of applying\n"
     95     "  the output template to the sources (see \"gn help source_expansion\").\n"
     96     "  This will be the same result (though with guaranteed absolute file\n"
     97     "  paths), as process_file_template will return for those inputs\n"
     98     "  (see \"gn help process_file_template\").\n"
     99     "\n"
    100     "  binary targets (executables, libraries): this will return a list\n"
    101     "  of the resulting binary file(s). The \"main output\" (the actual\n"
    102     "  binary or library) will always be the 0th element in the result.\n"
    103     "  Depending on the platform and output type, there may be other output\n"
    104     "  files as well (like import libraries) which will follow.\n"
    105     "\n"
    106     "  source sets and groups: this will return a list containing the path of\n"
    107     "  the \"stamp\" file that Ninja will produce once all outputs are\n"
    108     "  generated. This probably isn't very useful.\n"
    109     "\n"
    110     "Example\n"
    111     "\n"
    112     "  # Say this action generates a bunch of C source files.\n"
    113     "  action_foreach(\"my_action\") {\n"
    114     "    sources = [ ... ]\n"
    115     "    outputs = [ ... ]\n"
    116     "  }\n"
    117     "\n"
    118     "  # Compile the resulting source files into a source set.\n"
    119     "  source_set(\"my_lib\") {\n"
    120     "    sources = get_target_outputs(\":my_action\")\n"
    121     "  }\n";
    122 
    123 Value RunGetTargetOutputs(Scope* scope,
    124                           const FunctionCallNode* function,
    125                           const std::vector<Value>& args,
    126                           Err* err) {
    127   if (args.size() != 1) {
    128     *err = Err(function, "Expected one argument.");
    129     return Value();
    130   }
    131 
    132   // Resolve the requested label.
    133   Label label = Label::Resolve(scope->GetSourceDir(),
    134                                ToolchainLabelForScope(scope), args[0], err);
    135   if (label.is_null())
    136     return Value();
    137 
    138   // Find the referenced target. The targets previously encountered in this
    139   // scope will have been stashed in the item collector (they'll be dispatched
    140   // when this file is done running) so we can look through them.
    141   const Target* target = NULL;
    142   Scope::ItemVector* collector = scope->GetItemCollector();
    143   if (!collector) {
    144     *err = Err(function, "No targets defined in this context.");
    145     return Value();
    146   }
    147   for (size_t i = 0; i < collector->size(); i++) {
    148     const Item* item = (*collector)[i]->get();
    149     if (item->label() != label)
    150       continue;
    151 
    152     const Target* as_target = item->AsTarget();
    153     if (!as_target) {
    154       *err = Err(function, "Label does not refer to a target.",
    155           label.GetUserVisibleName(false) +
    156           "\nrefers to a " + item->GetItemTypeName());
    157       return Value();
    158     }
    159     target = as_target;
    160     break;
    161   }
    162 
    163   if (!target) {
    164     *err = Err(function, "Target not found in this context.",
    165         label.GetUserVisibleName(false) +
    166         "\nwas not found. get_target_outputs() can only be used for targets\n"
    167         "previously defined in the current file.");
    168     return Value();
    169   }
    170 
    171   std::vector<std::string> files;
    172   GetOutputsForTarget(scope->settings(), target, &files);
    173 
    174   Value ret(function, Value::LIST);
    175   ret.list_value().reserve(files.size());
    176   for (size_t i = 0; i < files.size(); i++)
    177     ret.list_value().push_back(Value(function, files[i]));
    178 
    179   return ret;
    180 }
    181 
    182 }  // namespace functions
    183