blob: fb0dafcf0adb7dea689b7278be8db8f2a6539f65 [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 != "" {
91 ctx.AddFarVariationDependencies([]blueprint.Variation{{"hostordevice", common.Host.String()}},
92 g.properties.Tool)
93 }
Colin Crossd350ecd2015-04-28 13:25:36 -070094 }
Colin Crossd350ecd2015-04-28 13:25:36 -070095}
96
97func (g *generator) GenerateAndroidBuildActions(ctx common.AndroidModuleContext) {
98 g.rule = ctx.Rule(pctx, "generator", blueprint.RuleParams{
99 Command: "PATH=$$PATH:$hostBin " + g.properties.Cmd,
100 })
101
102 ctx.VisitDirectDeps(func(module blueprint.Module) {
103 if t, ok := module.(HostToolProvider); ok {
104 p := t.HostToolPath()
105 if p != "" {
106 g.deps = append(g.deps, p)
107 } else {
108 ctx.ModuleErrorf("host tool %q missing output file", ctx.OtherModuleName(module))
109 }
110 } else {
111 ctx.ModuleErrorf("unknown dependency %q", ctx.OtherModuleName(module))
112 }
113 })
114
115 for _, task := range g.tasks(ctx) {
116 g.generateSourceFile(ctx, task)
117 }
118}
119
120func (g *generator) generateSourceFile(ctx common.AndroidModuleContext, task generateTask) {
121
122 ctx.Build(pctx, blueprint.BuildParams{
123 Rule: g.rule,
124 Inputs: task.in,
125 Implicits: g.deps,
126 Outputs: []string{task.out},
127 })
128
129 g.outputFiles = append(g.outputFiles, task.out)
130}
131
132func generatorFactory(tasks taskFunc, props ...interface{}) (blueprint.Module, []interface{}) {
133 module := &generator{
134 tasks: tasks,
135 }
136
137 props = append(props, &module.properties)
138
139 return common.InitAndroidModule(module, props...)
140}
141
142func GenSrcsFactory() (blueprint.Module, []interface{}) {
143 properties := &genSrcsProperties{}
144
145 tasks := func(ctx common.AndroidModuleContext) []generateTask {
Dan Willemsen2ef08f42015-06-30 18:15:24 -0700146 srcFiles := ctx.ExpandSources(properties.Srcs, nil)
Colin Crossd350ecd2015-04-28 13:25:36 -0700147 tasks := make([]generateTask, 0, len(srcFiles))
148 for _, in := range srcFiles {
149 out := pathtools.ReplaceExtension(in, properties.Output_extension)
150 out = filepath.Join(common.ModuleGenDir(ctx), out)
151 tasks = append(tasks, generateTask{[]string{in}, out})
152 }
153 return tasks
154 }
155
156 return generatorFactory(tasks, properties)
157}
158
159type genSrcsProperties struct {
Colin Cross7d5136f2015-05-11 13:39:40 -0700160 // list of input files
Colin Cross5049f022015-03-18 13:28:46 -0700161 Srcs []string
162
Colin Cross7d5136f2015-05-11 13:39:40 -0700163 // extension that will be substituted for each output file
Colin Cross5049f022015-03-18 13:28:46 -0700164 Output_extension string
165}
166
Colin Crossd350ecd2015-04-28 13:25:36 -0700167func GenRuleFactory() (blueprint.Module, []interface{}) {
168 properties := &genRuleProperties{}
Colin Cross5049f022015-03-18 13:28:46 -0700169
Colin Crossd350ecd2015-04-28 13:25:36 -0700170 tasks := func(ctx common.AndroidModuleContext) []generateTask {
171 return []generateTask{
172 {
Dan Willemsen2ef08f42015-06-30 18:15:24 -0700173 in: ctx.ExpandSources(properties.Srcs, nil),
Colin Crossd350ecd2015-04-28 13:25:36 -0700174 out: filepath.Join(common.ModuleGenDir(ctx), properties.Out),
175 },
176 }
Colin Cross5049f022015-03-18 13:28:46 -0700177 }
Colin Crossd350ecd2015-04-28 13:25:36 -0700178
179 return generatorFactory(tasks, properties)
Colin Cross5049f022015-03-18 13:28:46 -0700180}
181
Colin Crossd350ecd2015-04-28 13:25:36 -0700182type genRuleProperties struct {
Colin Cross7d5136f2015-05-11 13:39:40 -0700183 // list of input files
Colin Crossd350ecd2015-04-28 13:25:36 -0700184 Srcs []string
Colin Cross5049f022015-03-18 13:28:46 -0700185
Colin Cross7d5136f2015-05-11 13:39:40 -0700186 // name of the output file that will be generated
Colin Crossd350ecd2015-04-28 13:25:36 -0700187 Out string
Colin Cross5049f022015-03-18 13:28:46 -0700188}