blob: a8f4580c3a17a6033bf805f235fd2301b8a49d55 [file] [log] [blame]
Andres Moralesda8706f2015-04-29 12:46:49 -07001package main
2
3import (
4 "bufio"
Andres Morales8ae47de2015-05-11 12:26:07 -07005 "errors"
Andres Moralesda8706f2015-04-29 12:46:49 -07006 "fmt"
7 "os"
8 "path"
Andres Morales8ae47de2015-05-11 12:26:07 -07009 "path/filepath"
Andres Moralesaf11df12015-04-30 12:14:34 -070010 "regexp"
Andres Moralesda8706f2015-04-29 12:46:49 -070011 "strings"
12
13 bpparser "github.com/google/blueprint/parser"
14)
15
Andres Morales8ae47de2015-05-11 12:26:07 -070016var recursiveSubdirRegex *regexp.Regexp = regexp.MustCompile("(.+)/\\*\\*/(.+)")
17
Dan Willemsen3a4045d2015-06-24 15:37:17 -070018type Module struct {
19 bpmod *bpparser.Module
20 bpname string
21 mkname string
22 isHostRule bool
23}
24
25func newModule(mod *bpparser.Module) *Module {
26 return &Module{
27 bpmod: mod,
28 bpname: mod.Type.Name,
29 }
30}
31
32func (m *Module) translateRuleName() {
33 name := fmt.Sprintf(m.bpname)
34 if translation, ok := moduleTypeToRule[m.bpname]; ok {
35 name = translation
36 }
37
38 if m.isHostRule {
39 if trans, ok := targetToHostModuleRule[name]; ok {
40 name = trans
41 } else {
42 name = "NO CORRESPONDING HOST RULE" + name
43 }
44 } else {
45 m.isHostRule = strings.Contains(name, "HOST")
46 }
47
48 m.mkname = name
49}
50
Andres Moralesda8706f2015-04-29 12:46:49 -070051type androidMkWriter struct {
52 *bufio.Writer
53
Andres Moralesaf11df12015-04-30 12:14:34 -070054 blueprint *bpparser.File
55 path string
56
Dan Willemsen360a39c2015-06-11 14:34:50 -070057 printedLocalPath bool
58
Andres Moralesaf11df12015-04-30 12:14:34 -070059 mapScope map[string][]*bpparser.Property
Andres Moralesda8706f2015-04-29 12:46:49 -070060}
61
Andres Moralesaf11df12015-04-30 12:14:34 -070062func valueToString(value bpparser.Value) string {
Andres Moralesda8706f2015-04-29 12:46:49 -070063 if value.Variable != "" {
64 return fmt.Sprintf("$(%s)", value.Variable)
Colin Crossff3b7952015-06-22 15:39:35 -070065 } else if value.Expression != nil {
66 if value.Expression.Operator != '+' {
67 panic(fmt.Errorf("unexpected operator '%c'", value.Expression.Operator))
68 }
Colin Crosseb050832015-06-22 17:26:12 -070069 return fmt.Sprintf("%s%s",
Colin Crossff3b7952015-06-22 15:39:35 -070070 valueToString(value.Expression.Args[0]),
71 valueToString(value.Expression.Args[1]))
Andres Moralesda8706f2015-04-29 12:46:49 -070072 } else {
73 switch value.Type {
74 case bpparser.Bool:
Ying Wang38284902015-06-02 18:44:59 -070075 return fmt.Sprintf("%t", value.BoolValue)
Andres Moralesda8706f2015-04-29 12:46:49 -070076 case bpparser.String:
Ying Wang38284902015-06-02 18:44:59 -070077 return fmt.Sprintf("%s", processWildcards(value.StringValue))
Andres Moralesda8706f2015-04-29 12:46:49 -070078 case bpparser.List:
Colin Crossff3b7952015-06-22 15:39:35 -070079 return fmt.Sprintf("\\\n%s", listToMkString(value.ListValue))
Andres Moralesda8706f2015-04-29 12:46:49 -070080 case bpparser.Map:
Andres Moralesaf11df12015-04-30 12:14:34 -070081 return fmt.Sprintf("ERROR can't convert map to string")
82 default:
83 return fmt.Sprintf("ERROR: unsupported type %d", value.Type)
Andres Moralesda8706f2015-04-29 12:46:49 -070084 }
85 }
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
121func listToMkString(list []bpparser.Value) string {
Andres Moralesda8706f2015-04-29 12:46:49 -0700122 lines := make([]string, 0, len(list))
123 for _, tok := range list {
Colin Crosseb050832015-06-22 17:26:12 -0700124 lines = append(lines, fmt.Sprintf(" %s", valueToString(tok)))
Andres Moralesda8706f2015-04-29 12:46:49 -0700125 }
126
127 return strings.Join(lines, " \\\n")
128}
129
Andres Moralesaf11df12015-04-30 12:14:34 -0700130func translateTargetConditionals(props []*bpparser.Property,
131 disabledBuilds map[string]bool, isHostRule bool) (computedProps []string) {
132 for _, target := range props {
133 conditionals := targetScopedPropertyConditionals
Dan Willemsen68fdfcc2015-06-11 14:05:01 -0700134 altConditionals := hostScopedPropertyConditionals
Andres Moralesaf11df12015-04-30 12:14:34 -0700135 if isHostRule {
Dan Willemsen68fdfcc2015-06-11 14:05:01 -0700136 conditionals, altConditionals = altConditionals, conditionals
Andres Moralesaf11df12015-04-30 12:14:34 -0700137 }
138
139 conditional, ok := conditionals[target.Name.Name]
140 if !ok {
Dan Willemsen68fdfcc2015-06-11 14:05:01 -0700141 if _, ok := altConditionals[target.Name.Name]; ok {
142 // This is only for the other build type
143 continue
144 } else {
145 // not found
146 conditional = fmt.Sprintf(
147 "ifeq(true, true) # ERROR: unsupported conditional [%s]",
148 target.Name.Name)
149 }
Andres Moralesaf11df12015-04-30 12:14:34 -0700150 }
151
152 var scopedProps []string
153 for _, targetScopedProp := range target.Value.MapValue {
154 if mkProp, ok := standardProperties[targetScopedProp.Name.Name]; ok {
155 scopedProps = append(scopedProps, fmt.Sprintf("%s += %s",
156 mkProp.string, valueToString(targetScopedProp.Value)))
Dan Willemsen57ad08c2015-06-10 16:20:14 -0700157 } else if rwProp, ok := rewriteProperties[targetScopedProp.Name.Name]; ok {
158 scopedProps = append(scopedProps, rwProp.f(rwProp.string, targetScopedProp, nil)...)
Andres Moralesaf11df12015-04-30 12:14:34 -0700159 } else if "disabled" == targetScopedProp.Name.Name {
160 if targetScopedProp.Value.BoolValue {
161 disabledBuilds[target.Name.Name] = true
162 } else {
163 delete(disabledBuilds, target.Name.Name)
164 }
165 }
166 }
167
168 if len(scopedProps) > 0 {
Dan Willemsen68fdfcc2015-06-11 14:05:01 -0700169 if conditional != "" {
170 computedProps = append(computedProps, conditional)
171 computedProps = append(computedProps, scopedProps...)
172 computedProps = append(computedProps, "endif")
173 } else {
174 computedProps = append(computedProps, scopedProps...)
175 }
Andres Moralesaf11df12015-04-30 12:14:34 -0700176 }
Andres Moralesda8706f2015-04-29 12:46:49 -0700177 }
Andres Moralesaf11df12015-04-30 12:14:34 -0700178
179 return
180}
181
182func translateSuffixProperties(suffixProps []*bpparser.Property,
183 suffixMap map[string]string) (computedProps []string) {
184 for _, suffixProp := range suffixProps {
185 if suffix, ok := suffixMap[suffixProp.Name.Name]; ok {
186 for _, stdProp := range suffixProp.Value.MapValue {
187 if mkProp, ok := standardProperties[stdProp.Name.Name]; ok {
188 computedProps = append(computedProps, fmt.Sprintf("%s_%s := %s", mkProp.string, suffix, valueToString(stdProp.Value)))
Dan Willemsen57ad08c2015-06-10 16:20:14 -0700189 } else if rwProp, ok := rewriteProperties[stdProp.Name.Name]; ok {
190 computedProps = append(computedProps, rwProp.f(rwProp.string, stdProp, &suffix)...)
Andres Moralesaf11df12015-04-30 12:14:34 -0700191 } else {
192 computedProps = append(computedProps, fmt.Sprintf("# ERROR: unsupported property %s", stdProp.Name.Name))
193 }
194 }
195 }
196 }
197 return
198}
199
Dan Willemsen57ad08c2015-06-10 16:20:14 -0700200func prependLocalPath(name string, prop *bpparser.Property, suffix *string) (computedProps []string) {
Dan Willemsen57ad08c2015-06-10 16:20:14 -0700201 if suffix != nil {
202 name += "_" + *suffix
203 }
Colin Crossff3b7952015-06-22 15:39:35 -0700204 return []string{
205 fmt.Sprintf("%s := $(addprefix $(LOCAL_PATH)/,%s)\n", name, valueToString(prop.Value)),
206 }
Dan Willemsen57ad08c2015-06-10 16:20:14 -0700207}
208
Dan Willemsen1d9f2792015-06-22 15:40:14 -0700209func prependLocalModule(name string, prop *bpparser.Property, suffix *string) (computedProps []string) {
210 if suffix != nil {
211 name += "_" + *suffix
212 }
213 return []string {
Dan Willemsend7b11dd2015-06-22 16:25:39 -0700214 fmt.Sprintf("%s := $(LOCAL_MODULE)%s\n", name, valueToString(prop.Value)),
Dan Willemsen1d9f2792015-06-22 15:40:14 -0700215 }
216}
217
Dan Willemsen3a4045d2015-06-24 15:37:17 -0700218func modulePropBool(module *bpparser.Module, name string) bool {
219 for _, prop := range module.Properties {
220 if name == prop.Name.Name {
221 return prop.Value.BoolValue
222 }
223 }
224 return false
225}
226
Andres Moralesaf11df12015-04-30 12:14:34 -0700227func (w *androidMkWriter) lookupMap(parent bpparser.Value) (mapValue []*bpparser.Property) {
228 if parent.Variable != "" {
229 mapValue = w.mapScope[parent.Variable]
230 } else {
231 mapValue = parent.MapValue
232 }
233 return
Andres Moralesda8706f2015-04-29 12:46:49 -0700234}
235
236func (w *androidMkWriter) handleComment(comment *bpparser.Comment) {
237 for _, c := range comment.Comment {
Andres Moralesaf11df12015-04-30 12:14:34 -0700238 fmt.Fprintf(w, "#%s\n", c)
Andres Moralesda8706f2015-04-29 12:46:49 -0700239 }
240}
241
Andres Moralesaf11df12015-04-30 12:14:34 -0700242func (w *androidMkWriter) writeModule(moduleRule string, props []string,
243 disabledBuilds map[string]bool, isHostRule bool) {
244 disabledConditionals := disabledTargetConditionals
245 if isHostRule {
246 disabledConditionals = disabledHostConditionals
247 }
248 for build, _ := range disabledBuilds {
249 if conditional, ok := disabledConditionals[build]; ok {
250 fmt.Fprintf(w, "%s\n", conditional)
251 defer fmt.Fprintf(w, "endif\n")
Andres Moralesda8706f2015-04-29 12:46:49 -0700252 }
Andres Moralesaf11df12015-04-30 12:14:34 -0700253 }
Andres Moralesda8706f2015-04-29 12:46:49 -0700254
Andres Moralesaf11df12015-04-30 12:14:34 -0700255 fmt.Fprintf(w, "include $(CLEAR_VARS)\n")
256 fmt.Fprintf(w, "%s\n", strings.Join(props, "\n"))
257 fmt.Fprintf(w, "include $(%s)\n\n", moduleRule)
258}
Andres Moralesda8706f2015-04-29 12:46:49 -0700259
Dan Willemsen3a4045d2015-06-24 15:37:17 -0700260func (w *androidMkWriter) parsePropsAndWriteModule(module *Module) {
261 standardProps := make([]string, 0, len(module.bpmod.Properties))
Andres Moralesaf11df12015-04-30 12:14:34 -0700262 disabledBuilds := make(map[string]bool)
Dan Willemsen3a4045d2015-06-24 15:37:17 -0700263 for _, prop := range module.bpmod.Properties {
Andres Moralesaf11df12015-04-30 12:14:34 -0700264 if mkProp, ok := standardProperties[prop.Name.Name]; ok {
265 standardProps = append(standardProps, fmt.Sprintf("%s := %s", mkProp.string, valueToString(prop.Value)))
Dan Willemsen57ad08c2015-06-10 16:20:14 -0700266 } else if rwProp, ok := rewriteProperties[prop.Name.Name]; ok {
267 standardProps = append(standardProps, rwProp.f(rwProp.string, prop, nil)...)
Andres Moralesaf11df12015-04-30 12:14:34 -0700268 } else if suffixMap, ok := suffixProperties[prop.Name.Name]; ok {
269 suffixProps := w.lookupMap(prop.Value)
270 standardProps = append(standardProps, translateSuffixProperties(suffixProps, suffixMap)...)
271 } else if "target" == prop.Name.Name {
272 props := w.lookupMap(prop.Value)
Dan Willemsen3a4045d2015-06-24 15:37:17 -0700273 standardProps = append(standardProps, translateTargetConditionals(props, disabledBuilds, module.isHostRule)...)
Dan Willemsen0a544692015-06-24 15:50:07 -0700274 } else if _, ok := ignoredProperties[prop.Name.Name]; ok {
Andres Moralesaf11df12015-04-30 12:14:34 -0700275 } else {
276 standardProps = append(standardProps, fmt.Sprintf("# ERROR: Unsupported property %s", prop.Name.Name))
277 }
278 }
279
Dan Willemsen3a4045d2015-06-24 15:37:17 -0700280 w.writeModule(module.mkname, standardProps, disabledBuilds, module.isHostRule)
Dan Willemsen68fdfcc2015-06-11 14:05:01 -0700281}
282
Dan Willemsen3a4045d2015-06-24 15:37:17 -0700283func (w *androidMkWriter) mutateModule(module *Module) (modules []*Module) {
284 modules = []*Module{module}
Dan Willemsen49f50452015-06-24 14:56:00 -0700285
Dan Willemsen3a4045d2015-06-24 15:37:17 -0700286 if module.bpname == "cc_library" {
287 modules = []*Module{
288 newModule(module.bpmod),
289 newModule(module.bpmod),
290 }
291 modules[0].bpname = "cc_library_shared"
292 modules[1].bpname = "cc_library_static"
293 }
294
295 for _, mod := range modules {
296 mod.translateRuleName()
297 if mod.isHostRule || !modulePropBool(mod.bpmod, "host_supported") {
298 continue
299 }
300
301 m := &Module{
302 bpmod: mod.bpmod,
303 bpname: mod.bpname,
304 isHostRule: true,
305 }
306 m.translateRuleName()
307 modules = append(modules, m)
Dan Willemsen68fdfcc2015-06-11 14:05:01 -0700308 }
309
Dan Willemsen49f50452015-06-24 14:56:00 -0700310 return
311}
Dan Willemsen68fdfcc2015-06-11 14:05:01 -0700312
Dan Willemsen49f50452015-06-24 14:56:00 -0700313func (w *androidMkWriter) handleModule(inputModule *bpparser.Module) {
Dan Willemsen3a4045d2015-06-24 15:37:17 -0700314 modules := w.mutateModule(newModule(inputModule))
Dan Willemsen49f50452015-06-24 14:56:00 -0700315
316 for _, module := range modules {
Dan Willemsen3a4045d2015-06-24 15:37:17 -0700317 w.parsePropsAndWriteModule(module)
Andres Moralesaf11df12015-04-30 12:14:34 -0700318 }
319}
320
321func (w *androidMkWriter) handleSubdirs(value bpparser.Value) {
Andres Morales8ae47de2015-05-11 12:26:07 -0700322 subdirs := make([]string, 0, len(value.ListValue))
323 for _, tok := range value.ListValue {
324 subdirs = append(subdirs, tok.StringValue)
Andres Moralesda8706f2015-04-29 12:46:49 -0700325 }
Ying Wang38284902015-06-02 18:44:59 -0700326 // The current makefile may be generated to outside the source tree (such as the out directory), with a different structure.
327 fmt.Fprintf(w, "# Uncomment the following line if you really want to include subdir Android.mks.\n")
328 fmt.Fprintf(w, "# include $(wildcard $(addsuffix $(LOCAL_PATH)/%s/, Android.mk))\n", strings.Join(subdirs, " "))
Andres Moralesda8706f2015-04-29 12:46:49 -0700329}
330
331func (w *androidMkWriter) handleAssignment(assignment *bpparser.Assignment) {
Andres Moralesaf11df12015-04-30 12:14:34 -0700332 if "subdirs" == assignment.Name.Name {
333 w.handleSubdirs(assignment.OrigValue)
334 } else if assignment.OrigValue.Type == bpparser.Map {
335 // maps may be assigned in Soong, but can only be translated to .mk
336 // in the context of the module
337 w.mapScope[assignment.Name.Name] = assignment.OrigValue.MapValue
338 } else {
339 assigner := ":="
340 if assignment.Assigner != "=" {
341 assigner = assignment.Assigner
342 }
343 fmt.Fprintf(w, "%s %s %s\n", assignment.Name.Name, assigner,
344 valueToString(assignment.OrigValue))
Andres Moralesda8706f2015-04-29 12:46:49 -0700345 }
Andres Moralesda8706f2015-04-29 12:46:49 -0700346}
347
348func (w *androidMkWriter) iter() <-chan interface{} {
Andres Moralesaf11df12015-04-30 12:14:34 -0700349 ch := make(chan interface{}, len(w.blueprint.Comments)+len(w.blueprint.Defs))
Andres Moralesda8706f2015-04-29 12:46:49 -0700350 go func() {
351 commIdx := 0
352 defsIdx := 0
Andres Moralesaf11df12015-04-30 12:14:34 -0700353 for defsIdx < len(w.blueprint.Defs) || commIdx < len(w.blueprint.Comments) {
354 if defsIdx == len(w.blueprint.Defs) {
355 ch <- w.blueprint.Comments[commIdx]
Andres Moralesda8706f2015-04-29 12:46:49 -0700356 commIdx++
Andres Moralesaf11df12015-04-30 12:14:34 -0700357 } else if commIdx == len(w.blueprint.Comments) {
358 ch <- w.blueprint.Defs[defsIdx]
Andres Moralesda8706f2015-04-29 12:46:49 -0700359 defsIdx++
360 } else {
361 commentsPos := 0
362 defsPos := 0
363
Andres Moralesaf11df12015-04-30 12:14:34 -0700364 def := w.blueprint.Defs[defsIdx]
Andres Moralesda8706f2015-04-29 12:46:49 -0700365 switch def := def.(type) {
366 case *bpparser.Module:
367 defsPos = def.LbracePos.Line
368 case *bpparser.Assignment:
369 defsPos = def.Pos.Line
370 }
371
Andres Moralesaf11df12015-04-30 12:14:34 -0700372 comment := w.blueprint.Comments[commIdx]
Andres Moralesda8706f2015-04-29 12:46:49 -0700373 commentsPos = comment.Pos.Line
374
375 if commentsPos < defsPos {
376 commIdx++
377 ch <- comment
378 } else {
379 defsIdx++
380 ch <- def
381 }
382 }
383 }
384 close(ch)
385 }()
386 return ch
387}
388
Andres Morales8ae47de2015-05-11 12:26:07 -0700389func (w *androidMkWriter) handleLocalPath() error {
Dan Willemsen360a39c2015-06-11 14:34:50 -0700390 if w.printedLocalPath {
391 return nil
392 }
393 w.printedLocalPath = true
394
Ying Wang38284902015-06-02 18:44:59 -0700395 localPath, err := filepath.Abs(w.path)
Andres Morales8ae47de2015-05-11 12:26:07 -0700396 if err != nil {
397 return err
398 }
399
Ying Wang38284902015-06-02 18:44:59 -0700400 top, err := getTopOfAndroidTree(localPath)
Andres Morales8ae47de2015-05-11 12:26:07 -0700401 if err != nil {
402 return err
403 }
404
Ying Wang38284902015-06-02 18:44:59 -0700405 rel, err := filepath.Rel(top, localPath)
Andres Morales8ae47de2015-05-11 12:26:07 -0700406 if err != nil {
407 return err
408 }
409
410 w.WriteString("LOCAL_PATH := " + rel + "\n")
Dan Willemsenc2666e62015-06-10 16:18:58 -0700411 w.WriteString("LOCAL_MODULE_MAKEFILE := $(lastword $(MAKEFILE_LIST))\n\n")
Andres Morales8ae47de2015-05-11 12:26:07 -0700412 return nil
413}
414
Ying Wang38284902015-06-02 18:44:59 -0700415func (w *androidMkWriter) write(androidMk string) error {
416 fmt.Printf("Writing %s\n", androidMk)
Andres Moralesda8706f2015-04-29 12:46:49 -0700417
Ying Wang38284902015-06-02 18:44:59 -0700418 f, err := os.Create(androidMk)
Andres Moralesda8706f2015-04-29 12:46:49 -0700419 if err != nil {
420 panic(err)
421 }
422
Andres Moralesaf11df12015-04-30 12:14:34 -0700423 defer f.Close()
Andres Moralesda8706f2015-04-29 12:46:49 -0700424
425 w.Writer = bufio.NewWriter(f)
426
427 for block := range w.iter() {
428 switch block := block.(type) {
429 case *bpparser.Module:
Dan Willemsen360a39c2015-06-11 14:34:50 -0700430 if err := w.handleLocalPath(); err != nil {
431 return err
432 }
Andres Moralesda8706f2015-04-29 12:46:49 -0700433 w.handleModule(block)
434 case *bpparser.Assignment:
Dan Willemsen360a39c2015-06-11 14:34:50 -0700435 if err := w.handleLocalPath(); err != nil {
436 return err
437 }
Andres Moralesda8706f2015-04-29 12:46:49 -0700438 w.handleAssignment(block)
439 case bpparser.Comment:
440 w.handleComment(&block)
441 }
442 }
443
444 if err = w.Flush(); err != nil {
445 panic(err)
446 }
Ying Wang38284902015-06-02 18:44:59 -0700447 return nil
Andres Moralesda8706f2015-04-29 12:46:49 -0700448}
449
450func main() {
451 if len(os.Args) < 2 {
452 fmt.Println("No filename supplied")
Ying Wang38284902015-06-02 18:44:59 -0700453 os.Exit(1)
Andres Moralesda8706f2015-04-29 12:46:49 -0700454 }
455
Ying Wang38284902015-06-02 18:44:59 -0700456 androidBp := os.Args[1]
457 var androidMk string
458 if len(os.Args) >= 3 {
459 androidMk = os.Args[2]
460 } else {
461 androidMk = androidBp + ".mk"
462 }
463
464 reader, err := os.Open(androidBp)
Andres Moralesda8706f2015-04-29 12:46:49 -0700465 if err != nil {
466 fmt.Println(err.Error())
Ying Wang38284902015-06-02 18:44:59 -0700467 os.Exit(1)
Andres Moralesda8706f2015-04-29 12:46:49 -0700468 }
469
470 scope := bpparser.NewScope(nil)
Ying Wang38284902015-06-02 18:44:59 -0700471 blueprint, errs := bpparser.Parse(androidBp, reader, scope)
Andres Moralesda8706f2015-04-29 12:46:49 -0700472 if len(errs) > 0 {
Ying Wang38284902015-06-02 18:44:59 -0700473 fmt.Println("%d errors parsing %s", len(errs), androidBp)
Andres Moralesda8706f2015-04-29 12:46:49 -0700474 fmt.Println(errs)
Ying Wang38284902015-06-02 18:44:59 -0700475 os.Exit(1)
Andres Moralesda8706f2015-04-29 12:46:49 -0700476 }
477
478 writer := &androidMkWriter{
Andres Moralesaf11df12015-04-30 12:14:34 -0700479 blueprint: blueprint,
Ying Wang38284902015-06-02 18:44:59 -0700480 path: path.Dir(androidBp),
Andres Moralesaf11df12015-04-30 12:14:34 -0700481 mapScope: make(map[string][]*bpparser.Property),
Andres Moralesda8706f2015-04-29 12:46:49 -0700482 }
483
Ying Wang38284902015-06-02 18:44:59 -0700484 err = writer.write(androidMk)
485 if err != nil {
486 fmt.Println(err.Error())
487 os.Exit(1)
488 }
Andres Moralesda8706f2015-04-29 12:46:49 -0700489}