blob: b7e84323d7b48d61e944d3f6dc3c39241392aa49 [file] [log] [blame]
Colin Crossfeec25b2019-01-30 17:32:39 -08001// Copyright 2018 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 android
16
17import (
18 "fmt"
19 "path/filepath"
20 "sort"
21 "strings"
22
23 "github.com/google/blueprint"
24 "github.com/google/blueprint/proptools"
25)
26
27type RuleBuilderInstall struct {
28 From, To string
29}
30
31type RuleBuilder struct {
32 commands []*RuleBuilderCommand
33 installs []RuleBuilderInstall
34 restat bool
35}
36
37func (r *RuleBuilder) Restat() *RuleBuilder {
38 r.restat = true
39 return r
40}
41
42func (r *RuleBuilder) Install(from, to string) {
43 r.installs = append(r.installs, RuleBuilderInstall{from, to})
44}
45
46func (r *RuleBuilder) Command() *RuleBuilderCommand {
47 command := &RuleBuilderCommand{}
48 r.commands = append(r.commands, command)
49 return command
50}
51
52func (r *RuleBuilder) Inputs() []string {
53 outputs := r.outputSet()
54
55 inputs := make(map[string]bool)
56 for _, c := range r.commands {
57 for _, input := range c.inputs {
58 if !outputs[input] {
59 inputs[input] = true
60 }
61 }
62 }
63
64 var inputList []string
65 for input := range inputs {
66 inputList = append(inputList, input)
67 }
68 sort.Strings(inputList)
69
70 return inputList
71}
72
73func (r *RuleBuilder) outputSet() map[string]bool {
74 outputs := make(map[string]bool)
75 for _, c := range r.commands {
76 for _, output := range c.outputs {
77 outputs[output] = true
78 }
79 }
80 return outputs
81}
82
83func (r *RuleBuilder) Outputs() []string {
84 outputs := r.outputSet()
85
86 var outputList []string
87 for output := range outputs {
88 outputList = append(outputList, output)
89 }
90 sort.Strings(outputList)
91 return outputList
92}
93
94func (r *RuleBuilder) Installs() []RuleBuilderInstall {
95 return append([]RuleBuilderInstall(nil), r.installs...)
96}
97
98func (r *RuleBuilder) Tools() []string {
99 var tools []string
100 for _, c := range r.commands {
101 tools = append(tools, c.tools...)
102 }
103 return tools
104}
105
106func (r *RuleBuilder) Commands() []string {
107 var commands []string
108 for _, c := range r.commands {
109 commands = append(commands, string(c.buf))
110 }
111 return commands
112}
113
114func (r *RuleBuilder) Build(pctx PackageContext, ctx ModuleContext, name string, desc string) {
115 var inputs Paths
116 for _, input := range r.Inputs() {
117 rel, isRel := MaybeRel(ctx, PathForModuleOut(ctx).String(), input)
118 if isRel {
119 inputs = append(inputs, PathForModuleOut(ctx, rel))
120 } else {
121 // TODO: use PathForOutput once boot image is moved to where PathForOutput can find it.
122 inputs = append(inputs, &unknownRulePath{input})
123 }
124 }
125
126 var outputs WritablePaths
127 for _, output := range r.Outputs() {
128 rel := Rel(ctx, PathForModuleOut(ctx).String(), output)
129 outputs = append(outputs, PathForModuleOut(ctx, rel))
130 }
131
132 if len(r.Commands()) > 0 {
133 ctx.Build(pctx, BuildParams{
134 Rule: ctx.Rule(pctx, name, blueprint.RuleParams{
135 Command: strings.Join(proptools.NinjaEscape(r.Commands()), " && "),
136 CommandDeps: r.Tools(),
137 }),
138 Implicits: inputs,
139 Outputs: outputs,
140 Description: desc,
141 })
142 }
143}
144
145type RuleBuilderCommand struct {
146 buf []byte
147 inputs []string
148 outputs []string
149 tools []string
150}
151
152func (c *RuleBuilderCommand) Text(text string) *RuleBuilderCommand {
153 if len(c.buf) > 0 {
154 c.buf = append(c.buf, ' ')
155 }
156 c.buf = append(c.buf, text...)
157 return c
158}
159
160func (c *RuleBuilderCommand) Textf(format string, a ...interface{}) *RuleBuilderCommand {
161 return c.Text(fmt.Sprintf(format, a...))
162}
163
164func (c *RuleBuilderCommand) Flag(flag string) *RuleBuilderCommand {
165 return c.Text(flag)
166}
167
168func (c *RuleBuilderCommand) FlagWithArg(flag, arg string) *RuleBuilderCommand {
169 return c.Text(flag + arg)
170}
171
172func (c *RuleBuilderCommand) FlagWithList(flag string, list []string, sep string) *RuleBuilderCommand {
173 return c.Text(flag + strings.Join(list, sep))
174}
175
176func (c *RuleBuilderCommand) Tool(path string) *RuleBuilderCommand {
177 c.tools = append(c.tools, path)
178 return c.Text(path)
179}
180
181func (c *RuleBuilderCommand) Input(path string) *RuleBuilderCommand {
182 c.inputs = append(c.inputs, path)
183 return c.Text(path)
184}
185
186func (c *RuleBuilderCommand) Implicit(path string) *RuleBuilderCommand {
187 c.inputs = append(c.inputs, path)
188 return c
189}
190
191func (c *RuleBuilderCommand) Implicits(paths []string) *RuleBuilderCommand {
192 c.inputs = append(c.inputs, paths...)
193 return c
194}
195
196func (c *RuleBuilderCommand) Output(path string) *RuleBuilderCommand {
197 c.outputs = append(c.outputs, path)
198 return c.Text(path)
199}
200
201func (c *RuleBuilderCommand) ImplicitOutput(path string) *RuleBuilderCommand {
202 c.outputs = append(c.outputs, path)
203 return c
204}
205
206func (c *RuleBuilderCommand) FlagWithInput(flag, path string) *RuleBuilderCommand {
207 c.inputs = append(c.inputs, path)
208 return c.Text(flag + path)
209}
210
211func (c *RuleBuilderCommand) FlagWithInputList(flag string, paths []string, sep string) *RuleBuilderCommand {
212 c.inputs = append(c.inputs, paths...)
213 return c.FlagWithList(flag, paths, sep)
214}
215
216func (c *RuleBuilderCommand) FlagWithOutput(flag, path string) *RuleBuilderCommand {
217 c.outputs = append(c.outputs, path)
218 return c.Text(flag + path)
219}
220
221type unknownRulePath struct {
222 path string
223}
224
225var _ Path = (*unknownRulePath)(nil)
226
227func (p *unknownRulePath) String() string { return p.path }
228func (p *unknownRulePath) Ext() string { return filepath.Ext(p.path) }
229func (p *unknownRulePath) Base() string { return filepath.Base(p.path) }
230func (p *unknownRulePath) Rel() string { return p.path }