blob: a5cf91ae48e7811e71af25e9d382f20d29432249 [file] [log] [blame]
Andres Moralesda8706f2015-04-29 12:46:49 -07001package main
2
3import (
Colin Crossb0931242015-06-29 14:18:27 -07004 "bytes"
Andres Morales8ae47de2015-05-11 12:26:07 -07005 "errors"
Andres Moralesda8706f2015-04-29 12:46:49 -07006 "fmt"
Colin Crossb0931242015-06-29 14:18:27 -07007 "io"
Andres Moralesda8706f2015-04-29 12:46:49 -07008 "os"
9 "path"
Andres Morales8ae47de2015-05-11 12:26:07 -070010 "path/filepath"
Andres Moralesaf11df12015-04-30 12:14:34 -070011 "regexp"
Andres Moralesda8706f2015-04-29 12:46:49 -070012 "strings"
Colin Crossb1a66c02015-06-29 16:24:57 -070013 "text/scanner"
Andres Moralesda8706f2015-04-29 12:46:49 -070014
Colin Crossb3245e92015-06-30 16:27:57 -070015 "github.com/google/blueprint"
Andres Moralesda8706f2015-04-29 12:46:49 -070016 bpparser "github.com/google/blueprint/parser"
17)
18
Andres Morales8ae47de2015-05-11 12:26:07 -070019var recursiveSubdirRegex *regexp.Regexp = regexp.MustCompile("(.+)/\\*\\*/(.+)")
20
Dan Willemsen3a4045d2015-06-24 15:37:17 -070021type Module struct {
22 bpmod *bpparser.Module
23 bpname string
24 mkname string
25 isHostRule bool
26}
27
28func newModule(mod *bpparser.Module) *Module {
29 return &Module{
30 bpmod: mod,
31 bpname: mod.Type.Name,
32 }
33}
34
Colin Crossb0931242015-06-29 14:18:27 -070035func (m *Module) translateRuleName() error {
36 var name string
Dan Willemsen3a4045d2015-06-24 15:37:17 -070037 if translation, ok := moduleTypeToRule[m.bpname]; ok {
38 name = translation
Colin Crossb0931242015-06-29 14:18:27 -070039 } else {
40 return fmt.Errorf("Unknown module type %q", m.bpname)
Dan Willemsen3a4045d2015-06-24 15:37:17 -070041 }
42
43 if m.isHostRule {
44 if trans, ok := targetToHostModuleRule[name]; ok {
45 name = trans
46 } else {
Colin Crossb0931242015-06-29 14:18:27 -070047 return fmt.Errorf("No corresponding host rule for %q", name)
Dan Willemsen3a4045d2015-06-24 15:37:17 -070048 }
49 } else {
50 m.isHostRule = strings.Contains(name, "HOST")
51 }
52
53 m.mkname = name
Colin Crossb0931242015-06-29 14:18:27 -070054
55 return nil
Dan Willemsen3a4045d2015-06-24 15:37:17 -070056}
57
Andres Moralesda8706f2015-04-29 12:46:49 -070058type androidMkWriter struct {
Colin Crossb0931242015-06-29 14:18:27 -070059 io.Writer
Andres Moralesda8706f2015-04-29 12:46:49 -070060
Andres Moralesaf11df12015-04-30 12:14:34 -070061 blueprint *bpparser.File
62 path string
Andres Moralesda8706f2015-04-29 12:46:49 -070063}
64
Colin Crossb0931242015-06-29 14:18:27 -070065func (w *androidMkWriter) WriteString(s string) (int, error) {
66 return io.WriteString(w.Writer, s)
67}
68
69func valueToString(value bpparser.Value) (string, error) {
Colin Crossb3245e92015-06-30 16:27:57 -070070 switch value.Type {
71 case bpparser.Bool:
72 return fmt.Sprintf("%t", value.BoolValue), nil
73 case bpparser.String:
74 return fmt.Sprintf("%s", processWildcards(value.StringValue)), nil
75 case bpparser.List:
76 val, err := listToMkString(value.ListValue)
Colin Crossb0931242015-06-29 14:18:27 -070077 if err != nil {
78 return "", err
79 }
Colin Crossb3245e92015-06-30 16:27:57 -070080 return fmt.Sprintf("\\\n%s", val), nil
81 case bpparser.Map:
82 return "", fmt.Errorf("Can't convert map to string")
83 default:
84 return "", fmt.Errorf("ERROR: unsupported type %d", value.Type)
Andres Moralesda8706f2015-04-29 12:46:49 -070085 }
Andres Moralesda8706f2015-04-29 12:46:49 -070086}
87
Andres Morales8ae47de2015-05-11 12:26:07 -070088func getTopOfAndroidTree(wd string) (string, error) {
89 if !filepath.IsAbs(wd) {
90 return "", errors.New("path must be absolute: " + wd)
91 }
92
93 topfile := "build/soong/bootstrap.bash"
94
95 for "/" != wd {
96 expected := filepath.Join(wd, topfile)
97
98 if _, err := os.Stat(expected); err == nil {
99 // Found the top
100 return wd, nil
101 }
102
103 wd = filepath.Join(wd, "..")
104 }
105
106 return "", errors.New("couldn't find top of tree from " + wd)
107}
108
Andres Moralesaf11df12015-04-30 12:14:34 -0700109// TODO: handle non-recursive wildcards?
110func processWildcards(s string) string {
Andres Morales8ae47de2015-05-11 12:26:07 -0700111 submatches := recursiveSubdirRegex.FindStringSubmatch(s)
112 if len(submatches) > 2 {
Andres Moralesaf11df12015-04-30 12:14:34 -0700113 // Found a wildcard rule
114 return fmt.Sprintf("$(call find-files-in-subdirs, $(LOCAL_PATH), %s, %s)",
Andres Morales8ae47de2015-05-11 12:26:07 -0700115 submatches[2], submatches[1])
Andres Moralesaf11df12015-04-30 12:14:34 -0700116 }
117
118 return s
119}
120
Colin Crossb0931242015-06-29 14:18:27 -0700121func listToMkString(list []bpparser.Value) (string, error) {
Andres Moralesda8706f2015-04-29 12:46:49 -0700122 lines := make([]string, 0, len(list))
123 for _, tok := range list {
Colin Crossb0931242015-06-29 14:18:27 -0700124 val, err := valueToString(tok)
125 if err != nil {
126 return "", err
127 }
128 lines = append(lines, fmt.Sprintf(" %s", val))
Andres Moralesda8706f2015-04-29 12:46:49 -0700129 }
130
Colin Crossb0931242015-06-29 14:18:27 -0700131 return strings.Join(lines, " \\\n"), nil
Andres Moralesda8706f2015-04-29 12:46:49 -0700132}
133
Andres Moralesaf11df12015-04-30 12:14:34 -0700134func translateTargetConditionals(props []*bpparser.Property,
Colin Crossb0931242015-06-29 14:18:27 -0700135 disabledBuilds map[string]bool, isHostRule bool) (computedProps []string, err error) {
Andres Moralesaf11df12015-04-30 12:14:34 -0700136 for _, target := range props {
137 conditionals := targetScopedPropertyConditionals
Dan Willemsen68fdfcc2015-06-11 14:05:01 -0700138 altConditionals := hostScopedPropertyConditionals
Andres Moralesaf11df12015-04-30 12:14:34 -0700139 if isHostRule {
Dan Willemsen68fdfcc2015-06-11 14:05:01 -0700140 conditionals, altConditionals = altConditionals, conditionals
Andres Moralesaf11df12015-04-30 12:14:34 -0700141 }
142
143 conditional, ok := conditionals[target.Name.Name]
144 if !ok {
Dan Willemsen68fdfcc2015-06-11 14:05:01 -0700145 if _, ok := altConditionals[target.Name.Name]; ok {
146 // This is only for the other build type
147 continue
148 } else {
Colin Crossb0931242015-06-29 14:18:27 -0700149 return nil, fmt.Errorf("Unsupported conditional %q", target.Name.Name)
Dan Willemsen68fdfcc2015-06-11 14:05:01 -0700150 }
Andres Moralesaf11df12015-04-30 12:14:34 -0700151 }
152
153 var scopedProps []string
154 for _, targetScopedProp := range target.Value.MapValue {
155 if mkProp, ok := standardProperties[targetScopedProp.Name.Name]; ok {
Colin Crossb0931242015-06-29 14:18:27 -0700156 val, err := valueToString(targetScopedProp.Value)
157 if err != nil {
158 return nil, err
159 }
Andres Moralesaf11df12015-04-30 12:14:34 -0700160 scopedProps = append(scopedProps, fmt.Sprintf("%s += %s",
Colin Crossb0931242015-06-29 14:18:27 -0700161 mkProp.string, val))
Dan Willemsen57ad08c2015-06-10 16:20:14 -0700162 } else if rwProp, ok := rewriteProperties[targetScopedProp.Name.Name]; ok {
Colin Crossb0931242015-06-29 14:18:27 -0700163 props, err := rwProp.f(rwProp.string, targetScopedProp, nil)
164 if err != nil {
165 return nil, err
166 }
167 scopedProps = append(scopedProps, props...)
Andres Moralesaf11df12015-04-30 12:14:34 -0700168 } else if "disabled" == targetScopedProp.Name.Name {
169 if targetScopedProp.Value.BoolValue {
170 disabledBuilds[target.Name.Name] = true
171 } else {
172 delete(disabledBuilds, target.Name.Name)
173 }
Colin Crossb0931242015-06-29 14:18:27 -0700174 } else {
175 return nil, fmt.Errorf("Unsupported target property %q", targetScopedProp.Name.Name)
Andres Moralesaf11df12015-04-30 12:14:34 -0700176 }
177 }
178
179 if len(scopedProps) > 0 {
Dan Willemsen68fdfcc2015-06-11 14:05:01 -0700180 if conditional != "" {
181 computedProps = append(computedProps, conditional)
182 computedProps = append(computedProps, scopedProps...)
183 computedProps = append(computedProps, "endif")
184 } else {
185 computedProps = append(computedProps, scopedProps...)
186 }
Andres Moralesaf11df12015-04-30 12:14:34 -0700187 }
Andres Moralesda8706f2015-04-29 12:46:49 -0700188 }
Andres Moralesaf11df12015-04-30 12:14:34 -0700189
190 return
191}
192
193func translateSuffixProperties(suffixProps []*bpparser.Property,
Colin Crossb0931242015-06-29 14:18:27 -0700194 suffixMap map[string]string) (computedProps []string, err error) {
Andres Moralesaf11df12015-04-30 12:14:34 -0700195 for _, suffixProp := range suffixProps {
196 if suffix, ok := suffixMap[suffixProp.Name.Name]; ok {
197 for _, stdProp := range suffixProp.Value.MapValue {
198 if mkProp, ok := standardProperties[stdProp.Name.Name]; ok {
Colin Crossb0931242015-06-29 14:18:27 -0700199 val, err := valueToString(stdProp.Value)
200 if err != nil {
201 return nil, err
202 }
203 computedProps = append(computedProps, fmt.Sprintf("%s_%s := %s", mkProp.string, suffix, val))
Dan Willemsen57ad08c2015-06-10 16:20:14 -0700204 } else if rwProp, ok := rewriteProperties[stdProp.Name.Name]; ok {
Colin Crossb0931242015-06-29 14:18:27 -0700205 props, err := rwProp.f(rwProp.string, stdProp, &suffix)
206 if err != nil {
207 return nil, err
208 }
209 computedProps = append(computedProps, props...)
Andres Moralesaf11df12015-04-30 12:14:34 -0700210 } else {
Colin Crossb0931242015-06-29 14:18:27 -0700211 return nil, fmt.Errorf("Unsupported property %q", stdProp.Name.Name)
Andres Moralesaf11df12015-04-30 12:14:34 -0700212 }
213 }
Colin Crossb0931242015-06-29 14:18:27 -0700214 } else {
215 return nil, fmt.Errorf("Unsupported suffix property %q", suffixProp.Name.Name)
Andres Moralesaf11df12015-04-30 12:14:34 -0700216 }
217 }
218 return
219}
220
Colin Crossb0931242015-06-29 14:18:27 -0700221func prependLocalPath(name string, prop *bpparser.Property, suffix *string) ([]string, error) {
Dan Willemsen57ad08c2015-06-10 16:20:14 -0700222 if suffix != nil {
223 name += "_" + *suffix
224 }
Colin Crossb0931242015-06-29 14:18:27 -0700225 val, err := valueToString(prop.Value)
226 if err != nil {
227 return nil, err
228 }
Colin Crossff3b7952015-06-22 15:39:35 -0700229 return []string{
Colin Crossb0931242015-06-29 14:18:27 -0700230 fmt.Sprintf("%s := $(addprefix $(LOCAL_PATH)/,%s)\n", name, val),
231 }, nil
Dan Willemsen57ad08c2015-06-10 16:20:14 -0700232}
233
Colin Crossb0931242015-06-29 14:18:27 -0700234func prependLocalModule(name string, prop *bpparser.Property, suffix *string) ([]string, error) {
Dan Willemsen1d9f2792015-06-22 15:40:14 -0700235 if suffix != nil {
236 name += "_" + *suffix
237 }
Colin Crossb0931242015-06-29 14:18:27 -0700238 val, err := valueToString(prop.Value)
239 if err != nil {
240 return nil, err
Dan Willemsen1d9f2792015-06-22 15:40:14 -0700241 }
Colin Crossb0931242015-06-29 14:18:27 -0700242 return []string{
243 fmt.Sprintf("%s := $(LOCAL_MODULE)%s\n", name, val),
244 }, nil
Dan Willemsen1d9f2792015-06-22 15:40:14 -0700245}
246
Dan Willemsen3a4045d2015-06-24 15:37:17 -0700247func modulePropBool(module *bpparser.Module, name string) bool {
248 for _, prop := range module.Properties {
249 if name == prop.Name.Name {
250 return prop.Value.BoolValue
251 }
252 }
253 return false
254}
255
Andres Moralesaf11df12015-04-30 12:14:34 -0700256func (w *androidMkWriter) writeModule(moduleRule string, props []string,
257 disabledBuilds map[string]bool, isHostRule bool) {
258 disabledConditionals := disabledTargetConditionals
259 if isHostRule {
260 disabledConditionals = disabledHostConditionals
261 }
262 for build, _ := range disabledBuilds {
263 if conditional, ok := disabledConditionals[build]; ok {
264 fmt.Fprintf(w, "%s\n", conditional)
265 defer fmt.Fprintf(w, "endif\n")
Andres Moralesda8706f2015-04-29 12:46:49 -0700266 }
Andres Moralesaf11df12015-04-30 12:14:34 -0700267 }
Andres Moralesda8706f2015-04-29 12:46:49 -0700268
Andres Moralesaf11df12015-04-30 12:14:34 -0700269 fmt.Fprintf(w, "include $(CLEAR_VARS)\n")
270 fmt.Fprintf(w, "%s\n", strings.Join(props, "\n"))
271 fmt.Fprintf(w, "include $(%s)\n\n", moduleRule)
272}
Andres Moralesda8706f2015-04-29 12:46:49 -0700273
Colin Crossb0931242015-06-29 14:18:27 -0700274func (w *androidMkWriter) parsePropsAndWriteModule(module *Module) error {
Dan Willemsen3a4045d2015-06-24 15:37:17 -0700275 standardProps := make([]string, 0, len(module.bpmod.Properties))
Andres Moralesaf11df12015-04-30 12:14:34 -0700276 disabledBuilds := make(map[string]bool)
Dan Willemsen3a4045d2015-06-24 15:37:17 -0700277 for _, prop := range module.bpmod.Properties {
Andres Moralesaf11df12015-04-30 12:14:34 -0700278 if mkProp, ok := standardProperties[prop.Name.Name]; ok {
Colin Crossb0931242015-06-29 14:18:27 -0700279 val, err := valueToString(prop.Value)
280 if err != nil {
281 return err
282 }
283 standardProps = append(standardProps, fmt.Sprintf("%s := %s", mkProp.string, val))
Dan Willemsen57ad08c2015-06-10 16:20:14 -0700284 } else if rwProp, ok := rewriteProperties[prop.Name.Name]; ok {
Colin Crossb0931242015-06-29 14:18:27 -0700285 props, err := rwProp.f(rwProp.string, prop, nil)
286 if err != nil {
287 return err
288 }
289 standardProps = append(standardProps, props...)
Andres Moralesaf11df12015-04-30 12:14:34 -0700290 } else if suffixMap, ok := suffixProperties[prop.Name.Name]; ok {
Colin Crossb3245e92015-06-30 16:27:57 -0700291 props, err := translateSuffixProperties(prop.Value.MapValue, suffixMap)
Colin Crossb0931242015-06-29 14:18:27 -0700292 if err != nil {
293 return err
294 }
295 standardProps = append(standardProps, props...)
Andres Moralesaf11df12015-04-30 12:14:34 -0700296 } else if "target" == prop.Name.Name {
Colin Crossb3245e92015-06-30 16:27:57 -0700297 props, err := translateTargetConditionals(prop.Value.MapValue, disabledBuilds, module.isHostRule)
Colin Crossb0931242015-06-29 14:18:27 -0700298 if err != nil {
299 return err
300 }
301 standardProps = append(standardProps, props...)
Dan Willemsen0a544692015-06-24 15:50:07 -0700302 } else if _, ok := ignoredProperties[prop.Name.Name]; ok {
Andres Moralesaf11df12015-04-30 12:14:34 -0700303 } else {
Colin Crossb0931242015-06-29 14:18:27 -0700304 return fmt.Errorf("Unsupported property %q", prop.Name.Name)
Andres Moralesaf11df12015-04-30 12:14:34 -0700305 }
306 }
307
Dan Willemsen3a4045d2015-06-24 15:37:17 -0700308 w.writeModule(module.mkname, standardProps, disabledBuilds, module.isHostRule)
Colin Crossb0931242015-06-29 14:18:27 -0700309
310 return nil
Dan Willemsen68fdfcc2015-06-11 14:05:01 -0700311}
312
Colin Crossb0931242015-06-29 14:18:27 -0700313func (w *androidMkWriter) mutateModule(module *Module) (modules []*Module, err error) {
Dan Willemsen3a4045d2015-06-24 15:37:17 -0700314 modules = []*Module{module}
Dan Willemsen49f50452015-06-24 14:56:00 -0700315
Dan Willemsen3a4045d2015-06-24 15:37:17 -0700316 if module.bpname == "cc_library" {
317 modules = []*Module{
318 newModule(module.bpmod),
319 newModule(module.bpmod),
320 }
321 modules[0].bpname = "cc_library_shared"
322 modules[1].bpname = "cc_library_static"
323 }
324
325 for _, mod := range modules {
Colin Crossb0931242015-06-29 14:18:27 -0700326 err := mod.translateRuleName()
327 if err != nil {
328 return nil, err
329 }
Dan Willemsen3a4045d2015-06-24 15:37:17 -0700330 if mod.isHostRule || !modulePropBool(mod.bpmod, "host_supported") {
331 continue
332 }
333
334 m := &Module{
335 bpmod: mod.bpmod,
336 bpname: mod.bpname,
337 isHostRule: true,
338 }
Colin Crossb0931242015-06-29 14:18:27 -0700339 err = m.translateRuleName()
340 if err != nil {
341 return nil, err
342 }
Dan Willemsen3a4045d2015-06-24 15:37:17 -0700343 modules = append(modules, m)
Dan Willemsen68fdfcc2015-06-11 14:05:01 -0700344 }
345
Dan Willemsen49f50452015-06-24 14:56:00 -0700346 return
347}
Dan Willemsen68fdfcc2015-06-11 14:05:01 -0700348
Colin Crossb0931242015-06-29 14:18:27 -0700349func (w *androidMkWriter) handleModule(inputModule *bpparser.Module) error {
Colin Crossb1a66c02015-06-29 16:24:57 -0700350 comment := w.getCommentBlock(inputModule.Type.Pos)
351 if translation, translated, err := getCommentTranslation(comment); err != nil {
352 return err
353 } else if translated {
354 w.WriteString(translation)
355 return nil
356 }
357
Colin Cross70a5f072015-06-29 17:44:56 -0700358 if ignoredModuleType[inputModule.Type.Name] {
359 return nil
360 }
361
Colin Crossb0931242015-06-29 14:18:27 -0700362 modules, err := w.mutateModule(newModule(inputModule))
363 if err != nil {
364 return err
365 }
Dan Willemsen49f50452015-06-24 14:56:00 -0700366
367 for _, module := range modules {
Colin Crossb0931242015-06-29 14:18:27 -0700368 err := w.parsePropsAndWriteModule(module)
369 if err != nil {
370 return err
371 }
Andres Moralesaf11df12015-04-30 12:14:34 -0700372 }
Colin Crossb0931242015-06-29 14:18:27 -0700373
374 return nil
Andres Moralesaf11df12015-04-30 12:14:34 -0700375}
376
377func (w *androidMkWriter) handleSubdirs(value bpparser.Value) {
Andres Morales8ae47de2015-05-11 12:26:07 -0700378 subdirs := make([]string, 0, len(value.ListValue))
379 for _, tok := range value.ListValue {
380 subdirs = append(subdirs, tok.StringValue)
Andres Moralesda8706f2015-04-29 12:46:49 -0700381 }
Ying Wang38284902015-06-02 18:44:59 -0700382 // The current makefile may be generated to outside the source tree (such as the out directory), with a different structure.
383 fmt.Fprintf(w, "# Uncomment the following line if you really want to include subdir Android.mks.\n")
384 fmt.Fprintf(w, "# include $(wildcard $(addsuffix $(LOCAL_PATH)/%s/, Android.mk))\n", strings.Join(subdirs, " "))
Andres Moralesda8706f2015-04-29 12:46:49 -0700385}
386
Andres Morales8ae47de2015-05-11 12:26:07 -0700387func (w *androidMkWriter) handleLocalPath() error {
Colin Crossb3245e92015-06-30 16:27:57 -0700388 w.WriteString("LOCAL_PATH := " + w.path + "\n")
Dan Willemsenc2666e62015-06-10 16:18:58 -0700389 w.WriteString("LOCAL_MODULE_MAKEFILE := $(lastword $(MAKEFILE_LIST))\n\n")
Andres Morales8ae47de2015-05-11 12:26:07 -0700390 return nil
391}
392
Colin Crossb1a66c02015-06-29 16:24:57 -0700393// Returns any block comment on the line preceding pos as a string
394func (w *androidMkWriter) getCommentBlock(pos scanner.Position) string {
395 var buf []byte
396
397 comments := w.blueprint.Comments
398 for i, c := range comments {
399 if c.EndLine() == pos.Line-1 {
400 line := pos.Line
401 for j := i; j >= 0; j-- {
402 c = comments[j]
403 if c.EndLine() == line-1 {
404 buf = append([]byte(c.Text()), buf...)
405 line = c.Pos.Line
406 } else {
407 break
408 }
409 }
410 }
411 }
412
413 return string(buf)
414}
415
416func getCommentTranslation(comment string) (string, bool, error) {
417 lines := strings.Split(comment, "\n")
418
419 if directive, i, err := getCommentDirective(lines); err != nil {
420 return "", false, err
421 } else if directive != "" {
422 switch directive {
423 case "ignore":
424 return "", true, nil
425 case "start":
426 return getCommentTranslationBlock(lines[i+1:])
427 case "end":
428 return "", false, fmt.Errorf("Unexpected Android.mk:end translation directive")
429 default:
430 return "", false, fmt.Errorf("Unknown Android.mk module translation directive %q", directive)
431 }
432 }
433
434 return "", false, nil
435}
436
437func getCommentTranslationBlock(lines []string) (string, bool, error) {
438 var buf []byte
439
440 for _, line := range lines {
441 if directive := getLineCommentDirective(line); directive != "" {
442 switch directive {
443 case "end":
444 return string(buf), true, nil
445 default:
446 return "", false, fmt.Errorf("Unexpected Android.mk translation directive %q inside start", directive)
447 }
448 } else {
449 buf = append(buf, line...)
450 buf = append(buf, '\n')
451 }
452 }
453
454 return "", false, fmt.Errorf("Missing Android.mk:end translation directive")
455}
456
457func getCommentDirective(lines []string) (directive string, n int, err error) {
458 for i, line := range lines {
459 if directive := getLineCommentDirective(line); directive != "" {
460 return strings.ToLower(directive), i, nil
461 }
462 }
463
464 return "", -1, nil
465}
466
467func getLineCommentDirective(line string) string {
468 line = strings.TrimSpace(line)
469 if strings.HasPrefix(line, "Android.mk:") {
470 line = strings.TrimPrefix(line, "Android.mk:")
471 line = strings.TrimSpace(line)
472 return line
473 }
474
475 return ""
476}
477
Colin Crossb0931242015-06-29 14:18:27 -0700478func (w *androidMkWriter) write(writer io.Writer) (err error) {
479 w.Writer = writer
Andres Moralesda8706f2015-04-29 12:46:49 -0700480
Colin Crossb0931242015-06-29 14:18:27 -0700481 if err = w.handleLocalPath(); err != nil {
Colin Cross26478b72015-06-29 13:46:00 -0700482 return err
483 }
484
485 for _, block := range w.blueprint.Defs {
Andres Moralesda8706f2015-04-29 12:46:49 -0700486 switch block := block.(type) {
487 case *bpparser.Module:
Colin Crossb0931242015-06-29 14:18:27 -0700488 err = w.handleModule(block)
Andres Moralesda8706f2015-04-29 12:46:49 -0700489 case *bpparser.Assignment:
Colin Crossb3245e92015-06-30 16:27:57 -0700490 // Nothing
Colin Crossb0931242015-06-29 14:18:27 -0700491 default:
492 return fmt.Errorf("Unhandled def %v", block)
493 }
494 if err != nil {
495 return err
Andres Moralesda8706f2015-04-29 12:46:49 -0700496 }
497 }
498
Ying Wang38284902015-06-02 18:44:59 -0700499 return nil
Andres Moralesda8706f2015-04-29 12:46:49 -0700500}
501
Colin Crossb3245e92015-06-30 16:27:57 -0700502func translate(rootFile, androidBp, androidMk string) error {
Andres Moralesda8706f2015-04-29 12:46:49 -0700503
Colin Crossb3245e92015-06-30 16:27:57 -0700504 ctx := blueprint.NewContext()
505
506 var blueprintFile *bpparser.File
507
508 _, errs := ctx.WalkBlueprintsFiles(rootFile, func(file *bpparser.File) {
509 if file.Name == androidBp {
510 blueprintFile = file
511 }
512 })
Andres Moralesda8706f2015-04-29 12:46:49 -0700513 if len(errs) > 0 {
Colin Crossb0931242015-06-29 14:18:27 -0700514 return errs[0]
Andres Moralesda8706f2015-04-29 12:46:49 -0700515 }
516
Colin Crossb3245e92015-06-30 16:27:57 -0700517 if blueprintFile == nil {
518 return fmt.Errorf("File %q wasn't parsed from %q", androidBp, rootFile)
519 }
520
Andres Moralesda8706f2015-04-29 12:46:49 -0700521 writer := &androidMkWriter{
Colin Crossb3245e92015-06-30 16:27:57 -0700522 blueprint: blueprintFile,
Ying Wang38284902015-06-02 18:44:59 -0700523 path: path.Dir(androidBp),
Andres Moralesda8706f2015-04-29 12:46:49 -0700524 }
525
Colin Crossb0931242015-06-29 14:18:27 -0700526 buf := &bytes.Buffer{}
527
Colin Crossb3245e92015-06-30 16:27:57 -0700528 err := writer.write(buf)
Ying Wang38284902015-06-02 18:44:59 -0700529 if err != nil {
Colin Crossb0931242015-06-29 14:18:27 -0700530 os.Remove(androidMk)
531 return err
532 }
533
534 f, err := os.Create(androidMk)
535 if err != nil {
536 return err
537 }
538 defer f.Close()
539
540 _, err = f.Write(buf.Bytes())
541
542 return err
543}
544
545func main() {
Colin Crossb3245e92015-06-30 16:27:57 -0700546 if len(os.Args) < 4 {
547 fmt.Fprintln(os.Stderr, "Expected root Android.bp, input and output filename arguments")
Colin Crossb0931242015-06-29 14:18:27 -0700548 os.Exit(1)
549 }
550
Colin Crossb3245e92015-06-30 16:27:57 -0700551 rootFile := os.Args[1]
552 androidBp, err := filepath.Rel(filepath.Dir(rootFile), os.Args[2])
553 if err != nil {
554 fmt.Fprintf(os.Stderr, "Android.bp file %q is not relative to %q: %s\n",
555 os.Args[2], rootFile, err.Error())
556 os.Exit(1)
557 }
558 androidMk := os.Args[3]
Colin Crossb0931242015-06-29 14:18:27 -0700559
Colin Crossb3245e92015-06-30 16:27:57 -0700560 err = translate(rootFile, androidBp, androidMk)
Colin Crossb0931242015-06-29 14:18:27 -0700561 if err != nil {
562 fmt.Fprintf(os.Stderr, "Error translating %s: %s\n", androidBp, err.Error())
Ying Wang38284902015-06-02 18:44:59 -0700563 os.Exit(1)
564 }
Andres Moralesda8706f2015-04-29 12:46:49 -0700565}