- add sources.
[platform/framework/web/crosswalk.git] / src / tools / gn / file_template.h
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/value.h"
14
15 struct EscapeOptions;
16 class ParseNode;
17
18 extern const char kSourceExpansion_Help[];
19
20 // A FileTemplate object implements source expansion for a given "template"
21 // (either outputs or args, depending on the target type).
22 //
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
27 // substitutions.
28 class FileTemplate {
29  public:
30   struct Subrange {
31     enum Type {
32       LITERAL = 0,
33
34       // {{source}} -> expands to be the source file name relative to the build
35       // root dir.
36       SOURCE,
37
38       // {{source_name_part}} -> file name without extension or directory.
39       // Maps "foo/bar.txt" to "bar".
40       NAME_PART,
41
42       // {{source_file_part}} -> file name including extension but no directory.
43       // Maps "foo/bar.txt" to "bar.txt".
44       FILE_PART,
45
46       NUM_TYPES  // Must be last
47     };
48     Subrange(Type t, const std::string& l = std::string())
49         : type(t),
50           literal(l) {
51     }
52
53     Type type;
54
55     // When type_ == LITERAL, this specifies the literal.
56     std::string literal;
57   };
58
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);
63   ~FileTemplate();
64
65   // Returns true if the given substitution type is used by this template.
66   bool IsTypeUsed(Subrange::Type type) const;
67
68   // Returns true if there are any substitutions.
69   bool has_substitutions() const { return has_substitutions_; }
70
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,
77              Err* err) const;
78   void ApplyString(const std::string& input,
79                    std::vector<std::string>* output) const;
80
81   // Writes a string representing the template with Ninja variables for the
82   // substitutions, and the literals escaped for Ninja consumption.
83   //
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.
88   //
89   // If this template is nonempty, we will first print out a space to separate
90   // it from the previous command.
91   //
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;
97
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.
101   //
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(
106       std::ostream& out,
107       const std::string& source,
108       const EscapeOptions& escape_options) const;
109
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);
113
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);
118
119   // Known template types, these include the "{{ }}"
120   static const char kSource[];
121   static const char kSourceNamePart[];
122   static const char kSourceFilePart[];
123
124  private:
125   typedef base::StackVector<Subrange, 8> Template;
126   typedef base::StackVector<Template, 8> TemplateVector;
127
128   void ParseInput(const Value& value, Err* err);
129
130   // Parses a template string and adds it to the templates_ list.
131   void ParseOneTemplateString(const std::string& str);
132
133   TemplateVector templates_;
134
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];
139
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_;
143 };
144
145 #endif  // TOOLS_GN_FILE_TEMPLATE_H_