• 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 genrule
16
17import (
18	"github.com/google/blueprint"
19
20	"android/soong"
21	"android/soong/common"
22)
23
24func init() {
25	soong.RegisterModuleType("gensrcs", GenSrcsFactory)
26	soong.RegisterModuleType("genrule", GenRuleFactory)
27
28	common.RegisterBottomUpMutator("genrule_deps", genruleDepsMutator)
29}
30
31var (
32	pctx = common.NewPackageContext("android/soong/genrule")
33)
34
35func init() {
36	pctx.SourcePathVariable("srcDir", "")
37	pctx.HostBinToolVariable("hostBin", "")
38}
39
40type SourceFileGenerator interface {
41	GeneratedSourceFiles() common.Paths
42}
43
44type HostToolProvider interface {
45	HostToolPath() common.OptionalPath
46}
47
48type generatorProperties struct {
49	// command to run on one or more input files.  Available variables for substitution:
50	// $in: one or more input files
51	// $out: a single output file
52	// $srcDir: the root directory of the source tree
53	// The host bin directory will be in the path
54	Cmd string
55
56	// name of the module (if any) that produces the host executable.   Leave empty for
57	// prebuilts or scripts that do not need a module to build them.
58	Tool string
59}
60
61type generator struct {
62	common.AndroidModuleBase
63
64	properties generatorProperties
65
66	tasks taskFunc
67
68	deps common.Paths
69	rule blueprint.Rule
70
71	outputFiles common.Paths
72}
73
74type taskFunc func(ctx common.AndroidModuleContext) []generateTask
75
76type generateTask struct {
77	in  common.Paths
78	out common.ModuleGenPath
79}
80
81func (g *generator) GeneratedSourceFiles() common.Paths {
82	return g.outputFiles
83}
84
85func genruleDepsMutator(ctx common.AndroidBottomUpMutatorContext) {
86	if g, ok := ctx.Module().(*generator); ok {
87		if g.properties.Tool != "" {
88			ctx.AddFarVariationDependencies([]blueprint.Variation{
89				{"host_or_device", common.Host.String()},
90				{"host_type", common.CurrentHostType().String()},
91			}, g.properties.Tool)
92		}
93	}
94}
95
96func (g *generator) GenerateAndroidBuildActions(ctx common.AndroidModuleContext) {
97	g.rule = ctx.Rule(pctx, "generator", blueprint.RuleParams{
98		Command: "PATH=$$PATH:$hostBin " + g.properties.Cmd,
99	})
100
101	ctx.VisitDirectDeps(func(module blueprint.Module) {
102		if t, ok := module.(HostToolProvider); ok {
103			p := t.HostToolPath()
104			if p.Valid() {
105				g.deps = append(g.deps, p.Path())
106			} else {
107				ctx.ModuleErrorf("host tool %q missing output file", ctx.OtherModuleName(module))
108			}
109		} else {
110			ctx.ModuleErrorf("unknown dependency %q", ctx.OtherModuleName(module))
111		}
112	})
113
114	for _, task := range g.tasks(ctx) {
115		g.generateSourceFile(ctx, task)
116	}
117}
118
119func (g *generator) generateSourceFile(ctx common.AndroidModuleContext, task generateTask) {
120	ctx.ModuleBuild(pctx, common.ModuleBuildParams{
121		Rule:      g.rule,
122		Output:    task.out,
123		Inputs:    task.in,
124		Implicits: g.deps,
125	})
126
127	g.outputFiles = append(g.outputFiles, task.out)
128}
129
130func generatorFactory(tasks taskFunc, props ...interface{}) (blueprint.Module, []interface{}) {
131	module := &generator{
132		tasks: tasks,
133	}
134
135	props = append(props, &module.properties)
136
137	return common.InitAndroidModule(module, props...)
138}
139
140func GenSrcsFactory() (blueprint.Module, []interface{}) {
141	properties := &genSrcsProperties{}
142
143	tasks := func(ctx common.AndroidModuleContext) []generateTask {
144		srcFiles := ctx.ExpandSources(properties.Srcs, nil)
145		tasks := make([]generateTask, 0, len(srcFiles))
146		for _, in := range srcFiles {
147			tasks = append(tasks, generateTask{
148				in:  common.Paths{in},
149				out: common.GenPathWithExt(ctx, in, properties.Output_extension),
150			})
151		}
152		return tasks
153	}
154
155	return generatorFactory(tasks, properties)
156}
157
158type genSrcsProperties struct {
159	// list of input files
160	Srcs []string
161
162	// extension that will be substituted for each output file
163	Output_extension string
164}
165
166func GenRuleFactory() (blueprint.Module, []interface{}) {
167	properties := &genRuleProperties{}
168
169	tasks := func(ctx common.AndroidModuleContext) []generateTask {
170		return []generateTask{
171			{
172				in:  ctx.ExpandSources(properties.Srcs, nil),
173				out: properties.Out,
174			},
175		}
176	}
177
178	return generatorFactory(tasks, properties)
179}
180
181type genRuleProperties struct {
182	// list of input files
183	Srcs []string
184
185	// name of the output file that will be generated
186	Out common.ModuleGenPath
187}
188