| // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "base/stl_util.h" |
| #include "tools/gn/functions.h" |
| #include "tools/gn/parse_tree.h" |
| #include "tools/gn/scope.h" |
| #include "tools/gn/settings.h" |
| #include "tools/gn/substitution_list.h" |
| #include "tools/gn/substitution_writer.h" |
| #include "tools/gn/target.h" |
| #include "tools/gn/value_extractors.h" |
| |
| namespace functions { |
| |
| const char kProcessFileTemplate[] = "process_file_template"; |
| const char kProcessFileTemplate_HelpShort[] = |
| "process_file_template: Do template expansion over a list of files."; |
| const char kProcessFileTemplate_Help[] = |
| R"(process_file_template: Do template expansion over a list of files. |
| |
| process_file_template(source_list, template) |
| |
| process_file_template applies a template list to a source file list, |
| returning the result of applying each template to each source. This is |
| typically used for computing output file names from input files. |
| |
| In most cases, get_target_outputs() will give the same result with shorter, |
| more maintainable code. This function should only be used when that function |
| can't be used (like there's no target or the target is defined in another |
| build file). |
| |
| Arguments |
| |
| The source_list is a list of file names. |
| |
| The template can be a string or a list. If it is a list, multiple output |
| strings are generated for each input. |
| |
| The template should contain source expansions to which each name in the |
| source list is applied. See "gn help source_expansion". |
| |
| Example |
| |
| sources = [ |
| "foo.idl", |
| "bar.idl", |
| ] |
| myoutputs = process_file_template( |
| sources, |
| [ "$target_gen_dir/{{source_name_part}}.cc", |
| "$target_gen_dir/{{source_name_part}}.h" ]) |
| |
| The result in this case will be: |
| [ "//out/Debug/foo.cc" |
| "//out/Debug/foo.h" |
| "//out/Debug/bar.cc" |
| "//out/Debug/bar.h" ] |
| )"; |
| |
| Value RunProcessFileTemplate(Scope* scope, |
| const FunctionCallNode* function, |
| const std::vector<Value>& args, |
| Err* err) { |
| if (args.size() != 2) { |
| *err = Err(function->function(), "Expected two arguments"); |
| return Value(); |
| } |
| |
| // Source list. |
| Target::FileList input_files; |
| if (!ExtractListOfRelativeFiles(scope->settings()->build_settings(), args[0], |
| scope->GetSourceDir(), &input_files, err)) |
| return Value(); |
| |
| std::vector<std::string> result_files; |
| SubstitutionList subst; |
| |
| // Template. |
| const Value& template_arg = args[1]; |
| if (template_arg.type() == Value::STRING) { |
| // Convert the string to a SubstitutionList with one pattern in it to |
| // simplify the code below. |
| std::vector<std::string> list; |
| list.push_back(template_arg.string_value()); |
| if (!subst.Parse(list, template_arg.origin(), err)) |
| return Value(); |
| } else if (template_arg.type() == Value::LIST) { |
| if (!subst.Parse(template_arg, err)) |
| return Value(); |
| } else { |
| *err = Err(template_arg, "Not a string or a list."); |
| return Value(); |
| } |
| |
| auto& types = subst.required_types(); |
| if (base::ContainsValue(types, &SubstitutionSourceTargetRelative)) { |
| *err = Err(template_arg, "Not a valid substitution type for the function."); |
| return Value(); |
| } |
| |
| SubstitutionWriter::ApplyListToSourcesAsString( |
| nullptr, scope->settings(), subst, input_files, &result_files); |
| |
| // Convert the list of strings to the return Value. |
| Value ret(function, Value::LIST); |
| ret.list_value().reserve(result_files.size()); |
| for (const auto& file : result_files) |
| ret.list_value().push_back(Value(function, file)); |
| |
| return ret; |
| } |
| |
| } // namespace functions |