gen.go 12 KB

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