blob: 46753a0d8c08f8b54d47af308d9c7793eb4b2dc3 [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"
13
14 bpparser "github.com/google/blueprint/parser"
15)
16
Andres Morales8ae47de2015-05-11 12:26:07 -070017var recursiveSubdirRegex *regexp.Regexp = regexp.MustCompile("(.+)/\\*\\*/(.+)")
18
Dan Willemsen3a4045d2015-06-24 15:37:17 -070019type Module struct {
20 bpmod *bpparser.Module
21 bpname string
22 mkname string
23 isHostRule bool
24}
25
26func newModule(mod *bpparser.Module) *Module {
27 return &Module{
28 bpmod: mod,
29 bpname: mod.Type.Name,
30 }
31}
32
Colin Crossb0931242015-06-29 14:18:27 -070033func (m *Module) translateRuleName() error {
34 var name string
Dan Willemsen3a4045d2015-06-24 15:37:17 -070035 if translation, ok := moduleTypeToRule[m.bpname]; ok {
36 name = translation
Colin Crossb0931242015-06-29 14:18:27 -070037 } else {
38 return fmt.Errorf("Unknown module type %q", m.bpname)
Dan Willemsen3a4045d2015-06-24 15:37:17 -070039 }
40
41 if m.isHostRule {
42 if trans, ok := targetToHostModuleRule[name]; ok {
43 name = trans
44 } else {
Colin Crossb0931242015-06-29 14:18:27 -070045 return fmt.Errorf("No corresponding host rule for %q", name)
Dan Willemsen3a4045d2015-06-24 15:37:17 -070046 }
47 } else {
48 m.isHostRule = strings.Contains(name, "HOST")
49 }
50
51 m.mkname = name
Colin Crossb0931242015-06-29 14:18:27 -070052
53 return nil
Dan Willemsen3a4045d2015-06-24 15:37:17 -070054}
55
Andres Moralesda8706f2015-04-29 12:46:49 -070056type androidMkWriter struct {
Colin Crossb0931242015-06-29 14:18:27 -070057 io.Writer
Andres Moralesda8706f2015-04-29 12:46:49 -070058
Andres Moralesaf11df12015-04-30 12:14:34 -070059 blueprint *bpparser.File
60 path string
61
Dan Willemsen360a39c2015-06-11 14:34:50 -070062 printedLocalPath bool
63
Andres Moralesaf11df12015-04-30 12:14:34 -070064 mapScope map[string][]*bpparser.Property
Andres Moralesda8706f2015-04-29 12:46:49 -070065}
66
Colin Crossb0931242015-06-29 14:18:27 -070067func (w *androidMkWriter) WriteString(s string) (int, error) {
68 return io.WriteString(w.Writer, s)
69}
70
71func valueToString(value bpparser.Value) (string, error) {
Andres Moralesda8706f2015-04-29 12:46:49 -070072 if value.Variable != "" {
Colin Crossb0931242015-06-29 14:18:27 -070073 return fmt.Sprintf("$(%s)", value.Variable), nil
Colin Crossff3b7952015-06-22 15:39:35 -070074 } else if value.Expression != nil {
75 if value.Expression.Operator != '+' {
Colin Crossb0931242015-06-29 14:18:27 -070076 return "", fmt.Errorf("unexpected operator '%c'", value.Expression.Operator)
Colin Crossff3b7952015-06-22 15:39:35 -070077 }
Colin Crossb0931242015-06-29 14:18:27 -070078 val1, err := valueToString(value.Expression.Args[0])
79 if err != nil {
80 return "", err
81 }
82 val2, err := valueToString(value.Expression.Args[1])
83 if err != nil {
84 return "", err
85 }
86 return fmt.Sprintf("%s%s", val1, val2), nil
Andres Moralesda8706f2015-04-29 12:46:49 -070087 } else {
88 switch value.Type {
89 case bpparser.Bool:
Colin Crossb0931242015-06-29 14:18:27 -070090 return fmt.Sprintf("%t", value.BoolValue), nil
Andres Moralesda8706f2015-04-29 12:46:49 -070091 case bpparser.String:
Colin Crossb0931242015-06-29 14:18:27 -070092 return fmt.Sprintf("%s", processWildcards(value.StringValue)), nil
Andres Moralesda8706f2015-04-29 12:46:49 -070093 case bpparser.List:
Colin Crossb0931242015-06-29 14:18:27 -070094 val, err := listToMkString(value.ListValue)
95 if err != nil {
96 return "", err
97 }
98 return fmt.Sprintf("\\\n%s", val), nil
Andres Moralesda8706f2015-04-29 12:46:49 -070099 case bpparser.Map:
Colin Crossb0931242015-06-29 14:18:27 -0700100 return "", fmt.Errorf("Can't convert map to string")
Andres Moralesaf11df12015-04-30 12:14:34 -0700101 default:
Colin Crossb0931242015-06-29 14:18:27 -0700102 return "", fmt.Errorf("ERROR: unsupported type %d", value.Type)
Andres Moralesda8706f2015-04-29 12:46:49 -0700103 }
104 }
Andres Moralesda8706f2015-04-29 12:46:49 -0700105}
106
Andres Morales8ae47de2015-05-11 12:26:07 -0700107func getTopOfAndroidTree(wd string) (string, error) {
108 if !filepath.IsAbs(wd) {
109 return "", errors.New("path must be absolute: " + wd)
110 }
111
112 topfile := "build/soong/bootstrap.bash"
113
114 for "/" != wd {
115 expected := filepath.Join(wd, topfile)
116
117 if _, err := os.Stat(expected); err == nil {
118 // Found the top
119 return wd, nil
120 }
121
122 wd = filepath.Join(wd, "..")
123 }
124
125 return "", errors.New("couldn't find top of tree from " + wd)
126}
127
Andres Moralesaf11df12015-04-30 12:14:34 -0700128// TODO: handle non-recursive wildcards?
129func processWildcards(s string) string {
Andres Morales8ae47de2015-05-11 12:26:07 -0700130 submatches := recursiveSubdirRegex.FindStringSubmatch(s)
131 if len(submatches) > 2 {
Andres Moralesaf11df12015-04-30 12:14:34 -0700132 // Found a wildcard rule
133 return fmt.Sprintf("$(call find-files-in-subdirs, $(LOCAL_PATH), %s, %s)",
Andres Morales8ae47de2015-05-11 12:26:07 -0700134 submatches[2], submatches[1])
Andres Moralesaf11df12015-04-30 12:14:34 -0700135 }
136
137 return s
138}
139
Colin Crossb0931242015-06-29 14:18:27 -0700140func listToMkString(list []bpparser.Value) (string, error) {
Andres Moralesda8706f2015-04-29 12:46:49 -0700141 lines := make([]string, 0, len(list))
142 for _, tok := range list {
Colin Crossb0931242015-06-29 14:18:27 -0700143 val, err := valueToString(tok)
144 if err != nil {
145 return "", err
146 }
147 lines = append(lines, fmt.Sprintf(" %s", val))
Andres Moralesda8706f2015-04-29 12:46:49 -0700148 }
149
Colin Crossb0931242015-06-29 14:18:27 -0700150 return strings.Join(lines, " \\\n"), nil
Andres Moralesda8706f2015-04-29 12:46:49 -0700151}
152
Andres Moralesaf11df12015-04-30 12:14:34 -0700153func translateTargetConditionals(props []*bpparser.Property,
Colin Crossb0931242015-06-29 14:18:27 -0700154 disabledBuilds map[string]bool, isHostRule bool) (computedProps []string, err error) {
Andres Moralesaf11df12015-04-30 12:14:34 -0700155 for _, target := range props {
156 conditionals := targetScopedPropertyConditionals
Dan Willemsen68fdfcc2015-06-11 14:05:01 -0700157 altConditionals := hostScopedPropertyConditionals
Andres Moralesaf11df12015-04-30 12:14:34 -0700158 if isHostRule {
Dan Willemsen68fdfcc2015-06-11 14:05:01 -0700159 conditionals, altConditionals = altConditionals, conditionals
Andres Moralesaf11df12015-04-30 12:14:34 -0700160 }
161
162 conditional, ok := conditionals[target.Name.Name]
163 if !ok {
Dan Willemsen68fdfcc2015-06-11 14:05:01 -0700164 if _, ok := altConditionals[target.Name.Name]; ok {
165 // This is only for the other build type
166 continue
167 } else {
Colin Crossb0931242015-06-29 14:18:27 -0700168 return nil, fmt.Errorf("Unsupported conditional %q", target.Name.Name)
Dan Willemsen68fdfcc2015-06-11 14:05:01 -0700169 }
Andres Moralesaf11df12015-04-30 12:14:34 -0700170 }
171
172 var scopedProps []string
173 for _, targetScopedProp := range target.Value.MapValue {
174 if mkProp, ok := standardProperties[targetScopedProp.Name.Name]; ok {
Colin Crossb0931242015-06-29 14:18:27 -0700175 val, err := valueToString(targetScopedProp.Value)
176 if err != nil {
177 return nil, err
178 }
Andres Moralesaf11df12015-04-30 12:14:34 -0700179 scopedProps = append(scopedProps, fmt.Sprintf("%s += %s",
Colin Crossb0931242015-06-29 14:18:27 -0700180 mkProp.string, val))
Dan Willemsen57ad08c2015-06-10 16:20:14 -0700181 } else if rwProp, ok := rewriteProperties[targetScopedProp.Name.Name]; ok {
Colin Crossb0931242015-06-29 14:18:27 -0700182 props, err := rwProp.f(rwProp.string, targetScopedProp, nil)
183 if err != nil {
184 return nil, err
185 }
186 scopedProps = append(scopedProps, props...)
Andres Moralesaf11df12015-04-30 12:14:34 -0700187 } else if "disabled" == targetScopedProp.Name.Name {
188 if targetScopedProp.Value.BoolValue {
189 disabledBuilds[target.Name.Name] = true
190 } else {
191 delete(disabledBuilds, target.Name.Name)
192 }
Colin Crossb0931242015-06-29 14:18:27 -0700193 } else {
194 return nil, fmt.Errorf("Unsupported target property %q", targetScopedProp.Name.Name)
Andres Moralesaf11df12015-04-30 12:14:34 -0700195 }
196 }
197
198 if len(scopedProps) > 0 {
Dan Willemsen68fdfcc2015-06-11 14:05:01 -0700199 if conditional != "" {
200 computedProps = append(computedProps, conditional)
201 computedProps = append(computedProps, scopedProps...)
202 computedProps = append(computedProps, "endif")
203 } else {
204 computedProps = append(computedProps, scopedProps...)
205 }
Andres Moralesaf11df12015-04-30 12:14:34 -0700206 }
Andres Moralesda8706f2015-04-29 12:46:49 -0700207 }
Andres Moralesaf11df12015-04-30 12:14:34 -0700208
209 return
210}
211
212func translateSuffixProperties(suffixProps []*bpparser.Property,
Colin Crossb0931242015-06-29 14:18:27 -0700213 suffixMap map[string]string) (computedProps []string, err error) {
Andres Moralesaf11df12015-04-30 12:14:34 -0700214 for _, suffixProp := range suffixProps {
215 if suffix, ok := suffixMap[suffixProp.Name.Name]; ok {
216 for _, stdProp := range suffixProp.Value.MapValue {
217 if mkProp, ok := standardProperties[stdProp.Name.Name]; ok {
Colin Crossb0931242015-06-29 14:18:27 -0700218 val, err := valueToString(stdProp.Value)
219 if err != nil {
220 return nil, err
221 }
222 computedProps = append(computedProps, fmt.Sprintf("%s_%s := %s", mkProp.string, suffix, val))
Dan Willemsen57ad08c2015-06-10 16:20:14 -0700223 } else if rwProp, ok := rewriteProperties[stdProp.Name.Name]; ok {
Colin Crossb0931242015-06-29 14:18:27 -0700224 props, err := rwProp.f(rwProp.string, stdProp, &suffix)
225 if err != nil {
226 return nil, err
227 }
228 computedProps = append(computedProps, props...)
Andres Moralesaf11df12015-04-30 12:14:34 -0700229 } else {
Colin Crossb0931242015-06-29 14:18:27 -0700230 return nil, fmt.Errorf("Unsupported property %q", stdProp.Name.Name)
Andres Moralesaf11df12015-04-30 12:14:34 -0700231 }
232 }
Colin Crossb0931242015-06-29 14:18:27 -0700233 } else {
234 return nil, fmt.Errorf("Unsupported suffix property %q", suffixProp.Name.Name)
Andres Moralesaf11df12015-04-30 12:14:34 -0700235 }
236 }
237 return
238}
239
Colin Crossb0931242015-06-29 14:18:27 -0700240func prependLocalPath(name string, prop *bpparser.Property, suffix *string) ([]string, error) {
Dan Willemsen57ad08c2015-06-10 16:20:14 -0700241 if suffix != nil {
242 name += "_" + *suffix
243 }
Colin Crossb0931242015-06-29 14:18:27 -0700244 val, err := valueToString(prop.Value)
245 if err != nil {
246 return nil, err
247 }
Colin Crossff3b7952015-06-22 15:39:35 -0700248 return []string{
Colin Crossb0931242015-06-29 14:18:27 -0700249 fmt.Sprintf("%s := $(addprefix $(LOCAL_PATH)/,%s)\n", name, val),
250 }, nil
Dan Willemsen57ad08c2015-06-10 16:20:14 -0700251}
252
Colin Crossb0931242015-06-29 14:18:27 -0700253func prependLocalModule(name string, prop *bpparser.Property, suffix *string) ([]string, error) {
Dan Willemsen1d9f2792015-06-22 15:40:14 -0700254 if suffix != nil {
255 name += "_" + *suffix
256 }
Colin Crossb0931242015-06-29 14:18:27 -0700257 val, err := valueToString(prop.Value)
258 if err != nil {
259 return nil, err
Dan Willemsen1d9f2792015-06-22 15:40:14 -0700260 }
Colin Crossb0931242015-06-29 14:18:27 -0700261 return []string{
262 fmt.Sprintf("%s := $(LOCAL_MODULE)%s\n", name, val),
263 }, nil
Dan Willemsen1d9f2792015-06-22 15:40:14 -0700264}
265
Dan Willemsen3a4045d2015-06-24 15:37:17 -0700266func modulePropBool(module *bpparser.Module, name string) bool {
267 for _, prop := range module.Properties {
268 if name == prop.Name.Name {
269 return prop.Value.BoolValue
270 }
271 }
272 return false
273}
274
Andres Moralesaf11df12015-04-30 12:14:34 -0700275func (w *androidMkWriter) lookupMap(parent bpparser.Value) (mapValue []*bpparser.Property) {
276 if parent.Variable != "" {
277 mapValue = w.mapScope[parent.Variable]
278 } else {
279 mapValue = parent.MapValue
280 }
281 return
Andres Moralesda8706f2015-04-29 12:46:49 -0700282}
283
Andres Moralesaf11df12015-04-30 12:14:34 -0700284func (w *androidMkWriter) writeModule(moduleRule string, props []string,
285 disabledBuilds map[string]bool, isHostRule bool) {
286 disabledConditionals := disabledTargetConditionals
287 if isHostRule {
288 disabledConditionals = disabledHostConditionals
289 }
290 for build, _ := range disabledBuilds {
291 if conditional, ok := disabledConditionals[build]; ok {
292 fmt.Fprintf(w, "%s\n", conditional)
293 defer fmt.Fprintf(w, "endif\n")
Andres Moralesda8706f2015-04-29 12:46:49 -0700294 }
Andres Moralesaf11df12015-04-30 12:14:34 -0700295 }
Andres Moralesda8706f2015-04-29 12:46:49 -0700296
Andres Moralesaf11df12015-04-30 12:14:34 -0700297 fmt.Fprintf(w, "include $(CLEAR_VARS)\n")
298 fmt.Fprintf(w, "%s\n", strings.Join(props, "\n"))
299 fmt.Fprintf(w, "include $(%s)\n\n", moduleRule)
300}
Andres Moralesda8706f2015-04-29 12:46:49 -0700301
Colin Crossb0931242015-06-29 14:18:27 -0700302func (w *androidMkWriter) parsePropsAndWriteModule(module *Module) error {
Dan Willemsen3a4045d2015-06-24 15:37:17 -0700303 standardProps := make([]string, 0, len(module.bpmod.Properties))
Andres Moralesaf11df12015-04-30 12:14:34 -0700304 disabledBuilds := make(map[string]bool)
Dan Willemsen3a4045d2015-06-24 15:37:17 -0700305 for _, prop := range module.bpmod.Properties {
Andres Moralesaf11df12015-04-30 12:14:34 -0700306 if mkProp, ok := standardProperties[prop.Name.Name]; ok {
Colin Crossb0931242015-06-29 14:18:27 -0700307 val, err := valueToString(prop.Value)
308 if err != nil {
309 return err
310 }
311 standardProps = append(standardProps, fmt.Sprintf("%s := %s", mkProp.string, val))
Dan Willemsen57ad08c2015-06-10 16:20:14 -0700312 } else if rwProp, ok := rewriteProperties[prop.Name.Name]; ok {
Colin Crossb0931242015-06-29 14:18:27 -0700313 props, err := rwProp.f(rwProp.string, prop, nil)
314 if err != nil {
315 return err
316 }
317 standardProps = append(standardProps, props...)
Andres Moralesaf11df12015-04-30 12:14:34 -0700318 } else if suffixMap, ok := suffixProperties[prop.Name.Name]; ok {
319 suffixProps := w.lookupMap(prop.Value)
Colin Crossb0931242015-06-29 14:18:27 -0700320 props, err := translateSuffixProperties(suffixProps, suffixMap)
321 if err != nil {
322 return err
323 }
324 standardProps = append(standardProps, props...)
Andres Moralesaf11df12015-04-30 12:14:34 -0700325 } else if "target" == prop.Name.Name {
Colin Crossb0931242015-06-29 14:18:27 -0700326 suffixProps := w.lookupMap(prop.Value)
327 props, err := translateTargetConditionals(suffixProps, disabledBuilds, module.isHostRule)
328 if err != nil {
329 return err
330 }
331 standardProps = append(standardProps, props...)
Dan Willemsen0a544692015-06-24 15:50:07 -0700332 } else if _, ok := ignoredProperties[prop.Name.Name]; ok {
Andres Moralesaf11df12015-04-30 12:14:34 -0700333 } else {
Colin Crossb0931242015-06-29 14:18:27 -0700334 return fmt.Errorf("Unsupported property %q", prop.Name.Name)
Andres Moralesaf11df12015-04-30 12:14:34 -0700335 }
336 }
337
Dan Willemsen3a4045d2015-06-24 15:37:17 -0700338 w.writeModule(module.mkname, standardProps, disabledBuilds, module.isHostRule)
Colin Crossb0931242015-06-29 14:18:27 -0700339
340 return nil
Dan Willemsen68fdfcc2015-06-11 14:05:01 -0700341}
342
Colin Crossb0931242015-06-29 14:18:27 -0700343func (w *androidMkWriter) mutateModule(module *Module) (modules []*Module, err error) {
Dan Willemsen3a4045d2015-06-24 15:37:17 -0700344 modules = []*Module{module}
Dan Willemsen49f50452015-06-24 14:56:00 -0700345
Dan Willemsen3a4045d2015-06-24 15:37:17 -0700346 if module.bpname == "cc_library" {
347 modules = []*Module{
348 newModule(module.bpmod),
349 newModule(module.bpmod),
350 }
351 modules[0].bpname = "cc_library_shared"
352 modules[1].bpname = "cc_library_static"
353 }
354
355 for _, mod := range modules {
Colin Crossb0931242015-06-29 14:18:27 -0700356 err := mod.translateRuleName()
357 if err != nil {
358 return nil, err
359 }
Dan Willemsen3a4045d2015-06-24 15:37:17 -0700360 if mod.isHostRule || !modulePropBool(mod.bpmod, "host_supported") {
361 continue
362 }
363
364 m := &Module{
365 bpmod: mod.bpmod,
366 bpname: mod.bpname,
367 isHostRule: true,
368 }
Colin Crossb0931242015-06-29 14:18:27 -0700369 err = m.translateRuleName()
370 if err != nil {
371 return nil, err
372 }
Dan Willemsen3a4045d2015-06-24 15:37:17 -0700373 modules = append(modules, m)
Dan Willemsen68fdfcc2015-06-11 14:05:01 -0700374 }
375
Dan Willemsen49f50452015-06-24 14:56:00 -0700376 return
377}
Dan Willemsen68fdfcc2015-06-11 14:05:01 -0700378
Colin Crossb0931242015-06-29 14:18:27 -0700379func (w *androidMkWriter) handleModule(inputModule *bpparser.Module) error {
380 modules, err := w.mutateModule(newModule(inputModule))
381 if err != nil {
382 return err
383 }
Dan Willemsen49f50452015-06-24 14:56:00 -0700384
385 for _, module := range modules {
Colin Crossb0931242015-06-29 14:18:27 -0700386 err := w.parsePropsAndWriteModule(module)
387 if err != nil {
388 return err
389 }
Andres Moralesaf11df12015-04-30 12:14:34 -0700390 }
Colin Crossb0931242015-06-29 14:18:27 -0700391
392 return nil
Andres Moralesaf11df12015-04-30 12:14:34 -0700393}
394
395func (w *androidMkWriter) handleSubdirs(value bpparser.Value) {
Andres Morales8ae47de2015-05-11 12:26:07 -0700396 subdirs := make([]string, 0, len(value.ListValue))
397 for _, tok := range value.ListValue {
398 subdirs = append(subdirs, tok.StringValue)
Andres Moralesda8706f2015-04-29 12:46:49 -0700399 }
Ying Wang38284902015-06-02 18:44:59 -0700400 // The current makefile may be generated to outside the source tree (such as the out directory), with a different structure.
401 fmt.Fprintf(w, "# Uncomment the following line if you really want to include subdir Android.mks.\n")
402 fmt.Fprintf(w, "# include $(wildcard $(addsuffix $(LOCAL_PATH)/%s/, Android.mk))\n", strings.Join(subdirs, " "))
Andres Moralesda8706f2015-04-29 12:46:49 -0700403}
404
Colin Crossb0931242015-06-29 14:18:27 -0700405func (w *androidMkWriter) handleAssignment(assignment *bpparser.Assignment) error {
Andres Moralesaf11df12015-04-30 12:14:34 -0700406 if "subdirs" == assignment.Name.Name {
407 w.handleSubdirs(assignment.OrigValue)
408 } else if assignment.OrigValue.Type == bpparser.Map {
409 // maps may be assigned in Soong, but can only be translated to .mk
410 // in the context of the module
411 w.mapScope[assignment.Name.Name] = assignment.OrigValue.MapValue
412 } else {
413 assigner := ":="
414 if assignment.Assigner != "=" {
415 assigner = assignment.Assigner
416 }
Colin Crossb0931242015-06-29 14:18:27 -0700417 val, err := valueToString(assignment.OrigValue)
418 if err != nil {
419 return err
420 }
421 fmt.Fprintf(w, "%s %s %s\n", assignment.Name.Name, assigner, val)
Andres Moralesda8706f2015-04-29 12:46:49 -0700422 }
Colin Crossb0931242015-06-29 14:18:27 -0700423
424 return nil
Andres Moralesda8706f2015-04-29 12:46:49 -0700425}
426
Andres Morales8ae47de2015-05-11 12:26:07 -0700427func (w *androidMkWriter) handleLocalPath() error {
Dan Willemsen360a39c2015-06-11 14:34:50 -0700428 if w.printedLocalPath {
429 return nil
430 }
431 w.printedLocalPath = true
432
Ying Wang38284902015-06-02 18:44:59 -0700433 localPath, err := filepath.Abs(w.path)
Andres Morales8ae47de2015-05-11 12:26:07 -0700434 if err != nil {
435 return err
436 }
437
Ying Wang38284902015-06-02 18:44:59 -0700438 top, err := getTopOfAndroidTree(localPath)
Andres Morales8ae47de2015-05-11 12:26:07 -0700439 if err != nil {
440 return err
441 }
442
Ying Wang38284902015-06-02 18:44:59 -0700443 rel, err := filepath.Rel(top, localPath)
Andres Morales8ae47de2015-05-11 12:26:07 -0700444 if err != nil {
445 return err
446 }
447
448 w.WriteString("LOCAL_PATH := " + rel + "\n")
Dan Willemsenc2666e62015-06-10 16:18:58 -0700449 w.WriteString("LOCAL_MODULE_MAKEFILE := $(lastword $(MAKEFILE_LIST))\n\n")
Andres Morales8ae47de2015-05-11 12:26:07 -0700450 return nil
451}
452
Colin Crossb0931242015-06-29 14:18:27 -0700453func (w *androidMkWriter) write(writer io.Writer) (err error) {
454 w.Writer = writer
Andres Moralesda8706f2015-04-29 12:46:49 -0700455
Colin Crossb0931242015-06-29 14:18:27 -0700456 if err = w.handleLocalPath(); err != nil {
Colin Cross26478b72015-06-29 13:46:00 -0700457 return err
458 }
459
460 for _, block := range w.blueprint.Defs {
Andres Moralesda8706f2015-04-29 12:46:49 -0700461 switch block := block.(type) {
462 case *bpparser.Module:
Colin Crossb0931242015-06-29 14:18:27 -0700463 err = w.handleModule(block)
Andres Moralesda8706f2015-04-29 12:46:49 -0700464 case *bpparser.Assignment:
Colin Crossb0931242015-06-29 14:18:27 -0700465 err = w.handleAssignment(block)
466 default:
467 return fmt.Errorf("Unhandled def %v", block)
468 }
469 if err != nil {
470 return err
Andres Moralesda8706f2015-04-29 12:46:49 -0700471 }
472 }
473
Ying Wang38284902015-06-02 18:44:59 -0700474 return nil
Andres Moralesda8706f2015-04-29 12:46:49 -0700475}
476
Colin Crossb0931242015-06-29 14:18:27 -0700477func translate(androidBp, androidMk string) error {
Ying Wang38284902015-06-02 18:44:59 -0700478 reader, err := os.Open(androidBp)
Andres Moralesda8706f2015-04-29 12:46:49 -0700479 if err != nil {
Colin Crossb0931242015-06-29 14:18:27 -0700480 return err
Andres Moralesda8706f2015-04-29 12:46:49 -0700481 }
482
483 scope := bpparser.NewScope(nil)
Ying Wang38284902015-06-02 18:44:59 -0700484 blueprint, errs := bpparser.Parse(androidBp, reader, scope)
Andres Moralesda8706f2015-04-29 12:46:49 -0700485 if len(errs) > 0 {
Colin Crossb0931242015-06-29 14:18:27 -0700486 return errs[0]
Andres Moralesda8706f2015-04-29 12:46:49 -0700487 }
488
489 writer := &androidMkWriter{
Andres Moralesaf11df12015-04-30 12:14:34 -0700490 blueprint: blueprint,
Ying Wang38284902015-06-02 18:44:59 -0700491 path: path.Dir(androidBp),
Andres Moralesaf11df12015-04-30 12:14:34 -0700492 mapScope: make(map[string][]*bpparser.Property),
Andres Moralesda8706f2015-04-29 12:46:49 -0700493 }
494
Colin Crossb0931242015-06-29 14:18:27 -0700495 buf := &bytes.Buffer{}
496
497 err = writer.write(buf)
Ying Wang38284902015-06-02 18:44:59 -0700498 if err != nil {
Colin Crossb0931242015-06-29 14:18:27 -0700499 os.Remove(androidMk)
500 return err
501 }
502
503 f, err := os.Create(androidMk)
504 if err != nil {
505 return err
506 }
507 defer f.Close()
508
509 _, err = f.Write(buf.Bytes())
510
511 return err
512}
513
514func main() {
515 if len(os.Args) < 3 {
516 fmt.Fprintln(os.Stderr, "Expected input and output filename arguments")
517 os.Exit(1)
518 }
519
520 androidBp := os.Args[1]
521 androidMk := os.Args[2]
522
523 err := translate(androidBp, androidMk)
524
525 if err != nil {
526 fmt.Fprintf(os.Stderr, "Error translating %s: %s\n", androidBp, err.Error())
Ying Wang38284902015-06-02 18:44:59 -0700527 os.Exit(1)
528 }
Andres Moralesda8706f2015-04-29 12:46:49 -0700529}