blob: ca33cb807bfdfa7099128a475aa976b1f12c2605 [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
Andres Moralesda8706f2015-04-29 12:46:49 -070021type androidMkWriter struct {
Colin Crossb0931242015-06-29 14:18:27 -070022 io.Writer
Andres Moralesda8706f2015-04-29 12:46:49 -070023
Andres Moralesaf11df12015-04-30 12:14:34 -070024 blueprint *bpparser.File
25 path string
Andres Moralesda8706f2015-04-29 12:46:49 -070026}
27
Colin Crossb0931242015-06-29 14:18:27 -070028func (w *androidMkWriter) WriteString(s string) (int, error) {
29 return io.WriteString(w.Writer, s)
30}
31
32func valueToString(value bpparser.Value) (string, error) {
Colin Crossb3245e92015-06-30 16:27:57 -070033 switch value.Type {
34 case bpparser.Bool:
35 return fmt.Sprintf("%t", value.BoolValue), nil
36 case bpparser.String:
37 return fmt.Sprintf("%s", processWildcards(value.StringValue)), nil
38 case bpparser.List:
39 val, err := listToMkString(value.ListValue)
Colin Crossb0931242015-06-29 14:18:27 -070040 if err != nil {
41 return "", err
42 }
Colin Crossb3245e92015-06-30 16:27:57 -070043 return fmt.Sprintf("\\\n%s", val), nil
44 case bpparser.Map:
45 return "", fmt.Errorf("Can't convert map to string")
46 default:
47 return "", fmt.Errorf("ERROR: unsupported type %d", value.Type)
Andres Moralesda8706f2015-04-29 12:46:49 -070048 }
Andres Moralesda8706f2015-04-29 12:46:49 -070049}
50
Dan Willemsen27012122015-06-26 17:40:54 -070051func appendValueToValue(dest bpparser.Value, src bpparser.Value) (bpparser.Value, error) {
52 if src.Type != dest.Type {
53 return bpparser.Value{}, fmt.Errorf("ERROR: source and destination types don't match")
54 }
55 switch dest.Type {
56 case bpparser.List:
57 dest.ListValue = append(dest.ListValue, src.ListValue...)
58 return dest, nil
59 case bpparser.String:
60 dest.StringValue += src.StringValue
61 return dest, nil
62 default:
63 return bpparser.Value{}, fmt.Errorf("ERROR: unsupported append with type %s", dest.Type.String())
64 }
65}
66
Andres Morales8ae47de2015-05-11 12:26:07 -070067func getTopOfAndroidTree(wd string) (string, error) {
68 if !filepath.IsAbs(wd) {
69 return "", errors.New("path must be absolute: " + wd)
70 }
71
72 topfile := "build/soong/bootstrap.bash"
73
74 for "/" != wd {
75 expected := filepath.Join(wd, topfile)
76
77 if _, err := os.Stat(expected); err == nil {
78 // Found the top
79 return wd, nil
80 }
81
82 wd = filepath.Join(wd, "..")
83 }
84
85 return "", errors.New("couldn't find top of tree from " + wd)
86}
87
Andres Moralesaf11df12015-04-30 12:14:34 -070088// TODO: handle non-recursive wildcards?
89func processWildcards(s string) string {
Andres Morales8ae47de2015-05-11 12:26:07 -070090 submatches := recursiveSubdirRegex.FindStringSubmatch(s)
91 if len(submatches) > 2 {
Andres Moralesaf11df12015-04-30 12:14:34 -070092 // Found a wildcard rule
93 return fmt.Sprintf("$(call find-files-in-subdirs, $(LOCAL_PATH), %s, %s)",
Andres Morales8ae47de2015-05-11 12:26:07 -070094 submatches[2], submatches[1])
Andres Moralesaf11df12015-04-30 12:14:34 -070095 }
96
97 return s
98}
99
Colin Crossb0931242015-06-29 14:18:27 -0700100func listToMkString(list []bpparser.Value) (string, error) {
Andres Moralesda8706f2015-04-29 12:46:49 -0700101 lines := make([]string, 0, len(list))
102 for _, tok := range list {
Colin Crossb0931242015-06-29 14:18:27 -0700103 val, err := valueToString(tok)
104 if err != nil {
105 return "", err
106 }
107 lines = append(lines, fmt.Sprintf(" %s", val))
Andres Moralesda8706f2015-04-29 12:46:49 -0700108 }
109
Colin Crossb0931242015-06-29 14:18:27 -0700110 return strings.Join(lines, " \\\n"), nil
Andres Moralesda8706f2015-04-29 12:46:49 -0700111}
112
Andres Moralesaf11df12015-04-30 12:14:34 -0700113func translateTargetConditionals(props []*bpparser.Property,
Colin Crossb0931242015-06-29 14:18:27 -0700114 disabledBuilds map[string]bool, isHostRule bool) (computedProps []string, err error) {
Andres Moralesaf11df12015-04-30 12:14:34 -0700115 for _, target := range props {
116 conditionals := targetScopedPropertyConditionals
Dan Willemsen68fdfcc2015-06-11 14:05:01 -0700117 altConditionals := hostScopedPropertyConditionals
Andres Moralesaf11df12015-04-30 12:14:34 -0700118 if isHostRule {
Dan Willemsen68fdfcc2015-06-11 14:05:01 -0700119 conditionals, altConditionals = altConditionals, conditionals
Andres Moralesaf11df12015-04-30 12:14:34 -0700120 }
121
122 conditional, ok := conditionals[target.Name.Name]
123 if !ok {
Dan Willemsen68fdfcc2015-06-11 14:05:01 -0700124 if _, ok := altConditionals[target.Name.Name]; ok {
125 // This is only for the other build type
126 continue
127 } else {
Colin Crossb0931242015-06-29 14:18:27 -0700128 return nil, fmt.Errorf("Unsupported conditional %q", target.Name.Name)
Dan Willemsen68fdfcc2015-06-11 14:05:01 -0700129 }
Andres Moralesaf11df12015-04-30 12:14:34 -0700130 }
131
132 var scopedProps []string
133 for _, targetScopedProp := range target.Value.MapValue {
134 if mkProp, ok := standardProperties[targetScopedProp.Name.Name]; ok {
Colin Crossb0931242015-06-29 14:18:27 -0700135 val, err := valueToString(targetScopedProp.Value)
136 if err != nil {
137 return nil, err
138 }
Andres Moralesaf11df12015-04-30 12:14:34 -0700139 scopedProps = append(scopedProps, fmt.Sprintf("%s += %s",
Colin Crossb0931242015-06-29 14:18:27 -0700140 mkProp.string, val))
Dan Willemsen57ad08c2015-06-10 16:20:14 -0700141 } else if rwProp, ok := rewriteProperties[targetScopedProp.Name.Name]; ok {
Colin Crossb0931242015-06-29 14:18:27 -0700142 props, err := rwProp.f(rwProp.string, targetScopedProp, nil)
143 if err != nil {
144 return nil, err
145 }
146 scopedProps = append(scopedProps, props...)
Andres Moralesaf11df12015-04-30 12:14:34 -0700147 } else if "disabled" == targetScopedProp.Name.Name {
148 if targetScopedProp.Value.BoolValue {
149 disabledBuilds[target.Name.Name] = true
150 } else {
151 delete(disabledBuilds, target.Name.Name)
152 }
Colin Crossb0931242015-06-29 14:18:27 -0700153 } else {
154 return nil, fmt.Errorf("Unsupported target property %q", targetScopedProp.Name.Name)
Andres Moralesaf11df12015-04-30 12:14:34 -0700155 }
156 }
157
158 if len(scopedProps) > 0 {
Dan Willemsen68fdfcc2015-06-11 14:05:01 -0700159 if conditional != "" {
160 computedProps = append(computedProps, conditional)
161 computedProps = append(computedProps, scopedProps...)
162 computedProps = append(computedProps, "endif")
163 } else {
164 computedProps = append(computedProps, scopedProps...)
165 }
Andres Moralesaf11df12015-04-30 12:14:34 -0700166 }
Andres Moralesda8706f2015-04-29 12:46:49 -0700167 }
Andres Moralesaf11df12015-04-30 12:14:34 -0700168
169 return
170}
171
172func translateSuffixProperties(suffixProps []*bpparser.Property,
Colin Crossb0931242015-06-29 14:18:27 -0700173 suffixMap map[string]string) (computedProps []string, err error) {
Andres Moralesaf11df12015-04-30 12:14:34 -0700174 for _, suffixProp := range suffixProps {
175 if suffix, ok := suffixMap[suffixProp.Name.Name]; ok {
176 for _, stdProp := range suffixProp.Value.MapValue {
177 if mkProp, ok := standardProperties[stdProp.Name.Name]; ok {
Colin Crossb0931242015-06-29 14:18:27 -0700178 val, err := valueToString(stdProp.Value)
179 if err != nil {
180 return nil, err
181 }
182 computedProps = append(computedProps, fmt.Sprintf("%s_%s := %s", mkProp.string, suffix, val))
Dan Willemsen57ad08c2015-06-10 16:20:14 -0700183 } else if rwProp, ok := rewriteProperties[stdProp.Name.Name]; ok {
Colin Crossb0931242015-06-29 14:18:27 -0700184 props, err := rwProp.f(rwProp.string, stdProp, &suffix)
185 if err != nil {
186 return nil, err
187 }
188 computedProps = append(computedProps, props...)
Andres Moralesaf11df12015-04-30 12:14:34 -0700189 } else {
Colin Crossb0931242015-06-29 14:18:27 -0700190 return nil, fmt.Errorf("Unsupported property %q", stdProp.Name.Name)
Andres Moralesaf11df12015-04-30 12:14:34 -0700191 }
192 }
Colin Crossb0931242015-06-29 14:18:27 -0700193 } else {
194 return nil, fmt.Errorf("Unsupported suffix property %q", suffixProp.Name.Name)
Andres Moralesaf11df12015-04-30 12:14:34 -0700195 }
196 }
197 return
198}
199
Colin Crossc41f6302015-06-30 12:19:47 -0700200func appendAssign(name string, prop *bpparser.Property, suffix *string) ([]string, error) {
201 if suffix != nil {
202 name += "_" + *suffix
203 }
204 val, err := valueToString(prop.Value)
205 if err != nil {
206 return nil, err
207 }
208 return []string{
209 fmt.Sprintf("%s += %s", name, val),
210 }, nil
211}
212
Colin Crossb0931242015-06-29 14:18:27 -0700213func prependLocalPath(name string, prop *bpparser.Property, suffix *string) ([]string, error) {
Dan Willemsen57ad08c2015-06-10 16:20:14 -0700214 if suffix != nil {
215 name += "_" + *suffix
216 }
Colin Crossb0931242015-06-29 14:18:27 -0700217 val, err := valueToString(prop.Value)
218 if err != nil {
219 return nil, err
220 }
Colin Crossff3b7952015-06-22 15:39:35 -0700221 return []string{
Colin Crossc41f6302015-06-30 12:19:47 -0700222 fmt.Sprintf("%s += $(addprefix $(LOCAL_PATH)/,%s)", name, val),
Colin Crossb0931242015-06-29 14:18:27 -0700223 }, nil
Dan Willemsen57ad08c2015-06-10 16:20:14 -0700224}
225
Colin Crossb0931242015-06-29 14:18:27 -0700226func prependLocalModule(name string, prop *bpparser.Property, suffix *string) ([]string, error) {
Dan Willemsen1d9f2792015-06-22 15:40:14 -0700227 if suffix != nil {
228 name += "_" + *suffix
229 }
Colin Crossb0931242015-06-29 14:18:27 -0700230 val, err := valueToString(prop.Value)
231 if err != nil {
232 return nil, err
Dan Willemsen1d9f2792015-06-22 15:40:14 -0700233 }
Colin Crossb0931242015-06-29 14:18:27 -0700234 return []string{
235 fmt.Sprintf("%s := $(LOCAL_MODULE)%s\n", name, val),
236 }, nil
Dan Willemsen1d9f2792015-06-22 15:40:14 -0700237}
238
Andres Moralesaf11df12015-04-30 12:14:34 -0700239func (w *androidMkWriter) writeModule(moduleRule string, props []string,
240 disabledBuilds map[string]bool, isHostRule bool) {
241 disabledConditionals := disabledTargetConditionals
242 if isHostRule {
243 disabledConditionals = disabledHostConditionals
244 }
245 for build, _ := range disabledBuilds {
246 if conditional, ok := disabledConditionals[build]; ok {
247 fmt.Fprintf(w, "%s\n", conditional)
248 defer fmt.Fprintf(w, "endif\n")
Andres Moralesda8706f2015-04-29 12:46:49 -0700249 }
Andres Moralesaf11df12015-04-30 12:14:34 -0700250 }
Andres Moralesda8706f2015-04-29 12:46:49 -0700251
Andres Moralesaf11df12015-04-30 12:14:34 -0700252 fmt.Fprintf(w, "include $(CLEAR_VARS)\n")
253 fmt.Fprintf(w, "%s\n", strings.Join(props, "\n"))
254 fmt.Fprintf(w, "include $(%s)\n\n", moduleRule)
255}
Andres Moralesda8706f2015-04-29 12:46:49 -0700256
Colin Crossb0931242015-06-29 14:18:27 -0700257func (w *androidMkWriter) parsePropsAndWriteModule(module *Module) error {
Dan Willemsen3a4045d2015-06-24 15:37:17 -0700258 standardProps := make([]string, 0, len(module.bpmod.Properties))
Andres Moralesaf11df12015-04-30 12:14:34 -0700259 disabledBuilds := make(map[string]bool)
Dan Willemsen3a4045d2015-06-24 15:37:17 -0700260 for _, prop := range module.bpmod.Properties {
Andres Moralesaf11df12015-04-30 12:14:34 -0700261 if mkProp, ok := standardProperties[prop.Name.Name]; ok {
Colin Crossb0931242015-06-29 14:18:27 -0700262 val, err := valueToString(prop.Value)
263 if err != nil {
264 return err
265 }
266 standardProps = append(standardProps, fmt.Sprintf("%s := %s", mkProp.string, val))
Dan Willemsen57ad08c2015-06-10 16:20:14 -0700267 } else if rwProp, ok := rewriteProperties[prop.Name.Name]; ok {
Colin Crossb0931242015-06-29 14:18:27 -0700268 props, err := rwProp.f(rwProp.string, prop, nil)
269 if err != nil {
270 return err
271 }
272 standardProps = append(standardProps, props...)
Andres Moralesaf11df12015-04-30 12:14:34 -0700273 } else if suffixMap, ok := suffixProperties[prop.Name.Name]; ok {
Colin Crossb3245e92015-06-30 16:27:57 -0700274 props, err := translateSuffixProperties(prop.Value.MapValue, suffixMap)
Colin Crossb0931242015-06-29 14:18:27 -0700275 if err != nil {
276 return err
277 }
278 standardProps = append(standardProps, props...)
Andres Moralesaf11df12015-04-30 12:14:34 -0700279 } else if "target" == prop.Name.Name {
Colin Crossb3245e92015-06-30 16:27:57 -0700280 props, err := translateTargetConditionals(prop.Value.MapValue, disabledBuilds, module.isHostRule)
Colin Crossb0931242015-06-29 14:18:27 -0700281 if err != nil {
282 return err
283 }
284 standardProps = append(standardProps, props...)
Dan Willemsen0a544692015-06-24 15:50:07 -0700285 } else if _, ok := ignoredProperties[prop.Name.Name]; ok {
Andres Moralesaf11df12015-04-30 12:14:34 -0700286 } else {
Colin Crossb0931242015-06-29 14:18:27 -0700287 return fmt.Errorf("Unsupported property %q", prop.Name.Name)
Andres Moralesaf11df12015-04-30 12:14:34 -0700288 }
289 }
290
Dan Willemsen3a4045d2015-06-24 15:37:17 -0700291 w.writeModule(module.mkname, standardProps, disabledBuilds, module.isHostRule)
Colin Crossb0931242015-06-29 14:18:27 -0700292
293 return nil
Dan Willemsen68fdfcc2015-06-11 14:05:01 -0700294}
295
Colin Crossb0931242015-06-29 14:18:27 -0700296func (w *androidMkWriter) mutateModule(module *Module) (modules []*Module, err error) {
Dan Willemsen3a4045d2015-06-24 15:37:17 -0700297 modules = []*Module{module}
Dan Willemsen49f50452015-06-24 14:56:00 -0700298
Dan Willemsen3a4045d2015-06-24 15:37:17 -0700299 if module.bpname == "cc_library" {
300 modules = []*Module{
301 newModule(module.bpmod),
302 newModule(module.bpmod),
303 }
Dan Willemsen27012122015-06-26 17:40:54 -0700304
305 ccLinkageCopy := func(props Properties, prop *bpparser.Property) error {
306 for _, p := range prop.Value.MapValue {
307 err := props.AppendToProp(p.Name.Name, p)
308 if err != nil {
309 return err
310 }
311 }
312 props.DeleteProp(prop.Name.Name)
313 return nil
314 }
315 ccLinkageDelete := func(props Properties, prop *bpparser.Property) error {
316 props.DeleteProp(prop.Name.Name)
317 return nil
318 }
319
Dan Willemsen3a4045d2015-06-24 15:37:17 -0700320 modules[0].bpname = "cc_library_shared"
Dan Willemsen27012122015-06-26 17:40:54 -0700321 err := modules[0].IterateArchPropertiesWithName("shared", ccLinkageCopy)
322 if err != nil {
323 return nil, err
324 }
325 err = modules[0].IterateArchPropertiesWithName("static", ccLinkageDelete)
326 if err != nil {
327 return nil, err
328 }
329
Dan Willemsen3a4045d2015-06-24 15:37:17 -0700330 modules[1].bpname = "cc_library_static"
Dan Willemsen27012122015-06-26 17:40:54 -0700331 err = modules[1].IterateArchPropertiesWithName("shared", ccLinkageDelete)
332 if err != nil {
333 return nil, err
334 }
335 err = modules[1].IterateArchPropertiesWithName("static", ccLinkageCopy)
336 if err != nil {
337 return nil, err
338 }
Dan Willemsen3a4045d2015-06-24 15:37:17 -0700339 }
340
341 for _, mod := range modules {
Colin Crossb0931242015-06-29 14:18:27 -0700342 err := mod.translateRuleName()
343 if err != nil {
344 return nil, err
345 }
Dan Willemsen27012122015-06-26 17:40:54 -0700346 if mod.isHostRule || !mod.PropBool("host_supported") {
Dan Willemsen3a4045d2015-06-24 15:37:17 -0700347 continue
348 }
349
350 m := &Module{
351 bpmod: mod.bpmod,
352 bpname: mod.bpname,
353 isHostRule: true,
354 }
Colin Crossb0931242015-06-29 14:18:27 -0700355 err = m.translateRuleName()
356 if err != nil {
357 return nil, err
358 }
Dan Willemsen3a4045d2015-06-24 15:37:17 -0700359 modules = append(modules, m)
Dan Willemsen68fdfcc2015-06-11 14:05:01 -0700360 }
361
Dan Willemsen49f50452015-06-24 14:56:00 -0700362 return
363}
Dan Willemsen68fdfcc2015-06-11 14:05:01 -0700364
Colin Crossb0931242015-06-29 14:18:27 -0700365func (w *androidMkWriter) handleModule(inputModule *bpparser.Module) error {
Colin Crossb1a66c02015-06-29 16:24:57 -0700366 comment := w.getCommentBlock(inputModule.Type.Pos)
367 if translation, translated, err := getCommentTranslation(comment); err != nil {
368 return err
369 } else if translated {
370 w.WriteString(translation)
371 return nil
372 }
373
Colin Cross70a5f072015-06-29 17:44:56 -0700374 if ignoredModuleType[inputModule.Type.Name] {
375 return nil
376 }
377
Colin Crossb0931242015-06-29 14:18:27 -0700378 modules, err := w.mutateModule(newModule(inputModule))
379 if err != nil {
380 return err
381 }
Dan Willemsen49f50452015-06-24 14:56:00 -0700382
383 for _, module := range modules {
Colin Crossb0931242015-06-29 14:18:27 -0700384 err := w.parsePropsAndWriteModule(module)
385 if err != nil {
386 return err
387 }
Andres Moralesaf11df12015-04-30 12:14:34 -0700388 }
Colin Crossb0931242015-06-29 14:18:27 -0700389
390 return nil
Andres Moralesaf11df12015-04-30 12:14:34 -0700391}
392
393func (w *androidMkWriter) handleSubdirs(value bpparser.Value) {
Andres Morales8ae47de2015-05-11 12:26:07 -0700394 subdirs := make([]string, 0, len(value.ListValue))
395 for _, tok := range value.ListValue {
396 subdirs = append(subdirs, tok.StringValue)
Andres Moralesda8706f2015-04-29 12:46:49 -0700397 }
Ying Wang38284902015-06-02 18:44:59 -0700398 // The current makefile may be generated to outside the source tree (such as the out directory), with a different structure.
399 fmt.Fprintf(w, "# Uncomment the following line if you really want to include subdir Android.mks.\n")
400 fmt.Fprintf(w, "# include $(wildcard $(addsuffix $(LOCAL_PATH)/%s/, Android.mk))\n", strings.Join(subdirs, " "))
Andres Moralesda8706f2015-04-29 12:46:49 -0700401}
402
Andres Morales8ae47de2015-05-11 12:26:07 -0700403func (w *androidMkWriter) handleLocalPath() error {
Colin Crossb3245e92015-06-30 16:27:57 -0700404 w.WriteString("LOCAL_PATH := " + w.path + "\n")
Dan Willemsenc2666e62015-06-10 16:18:58 -0700405 w.WriteString("LOCAL_MODULE_MAKEFILE := $(lastword $(MAKEFILE_LIST))\n\n")
Andres Morales8ae47de2015-05-11 12:26:07 -0700406 return nil
407}
408
Colin Crossb1a66c02015-06-29 16:24:57 -0700409// Returns any block comment on the line preceding pos as a string
410func (w *androidMkWriter) getCommentBlock(pos scanner.Position) string {
411 var buf []byte
412
413 comments := w.blueprint.Comments
414 for i, c := range comments {
415 if c.EndLine() == pos.Line-1 {
416 line := pos.Line
417 for j := i; j >= 0; j-- {
418 c = comments[j]
419 if c.EndLine() == line-1 {
420 buf = append([]byte(c.Text()), buf...)
421 line = c.Pos.Line
422 } else {
423 break
424 }
425 }
426 }
427 }
428
429 return string(buf)
430}
431
432func getCommentTranslation(comment string) (string, bool, error) {
433 lines := strings.Split(comment, "\n")
434
435 if directive, i, err := getCommentDirective(lines); err != nil {
436 return "", false, err
437 } else if directive != "" {
438 switch directive {
439 case "ignore":
440 return "", true, nil
441 case "start":
442 return getCommentTranslationBlock(lines[i+1:])
443 case "end":
444 return "", false, fmt.Errorf("Unexpected Android.mk:end translation directive")
445 default:
446 return "", false, fmt.Errorf("Unknown Android.mk module translation directive %q", directive)
447 }
448 }
449
450 return "", false, nil
451}
452
453func getCommentTranslationBlock(lines []string) (string, bool, error) {
454 var buf []byte
455
456 for _, line := range lines {
457 if directive := getLineCommentDirective(line); directive != "" {
458 switch directive {
459 case "end":
460 return string(buf), true, nil
461 default:
462 return "", false, fmt.Errorf("Unexpected Android.mk translation directive %q inside start", directive)
463 }
464 } else {
465 buf = append(buf, line...)
466 buf = append(buf, '\n')
467 }
468 }
469
470 return "", false, fmt.Errorf("Missing Android.mk:end translation directive")
471}
472
473func getCommentDirective(lines []string) (directive string, n int, err error) {
474 for i, line := range lines {
475 if directive := getLineCommentDirective(line); directive != "" {
476 return strings.ToLower(directive), i, nil
477 }
478 }
479
480 return "", -1, nil
481}
482
483func getLineCommentDirective(line string) string {
484 line = strings.TrimSpace(line)
485 if strings.HasPrefix(line, "Android.mk:") {
486 line = strings.TrimPrefix(line, "Android.mk:")
487 line = strings.TrimSpace(line)
488 return line
489 }
490
491 return ""
492}
493
Colin Crossb0931242015-06-29 14:18:27 -0700494func (w *androidMkWriter) write(writer io.Writer) (err error) {
495 w.Writer = writer
Andres Moralesda8706f2015-04-29 12:46:49 -0700496
Colin Crossb0931242015-06-29 14:18:27 -0700497 if err = w.handleLocalPath(); err != nil {
Colin Cross26478b72015-06-29 13:46:00 -0700498 return err
499 }
500
501 for _, block := range w.blueprint.Defs {
Andres Moralesda8706f2015-04-29 12:46:49 -0700502 switch block := block.(type) {
503 case *bpparser.Module:
Colin Crossb0931242015-06-29 14:18:27 -0700504 err = w.handleModule(block)
Andres Moralesda8706f2015-04-29 12:46:49 -0700505 case *bpparser.Assignment:
Colin Crossb3245e92015-06-30 16:27:57 -0700506 // Nothing
Colin Crossb0931242015-06-29 14:18:27 -0700507 default:
508 return fmt.Errorf("Unhandled def %v", block)
509 }
510 if err != nil {
511 return err
Andres Moralesda8706f2015-04-29 12:46:49 -0700512 }
513 }
514
Ying Wang38284902015-06-02 18:44:59 -0700515 return nil
Andres Moralesda8706f2015-04-29 12:46:49 -0700516}
517
Colin Crossb3245e92015-06-30 16:27:57 -0700518func translate(rootFile, androidBp, androidMk string) error {
Andres Moralesda8706f2015-04-29 12:46:49 -0700519
Colin Crossb3245e92015-06-30 16:27:57 -0700520 ctx := blueprint.NewContext()
521
522 var blueprintFile *bpparser.File
523
524 _, errs := ctx.WalkBlueprintsFiles(rootFile, func(file *bpparser.File) {
525 if file.Name == androidBp {
526 blueprintFile = file
527 }
528 })
Andres Moralesda8706f2015-04-29 12:46:49 -0700529 if len(errs) > 0 {
Colin Crossb0931242015-06-29 14:18:27 -0700530 return errs[0]
Andres Moralesda8706f2015-04-29 12:46:49 -0700531 }
532
Colin Crossb3245e92015-06-30 16:27:57 -0700533 if blueprintFile == nil {
534 return fmt.Errorf("File %q wasn't parsed from %q", androidBp, rootFile)
535 }
536
Andres Moralesda8706f2015-04-29 12:46:49 -0700537 writer := &androidMkWriter{
Colin Crossb3245e92015-06-30 16:27:57 -0700538 blueprint: blueprintFile,
Ying Wang38284902015-06-02 18:44:59 -0700539 path: path.Dir(androidBp),
Andres Moralesda8706f2015-04-29 12:46:49 -0700540 }
541
Colin Crossb0931242015-06-29 14:18:27 -0700542 buf := &bytes.Buffer{}
543
Colin Crossb3245e92015-06-30 16:27:57 -0700544 err := writer.write(buf)
Ying Wang38284902015-06-02 18:44:59 -0700545 if err != nil {
Colin Crossb0931242015-06-29 14:18:27 -0700546 os.Remove(androidMk)
547 return err
548 }
549
550 f, err := os.Create(androidMk)
551 if err != nil {
552 return err
553 }
554 defer f.Close()
555
556 _, err = f.Write(buf.Bytes())
557
558 return err
559}
560
561func main() {
Colin Crossb3245e92015-06-30 16:27:57 -0700562 if len(os.Args) < 4 {
563 fmt.Fprintln(os.Stderr, "Expected root Android.bp, input and output filename arguments")
Colin Crossb0931242015-06-29 14:18:27 -0700564 os.Exit(1)
565 }
566
Colin Crossb3245e92015-06-30 16:27:57 -0700567 rootFile := os.Args[1]
568 androidBp, err := filepath.Rel(filepath.Dir(rootFile), os.Args[2])
569 if err != nil {
570 fmt.Fprintf(os.Stderr, "Android.bp file %q is not relative to %q: %s\n",
571 os.Args[2], rootFile, err.Error())
572 os.Exit(1)
573 }
574 androidMk := os.Args[3]
Colin Crossb0931242015-06-29 14:18:27 -0700575
Colin Crossb3245e92015-06-30 16:27:57 -0700576 err = translate(rootFile, androidBp, androidMk)
Colin Crossb0931242015-06-29 14:18:27 -0700577 if err != nil {
578 fmt.Fprintf(os.Stderr, "Error translating %s: %s\n", androidBp, err.Error())
Ying Wang38284902015-06-02 18:44:59 -0700579 os.Exit(1)
580 }
Andres Moralesda8706f2015-04-29 12:46:49 -0700581}