blob: 0f276d060d20dff6d6a17b00b376dabf7343c9d8 [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
23 "android/soong/common"
24)
25
Colin Cross5049f022015-03-18 13:28:46 -070026var (
27 pctx = blueprint.NewPackageContext("android/soong/genrule")
28)
29
30func init() {
Colin Cross1332b002015-04-07 17:11:30 -070031 pctx.VariableConfigMethod("srcDir", common.Config.SrcDir)
Colin Crossd350ecd2015-04-28 13:25:36 -070032 pctx.VariableConfigMethod("hostBin", common.Config.HostBin)
Colin Cross5049f022015-03-18 13:28:46 -070033}
34
35type SourceFileGenerator interface {
36 GeneratedSourceFiles() []string
37}
38
Colin Crossd350ecd2015-04-28 13:25:36 -070039type HostToolProvider interface {
40 HostToolPath() string
41}
Colin Cross5049f022015-03-18 13:28:46 -070042
Colin Crossd350ecd2015-04-28 13:25:36 -070043type generator struct {
44 common.AndroidModuleBase
45
46 properties struct {
47 // cmd: command to run on one or more input files. Available variables for substitution:
48 // $in: one or more input files
49 // $out: a single output file
50 // $srcDir: the root directory of the source tree
51 // The host bin directory will be in the path
52 Cmd string
53
54 // tool: name of the module (if any) that produces the host executable. Leave empty for
55 // prebuilts or scripts that do not need a module to build them.
56 Tool string
57 }
58
59 tasks taskFunc
60
61 deps []string
62 rule blueprint.Rule
63
64 outputFiles []string
65}
66
67type taskFunc func(ctx common.AndroidModuleContext) []generateTask
68
69type generateTask struct {
70 in []string
71 out string
72}
73
74func (g *generator) GeneratedSourceFiles() []string {
75 return g.outputFiles
76}
77
78func (g *generator) AndroidDynamicDependencies(ctx common.AndroidDynamicDependerModuleContext) []string {
79 if g.properties.Tool != "" {
80 return []string{g.properties.Tool}
81 }
82 return nil
83}
84
85func (g *generator) GenerateAndroidBuildActions(ctx common.AndroidModuleContext) {
86 g.rule = ctx.Rule(pctx, "generator", blueprint.RuleParams{
87 Command: "PATH=$$PATH:$hostBin " + g.properties.Cmd,
88 })
89
90 ctx.VisitDirectDeps(func(module blueprint.Module) {
91 if t, ok := module.(HostToolProvider); ok {
92 p := t.HostToolPath()
93 if p != "" {
94 g.deps = append(g.deps, p)
95 } else {
96 ctx.ModuleErrorf("host tool %q missing output file", ctx.OtherModuleName(module))
97 }
98 } else {
99 ctx.ModuleErrorf("unknown dependency %q", ctx.OtherModuleName(module))
100 }
101 })
102
103 for _, task := range g.tasks(ctx) {
104 g.generateSourceFile(ctx, task)
105 }
106}
107
108func (g *generator) generateSourceFile(ctx common.AndroidModuleContext, task generateTask) {
109
110 ctx.Build(pctx, blueprint.BuildParams{
111 Rule: g.rule,
112 Inputs: task.in,
113 Implicits: g.deps,
114 Outputs: []string{task.out},
115 })
116
117 g.outputFiles = append(g.outputFiles, task.out)
118}
119
120func generatorFactory(tasks taskFunc, props ...interface{}) (blueprint.Module, []interface{}) {
121 module := &generator{
122 tasks: tasks,
123 }
124
125 props = append(props, &module.properties)
126
127 return common.InitAndroidModule(module, props...)
128}
129
130func GenSrcsFactory() (blueprint.Module, []interface{}) {
131 properties := &genSrcsProperties{}
132
133 tasks := func(ctx common.AndroidModuleContext) []generateTask {
134 srcFiles := common.ExpandSources(ctx, properties.Srcs)
135 tasks := make([]generateTask, 0, len(srcFiles))
136 for _, in := range srcFiles {
137 out := pathtools.ReplaceExtension(in, properties.Output_extension)
138 out = filepath.Join(common.ModuleGenDir(ctx), out)
139 tasks = append(tasks, generateTask{[]string{in}, out})
140 }
141 return tasks
142 }
143
144 return generatorFactory(tasks, properties)
145}
146
147type genSrcsProperties struct {
Colin Cross5049f022015-03-18 13:28:46 -0700148 // srcs: list of input files
149 Srcs []string
150
151 // output_extension: extension that will be substituted for each output file
152 Output_extension string
153}
154
Colin Crossd350ecd2015-04-28 13:25:36 -0700155func GenRuleFactory() (blueprint.Module, []interface{}) {
156 properties := &genRuleProperties{}
Colin Cross5049f022015-03-18 13:28:46 -0700157
Colin Crossd350ecd2015-04-28 13:25:36 -0700158 tasks := func(ctx common.AndroidModuleContext) []generateTask {
159 return []generateTask{
160 {
161 in: common.ExpandSources(ctx, properties.Srcs),
162 out: filepath.Join(common.ModuleGenDir(ctx), properties.Out),
163 },
164 }
Colin Cross5049f022015-03-18 13:28:46 -0700165 }
Colin Crossd350ecd2015-04-28 13:25:36 -0700166
167 return generatorFactory(tasks, properties)
Colin Cross5049f022015-03-18 13:28:46 -0700168}
169
Colin Crossd350ecd2015-04-28 13:25:36 -0700170type genRuleProperties struct {
171 // srcs: list of input files
172 Srcs []string
Colin Cross5049f022015-03-18 13:28:46 -0700173
Colin Crossd350ecd2015-04-28 13:25:36 -0700174 // out: name of the output file that will be generated
175 Out string
Colin Cross5049f022015-03-18 13:28:46 -0700176}