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/bazel" 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(ctx android.ModuleContext, rule *android.RuleBuilder, aidlFile android.Path, aidlFlags string) (cppFile android.OutputPath, headerFiles android.Paths) { 109 aidlPackage := strings.TrimSuffix(aidlFile.Rel(), aidlFile.Base()) 110 baseName := strings.TrimSuffix(aidlFile.Base(), aidlFile.Ext()) 111 shortName := baseName 112 // TODO(b/111362593): aidl_to_cpp_common.cpp uses heuristics to figure out if 113 // an interface name has a leading I. Those same heuristics have been 114 // moved here. 115 if len(baseName) >= 2 && baseName[0] == 'I' && 116 strings.ToUpper(baseName)[1] == baseName[1] { 117 shortName = strings.TrimPrefix(baseName, "I") 118 } 119 120 outDir := android.PathForModuleGen(ctx, "aidl") 121 cppFile = outDir.Join(ctx, aidlPackage, baseName+".cpp") 122 depFile := outDir.Join(ctx, aidlPackage, baseName+".cpp.d") 123 headerI := outDir.Join(ctx, aidlPackage, baseName+".h") 124 headerBn := outDir.Join(ctx, aidlPackage, "Bn"+shortName+".h") 125 headerBp := outDir.Join(ctx, aidlPackage, "Bp"+shortName+".h") 126 127 baseDir := strings.TrimSuffix(aidlFile.String(), aidlFile.Rel()) 128 if baseDir != "" { 129 aidlFlags += " -I" + baseDir 130 } 131 132 cmd := rule.Command() 133 cmd.BuiltTool("aidl-cpp"). 134 FlagWithDepFile("-d", depFile). 135 Flag("--ninja"). 136 Flag(aidlFlags). 137 Input(aidlFile). 138 OutputDir(). 139 Output(cppFile). 140 ImplicitOutputs(android.WritablePaths{ 141 headerI, 142 headerBn, 143 headerBp, 144 }) 145 146 return cppFile, android.Paths{ 147 headerI, 148 headerBn, 149 headerBp, 150 } 151} 152 153type LexProperties struct { 154 // list of module-specific flags that will be used for .l and .ll compiles 155 Flags []string 156} 157 158func genLex(ctx android.ModuleContext, lexFile android.Path, outFile android.ModuleGenPath, props *LexProperties) { 159 var flags []string 160 if props != nil { 161 flags = props.Flags 162 } 163 flagsString := strings.Join(flags[:], " ") 164 ctx.Build(pctx, android.BuildParams{ 165 Rule: lex, 166 Description: "lex " + lexFile.Rel(), 167 Output: outFile, 168 Input: lexFile, 169 Args: map[string]string{"flags": flagsString}, 170 }) 171} 172 173type LexAttrs struct { 174 Srcs bazel.LabelListAttribute 175 Lexopts bazel.StringListAttribute 176} 177 178type LexNames struct { 179 cSrcName bazel.LabelAttribute 180 srcName bazel.LabelAttribute 181} 182 183func bp2BuildLex(ctx android.Bp2buildMutatorContext, moduleName string, ca compilerAttributes) LexNames { 184 names := LexNames{} 185 if !ca.lSrcs.IsEmpty() { 186 names.cSrcName = createLexTargetModule(ctx, moduleName+"_genlex_l", ca.lSrcs, ca.lexopts) 187 } 188 if !ca.llSrcs.IsEmpty() { 189 names.srcName = createLexTargetModule(ctx, moduleName+"_genlex_ll", ca.llSrcs, ca.lexopts) 190 } 191 return names 192} 193 194func createLexTargetModule(ctx android.Bp2buildMutatorContext, name string, srcs bazel.LabelListAttribute, opts bazel.StringListAttribute) bazel.LabelAttribute { 195 ctx.CreateBazelTargetModule( 196 bazel.BazelTargetModuleProperties{ 197 Rule_class: "genlex", 198 Bzl_load_location: "//build/bazel/rules/cc:flex.bzl", 199 }, 200 android.CommonAttributes{Name: name}, 201 &LexAttrs{ 202 Srcs: srcs, 203 Lexopts: opts, 204 }) 205 return bazel.LabelAttribute{Value: &bazel.Label{Label: ":" + name}} 206} 207 208func genSysprop(ctx android.ModuleContext, syspropFile android.Path) (android.Path, android.Paths) { 209 headerFile := android.PathForModuleGen(ctx, "sysprop", "include", syspropFile.Rel()+".h") 210 publicHeaderFile := android.PathForModuleGen(ctx, "sysprop/public", "include", syspropFile.Rel()+".h") 211 cppFile := android.PathForModuleGen(ctx, "sysprop", syspropFile.Rel()+".cpp") 212 213 headers := android.WritablePaths{headerFile, publicHeaderFile} 214 215 ctx.Build(pctx, android.BuildParams{ 216 Rule: sysprop, 217 Description: "sysprop " + syspropFile.Rel(), 218 Output: cppFile, 219 ImplicitOutputs: headers, 220 Input: syspropFile, 221 Args: map[string]string{ 222 "headerOutDir": filepath.Dir(headerFile.String()), 223 "publicOutDir": filepath.Dir(publicHeaderFile.String()), 224 "srcOutDir": filepath.Dir(cppFile.String()), 225 "includeName": syspropFile.Rel() + ".h", 226 }, 227 }) 228 229 return cppFile, headers.Paths() 230} 231 232func bp2buildCcSysprop(ctx android.Bp2buildMutatorContext, moduleName string, minSdkVersion *string, srcs bazel.LabelListAttribute) *bazel.LabelAttribute { 233 labels := SyspropLibraryLabels{ 234 SyspropLibraryLabel: moduleName + "_sysprop_library", 235 StaticLibraryLabel: moduleName + "_cc_sysprop_library_static", 236 } 237 Bp2buildSysprop(ctx, labels, srcs, minSdkVersion) 238 return createLabelAttributeCorrespondingToSrcs(":"+labels.StaticLibraryLabel, srcs) 239} 240 241// Creates a LabelAttribute for a given label where the value is only set for 242// the same config values that have values in a given LabelListAttribute 243func createLabelAttributeCorrespondingToSrcs(baseLabelName string, srcs bazel.LabelListAttribute) *bazel.LabelAttribute { 244 baseLabel := bazel.Label{Label: baseLabelName} 245 label := bazel.LabelAttribute{} 246 if !srcs.Value.IsNil() && !srcs.Value.IsEmpty() { 247 label.Value = &baseLabel 248 return &label 249 } 250 for axis, configToSrcs := range srcs.ConfigurableValues { 251 for config, val := range configToSrcs { 252 if !val.IsNil() && !val.IsEmpty() { 253 label.SetSelectValue(axis, config, baseLabel) 254 } 255 } 256 } 257 return &label 258} 259 260// Used to communicate information from the genSources method back to the library code that uses 261// it. 262type generatedSourceInfo struct { 263 // The headers created from .proto files 264 protoHeaders android.Paths 265 266 // The files that can be used as order only dependencies in order to ensure that the proto header 267 // files are up to date. 268 protoOrderOnlyDeps android.Paths 269 270 // The headers created from .aidl files 271 aidlHeaders android.Paths 272 273 // The files that can be used as order only dependencies in order to ensure that the aidl header 274 // files are up to date. 275 aidlOrderOnlyDeps android.Paths 276 277 // The headers created from .sysprop files 278 syspropHeaders android.Paths 279 280 // The files that can be used as order only dependencies in order to ensure that the sysprop 281 // header files are up to date. 282 syspropOrderOnlyDeps android.Paths 283} 284 285func genSources(ctx android.ModuleContext, srcFiles android.Paths, 286 buildFlags builderFlags) (android.Paths, android.Paths, generatedSourceInfo) { 287 288 var info generatedSourceInfo 289 290 var deps android.Paths 291 var rsFiles android.Paths 292 293 var aidlRule *android.RuleBuilder 294 295 var yaccRule_ *android.RuleBuilder 296 yaccRule := func() *android.RuleBuilder { 297 if yaccRule_ == nil { 298 yaccRule_ = android.NewRuleBuilder(pctx, ctx).Sbox(android.PathForModuleGen(ctx, "yacc"), 299 android.PathForModuleGen(ctx, "yacc.sbox.textproto")) 300 } 301 return yaccRule_ 302 } 303 304 for i, srcFile := range srcFiles { 305 switch srcFile.Ext() { 306 case ".y": 307 cFile := android.GenPathWithExt(ctx, "yacc", srcFile, "c") 308 srcFiles[i] = cFile 309 deps = append(deps, genYacc(ctx, yaccRule(), srcFile, cFile, buildFlags.yacc)...) 310 case ".yy": 311 cppFile := android.GenPathWithExt(ctx, "yacc", srcFile, "cpp") 312 srcFiles[i] = cppFile 313 deps = append(deps, genYacc(ctx, yaccRule(), srcFile, cppFile, buildFlags.yacc)...) 314 case ".l": 315 cFile := android.GenPathWithExt(ctx, "lex", srcFile, "c") 316 srcFiles[i] = cFile 317 genLex(ctx, srcFile, cFile, buildFlags.lex) 318 case ".ll": 319 cppFile := android.GenPathWithExt(ctx, "lex", srcFile, "cpp") 320 srcFiles[i] = cppFile 321 genLex(ctx, srcFile, cppFile, buildFlags.lex) 322 case ".proto": 323 ccFile, headerFile := genProto(ctx, srcFile, buildFlags) 324 srcFiles[i] = ccFile 325 info.protoHeaders = append(info.protoHeaders, headerFile) 326 // Use the generated header as an order only dep to ensure that it is up to date when needed. 327 info.protoOrderOnlyDeps = append(info.protoOrderOnlyDeps, headerFile) 328 case ".aidl": 329 if aidlRule == nil { 330 aidlRule = android.NewRuleBuilder(pctx, ctx).Sbox(android.PathForModuleGen(ctx, "aidl"), 331 android.PathForModuleGen(ctx, "aidl.sbox.textproto")) 332 } 333 cppFile, aidlHeaders := genAidl(ctx, aidlRule, srcFile, buildFlags.aidlFlags) 334 srcFiles[i] = cppFile 335 336 info.aidlHeaders = append(info.aidlHeaders, aidlHeaders...) 337 // Use the generated headers as order only deps to ensure that they are up to date when 338 // needed. 339 // TODO: Reduce the size of the ninja file by using one order only dep for the whole rule 340 info.aidlOrderOnlyDeps = append(info.aidlOrderOnlyDeps, aidlHeaders...) 341 case ".rscript", ".fs": 342 cppFile := rsGeneratedCppFile(ctx, srcFile) 343 rsFiles = append(rsFiles, srcFiles[i]) 344 srcFiles[i] = cppFile 345 case ".sysprop": 346 cppFile, headerFiles := genSysprop(ctx, srcFile) 347 srcFiles[i] = cppFile 348 info.syspropHeaders = append(info.syspropHeaders, headerFiles...) 349 // Use the generated headers as order only deps to ensure that they are up to date when 350 // needed. 351 info.syspropOrderOnlyDeps = append(info.syspropOrderOnlyDeps, headerFiles...) 352 } 353 } 354 355 if aidlRule != nil { 356 aidlRule.Build("aidl", "gen aidl") 357 } 358 359 if yaccRule_ != nil { 360 yaccRule_.Build("yacc", "gen yacc") 361 } 362 363 deps = append(deps, info.protoOrderOnlyDeps...) 364 deps = append(deps, info.aidlOrderOnlyDeps...) 365 deps = append(deps, info.syspropOrderOnlyDeps...) 366 367 if len(rsFiles) > 0 { 368 deps = append(deps, rsGenerateCpp(ctx, rsFiles, buildFlags.rsFlags)...) 369 } 370 371 return srcFiles, deps, info 372} 373