• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "base/stl_util.h"
6 #include "gn/functions.h"
7 #include "gn/parse_tree.h"
8 #include "gn/scope.h"
9 #include "gn/settings.h"
10 #include "gn/substitution_list.h"
11 #include "gn/substitution_writer.h"
12 #include "gn/target.h"
13 #include "gn/value_extractors.h"
14 
15 namespace functions {
16 
17 const char kProcessFileTemplate[] = "process_file_template";
18 const char kProcessFileTemplate_HelpShort[] =
19     "process_file_template: Do template expansion over a list of files.";
20 const char kProcessFileTemplate_Help[] =
21     R"(process_file_template: Do template expansion over a list of files.
22 
23   process_file_template(source_list, template)
24 
25   process_file_template applies a template list to a source file list,
26   returning the result of applying each template to each source. This is
27   typically used for computing output file names from input files.
28 
29   In most cases, get_target_outputs() will give the same result with shorter,
30   more maintainable code. This function should only be used when that function
31   can't be used (like there's no target or the target is defined in another
32   build file).
33 
34 Arguments
35 
36   The source_list is a list of file names.
37 
38   The template can be a string or a list. If it is a list, multiple output
39   strings are generated for each input.
40 
41   The template should contain source expansions to which each name in the
42   source list is applied. See "gn help source_expansion".
43 
44 Example
45 
46   sources = [
47     "foo.idl",
48     "bar.idl",
49   ]
50   myoutputs = process_file_template(
51       sources,
52       [ "$target_gen_dir/{{source_name_part}}.cc",
53         "$target_gen_dir/{{source_name_part}}.h" ])
54 
55  The result in this case will be:
56     [ "//out/Debug/foo.cc"
57       "//out/Debug/foo.h"
58       "//out/Debug/bar.cc"
59       "//out/Debug/bar.h" ]
60 )";
61 
RunProcessFileTemplate(Scope * scope,const FunctionCallNode * function,const std::vector<Value> & args,Err * err)62 Value RunProcessFileTemplate(Scope* scope,
63                              const FunctionCallNode* function,
64                              const std::vector<Value>& args,
65                              Err* err) {
66   if (args.size() != 2) {
67     *err = Err(function->function(), "Expected two arguments");
68     return Value();
69   }
70 
71   // Source list.
72   Target::FileList input_files;
73   if (!ExtractListOfRelativeFiles(scope->settings()->build_settings(), args[0],
74                                   scope->GetSourceDir(), &input_files, err))
75     return Value();
76 
77   std::vector<std::string> result_files;
78   SubstitutionList subst;
79 
80   // Template.
81   const Value& template_arg = args[1];
82   if (template_arg.type() == Value::STRING) {
83     // Convert the string to a SubstitutionList with one pattern in it to
84     // simplify the code below.
85     std::vector<std::string> list;
86     list.push_back(template_arg.string_value());
87     if (!subst.Parse(list, template_arg.origin(), err))
88       return Value();
89   } else if (template_arg.type() == Value::LIST) {
90     if (!subst.Parse(template_arg, err))
91       return Value();
92   } else {
93     *err = Err(template_arg, "Not a string or a list.");
94     return Value();
95   }
96 
97   auto& types = subst.required_types();
98   if (base::ContainsValue(types, &SubstitutionSourceTargetRelative)) {
99     *err = Err(template_arg, "Not a valid substitution type for the function.");
100     return Value();
101   }
102 
103   SubstitutionWriter::ApplyListToSourcesAsString(
104       nullptr, scope->settings(), subst, input_files, &result_files);
105 
106   // Convert the list of strings to the return Value.
107   Value ret(function, Value::LIST);
108   ret.list_value().reserve(result_files.size());
109   for (const auto& file : result_files)
110     ret.list_value().push_back(Value(function, file));
111 
112   return ret;
113 }
114 
115 }  // namespace functions
116