• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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