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