1// Copyright 2015 Google Inc. All rights reserved. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package cc 16 17import ( 18 "path/filepath" 19 "strings" 20 21 "github.com/google/blueprint" 22 23 "android/soong/android" 24) 25 26func init() { 27 pctx.SourcePathVariable("lexCmd", "prebuilts/build-tools/${config.HostPrebuiltTag}/bin/flex") 28 pctx.SourcePathVariable("m4Cmd", "prebuilts/build-tools/${config.HostPrebuiltTag}/bin/m4") 29 30 pctx.HostBinToolVariable("aidlCmd", "aidl-cpp") 31 pctx.HostBinToolVariable("syspropCmd", "sysprop_cpp") 32} 33 34var ( 35 lex = pctx.AndroidStaticRule("lex", 36 blueprint.RuleParams{ 37 Command: "M4=$m4Cmd $lexCmd $flags -o$out $in", 38 CommandDeps: []string{"$lexCmd", "$m4Cmd"}, 39 }, "flags") 40 41 sysprop = pctx.AndroidStaticRule("sysprop", 42 blueprint.RuleParams{ 43 Command: "$syspropCmd --header-dir=$headerOutDir --public-header-dir=$publicOutDir " + 44 "--source-dir=$srcOutDir --include-name=$includeName $in", 45 CommandDeps: []string{"$syspropCmd"}, 46 }, 47 "headerOutDir", "publicOutDir", "srcOutDir", "includeName") 48) 49 50type YaccProperties struct { 51 // list of module-specific flags that will be used for .y and .yy compiles 52 Flags []string 53 54 // whether the yacc files will produce a location.hh file 55 Gen_location_hh *bool 56 57 // whether the yacc files will product a position.hh file 58 Gen_position_hh *bool 59} 60 61func genYacc(ctx android.ModuleContext, rule *android.RuleBuilder, yaccFile android.Path, 62 outFile android.ModuleGenPath, props *YaccProperties) (headerFiles android.Paths) { 63 64 outDir := android.PathForModuleGen(ctx, "yacc") 65 headerFile := android.GenPathWithExt(ctx, "yacc", yaccFile, "h") 66 ret := android.Paths{headerFile} 67 68 cmd := rule.Command() 69 70 // Fix up #line markers to not use the sbox temporary directory 71 // android.sboxPathForOutput(outDir, outDir) returns the sbox placeholder for the out 72 // directory itself, without any filename appended. 73 sboxOutDir := cmd.PathForOutput(outDir) 74 sedCmd := "sed -i.bak 's#" + sboxOutDir + "#" + outDir.String() + "#'" 75 rule.Command().Text(sedCmd).Input(outFile) 76 rule.Command().Text(sedCmd).Input(headerFile) 77 78 var flags []string 79 if props != nil { 80 flags = props.Flags 81 82 if Bool(props.Gen_location_hh) { 83 locationHeader := outFile.InSameDir(ctx, "location.hh") 84 ret = append(ret, locationHeader) 85 cmd.ImplicitOutput(locationHeader) 86 rule.Command().Text(sedCmd).Input(locationHeader) 87 } 88 if Bool(props.Gen_position_hh) { 89 positionHeader := outFile.InSameDir(ctx, "position.hh") 90 ret = append(ret, positionHeader) 91 cmd.ImplicitOutput(positionHeader) 92 rule.Command().Text(sedCmd).Input(positionHeader) 93 } 94 } 95 96 cmd.Text("BISON_PKGDATADIR=prebuilts/build-tools/common/bison"). 97 FlagWithInput("M4=", ctx.Config().PrebuiltBuildTool(ctx, "m4")). 98 PrebuiltBuildTool(ctx, "bison"). 99 Flag("-d"). 100 Flags(flags). 101 FlagWithOutput("--defines=", headerFile). 102 Flag("-o").Output(outFile).Input(yaccFile) 103 104 return ret 105} 106 107func genAidl(ctx android.ModuleContext, rule *android.RuleBuilder, aidlFile android.Path, aidlFlags string) (cppFile android.OutputPath, headerFiles android.Paths) { 108 aidlPackage := strings.TrimSuffix(aidlFile.Rel(), aidlFile.Base()) 109 baseName := strings.TrimSuffix(aidlFile.Base(), aidlFile.Ext()) 110 shortName := baseName 111 // TODO(b/111362593): aidl_to_cpp_common.cpp uses heuristics to figure out if 112 // an interface name has a leading I. Those same heuristics have been 113 // moved here. 114 if len(baseName) >= 2 && baseName[0] == 'I' && 115 strings.ToUpper(baseName)[1] == baseName[1] { 116 shortName = strings.TrimPrefix(baseName, "I") 117 } 118 119 outDir := android.PathForModuleGen(ctx, "aidl") 120 cppFile = outDir.Join(ctx, aidlPackage, baseName+".cpp") 121 depFile := outDir.Join(ctx, aidlPackage, baseName+".cpp.d") 122 headerI := outDir.Join(ctx, aidlPackage, baseName+".h") 123 headerBn := outDir.Join(ctx, aidlPackage, "Bn"+shortName+".h") 124 headerBp := outDir.Join(ctx, aidlPackage, "Bp"+shortName+".h") 125 126 baseDir := strings.TrimSuffix(aidlFile.String(), aidlFile.Rel()) 127 if baseDir != "" { 128 aidlFlags += " -I" + baseDir 129 } 130 131 cmd := rule.Command() 132 cmd.BuiltTool("aidl-cpp"). 133 FlagWithDepFile("-d", depFile). 134 Flag("--ninja"). 135 Flag(aidlFlags). 136 Input(aidlFile). 137 OutputDir(). 138 Output(cppFile). 139 ImplicitOutputs(android.WritablePaths{ 140 headerI, 141 headerBn, 142 headerBp, 143 }) 144 145 return cppFile, android.Paths{ 146 headerI, 147 headerBn, 148 headerBp, 149 } 150} 151 152type LexProperties struct { 153 // list of module-specific flags that will be used for .l and .ll compiles 154 Flags []string 155} 156 157func genLex(ctx android.ModuleContext, lexFile android.Path, outFile android.ModuleGenPath, props *LexProperties) { 158 var flags []string 159 if props != nil { 160 flags = props.Flags 161 } 162 flagsString := strings.Join(flags[:], " ") 163 ctx.Build(pctx, android.BuildParams{ 164 Rule: lex, 165 Description: "lex " + lexFile.Rel(), 166 Output: outFile, 167 Input: lexFile, 168 Args: map[string]string{"flags": flagsString}, 169 }) 170} 171 172func genSysprop(ctx android.ModuleContext, syspropFile android.Path) (android.Path, android.Paths) { 173 headerFile := android.PathForModuleGen(ctx, "sysprop", "include", syspropFile.Rel()+".h") 174 publicHeaderFile := android.PathForModuleGen(ctx, "sysprop/public", "include", syspropFile.Rel()+".h") 175 cppFile := android.PathForModuleGen(ctx, "sysprop", syspropFile.Rel()+".cpp") 176 177 headers := android.WritablePaths{headerFile, publicHeaderFile} 178 179 ctx.Build(pctx, android.BuildParams{ 180 Rule: sysprop, 181 Description: "sysprop " + syspropFile.Rel(), 182 Output: cppFile, 183 ImplicitOutputs: headers, 184 Input: syspropFile, 185 Args: map[string]string{ 186 "headerOutDir": filepath.Dir(headerFile.String()), 187 "publicOutDir": filepath.Dir(publicHeaderFile.String()), 188 "srcOutDir": filepath.Dir(cppFile.String()), 189 "includeName": syspropFile.Rel() + ".h", 190 }, 191 }) 192 193 return cppFile, headers.Paths() 194} 195 196// Used to communicate information from the genSources method back to the library code that uses 197// it. 198type generatedSourceInfo struct { 199 // The headers created from .proto files 200 protoHeaders android.Paths 201 202 // The files that can be used as order only dependencies in order to ensure that the proto header 203 // files are up to date. 204 protoOrderOnlyDeps android.Paths 205 206 // The headers created from .aidl files 207 aidlHeaders android.Paths 208 209 // The files that can be used as order only dependencies in order to ensure that the aidl header 210 // files are up to date. 211 aidlOrderOnlyDeps android.Paths 212 213 // The headers created from .sysprop files 214 syspropHeaders android.Paths 215 216 // The files that can be used as order only dependencies in order to ensure that the sysprop 217 // header files are up to date. 218 syspropOrderOnlyDeps android.Paths 219} 220 221func genSources(ctx android.ModuleContext, srcFiles android.Paths, 222 buildFlags builderFlags) (android.Paths, android.Paths, generatedSourceInfo) { 223 224 var info generatedSourceInfo 225 226 var deps android.Paths 227 var rsFiles android.Paths 228 229 var aidlRule *android.RuleBuilder 230 231 var yaccRule_ *android.RuleBuilder 232 yaccRule := func() *android.RuleBuilder { 233 if yaccRule_ == nil { 234 yaccRule_ = android.NewRuleBuilder(pctx, ctx).Sbox(android.PathForModuleGen(ctx, "yacc"), 235 android.PathForModuleGen(ctx, "yacc.sbox.textproto")) 236 } 237 return yaccRule_ 238 } 239 240 for i, srcFile := range srcFiles { 241 switch srcFile.Ext() { 242 case ".y": 243 cFile := android.GenPathWithExt(ctx, "yacc", srcFile, "c") 244 srcFiles[i] = cFile 245 deps = append(deps, genYacc(ctx, yaccRule(), srcFile, cFile, buildFlags.yacc)...) 246 case ".yy": 247 cppFile := android.GenPathWithExt(ctx, "yacc", srcFile, "cpp") 248 srcFiles[i] = cppFile 249 deps = append(deps, genYacc(ctx, yaccRule(), srcFile, cppFile, buildFlags.yacc)...) 250 case ".l": 251 cFile := android.GenPathWithExt(ctx, "lex", srcFile, "c") 252 srcFiles[i] = cFile 253 genLex(ctx, srcFile, cFile, buildFlags.lex) 254 case ".ll": 255 cppFile := android.GenPathWithExt(ctx, "lex", srcFile, "cpp") 256 srcFiles[i] = cppFile 257 genLex(ctx, srcFile, cppFile, buildFlags.lex) 258 case ".proto": 259 ccFile, headerFile := genProto(ctx, srcFile, buildFlags) 260 srcFiles[i] = ccFile 261 info.protoHeaders = append(info.protoHeaders, headerFile) 262 // Use the generated header as an order only dep to ensure that it is up to date when needed. 263 info.protoOrderOnlyDeps = append(info.protoOrderOnlyDeps, headerFile) 264 case ".aidl": 265 if aidlRule == nil { 266 aidlRule = android.NewRuleBuilder(pctx, ctx).Sbox(android.PathForModuleGen(ctx, "aidl"), 267 android.PathForModuleGen(ctx, "aidl.sbox.textproto")) 268 } 269 cppFile, aidlHeaders := genAidl(ctx, aidlRule, srcFile, buildFlags.aidlFlags) 270 srcFiles[i] = cppFile 271 272 info.aidlHeaders = append(info.aidlHeaders, aidlHeaders...) 273 // Use the generated headers as order only deps to ensure that they are up to date when 274 // needed. 275 // TODO: Reduce the size of the ninja file by using one order only dep for the whole rule 276 info.aidlOrderOnlyDeps = append(info.aidlOrderOnlyDeps, aidlHeaders...) 277 case ".rscript", ".fs": 278 cppFile := rsGeneratedCppFile(ctx, srcFile) 279 rsFiles = append(rsFiles, srcFiles[i]) 280 srcFiles[i] = cppFile 281 case ".sysprop": 282 cppFile, headerFiles := genSysprop(ctx, srcFile) 283 srcFiles[i] = cppFile 284 info.syspropHeaders = append(info.syspropHeaders, headerFiles...) 285 // Use the generated headers as order only deps to ensure that they are up to date when 286 // needed. 287 info.syspropOrderOnlyDeps = append(info.syspropOrderOnlyDeps, headerFiles...) 288 } 289 } 290 291 if aidlRule != nil { 292 aidlRule.Build("aidl", "gen aidl") 293 } 294 295 if yaccRule_ != nil { 296 yaccRule_.Build("yacc", "gen yacc") 297 } 298 299 deps = append(deps, info.protoOrderOnlyDeps...) 300 deps = append(deps, info.aidlOrderOnlyDeps...) 301 deps = append(deps, info.syspropOrderOnlyDeps...) 302 303 if len(rsFiles) > 0 { 304 deps = append(deps, rsGenerateCpp(ctx, rsFiles, buildFlags.rsFlags)...) 305 } 306 307 return srcFiles, deps, info 308} 309