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