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 -o$out $in", 38 CommandDeps: []string{"$lexCmd", "$m4Cmd"}, 39 }) 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 windmc = pctx.AndroidStaticRule("windmc", 50 blueprint.RuleParams{ 51 Command: "$windmcCmd -r$$(dirname $out) -h$$(dirname $out) $in", 52 CommandDeps: []string{"$windmcCmd"}, 53 }, 54 "windmcCmd") 55) 56 57type YaccProperties struct { 58 // list of module-specific flags that will be used for .y and .yy compiles 59 Flags []string 60 61 // whether the yacc files will produce a location.hh file 62 Gen_location_hh *bool 63 64 // whether the yacc files will product a position.hh file 65 Gen_position_hh *bool 66} 67 68func genYacc(ctx android.ModuleContext, rule *android.RuleBuilder, yaccFile android.Path, 69 outFile android.ModuleGenPath, props *YaccProperties) (headerFiles android.Paths) { 70 71 outDir := android.PathForModuleGen(ctx, "yacc") 72 headerFile := android.GenPathWithExt(ctx, "yacc", yaccFile, "h") 73 ret := android.Paths{headerFile} 74 75 cmd := rule.Command() 76 77 // Fix up #line markers to not use the sbox temporary directory 78 sedCmd := "sed -i.bak 's#__SBOX_OUT_DIR__#" + outDir.String() + "#'" 79 rule.Command().Text(sedCmd).Input(outFile) 80 rule.Command().Text(sedCmd).Input(headerFile) 81 82 var flags []string 83 if props != nil { 84 flags = props.Flags 85 86 if Bool(props.Gen_location_hh) { 87 locationHeader := outFile.InSameDir(ctx, "location.hh") 88 ret = append(ret, locationHeader) 89 cmd.ImplicitOutput(locationHeader) 90 rule.Command().Text(sedCmd).Input(locationHeader) 91 } 92 if Bool(props.Gen_position_hh) { 93 positionHeader := outFile.InSameDir(ctx, "position.hh") 94 ret = append(ret, positionHeader) 95 cmd.ImplicitOutput(positionHeader) 96 rule.Command().Text(sedCmd).Input(positionHeader) 97 } 98 } 99 100 cmd.Text("BISON_PKGDATADIR=prebuilts/build-tools/common/bison"). 101 FlagWithInput("M4=", ctx.Config().PrebuiltBuildTool(ctx, "m4")). 102 PrebuiltBuildTool(ctx, "bison"). 103 Flag("-d"). 104 Flags(flags). 105 FlagWithOutput("--defines=", headerFile). 106 Flag("-o").Output(outFile).Input(yaccFile) 107 108 return ret 109} 110 111func genAidl(ctx android.ModuleContext, rule *android.RuleBuilder, aidlFile android.Path, 112 outFile, depFile android.ModuleGenPath, aidlFlags string) android.Paths { 113 114 aidlPackage := strings.TrimSuffix(aidlFile.Rel(), aidlFile.Base()) 115 baseName := strings.TrimSuffix(aidlFile.Base(), aidlFile.Ext()) 116 shortName := baseName 117 // TODO(b/111362593): aidl_to_cpp_common.cpp uses heuristics to figure out if 118 // an interface name has a leading I. Those same heuristics have been 119 // moved here. 120 if len(baseName) >= 2 && baseName[0] == 'I' && 121 strings.ToUpper(baseName)[1] == baseName[1] { 122 shortName = strings.TrimPrefix(baseName, "I") 123 } 124 125 outDir := android.PathForModuleGen(ctx, "aidl") 126 headerI := outDir.Join(ctx, aidlPackage, baseName+".h") 127 headerBn := outDir.Join(ctx, aidlPackage, "Bn"+shortName+".h") 128 headerBp := outDir.Join(ctx, aidlPackage, "Bp"+shortName+".h") 129 130 baseDir := strings.TrimSuffix(aidlFile.String(), aidlFile.Rel()) 131 if baseDir != "" { 132 aidlFlags += " -I" + baseDir 133 } 134 135 cmd := rule.Command() 136 cmd.BuiltTool(ctx, "aidl-cpp"). 137 FlagWithDepFile("-d", depFile). 138 Flag("--ninja"). 139 Flag(aidlFlags). 140 Input(aidlFile). 141 OutputDir(). 142 Output(outFile). 143 ImplicitOutputs(android.WritablePaths{ 144 headerI, 145 headerBn, 146 headerBp, 147 }) 148 149 return android.Paths{ 150 headerI, 151 headerBn, 152 headerBp, 153 } 154} 155 156func genLex(ctx android.ModuleContext, lexFile android.Path, outFile android.ModuleGenPath) { 157 ctx.Build(pctx, android.BuildParams{ 158 Rule: lex, 159 Description: "lex " + lexFile.Rel(), 160 Output: outFile, 161 Input: lexFile, 162 }) 163} 164 165func genSysprop(ctx android.ModuleContext, syspropFile android.Path) (android.Path, android.Paths) { 166 headerFile := android.PathForModuleGen(ctx, "sysprop", "include", syspropFile.Rel()+".h") 167 publicHeaderFile := android.PathForModuleGen(ctx, "sysprop/public", "include", syspropFile.Rel()+".h") 168 cppFile := android.PathForModuleGen(ctx, "sysprop", syspropFile.Rel()+".cpp") 169 170 headers := android.WritablePaths{headerFile, publicHeaderFile} 171 172 ctx.Build(pctx, android.BuildParams{ 173 Rule: sysprop, 174 Description: "sysprop " + syspropFile.Rel(), 175 Output: cppFile, 176 ImplicitOutputs: headers, 177 Input: syspropFile, 178 Args: map[string]string{ 179 "headerOutDir": filepath.Dir(headerFile.String()), 180 "publicOutDir": filepath.Dir(publicHeaderFile.String()), 181 "srcOutDir": filepath.Dir(cppFile.String()), 182 "includeName": syspropFile.Rel() + ".h", 183 }, 184 }) 185 186 return cppFile, headers.Paths() 187} 188 189func genWinMsg(ctx android.ModuleContext, srcFile android.Path, flags builderFlags) (android.Path, android.Path) { 190 headerFile := android.GenPathWithExt(ctx, "windmc", srcFile, "h") 191 rcFile := android.GenPathWithExt(ctx, "windmc", srcFile, "rc") 192 193 windmcCmd := gccCmd(flags.toolchain, "windmc") 194 195 ctx.Build(pctx, android.BuildParams{ 196 Rule: windmc, 197 Description: "windmc " + srcFile.Rel(), 198 Output: rcFile, 199 ImplicitOutput: headerFile, 200 Input: srcFile, 201 Args: map[string]string{ 202 "windmcCmd": windmcCmd, 203 }, 204 }) 205 206 return rcFile, headerFile 207} 208 209func genSources(ctx android.ModuleContext, srcFiles android.Paths, 210 buildFlags builderFlags) (android.Paths, android.Paths) { 211 212 var deps android.Paths 213 var rsFiles android.Paths 214 215 var aidlRule *android.RuleBuilder 216 217 var yaccRule_ *android.RuleBuilder 218 yaccRule := func() *android.RuleBuilder { 219 if yaccRule_ == nil { 220 yaccRule_ = android.NewRuleBuilder().Sbox(android.PathForModuleGen(ctx, "yacc")) 221 } 222 return yaccRule_ 223 } 224 225 for i, srcFile := range srcFiles { 226 switch srcFile.Ext() { 227 case ".y": 228 cFile := android.GenPathWithExt(ctx, "yacc", srcFile, "c") 229 srcFiles[i] = cFile 230 deps = append(deps, genYacc(ctx, yaccRule(), srcFile, cFile, buildFlags.yacc)...) 231 case ".yy": 232 cppFile := android.GenPathWithExt(ctx, "yacc", srcFile, "cpp") 233 srcFiles[i] = cppFile 234 deps = append(deps, genYacc(ctx, yaccRule(), srcFile, cppFile, buildFlags.yacc)...) 235 case ".l": 236 cFile := android.GenPathWithExt(ctx, "lex", srcFile, "c") 237 srcFiles[i] = cFile 238 genLex(ctx, srcFile, cFile) 239 case ".ll": 240 cppFile := android.GenPathWithExt(ctx, "lex", srcFile, "cpp") 241 srcFiles[i] = cppFile 242 genLex(ctx, srcFile, cppFile) 243 case ".proto": 244 ccFile, headerFile := genProto(ctx, srcFile, buildFlags) 245 srcFiles[i] = ccFile 246 deps = append(deps, headerFile) 247 case ".aidl": 248 if aidlRule == nil { 249 aidlRule = android.NewRuleBuilder().Sbox(android.PathForModuleGen(ctx, "aidl")) 250 } 251 cppFile := android.GenPathWithExt(ctx, "aidl", srcFile, "cpp") 252 depFile := android.GenPathWithExt(ctx, "aidl", srcFile, "cpp.d") 253 srcFiles[i] = cppFile 254 deps = append(deps, genAidl(ctx, aidlRule, srcFile, cppFile, depFile, buildFlags.aidlFlags)...) 255 case ".rscript", ".fs": 256 cppFile := rsGeneratedCppFile(ctx, srcFile) 257 rsFiles = append(rsFiles, srcFiles[i]) 258 srcFiles[i] = cppFile 259 case ".mc": 260 rcFile, headerFile := genWinMsg(ctx, srcFile, buildFlags) 261 srcFiles[i] = rcFile 262 deps = append(deps, headerFile) 263 case ".sysprop": 264 cppFile, headerFiles := genSysprop(ctx, srcFile) 265 srcFiles[i] = cppFile 266 deps = append(deps, headerFiles...) 267 } 268 } 269 270 if aidlRule != nil { 271 aidlRule.Build(pctx, ctx, "aidl", "gen aidl") 272 } 273 274 if yaccRule_ != nil { 275 yaccRule_.Build(pctx, ctx, "yacc", "gen yacc") 276 } 277 278 if len(rsFiles) > 0 { 279 deps = append(deps, rsGenerateCpp(ctx, rsFiles, buildFlags.rsFlags)...) 280 } 281 282 return srcFiles, deps 283} 284