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