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/functions.h"
      7 #include "tools/gn/parse_tree.h"
      8 #include "tools/gn/settings.h"
      9 #include "tools/gn/substitution_writer.h"
     10 #include "tools/gn/target.h"
     11 #include "tools/gn/value.h"
     12 
     13 namespace functions {
     14 
     15 const char kGetTargetOutputs[] = "get_target_outputs";
     16 const char kGetTargetOutputs_HelpShort[] =
     17     "get_target_outputs: [file list] Get the list of outputs from a target.";
     18 const char kGetTargetOutputs_Help[] =
     19     "get_target_outputs: [file list] Get the list of outputs from a target.\n"
     20     "\n"
     21     "  get_target_outputs(target_label)\n"
     22     "\n"
     23     "  Returns a list of output files for the named target. The named target\n"
     24     "  must have been previously defined in the current file before this\n"
     25     "  function is called (it can't reference targets in other files because\n"
     26     "  there isn't a defined execution order, and it obviously can't\n"
     27     "  reference targets that are defined after the function call).\n"
     28     "\n"
     29     "  Only copy and action targets are supported. The outputs from binary\n"
     30     "  targets will depend on the toolchain definition which won't\n"
     31     "  necessarily have been loaded by the time a given line of code has run,\n"
     32     "  and source sets and groups have no useful output file.\n"
     33     "\n"
     34     "Return value\n"
     35     "\n"
     36     "  The names in the resulting list will be absolute file paths (normally\n"
     37     "  like \"//out/Debug/bar.exe\", depending on the build directory).\n"
     38     "\n"
     39     "  action targets: this will just return the files specified in the\n"
     40     "  \"outputs\" variable of the target.\n"
     41     "\n"
     42     "  action_foreach targets: this will return the result of applying\n"
     43     "  the output template to the sources (see \"gn help source_expansion\").\n"
     44     "  This will be the same result (though with guaranteed absolute file\n"
     45     "  paths), as process_file_template will return for those inputs\n"
     46     "  (see \"gn help process_file_template\").\n"
     47     "\n"
     48     "  binary targets (executables, libraries): this will return a list\n"
     49     "  of the resulting binary file(s). The \"main output\" (the actual\n"
     50     "  binary or library) will always be the 0th element in the result.\n"
     51     "  Depending on the platform and output type, there may be other output\n"
     52     "  files as well (like import libraries) which will follow.\n"
     53     "\n"
     54     "  source sets and groups: this will return a list containing the path of\n"
     55     "  the \"stamp\" file that Ninja will produce once all outputs are\n"
     56     "  generated. This probably isn't very useful.\n"
     57     "\n"
     58     "Example\n"
     59     "\n"
     60     "  # Say this action generates a bunch of C source files.\n"
     61     "  action_foreach(\"my_action\") {\n"
     62     "    sources = [ ... ]\n"
     63     "    outputs = [ ... ]\n"
     64     "  }\n"
     65     "\n"
     66     "  # Compile the resulting source files into a source set.\n"
     67     "  source_set(\"my_lib\") {\n"
     68     "    sources = get_target_outputs(\":my_action\")\n"
     69     "  }\n";
     70 
     71 Value RunGetTargetOutputs(Scope* scope,
     72                           const FunctionCallNode* function,
     73                           const std::vector<Value>& args,
     74                           Err* err) {
     75   if (args.size() != 1) {
     76     *err = Err(function, "Expected one argument.");
     77     return Value();
     78   }
     79 
     80   // Resolve the requested label.
     81   Label label = Label::Resolve(scope->GetSourceDir(),
     82                                ToolchainLabelForScope(scope), args[0], err);
     83   if (label.is_null())
     84     return Value();
     85 
     86   // Find the referenced target. The targets previously encountered in this
     87   // scope will have been stashed in the item collector (they'll be dispatched
     88   // when this file is done running) so we can look through them.
     89   const Target* target = NULL;
     90   Scope::ItemVector* collector = scope->GetItemCollector();
     91   if (!collector) {
     92     *err = Err(function, "No targets defined in this context.");
     93     return Value();
     94   }
     95   for (size_t i = 0; i < collector->size(); i++) {
     96     const Item* item = (*collector)[i]->get();
     97     if (item->label() != label)
     98       continue;
     99 
    100     const Target* as_target = item->AsTarget();
    101     if (!as_target) {
    102       *err = Err(function, "Label does not refer to a target.",
    103           label.GetUserVisibleName(false) +
    104           "\nrefers to a " + item->GetItemTypeName());
    105       return Value();
    106     }
    107     target = as_target;
    108     break;
    109   }
    110 
    111   if (!target) {
    112     *err = Err(function, "Target not found in this context.",
    113         label.GetUserVisibleName(false) +
    114         "\nwas not found. get_target_outputs() can only be used for targets\n"
    115         "previously defined in the current file.");
    116     return Value();
    117   }
    118 
    119   // Compute the output list.
    120   std::vector<SourceFile> files;
    121   if (target->output_type() == Target::ACTION ||
    122       target->output_type() == Target::COPY_FILES ||
    123       target->output_type() == Target::ACTION_FOREACH) {
    124     target->action_values().GetOutputsAsSourceFiles(target, &files);
    125   } else {
    126     // Other types of targets are not supported.
    127     *err = Err(args[0], "Target is not an action, action_foreach, or copy.",
    128                "Only these target types are supported by get_target_outputs.");
    129     return Value();
    130   }
    131 
    132   // Convert to Values.
    133   Value ret(function, Value::LIST);
    134   ret.list_value().reserve(files.size());
    135   for (size_t i = 0; i < files.size(); i++)
    136     ret.list_value().push_back(Value(function, files[i].value()));
    137 
    138   return ret;
    139 }
    140 
    141 }  // namespace functions
    142