summaryrefslogtreecommitdiffstats
path: root/tools/gn/substitution_writer.h
blob: a450bbbc03c02f0ce13b8eb0cf0999705aac382d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef TOOLS_GN_SUBSTITUTION_WRITER_H_
#define TOOLS_GN_SUBSTITUTION_WRITER_H_

#include <iosfwd>
#include <vector>

#include "tools/gn/substitution_type.h"

struct EscapeOptions;
class OutputFile;
class Settings;
class SourceDir;
class SourceFile;
class SubstitutionList;
class SubstitutionPattern;
class Target;
class Tool;

// Help text for script source expansion.
extern const char kSourceExpansion_Help[];

// This class handles writing or applying substitution patterns to strings.
//
// There are several different uses:
//
//  - Source substitutions: These are used to compute action_foreach
//    outputs and arguments. Functions are provided to expand these in terms
//    of both OutputFiles (for writing Ninja files) as well as SourceFiles
//    (for computing lists used by code).
//
//  - Target substitutions: These are specific to the target+tool combination
//    and are shared between the compiler and linker ones. It includes things
//    like the target_gen_dir.
//
//  - Compiler substitutions: These are used to compute compiler outputs.
//    It includes all source substitutions (since they depend on the various
//    parts of the source file) as well as the target substitutions.
//
//  - Linker substitutions: These are used to compute linker outputs. It
//    includes the target substitutions.
//
// The compiler and linker specific substitutions do NOT include the various
// cflags, ldflags, libraries, etc. These are written by the ninja target
// writer since they depend on traversing the dependency tree.
class SubstitutionWriter {
 public:
  enum OutputStyle {
    OUTPUT_ABSOLUTE,  // Dirs will be absolute "//foo/bar".
    OUTPUT_RELATIVE,  // Dirs will be relative to a given directory.
  };

  // Writes the pattern to the given stream with no special handling, and with
  // Ninja variables replacing the patterns.
  static void WriteWithNinjaVariables(
      const SubstitutionPattern& pattern,
      const EscapeOptions& escape_options,
      std::ostream& out);

  // NOP substitutions ---------------------------------------------------------

  // Converts the given SubstitutionList to OutputFiles assuming there are
  // no substitutions (it will assert if there are). This is used for cases
  // like actions where the outputs are explicit, but the list is stored as
  // a SubstitutionList.
  static void GetListAsSourceFiles(
      const SubstitutionList& list,
      std::vector<SourceFile>* output);
  static void GetListAsOutputFiles(
      const Settings* settings,
      const SubstitutionList& list,
      std::vector<OutputFile>* output);

  // Source substitutions -----------------------------------------------------

  // Applies the substitution pattern to a source file, returning the result
  // as either a string, a SourceFile or an OutputFile. If the result is
  // expected to be a SourceFile or an OutputFile, this will CHECK if the
  // result isn't in the correct directory. The caller should validate this
  // first (see for example IsFileInOuputDir).
  static SourceFile ApplyPatternToSource(
      const Settings* settings,
      const SubstitutionPattern& pattern,
      const SourceFile& source);
  static std::string ApplyPatternToSourceAsString(
      const Settings* settings,
      const SubstitutionPattern& pattern,
      const SourceFile& source);
  static OutputFile ApplyPatternToSourceAsOutputFile(
      const Settings* settings,
      const SubstitutionPattern& pattern,
      const SourceFile& source);

  // Applies the substitution list to a source, APPENDING the result to the
  // given output vector. It works this way so one can call multiple times to
  // apply to multiple files and create a list. The result can either be
  // SourceFiles or OutputFiles.
  static void ApplyListToSource(
      const Settings* settings,
      const SubstitutionList& list,
      const SourceFile& source,
      std::vector<SourceFile>* output);
  static void ApplyListToSourceAsString(
      const Settings* settings,
      const SubstitutionList& list,
      const SourceFile& source,
      std::vector<std::string>* output);
  static void ApplyListToSourceAsOutputFile(
      const Settings* settings,
      const SubstitutionList& list,
      const SourceFile& source,
      std::vector<OutputFile>* output);

  // Like ApplyListToSource but applies the list to all sources and replaces
  // rather than appends the output (this produces the complete output).
  static void ApplyListToSources(
      const Settings* settings,
      const SubstitutionList& list,
      const std::vector<SourceFile>& sources,
      std::vector<SourceFile>* output);
  static void ApplyListToSourcesAsString(
      const Settings* settings,
      const SubstitutionList& list,
      const std::vector<SourceFile>& sources,
      std::vector<std::string>* output);
  static void ApplyListToSourcesAsOutputFile(
      const Settings* settings,
      const SubstitutionList& list,
      const std::vector<SourceFile>& sources,
      std::vector<OutputFile>* output);

  // Given a list of source replacement types used, writes the Ninja variable
  // definitions for the given source file to use for those replacements. The
  // variables will be indented two spaces. Since this is for writing to
  // Ninja files, paths will be relative to the build dir, and no definition
  // for {{source}} will be written since that maps to Ninja's implicit $in
  // variable.
  static void WriteNinjaVariablesForSource(
      const Settings* settings,
      const SourceFile& source,
      const std::vector<SubstitutionType>& types,
      const EscapeOptions& escape_options,
      std::ostream& out);

  // Extracts the given type of substitution related to a source file from the
  // given source file. If output_style is OUTPUT_RELATIVE, relative_to
  // indicates the directory that the relative directories should be relative
  // to, otherwise it is ignored.
  static std::string GetSourceSubstitution(
      const Settings* settings,
      const SourceFile& source,
      SubstitutionType type,
      OutputStyle output_style,
      const SourceDir& relative_to);

  // Target substitutions ------------------------------------------------------
  //
  // Handles the target substitutions that apply to both compiler and linker
  // tools.
  static OutputFile ApplyPatternToTargetAsOutputFile(
      const Target* target,
      const Tool* tool,
      const SubstitutionPattern& pattern);
  static void ApplyListToTargetAsOutputFile(
      const Target* target,
      const Tool* tool,
      const SubstitutionList& list,
      std::vector<OutputFile>* output);

  // This function is slightly different than the other substitution getters
  // since it can handle failure (since it is designed to be used by the
  // compiler and linker ones which will fall through if it's not a common tool
  // one).
  static bool GetTargetSubstitution(
      const Target* target,
      SubstitutionType type,
      std::string* result);
  static std::string GetTargetSubstitution(
      const Target* target,
      SubstitutionType type);

  // Compiler substitutions ----------------------------------------------------
  //
  // A compiler substitution allows both source and tool substitutions. These
  // are used to compute output names for compiler tools.

  static OutputFile ApplyPatternToCompilerAsOutputFile(
      const Target* target,
      const SourceFile& source,
      const SubstitutionPattern& pattern);
  static void ApplyListToCompilerAsOutputFile(
      const Target* target,
      const SourceFile& source,
      const SubstitutionList& list,
      std::vector<OutputFile>* output);

  // Like GetSourceSubstitution but for strings based on the target or
  // toolchain. This type of result will always be relative to the build
  // directory.
  static std::string GetCompilerSubstitution(
      const Target* target,
      const SourceFile& source,
      SubstitutionType type);

  // Linker substitutions ------------------------------------------------------

  static OutputFile ApplyPatternToLinkerAsOutputFile(
      const Target* target,
      const Tool* tool,
      const SubstitutionPattern& pattern);
  static void ApplyListToLinkerAsOutputFile(
      const Target* target,
      const Tool* tool,
      const SubstitutionList& list,
      std::vector<OutputFile>* output);

  // Like GetSourceSubstitution but for strings based on the target or
  // toolchain. This type of result will always be relative to the build
  // directory.
  static std::string GetLinkerSubstitution(
      const Target* target,
      const Tool* tool,
      SubstitutionType type);
};

#endif  // TOOLS_GN_SUBSTITUTION_WRITER_H_