OLD | NEW |
| (Empty) |
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 #ifndef TOOLS_GN_FILE_TEMPLATE_H_ | |
6 #define TOOLS_GN_FILE_TEMPLATE_H_ | |
7 | |
8 #include <iosfwd> | |
9 | |
10 #include "base/basictypes.h" | |
11 #include "base/containers/stack_container.h" | |
12 #include "tools/gn/err.h" | |
13 #include "tools/gn/source_dir.h" | |
14 #include "tools/gn/value.h" | |
15 | |
16 struct EscapeOptions; | |
17 class ParseNode; | |
18 class Settings; | |
19 class SourceFile; | |
20 class Target; | |
21 | |
22 extern const char kSourceExpansion_Help[]; | |
23 | |
24 // A FileTemplate object implements source expansion for a given "template" | |
25 // (either outputs or args, depending on the target type). | |
26 // | |
27 // There are two ways you can use this. You can make a template and then | |
28 // apply a source to it to get a list of outputs manually. Or you can do the | |
29 // actual substitution in Ninja, writing the arguments in a rule and using | |
30 // variables in build statements to invoke the rule with the right | |
31 // substitutions. | |
32 class FileTemplate { | |
33 public: | |
34 enum OutputStyle { | |
35 OUTPUT_ABSOLUTE, // Dirs will be absolute "//foo/bar". | |
36 OUTPUT_RELATIVE, // Dirs will be relative to a given directory. | |
37 }; | |
38 | |
39 struct Subrange { | |
40 // See the help in the .cc file for what these mean. | |
41 enum Type { | |
42 LITERAL = 0, | |
43 | |
44 SOURCE, // {{source}} | |
45 NAME_PART, // {{source_name_part}} | |
46 FILE_PART, // {{source_file_part}} | |
47 SOURCE_DIR, // {{source_dir}} | |
48 ROOT_RELATIVE_DIR, // {{root_relative_dir}} | |
49 SOURCE_GEN_DIR, // {{source_gen_dir}} | |
50 SOURCE_OUT_DIR, // {{source_out_dir}} | |
51 | |
52 NUM_TYPES // Must be last | |
53 }; | |
54 Subrange(Type t, const std::string& l = std::string()) | |
55 : type(t), | |
56 literal(l) { | |
57 } | |
58 | |
59 Type type; | |
60 | |
61 // When type_ == LITERAL, this specifies the literal. | |
62 std::string literal; | |
63 }; | |
64 | |
65 // Constructs a template from the given value. On error, the err will be | |
66 // set. In this case you should not use this object. | |
67 FileTemplate(const Settings* settings, | |
68 const Value& t, | |
69 OutputStyle output_style, | |
70 const SourceDir& relative_to, | |
71 Err* err); | |
72 FileTemplate(const Settings* settings, | |
73 const std::vector<std::string>& t, | |
74 OutputStyle output_style, | |
75 const SourceDir& relative_to); | |
76 FileTemplate(const Settings* settings, | |
77 const std::vector<SourceFile>& t, | |
78 OutputStyle output_style, | |
79 const SourceDir& relative_to); | |
80 | |
81 ~FileTemplate(); | |
82 | |
83 // Returns an output template representing the given target's script | |
84 // outputs. | |
85 static FileTemplate GetForTargetOutputs(const Target* target); | |
86 | |
87 // Returns true if the given substitution type is used by this template. | |
88 bool IsTypeUsed(Subrange::Type type) const; | |
89 | |
90 // Returns true if there are any substitutions. | |
91 bool has_substitutions() const { return has_substitutions_; } | |
92 | |
93 // Applies the template to one source file. The results will be *appended* to | |
94 // the output. | |
95 void Apply(const SourceFile& source, | |
96 std::vector<std::string>* output) const; | |
97 | |
98 // Writes a string representing the template with Ninja variables for the | |
99 // substitutions, and the literals escaped for Ninja consumption. | |
100 // | |
101 // For example, if the input is "foo{{source_name_part}}bar" this will write | |
102 // foo${source_name_part}bar. If there are multiple templates (we were | |
103 // constucted with a list of more than one item) then the values will be | |
104 // separated by spaces. | |
105 // | |
106 // If this template is nonempty, we will first print out a space to separate | |
107 // it from the previous command. | |
108 // | |
109 // The names used for the Ninja variables will be the same ones used by | |
110 // WriteNinjaVariablesForSubstitution. You would use this to define the Ninja | |
111 // rule, and then define the variables to substitute for each file using | |
112 // WriteNinjaVariablesForSubstitution. | |
113 void WriteWithNinjaExpansions(std::ostream& out) const; | |
114 | |
115 // Writes to the given stream the variable declarations for extracting the | |
116 // required parts of the given source file string. The results will be | |
117 // indented two spaces. | |
118 // | |
119 // This is used to set up a build statement to invoke a rule where the rule | |
120 // contains a representation of this file template to be expanded by Ninja | |
121 // (see GetWithNinjaExpansions). | |
122 void WriteNinjaVariablesForSubstitution( | |
123 std::ostream& out, | |
124 const SourceFile& source, | |
125 const EscapeOptions& escape_options) const; | |
126 | |
127 // Returns the Ninja variable name used by the above Ninja functions to | |
128 // substitute for the given type. | |
129 static const char* GetNinjaVariableNameForType(Subrange::Type type); | |
130 | |
131 // Extracts the given type of substitution from the given source file. | |
132 // If output_style is OUTPUT_RELATIVE, relative_to indicates the directory | |
133 // that the relative directories should be relative to, otherwise it is | |
134 // ignored. | |
135 static std::string GetSubstitution(const Settings* settings, | |
136 const SourceFile& source, | |
137 Subrange::Type type, | |
138 OutputStyle output_style, | |
139 const SourceDir& relative_to); | |
140 | |
141 // Known template types, these include the "{{ }}". | |
142 // IF YOU ADD NEW ONES: If the expansion expands to something inside the | |
143 // output directory, also update EnsureStringIsInOutputDir. | |
144 static const char kSource[]; | |
145 static const char kSourceNamePart[]; | |
146 static const char kSourceFilePart[]; | |
147 static const char kSourceDir[]; | |
148 static const char kRootRelDir[]; | |
149 static const char kSourceGenDir[]; | |
150 static const char kSourceOutDir[]; | |
151 | |
152 private: | |
153 typedef base::StackVector<Subrange, 8> Template; | |
154 typedef base::StackVector<Template, 8> TemplateVector; | |
155 | |
156 void ParseInput(const Value& value, Err* err); | |
157 | |
158 // Parses a template string and adds it to the templates_ list. | |
159 void ParseOneTemplateString(const std::string& str); | |
160 | |
161 const Settings* settings_; | |
162 OutputStyle output_style_; | |
163 SourceDir relative_to_; | |
164 | |
165 TemplateVector templates_; | |
166 | |
167 // The corresponding value is set to true if the given subrange type is | |
168 // required. This allows us to precompute these types whem applying them | |
169 // to a given source file. | |
170 bool types_required_[Subrange::NUM_TYPES]; | |
171 | |
172 // Set when any of the types_required_ is true. Otherwise, everythins is a | |
173 // literal (a common case so we can optimize some code paths). | |
174 bool has_substitutions_; | |
175 }; | |
176 | |
177 #endif // TOOLS_GN_FILE_TEMPLATE_H_ | |
OLD | NEW |