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