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