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/file_template.h"
      6 #include "tools/gn/functions.h"
      7 #include "tools/gn/parse_tree.h"
      8 #include "tools/gn/scope.h"
      9 #include "tools/gn/settings.h"
     10 #include "tools/gn/target.h"
     11 #include "tools/gn/value_extractors.h"
     12 
     13 namespace functions {
     14 
     15 const char kProcessFileTemplate[] = "process_file_template";
     16 const char kProcessFileTemplate_HelpShort[] =
     17     "process_file_template: Do template expansion over a list of files.";
     18 const char kProcessFileTemplate_Help[] =
     19     "process_file_template: Do template expansion over a list of files.\n"
     20     "\n"
     21     "  process_file_template(source_list, template)\n"
     22     "\n"
     23     "  process_file_template applies a template list to a source file list,\n"
     24     "  returning the result of applying each template to each source. This is\n"
     25     "  typically used for computing output file names from input files.\n"
     26     "\n"
     27     "  In most cases, get_target_outputs() will give the same result with\n"
     28     "  shorter, more maintainable code. This function should only be used\n"
     29     "  when that function can't be used (like there's no target or the target\n"
     30     "  is defined in another build file).\n"
     31     "\n"
     32     "Arguments:\n"
     33     "\n"
     34     "  The source_list is a list of file names.\n"
     35     "\n"
     36     "  The template can be a string or a list. If it is a list, multiple\n"
     37     "  output strings are generated for each input.\n"
     38     "\n"
     39     "  The following template substrings are used in the template arguments\n"
     40     "  and are replaced with the corresponding part of the input file name:\n"
     41     "\n"
     42     "    {{source}}\n"
     43     "        The entire source name.\n"
     44     "\n"
     45     "    {{source_name_part}}\n"
     46     "        The source name with no path or extension.\n"
     47     "\n"
     48     "Example:\n"
     49     "\n"
     50     "  sources = [\n"
     51     "    \"foo.idl\",\n"
     52     "    \"bar.idl\",\n"
     53     "  ]\n"
     54     "  myoutputs = process_file_template(\n"
     55     "      sources,\n"
     56     "      [ \"$target_gen_dir/{{source_name_part}}.cc\",\n"
     57     "        \"$target_gen_dir/{{source_name_part}}.h\" ])\n"
     58     "\n"
     59     " The result in this case will be:\n"
     60     "    [ \"//out/Debug/foo.cc\"\n"
     61     "      \"//out/Debug/foo.h\"\n"
     62     "      \"//out/Debug/bar.cc\"\n"
     63     "      \"//out/Debug/bar.h\" ]\n";
     64 
     65 Value RunProcessFileTemplate(Scope* scope,
     66                              const FunctionCallNode* function,
     67                              const std::vector<Value>& args,
     68                              Err* err) {
     69   if (args.size() != 2) {
     70     *err = Err(function->function(), "Expected two arguments");
     71     return Value();
     72   }
     73 
     74   FileTemplate file_template(scope->settings(), args[1], err);
     75   if (err->has_error())
     76     return Value();
     77 
     78   Target::FileList input_files;
     79   if (!ExtractListOfRelativeFiles(scope->settings()->build_settings(), args[0],
     80                                   scope->GetSourceDir(), &input_files, err))
     81     return Value();
     82 
     83   Value ret(function, Value::LIST);
     84 
     85   // Temporary holding place, allocate outside to re-use buffer.
     86   std::vector<std::string> string_output;
     87 
     88   for (size_t i = 0; i < input_files.size(); i++) {
     89     string_output.clear();
     90     file_template.Apply(input_files[i], &string_output);
     91     for (size_t out_i = 0; out_i < string_output.size(); out_i++)
     92       ret.list_value().push_back(Value(function, string_output[out_i]));
     93   }
     94   return ret;
     95 }
     96 
     97 }  // namespace functions
     98