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 "android/soong/aidl_library" 22 "github.com/google/blueprint" 23 24 "android/soong/android" 25) 26 27func init() { 28 pctx.SourcePathVariable("lexCmd", "prebuilts/build-tools/${config.HostPrebuiltTag}/bin/flex") 29 pctx.SourcePathVariable("m4Cmd", "prebuilts/build-tools/${config.HostPrebuiltTag}/bin/m4") 30 31 pctx.HostBinToolVariable("aidlCmd", "aidl-cpp") 32 pctx.HostBinToolVariable("syspropCmd", "sysprop_cpp") 33} 34 35var ( 36 lex = pctx.AndroidStaticRule("lex", 37 blueprint.RuleParams{ 38 Command: "M4=$m4Cmd $lexCmd $flags -o$out $in", 39 CommandDeps: []string{"$lexCmd", "$m4Cmd"}, 40 }, "flags") 41 42 sysprop = pctx.AndroidStaticRule("sysprop", 43 blueprint.RuleParams{ 44 Command: "$syspropCmd --header-dir=$headerOutDir --public-header-dir=$publicOutDir " + 45 "--source-dir=$srcOutDir --include-name=$includeName $in", 46 CommandDeps: []string{"$syspropCmd"}, 47 }, 48 "headerOutDir", "publicOutDir", "srcOutDir", "includeName") 49) 50 51type YaccProperties struct { 52 // list of module-specific flags that will be used for .y and .yy compiles 53 Flags []string 54 55 // whether the yacc files will produce a location.hh file 56 Gen_location_hh *bool 57 58 // whether the yacc files will product a position.hh file 59 Gen_position_hh *bool 60} 61 62func genYacc(ctx android.ModuleContext, rule *android.RuleBuilder, yaccFile android.Path, 63 outFile android.ModuleGenPath, props *YaccProperties) (headerFiles android.Paths) { 64 65 outDir := android.PathForModuleGen(ctx, "yacc") 66 headerFile := android.GenPathWithExt(ctx, "yacc", yaccFile, "h") 67 ret := android.Paths{headerFile} 68 69 cmd := rule.Command() 70 71 // Fix up #line markers to not use the sbox temporary directory 72 // android.sboxPathForOutput(outDir, outDir) returns the sbox placeholder for the out 73 // directory itself, without any filename appended. 74 sboxOutDir := cmd.PathForOutput(outDir) 75 sedCmd := "sed -i.bak 's#" + sboxOutDir + "#" + outDir.String() + "#'" 76 rule.Command().Text(sedCmd).Input(outFile) 77 rule.Command().Text(sedCmd).Input(headerFile) 78 79 var flags []string 80 if props != nil { 81 flags = props.Flags 82 83 if Bool(props.Gen_location_hh) { 84 locationHeader := outFile.InSameDir(ctx, "location.hh") 85 ret = append(ret, locationHeader) 86 cmd.ImplicitOutput(locationHeader) 87 rule.Command().Text(sedCmd).Input(locationHeader) 88 } 89 if Bool(props.Gen_position_hh) { 90 positionHeader := outFile.InSameDir(ctx, "position.hh") 91 ret = append(ret, positionHeader) 92 cmd.ImplicitOutput(positionHeader) 93 rule.Command().Text(sedCmd).Input(positionHeader) 94 } 95 } 96 97 cmd.Text("BISON_PKGDATADIR=prebuilts/build-tools/common/bison"). 98 FlagWithInput("M4=", ctx.Config().PrebuiltBuildTool(ctx, "m4")). 99 PrebuiltBuildTool(ctx, "bison"). 100 Flag("-d"). 101 Flags(flags). 102 FlagWithOutput("--defines=", headerFile). 103 Flag("-o").Output(outFile).Input(yaccFile) 104 105 return ret 106} 107 108func genAidl( 109 ctx android.ModuleContext, 110 rule *android.RuleBuilder, 111 outDirBase string, 112 aidlFile android.Path, 113 aidlHdrs android.Paths, 114 aidlFlags string, 115) (cppFile android.OutputPath, headerFiles android.Paths) { 116 aidlPackage := strings.TrimSuffix(aidlFile.Rel(), aidlFile.Base()) 117 baseName := strings.TrimSuffix(aidlFile.Base(), aidlFile.Ext()) 118 shortName := baseName 119 // TODO(b/111362593): aidl_to_cpp_common.cpp uses heuristics to figure out if 120 // an interface name has a leading I. Those same heuristics have been 121 // moved here. 122 if len(baseName) >= 2 && baseName[0] == 'I' && 123 strings.ToUpper(baseName)[1] == baseName[1] { 124 shortName = strings.TrimPrefix(baseName, "I") 125 } 126 127 outDir := android.PathForModuleGen(ctx, outDirBase) 128 cppFile = outDir.Join(ctx, aidlPackage, baseName+".cpp") 129 depFile := outDir.Join(ctx, aidlPackage, baseName+".cpp.d") 130 headerI := outDir.Join(ctx, aidlPackage, baseName+".h") 131 headerBn := outDir.Join(ctx, aidlPackage, "Bn"+shortName+".h") 132 headerBp := outDir.Join(ctx, aidlPackage, "Bp"+shortName+".h") 133 134 cmd := rule.Command() 135 cmd.BuiltTool("aidl-cpp"). 136 // libc++ is default stl for aidl-cpp (a cc_binary_host module) 137 ImplicitTool(ctx.Config().HostCcSharedLibPath(ctx, "libc++")). 138 FlagWithDepFile("-d", depFile). 139 Flag("--ninja"). 140 Flag(aidlFlags). 141 Input(aidlFile). 142 OutputDir(). 143 Output(cppFile). 144 ImplicitOutputs(android.WritablePaths{ 145 headerI, 146 headerBn, 147 headerBp, 148 }) 149 150 if aidlHdrs != nil { 151 cmd.Implicits(aidlHdrs) 152 } 153 154 return cppFile, android.Paths{ 155 headerI, 156 headerBn, 157 headerBp, 158 } 159} 160 161type LexProperties struct { 162 // list of module-specific flags that will be used for .l and .ll compiles 163 Flags []string 164} 165 166func genLex(ctx android.ModuleContext, lexFile android.Path, outFile android.ModuleGenPath, props *LexProperties) { 167 var flags []string 168 if props != nil { 169 flags = props.Flags 170 } 171 flagsString := strings.Join(flags[:], " ") 172 ctx.Build(pctx, android.BuildParams{ 173 Rule: lex, 174 Description: "lex " + lexFile.Rel(), 175 Output: outFile, 176 Input: lexFile, 177 Args: map[string]string{"flags": flagsString}, 178 }) 179} 180 181func genSysprop(ctx android.ModuleContext, syspropFile android.Path) (android.Path, android.Paths) { 182 headerFile := android.PathForModuleGen(ctx, "sysprop", "include", syspropFile.Rel()+".h") 183 publicHeaderFile := android.PathForModuleGen(ctx, "sysprop/public", "include", syspropFile.Rel()+".h") 184 cppFile := android.PathForModuleGen(ctx, "sysprop", syspropFile.Rel()+".cpp") 185 186 headers := android.WritablePaths{headerFile, publicHeaderFile} 187 188 ctx.Build(pctx, android.BuildParams{ 189 Rule: sysprop, 190 Description: "sysprop " + syspropFile.Rel(), 191 Output: cppFile, 192 ImplicitOutputs: headers, 193 Input: syspropFile, 194 Args: map[string]string{ 195 "headerOutDir": filepath.Dir(headerFile.String()), 196 "publicOutDir": filepath.Dir(publicHeaderFile.String()), 197 "srcOutDir": filepath.Dir(cppFile.String()), 198 "includeName": syspropFile.Rel() + ".h", 199 }, 200 }) 201 202 return cppFile, headers.Paths() 203} 204 205// Used to communicate information from the genSources method back to the library code that uses 206// it. 207type generatedSourceInfo struct { 208 // The headers created from .proto files 209 protoHeaders android.Paths 210 211 // The files that can be used as order only dependencies in order to ensure that the proto header 212 // files are up to date. 213 protoOrderOnlyDeps android.Paths 214 215 // The headers created from .aidl files 216 aidlHeaders android.Paths 217 218 // The files that can be used as order only dependencies in order to ensure that the aidl header 219 // files are up to date. 220 aidlOrderOnlyDeps android.Paths 221 222 // The headers created from .sysprop files 223 syspropHeaders android.Paths 224 225 // The files that can be used as order only dependencies in order to ensure that the sysprop 226 // header files are up to date. 227 syspropOrderOnlyDeps android.Paths 228 229 // List of generated code path. 230 // ex) '*.cpp' files generated from '*.ll / *.yy'. 231 generatedSources android.Paths 232} 233 234func genSources( 235 ctx android.ModuleContext, 236 aidlLibraryInfos []aidl_library.AidlLibraryInfo, 237 srcFiles android.Paths, 238 buildFlags builderFlags, 239) (android.Paths, android.Paths, generatedSourceInfo) { 240 241 var info generatedSourceInfo 242 243 var deps android.Paths 244 var rsFiles android.Paths 245 246 // aidlRule supports compiling aidl files from srcs prop while aidlLibraryRule supports 247 // compiling aidl files from aidl_library modules specified in aidl.libs prop. 248 // The rules are separated so that they don't wipe out the other's outputDir 249 var aidlRule *android.RuleBuilder 250 var aidlLibraryRule *android.RuleBuilder 251 252 var yaccRule_ *android.RuleBuilder 253 yaccRule := func() *android.RuleBuilder { 254 if yaccRule_ == nil { 255 yaccRule_ = android.NewRuleBuilder(pctx, ctx).Sbox(android.PathForModuleGen(ctx, "yacc"), 256 android.PathForModuleGen(ctx, "yacc.sbox.textproto")) 257 } 258 return yaccRule_ 259 } 260 261 var generatedSources android.Paths = nil 262 263 for i, srcFile := range srcFiles { 264 switch srcFile.Ext() { 265 case ".y": 266 cFile := android.GenPathWithExt(ctx, "yacc", srcFile, "c") 267 srcFiles[i] = cFile 268 deps = append(deps, genYacc(ctx, yaccRule(), srcFile, cFile, buildFlags.yacc)...) 269 generatedSources = append(generatedSources, cFile) 270 case ".yy": 271 cppFile := android.GenPathWithExt(ctx, "yacc", srcFile, "cpp") 272 srcFiles[i] = cppFile 273 deps = append(deps, genYacc(ctx, yaccRule(), srcFile, cppFile, buildFlags.yacc)...) 274 generatedSources = append(generatedSources, cppFile) 275 case ".l": 276 cFile := android.GenPathWithExt(ctx, "lex", srcFile, "c") 277 srcFiles[i] = cFile 278 genLex(ctx, srcFile, cFile, buildFlags.lex) 279 generatedSources = append(generatedSources, cFile) 280 case ".ll": 281 cppFile := android.GenPathWithExt(ctx, "lex", srcFile, "cpp") 282 srcFiles[i] = cppFile 283 genLex(ctx, srcFile, cppFile, buildFlags.lex) 284 generatedSources = append(generatedSources, cppFile) 285 case ".proto": 286 ccFile, headerFile := genProto(ctx, srcFile, buildFlags) 287 srcFiles[i] = ccFile 288 info.protoHeaders = append(info.protoHeaders, headerFile) 289 // Use the generated header as an order only dep to ensure that it is up to date when needed. 290 info.protoOrderOnlyDeps = append(info.protoOrderOnlyDeps, headerFile) 291 generatedSources = append(generatedSources, ccFile) 292 case ".aidl": 293 if aidlRule == nil { 294 aidlRule = android.NewRuleBuilder(pctx, ctx).Sbox(android.PathForModuleGen(ctx, "aidl"), 295 android.PathForModuleGen(ctx, "aidl.sbox.textproto")) 296 } 297 baseDir := strings.TrimSuffix(srcFile.String(), srcFile.Rel()) 298 cppFile, aidlHeaders := genAidl( 299 ctx, 300 aidlRule, 301 "aidl", 302 srcFile, 303 nil, 304 buildFlags.aidlFlags+" -I"+baseDir, 305 ) 306 srcFiles[i] = cppFile 307 308 info.aidlHeaders = append(info.aidlHeaders, aidlHeaders...) 309 // Use the generated headers as order only deps to ensure that they are up to date when 310 // needed. 311 // TODO: Reduce the size of the ninja file by using one order only dep for the whole rule 312 info.aidlOrderOnlyDeps = append(info.aidlOrderOnlyDeps, aidlHeaders...) 313 generatedSources = append(generatedSources, cppFile) 314 case ".rscript", ".fs": 315 cppFile := rsGeneratedCppFile(ctx, srcFile) 316 rsFiles = append(rsFiles, srcFiles[i]) 317 srcFiles[i] = cppFile 318 generatedSources = append(generatedSources, cppFile) 319 case ".sysprop": 320 cppFile, headerFiles := genSysprop(ctx, srcFile) 321 srcFiles[i] = cppFile 322 info.syspropHeaders = append(info.syspropHeaders, headerFiles...) 323 // Use the generated headers as order only deps to ensure that they are up to date when 324 // needed. 325 info.syspropOrderOnlyDeps = append(info.syspropOrderOnlyDeps, headerFiles...) 326 generatedSources = append(generatedSources, cppFile) 327 } 328 } 329 330 info.generatedSources = generatedSources 331 332 for _, aidlLibraryInfo := range aidlLibraryInfos { 333 if aidlLibraryRule == nil { 334 aidlLibraryRule = android.NewRuleBuilder(pctx, ctx).Sbox( 335 android.PathForModuleGen(ctx, "aidl_library"), 336 android.PathForModuleGen(ctx, "aidl_library.sbox.textproto"), 337 ).SandboxInputs() 338 } 339 for _, aidlSrc := range aidlLibraryInfo.Srcs { 340 cppFile, aidlHeaders := genAidl( 341 ctx, 342 aidlLibraryRule, 343 "aidl_library", 344 aidlSrc, 345 aidlLibraryInfo.Hdrs.ToList(), 346 buildFlags.aidlFlags, 347 ) 348 349 srcFiles = append(srcFiles, cppFile) 350 info.aidlHeaders = append(info.aidlHeaders, aidlHeaders...) 351 // Use the generated headers as order only deps to ensure that they are up to date when 352 // needed. 353 // TODO: Reduce the size of the ninja file by using one order only dep for the whole rule 354 info.aidlOrderOnlyDeps = append(info.aidlOrderOnlyDeps, aidlHeaders...) 355 } 356 } 357 358 if aidlRule != nil { 359 aidlRule.Build("aidl", "gen aidl") 360 } 361 362 if aidlLibraryRule != nil { 363 aidlLibraryRule.Build("aidl_library", "gen aidl_library") 364 } 365 366 if yaccRule_ != nil { 367 yaccRule_.Build("yacc", "gen yacc") 368 } 369 370 deps = append(deps, info.protoOrderOnlyDeps...) 371 deps = append(deps, info.aidlOrderOnlyDeps...) 372 deps = append(deps, info.syspropOrderOnlyDeps...) 373 374 if len(rsFiles) > 0 { 375 deps = append(deps, rsGenerateCpp(ctx, rsFiles, buildFlags.rsFlags)...) 376 } 377 378 return srcFiles, deps, info 379} 380