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