blob: 76b4f16a751699107bd4183dc0c909fdeef4303b [file] [log] [blame]
Colin Cross5049f022015-03-18 13:28:46 -07001// 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 "path/filepath"
19
Colin Cross70b40592015-03-23 12:57:34 -070020 "github.com/google/blueprint"
21 "github.com/google/blueprint/pathtools"
Colin Cross5049f022015-03-18 13:28:46 -070022
Colin Cross463a90e2015-06-17 14:20:06 -070023 "android/soong"
Colin Cross5049f022015-03-18 13:28:46 -070024 "android/soong/common"
25)
26
Colin Cross463a90e2015-06-17 14:20:06 -070027func init() {
28 soong.RegisterModuleType("gensrcs", GenSrcsFactory)
29 soong.RegisterModuleType("genrule", GenRuleFactory)
Colin Cross6362e272015-10-29 15:25:03 -070030
31 common.RegisterBottomUpMutator("genrule_deps", genruleDepsMutator)
Colin Cross463a90e2015-06-17 14:20:06 -070032}
33
Colin Cross5049f022015-03-18 13:28:46 -070034var (
35 pctx = blueprint.NewPackageContext("android/soong/genrule")
36)
37
38func init() {
Colin Cross1332b002015-04-07 17:11:30 -070039 pctx.VariableConfigMethod("srcDir", common.Config.SrcDir)
Colin Crossd350ecd2015-04-28 13:25:36 -070040 pctx.VariableConfigMethod("hostBin", common.Config.HostBin)
Colin Cross5049f022015-03-18 13:28:46 -070041}
42
43type SourceFileGenerator interface {
44 GeneratedSourceFiles() []string
45}
46
Colin Crossd350ecd2015-04-28 13:25:36 -070047type HostToolProvider interface {
48 HostToolPath() string
49}
Colin Cross5049f022015-03-18 13:28:46 -070050
Colin Cross7d5136f2015-05-11 13:39:40 -070051type generatorProperties struct {
52 // command to run on one or more input files. Available variables for substitution:
53 // $in: one or more input files
54 // $out: a single output file
55 // $srcDir: the root directory of the source tree
56 // The host bin directory will be in the path
57 Cmd string
58
59 // name of the module (if any) that produces the host executable. Leave empty for
60 // prebuilts or scripts that do not need a module to build them.
61 Tool string
62}
63
Colin Crossd350ecd2015-04-28 13:25:36 -070064type generator struct {
65 common.AndroidModuleBase
66
Colin Cross7d5136f2015-05-11 13:39:40 -070067 properties generatorProperties
Colin Crossd350ecd2015-04-28 13:25:36 -070068
69 tasks taskFunc
70
71 deps []string
72 rule blueprint.Rule
73
74 outputFiles []string
75}
76
77type taskFunc func(ctx common.AndroidModuleContext) []generateTask
78
79type generateTask struct {
80 in []string
81 out string
82}
83
84func (g *generator) GeneratedSourceFiles() []string {
85 return g.outputFiles
86}
87
Colin Cross6362e272015-10-29 15:25:03 -070088func genruleDepsMutator(ctx common.AndroidBottomUpMutatorContext) {
89 if g, ok := ctx.Module().(*generator); ok {
90 if g.properties.Tool != "" {
Dan Willemsen490fd492015-11-24 17:53:15 -080091 ctx.AddFarVariationDependencies([]blueprint.Variation{
92 {"host_or_device", common.Host.String()},
93 {"host_type", common.CurrentHostType().String()},
94 }, g.properties.Tool)
Colin Cross6362e272015-10-29 15:25:03 -070095 }
Colin Crossd350ecd2015-04-28 13:25:36 -070096 }
Colin Crossd350ecd2015-04-28 13:25:36 -070097}
98
99func (g *generator) GenerateAndroidBuildActions(ctx common.AndroidModuleContext) {
100 g.rule = ctx.Rule(pctx, "generator", blueprint.RuleParams{
101 Command: "PATH=$$PATH:$hostBin " + g.properties.Cmd,
102 })
103
104 ctx.VisitDirectDeps(func(module blueprint.Module) {
105 if t, ok := module.(HostToolProvider); ok {
106 p := t.HostToolPath()
107 if p != "" {
108 g.deps = append(g.deps, p)
109 } else {
110 ctx.ModuleErrorf("host tool %q missing output file", ctx.OtherModuleName(module))
111 }
112 } else {
113 ctx.ModuleErrorf("unknown dependency %q", ctx.OtherModuleName(module))
114 }
115 })
116
117 for _, task := range g.tasks(ctx) {
118 g.generateSourceFile(ctx, task)
119 }
120}
121
122func (g *generator) generateSourceFile(ctx common.AndroidModuleContext, task generateTask) {
123
124 ctx.Build(pctx, blueprint.BuildParams{
125 Rule: g.rule,
126 Inputs: task.in,
127 Implicits: g.deps,
128 Outputs: []string{task.out},
129 })
130
131 g.outputFiles = append(g.outputFiles, task.out)
132}
133
134func generatorFactory(tasks taskFunc, props ...interface{}) (blueprint.Module, []interface{}) {
135 module := &generator{
136 tasks: tasks,
137 }
138
139 props = append(props, &module.properties)
140
141 return common.InitAndroidModule(module, props...)
142}
143
144func GenSrcsFactory() (blueprint.Module, []interface{}) {
145 properties := &genSrcsProperties{}
146
147 tasks := func(ctx common.AndroidModuleContext) []generateTask {
Dan Willemsen2ef08f42015-06-30 18:15:24 -0700148 srcFiles := ctx.ExpandSources(properties.Srcs, nil)
Colin Crossd350ecd2015-04-28 13:25:36 -0700149 tasks := make([]generateTask, 0, len(srcFiles))
150 for _, in := range srcFiles {
151 out := pathtools.ReplaceExtension(in, properties.Output_extension)
152 out = filepath.Join(common.ModuleGenDir(ctx), out)
153 tasks = append(tasks, generateTask{[]string{in}, out})
154 }
155 return tasks
156 }
157
158 return generatorFactory(tasks, properties)
159}
160
161type genSrcsProperties struct {
Colin Cross7d5136f2015-05-11 13:39:40 -0700162 // list of input files
Colin Cross5049f022015-03-18 13:28:46 -0700163 Srcs []string
164
Colin Cross7d5136f2015-05-11 13:39:40 -0700165 // extension that will be substituted for each output file
Colin Cross5049f022015-03-18 13:28:46 -0700166 Output_extension string
167}
168
Colin Crossd350ecd2015-04-28 13:25:36 -0700169func GenRuleFactory() (blueprint.Module, []interface{}) {
170 properties := &genRuleProperties{}
Colin Cross5049f022015-03-18 13:28:46 -0700171
Colin Crossd350ecd2015-04-28 13:25:36 -0700172 tasks := func(ctx common.AndroidModuleContext) []generateTask {
173 return []generateTask{
174 {
Dan Willemsen2ef08f42015-06-30 18:15:24 -0700175 in: ctx.ExpandSources(properties.Srcs, nil),
Colin Crossd350ecd2015-04-28 13:25:36 -0700176 out: filepath.Join(common.ModuleGenDir(ctx), properties.Out),
177 },
178 }
Colin Cross5049f022015-03-18 13:28:46 -0700179 }
Colin Crossd350ecd2015-04-28 13:25:36 -0700180
181 return generatorFactory(tasks, properties)
Colin Cross5049f022015-03-18 13:28:46 -0700182}
183
Colin Crossd350ecd2015-04-28 13:25:36 -0700184type genRuleProperties struct {
Colin Cross7d5136f2015-05-11 13:39:40 -0700185 // list of input files
Colin Crossd350ecd2015-04-28 13:25:36 -0700186 Srcs []string
Colin Cross5049f022015-03-18 13:28:46 -0700187
Colin Cross7d5136f2015-05-11 13:39:40 -0700188 // name of the output file that will be generated
Colin Crossd350ecd2015-04-28 13:25:36 -0700189 Out string
Colin Cross5049f022015-03-18 13:28:46 -0700190}