1// Copyright 2014 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_SUBSTITUTION_WRITER_H_
6#define TOOLS_GN_SUBSTITUTION_WRITER_H_
7
8#include <iosfwd>
9#include <vector>
10
11#include "base/basictypes.h"
12#include "tools/gn/substitution_type.h"
13
14struct EscapeOptions;
15class OutputFile;
16class Settings;
17class SourceDir;
18class SourceFile;
19class SubstitutionList;
20class SubstitutionPattern;
21class Target;
22class Tool;
23
24// Help text for script source expansion.
25extern const char kSourceExpansion_Help[];
26
27// This class handles writing or applying substitution patterns to strings.
28//
29// There are several different uses:
30//
31//  - Source substitutions: These are used to compute action_foreach
32//    outputs and arguments. Functions are provided to expand these in terms
33//    of both OutputFiles (for writing Ninja files) as well as SourceFiles
34//    (for computing lists used by code).
35//
36//  - Target substitutions: These are specific to the target+tool combination
37//    and are shared between the compiler and linker ones. It includes things
38//    like the target_gen_dir.
39//
40//  - Compiler substitutions: These are used to compute compiler outputs.
41//    It includes all source substitutions (since they depend on the various
42//    parts of the source file) as well as the target substitutions.
43//
44//  - Linker substitutions: These are used to compute linker outputs. It
45//    includes the target substitutions.
46//
47// The compiler and linker specific substitutions do NOT include the various
48// cflags, ldflags, libraries, etc. These are written by the ninja target
49// writer since they depend on traversing the dependency tree.
50class SubstitutionWriter {
51 public:
52  enum OutputStyle {
53    OUTPUT_ABSOLUTE,  // Dirs will be absolute "//foo/bar".
54    OUTPUT_RELATIVE,  // Dirs will be relative to a given directory.
55  };
56
57  // Writes the pattern to the given stream with no special handling, and with
58  // Ninja variables replacing the patterns.
59  static void WriteWithNinjaVariables(
60      const SubstitutionPattern& pattern,
61      const EscapeOptions& escape_options,
62      std::ostream& out);
63
64  // NOP substitutions ---------------------------------------------------------
65
66  // Converts the given SubstitutionList to OutputFiles assuming there are
67  // no substitutions (it will assert if there are). This is used for cases
68  // like actions where the outputs are explicit, but the list is stored as
69  // a SubstitutionList.
70  static void GetListAsSourceFiles(
71      const SubstitutionList& list,
72      std::vector<SourceFile>* output);
73  static void GetListAsOutputFiles(
74      const Settings* settings,
75      const SubstitutionList& list,
76      std::vector<OutputFile>* output);
77
78  // Source substitutions -----------------------------------------------------
79
80  // Applies the substitution pattern to a source file, returning the result
81  // as either a string, a SourceFile or an OutputFile. If the result is
82  // expected to be a SourceFile or an OutputFile, this will CHECK if the
83  // result isn't in the correct directory. The caller should validate this
84  // first (see for example IsFileInOuputDir).
85  static SourceFile ApplyPatternToSource(
86      const Settings* settings,
87      const SubstitutionPattern& pattern,
88      const SourceFile& source);
89  static std::string ApplyPatternToSourceAsString(
90      const Settings* settings,
91      const SubstitutionPattern& pattern,
92      const SourceFile& source);
93  static OutputFile ApplyPatternToSourceAsOutputFile(
94      const Settings* settings,
95      const SubstitutionPattern& pattern,
96      const SourceFile& source);
97
98  // Applies the substitution list to a source, APPENDING the result to the
99  // given output vector. It works this way so one can call multiple times to
100  // apply to multiple files and create a list. The result can either be
101  // SourceFiles or OutputFiles.
102  static void ApplyListToSource(
103      const Settings* settings,
104      const SubstitutionList& list,
105      const SourceFile& source,
106      std::vector<SourceFile>* output);
107  static void ApplyListToSourceAsString(
108      const Settings* settings,
109      const SubstitutionList& list,
110      const SourceFile& source,
111      std::vector<std::string>* output);
112  static void ApplyListToSourceAsOutputFile(
113      const Settings* settings,
114      const SubstitutionList& list,
115      const SourceFile& source,
116      std::vector<OutputFile>* output);
117
118  // Like ApplyListToSource but applies the list to all sources and replaces
119  // rather than appesnds the output (this produces the complete output).
120  static void ApplyListToSources(
121      const Settings* settings,
122      const SubstitutionList& list,
123      const std::vector<SourceFile>& sources,
124      std::vector<SourceFile>* output);
125  static void ApplyListToSourcesAsString(
126      const Settings* settings,
127      const SubstitutionList& list,
128      const std::vector<SourceFile>& sources,
129      std::vector<std::string>* output);
130  static void ApplyListToSourcesAsOutputFile(
131      const Settings* settings,
132      const SubstitutionList& list,
133      const std::vector<SourceFile>& sources,
134      std::vector<OutputFile>* output);
135
136  // Given a list of source replacement types used, writes the Ninja variable
137  // definitions for the given source file to use for those replacements. The
138  // variables will be indented two spaces. Since this is for writing to
139  // Ninja files, paths will be relative to the build dir, and no definition
140  // for {{source}} will be written since that maps to Ninja's implicit $in
141  // variable.
142  static void WriteNinjaVariablesForSource(
143      const Settings* settings,
144      const SourceFile& source,
145      const std::vector<SubstitutionType>& types,
146      const EscapeOptions& escape_options,
147      std::ostream& out);
148
149  // Extracts the given type of substitution related to a source file from the
150  // given source file. If output_style is OUTPUT_RELATIVE, relative_to
151  // indicates the directory that the relative directories should be relative
152  // to, otherwise it is ignored.
153  static std::string GetSourceSubstitution(
154      const Settings* settings,
155      const SourceFile& source,
156      SubstitutionType type,
157      OutputStyle output_style,
158      const SourceDir& relative_to);
159
160  // Target substitutions ------------------------------------------------------
161  //
162  // Handles the target substitutions that apply to both compiler and linker
163  // tools.
164  static OutputFile ApplyPatternToTargetAsOutputFile(
165      const Target* target,
166      const Tool* tool,
167      const SubstitutionPattern& pattern);
168  static void ApplyListToTargetAsOutputFile(
169      const Target* target,
170      const Tool* tool,
171      const SubstitutionList& list,
172      std::vector<OutputFile>* output);
173
174  // This function is slightly different than the other substitution getters
175  // since it can handle failure (since it is designed to be used by the
176  // compiler and linker ones which will fall through if it's not a common tool
177  // one).
178  static bool GetTargetSubstitution(
179      const Target* target,
180      SubstitutionType type,
181      std::string* result);
182  static std::string GetTargetSubstitution(
183      const Target* target,
184      SubstitutionType type);
185
186  // Compiler substitutions ----------------------------------------------------
187  //
188  // A compiler substitution allows both source and tool substitutions. These
189  // are used to compute output names for compiler tools.
190
191  static OutputFile ApplyPatternToCompilerAsOutputFile(
192      const Target* target,
193      const SourceFile& source,
194      const SubstitutionPattern& pattern);
195  static void ApplyListToCompilerAsOutputFile(
196      const Target* target,
197      const SourceFile& source,
198      const SubstitutionList& list,
199      std::vector<OutputFile>* output);
200
201  // Like GetSourceSubstitution but for strings based on the target or
202  // toolchain. This type of result will always be relative to the build
203  // directory.
204  static std::string GetCompilerSubstitution(
205      const Target* target,
206      const SourceFile& source,
207      SubstitutionType type);
208
209  // Linker substitutions ------------------------------------------------------
210
211  static OutputFile ApplyPatternToLinkerAsOutputFile(
212      const Target* target,
213      const Tool* tool,
214      const SubstitutionPattern& pattern);
215  static void ApplyListToLinkerAsOutputFile(
216      const Target* target,
217      const Tool* tool,
218      const SubstitutionList& list,
219      std::vector<OutputFile>* output);
220
221  // Like GetSourceSubstitution but for strings based on the target or
222  // toolchain. This type of result will always be relative to the build
223  // directory.
224  static std::string GetLinkerSubstitution(
225      const Target* target,
226      const Tool* tool,
227      SubstitutionType type);
228};
229
230#endif  // TOOLS_GN_SUBSTITUTION_WRITER_H_
231