• 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 -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