| // 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 |