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.
5 #ifndef TOOLS_GN_FILE_TEMPLATE_H_
6 #define TOOLS_GN_FILE_TEMPLATE_H_
10 #include "base/basictypes.h"
11 #include "base/containers/stack_container.h"
12 #include "tools/gn/err.h"
13 #include "tools/gn/value.h"
18 extern const char kSourceExpansion_Help[];
20 // A FileTemplate object implements source expansion for a given "template"
21 // (either outputs or args, depending on the target type).
23 // There are two ways you can use this. You can make a template and then
24 // apply a source to it to get a list of outputs manually. Or you can do the
25 // actual substitution in Ninja, writing the arguments in a rule and using
26 // variables in build statements to invoke the rule with the right
34 // {{source}} -> expands to be the source file name relative to the build
38 // {{source_name_part}} -> file name without extension or directory.
39 // Maps "foo/bar.txt" to "bar".
42 // {{source_file_part}} -> file name including extension but no directory.
43 // Maps "foo/bar.txt" to "bar.txt".
46 NUM_TYPES // Must be last
48 Subrange(Type t, const std::string& l = std::string())
55 // When type_ == LITERAL, this specifies the literal.
59 // Constructs a template from the given value. On error, the err will be
60 // set. In this case you should not use this object.
61 FileTemplate(const Value& t, Err* err);
62 FileTemplate(const std::vector<std::string>& t);
65 // Returns true if the given substitution type is used by this template.
66 bool IsTypeUsed(Subrange::Type type) const;
68 // Returns true if there are any substitutions.
69 bool has_substitutions() const { return has_substitutions_; }
71 // Applies this template to the given list of sources, appending all
72 // results to the given dest list. The sources must be a list for the
73 // one that takes a value as an input, otherwise the given error will be set.
74 void Apply(const Value& sources,
75 const ParseNode* origin,
76 std::vector<Value>* dest,
78 void ApplyString(const std::string& input,
79 std::vector<std::string>* output) const;
81 // Writes a string representing the template with Ninja variables for the
82 // substitutions, and the literals escaped for Ninja consumption.
84 // For example, if the input is "foo{{source_name_part}}bar" this will write
85 // foo${source_name_part}bar. If there are multiple templates (we were
86 // constucted with a list of more than one item) then the values will be
87 // separated by spaces.
89 // If this template is nonempty, we will first print out a space to separate
90 // it from the previous command.
92 // The names used for the Ninja variables will be the same ones used by
93 // WriteNinjaVariablesForSubstitution. You would use this to define the Ninja
94 // rule, and then define the variables to substitute for each file using
95 // WriteNinjaVariablesForSubstitution.
96 void WriteWithNinjaExpansions(std::ostream& out) const;
98 // Writes to the given stream the variable declarations for extracting the
99 // required parts of the given source file string. The results will be
100 // indented two spaces.
102 // This is used to set up a build statement to invoke a rule where the rule
103 // contains a representation of this file template to be expanded by Ninja
104 // (see GetWithNinjaExpansions).
105 void WriteNinjaVariablesForSubstitution(
107 const std::string& source,
108 const EscapeOptions& escape_options) const;
110 // Returns the Ninja variable name used by the above Ninja functions to
111 // substitute for the given type.
112 static const char* GetNinjaVariableNameForType(Subrange::Type type);
114 // Extracts the given type of substitution from the given source. The source
115 // should be the file name relative to the output directory.
116 static std::string GetSubstitution(const std::string& source,
117 Subrange::Type type);
119 // Known template types, these include the "{{ }}"
120 static const char kSource[];
121 static const char kSourceNamePart[];
122 static const char kSourceFilePart[];
125 typedef base::StackVector<Subrange, 8> Template;
126 typedef base::StackVector<Template, 8> TemplateVector;
128 void ParseInput(const Value& value, Err* err);
130 // Parses a template string and adds it to the templates_ list.
131 void ParseOneTemplateString(const std::string& str);
133 TemplateVector templates_;
135 // The corresponding value is set to true if the given subrange type is
136 // required. This allows us to precompute these types whem applying them
137 // to a given source file.
138 bool types_required_[Subrange::NUM_TYPES];
140 // Set when any of the types_required_ is true. Otherwise, everythins is a
141 // literal (a common case so we can optimize some code paths).
142 bool has_substitutions_;
145 #endif // TOOLS_GN_FILE_TEMPLATE_H_