blob: ef7a364ebfdca6db89850fa10900c702c9bf1e8d [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 Crossc41f6302015-06-30 12:19:47 -0700221func appendAssign(name string, prop *bpparser.Property, suffix *string) ([]string, error) {
222 if suffix != nil {
223 name += "_" + *suffix
224 }
225 val, err := valueToString(prop.Value)
226 if err != nil {
227 return nil, err
228 }
229 return []string{
230 fmt.Sprintf("%s += %s", name, val),
231 }, nil
232}
233
Colin Crossb0931242015-06-29 14:18:27 -0700234func prependLocalPath(name string, prop *bpparser.Property, suffix *string) ([]string, error) {
Dan Willemsen57ad08c2015-06-10 16:20: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
241 }
Colin Crossff3b7952015-06-22 15:39:35 -0700242 return []string{
Colin Crossc41f6302015-06-30 12:19:47 -0700243 fmt.Sprintf("%s += $(addprefix $(LOCAL_PATH)/,%s)", name, val),
Colin Crossb0931242015-06-29 14:18:27 -0700244 }, nil
Dan Willemsen57ad08c2015-06-10 16:20:14 -0700245}
246
Colin Crossb0931242015-06-29 14:18:27 -0700247func prependLocalModule(name string, prop *bpparser.Property, suffix *string) ([]string, error) {
Dan Willemsen1d9f2792015-06-22 15:40:14 -0700248 if suffix != nil {
249 name += "_" + *suffix
250 }
Colin Crossb0931242015-06-29 14:18:27 -0700251 val, err := valueToString(prop.Value)
252 if err != nil {
253 return nil, err
Dan Willemsen1d9f2792015-06-22 15:40:14 -0700254 }
Colin Crossb0931242015-06-29 14:18:27 -0700255 return []string{
256 fmt.Sprintf("%s := $(LOCAL_MODULE)%s\n", name, val),
257 }, nil
Dan Willemsen1d9f2792015-06-22 15:40:14 -0700258}
259
Dan Willemsen3a4045d2015-06-24 15:37:17 -0700260func modulePropBool(module *bpparser.Module, name string) bool {
261 for _, prop := range module.Properties {
262 if name == prop.Name.Name {
263 return prop.Value.BoolValue
264 }
265 }
266 return false
267}
268
Andres Moralesaf11df12015-04-30 12:14:34 -0700269func (w *androidMkWriter) writeModule(moduleRule string, props []string,
270 disabledBuilds map[string]bool, isHostRule bool) {
271 disabledConditionals := disabledTargetConditionals
272 if isHostRule {
273 disabledConditionals = disabledHostConditionals
274 }
275 for build, _ := range disabledBuilds {
276 if conditional, ok := disabledConditionals[build]; ok {
277 fmt.Fprintf(w, "%s\n", conditional)
278 defer fmt.Fprintf(w, "endif\n")
Andres Moralesda8706f2015-04-29 12:46:49 -0700279 }
Andres Moralesaf11df12015-04-30 12:14:34 -0700280 }
Andres Moralesda8706f2015-04-29 12:46:49 -0700281
Andres Moralesaf11df12015-04-30 12:14:34 -0700282 fmt.Fprintf(w, "include $(CLEAR_VARS)\n")
283 fmt.Fprintf(w, "%s\n", strings.Join(props, "\n"))
284 fmt.Fprintf(w, "include $(%s)\n\n", moduleRule)
285}
Andres Moralesda8706f2015-04-29 12:46:49 -0700286
Colin Crossb0931242015-06-29 14:18:27 -0700287func (w *androidMkWriter) parsePropsAndWriteModule(module *Module) error {
Dan Willemsen3a4045d2015-06-24 15:37:17 -0700288 standardProps := make([]string, 0, len(module.bpmod.Properties))
Andres Moralesaf11df12015-04-30 12:14:34 -0700289 disabledBuilds := make(map[string]bool)
Dan Willemsen3a4045d2015-06-24 15:37:17 -0700290 for _, prop := range module.bpmod.Properties {
Andres Moralesaf11df12015-04-30 12:14:34 -0700291 if mkProp, ok := standardProperties[prop.Name.Name]; ok {
Colin Crossb0931242015-06-29 14:18:27 -0700292 val, err := valueToString(prop.Value)
293 if err != nil {
294 return err
295 }
296 standardProps = append(standardProps, fmt.Sprintf("%s := %s", mkProp.string, val))
Dan Willemsen57ad08c2015-06-10 16:20:14 -0700297 } else if rwProp, ok := rewriteProperties[prop.Name.Name]; ok {
Colin Crossb0931242015-06-29 14:18:27 -0700298 props, err := rwProp.f(rwProp.string, prop, nil)
299 if err != nil {
300 return err
301 }
302 standardProps = append(standardProps, props...)
Andres Moralesaf11df12015-04-30 12:14:34 -0700303 } else if suffixMap, ok := suffixProperties[prop.Name.Name]; ok {
Colin Crossb3245e92015-06-30 16:27:57 -0700304 props, err := translateSuffixProperties(prop.Value.MapValue, suffixMap)
Colin Crossb0931242015-06-29 14:18:27 -0700305 if err != nil {
306 return err
307 }
308 standardProps = append(standardProps, props...)
Andres Moralesaf11df12015-04-30 12:14:34 -0700309 } else if "target" == prop.Name.Name {
Colin Crossb3245e92015-06-30 16:27:57 -0700310 props, err := translateTargetConditionals(prop.Value.MapValue, disabledBuilds, module.isHostRule)
Colin Crossb0931242015-06-29 14:18:27 -0700311 if err != nil {
312 return err
313 }
314 standardProps = append(standardProps, props...)
Dan Willemsen0a544692015-06-24 15:50:07 -0700315 } else if _, ok := ignoredProperties[prop.Name.Name]; ok {
Andres Moralesaf11df12015-04-30 12:14:34 -0700316 } else {
Colin Crossb0931242015-06-29 14:18:27 -0700317 return fmt.Errorf("Unsupported property %q", prop.Name.Name)
Andres Moralesaf11df12015-04-30 12:14:34 -0700318 }
319 }
320
Dan Willemsen3a4045d2015-06-24 15:37:17 -0700321 w.writeModule(module.mkname, standardProps, disabledBuilds, module.isHostRule)
Colin Crossb0931242015-06-29 14:18:27 -0700322
323 return nil
Dan Willemsen68fdfcc2015-06-11 14:05:01 -0700324}
325
Colin Crossb0931242015-06-29 14:18:27 -0700326func (w *androidMkWriter) mutateModule(module *Module) (modules []*Module, err error) {
Dan Willemsen3a4045d2015-06-24 15:37:17 -0700327 modules = []*Module{module}
Dan Willemsen49f50452015-06-24 14:56:00 -0700328
Dan Willemsen3a4045d2015-06-24 15:37:17 -0700329 if module.bpname == "cc_library" {
330 modules = []*Module{
331 newModule(module.bpmod),
332 newModule(module.bpmod),
333 }
334 modules[0].bpname = "cc_library_shared"
335 modules[1].bpname = "cc_library_static"
336 }
337
338 for _, mod := range modules {
Colin Crossb0931242015-06-29 14:18:27 -0700339 err := mod.translateRuleName()
340 if err != nil {
341 return nil, err
342 }
Dan Willemsen3a4045d2015-06-24 15:37:17 -0700343 if mod.isHostRule || !modulePropBool(mod.bpmod, "host_supported") {
344 continue
345 }
346
347 m := &Module{
348 bpmod: mod.bpmod,
349 bpname: mod.bpname,
350 isHostRule: true,
351 }
Colin Crossb0931242015-06-29 14:18:27 -0700352 err = m.translateRuleName()
353 if err != nil {
354 return nil, err
355 }
Dan Willemsen3a4045d2015-06-24 15:37:17 -0700356 modules = append(modules, m)
Dan Willemsen68fdfcc2015-06-11 14:05:01 -0700357 }
358
Dan Willemsen49f50452015-06-24 14:56:00 -0700359 return
360}
Dan Willemsen68fdfcc2015-06-11 14:05:01 -0700361
Colin Crossb0931242015-06-29 14:18:27 -0700362func (w *androidMkWriter) handleModule(inputModule *bpparser.Module) error {
Colin Crossb1a66c02015-06-29 16:24:57 -0700363 comment := w.getCommentBlock(inputModule.Type.Pos)
364 if translation, translated, err := getCommentTranslation(comment); err != nil {
365 return err
366 } else if translated {
367 w.WriteString(translation)
368 return nil
369 }
370
Colin Cross70a5f072015-06-29 17:44:56 -0700371 if ignoredModuleType[inputModule.Type.Name] {
372 return nil
373 }
374
Colin Crossb0931242015-06-29 14:18:27 -0700375 modules, err := w.mutateModule(newModule(inputModule))
376 if err != nil {
377 return err
378 }
Dan Willemsen49f50452015-06-24 14:56:00 -0700379
380 for _, module := range modules {
Colin Crossb0931242015-06-29 14:18:27 -0700381 err := w.parsePropsAndWriteModule(module)
382 if err != nil {
383 return err
384 }
Andres Moralesaf11df12015-04-30 12:14:34 -0700385 }
Colin Crossb0931242015-06-29 14:18:27 -0700386
387 return nil
Andres Moralesaf11df12015-04-30 12:14:34 -0700388}
389
390func (w *androidMkWriter) handleSubdirs(value bpparser.Value) {
Andres Morales8ae47de2015-05-11 12:26:07 -0700391 subdirs := make([]string, 0, len(value.ListValue))
392 for _, tok := range value.ListValue {
393 subdirs = append(subdirs, tok.StringValue)
Andres Moralesda8706f2015-04-29 12:46:49 -0700394 }
Ying Wang38284902015-06-02 18:44:59 -0700395 // The current makefile may be generated to outside the source tree (such as the out directory), with a different structure.
396 fmt.Fprintf(w, "# Uncomment the following line if you really want to include subdir Android.mks.\n")
397 fmt.Fprintf(w, "# include $(wildcard $(addsuffix $(LOCAL_PATH)/%s/, Android.mk))\n", strings.Join(subdirs, " "))
Andres Moralesda8706f2015-04-29 12:46:49 -0700398}
399
Andres Morales8ae47de2015-05-11 12:26:07 -0700400func (w *androidMkWriter) handleLocalPath() error {
Colin Crossb3245e92015-06-30 16:27:57 -0700401 w.WriteString("LOCAL_PATH := " + w.path + "\n")
Dan Willemsenc2666e62015-06-10 16:18:58 -0700402 w.WriteString("LOCAL_MODULE_MAKEFILE := $(lastword $(MAKEFILE_LIST))\n\n")
Andres Morales8ae47de2015-05-11 12:26:07 -0700403 return nil
404}
405
Colin Crossb1a66c02015-06-29 16:24:57 -0700406// Returns any block comment on the line preceding pos as a string
407func (w *androidMkWriter) getCommentBlock(pos scanner.Position) string {
408 var buf []byte
409
410 comments := w.blueprint.Comments
411 for i, c := range comments {
412 if c.EndLine() == pos.Line-1 {
413 line := pos.Line
414 for j := i; j >= 0; j-- {
415 c = comments[j]
416 if c.EndLine() == line-1 {
417 buf = append([]byte(c.Text()), buf...)
418 line = c.Pos.Line
419 } else {
420 break
421 }
422 }
423 }
424 }
425
426 return string(buf)
427}
428
429func getCommentTranslation(comment string) (string, bool, error) {
430 lines := strings.Split(comment, "\n")
431
432 if directive, i, err := getCommentDirective(lines); err != nil {
433 return "", false, err
434 } else if directive != "" {
435 switch directive {
436 case "ignore":
437 return "", true, nil
438 case "start":
439 return getCommentTranslationBlock(lines[i+1:])
440 case "end":
441 return "", false, fmt.Errorf("Unexpected Android.mk:end translation directive")
442 default:
443 return "", false, fmt.Errorf("Unknown Android.mk module translation directive %q", directive)
444 }
445 }
446
447 return "", false, nil
448}
449
450func getCommentTranslationBlock(lines []string) (string, bool, error) {
451 var buf []byte
452
453 for _, line := range lines {
454 if directive := getLineCommentDirective(line); directive != "" {
455 switch directive {
456 case "end":
457 return string(buf), true, nil
458 default:
459 return "", false, fmt.Errorf("Unexpected Android.mk translation directive %q inside start", directive)
460 }
461 } else {
462 buf = append(buf, line...)
463 buf = append(buf, '\n')
464 }
465 }
466
467 return "", false, fmt.Errorf("Missing Android.mk:end translation directive")
468}
469
470func getCommentDirective(lines []string) (directive string, n int, err error) {
471 for i, line := range lines {
472 if directive := getLineCommentDirective(line); directive != "" {
473 return strings.ToLower(directive), i, nil
474 }
475 }
476
477 return "", -1, nil
478}
479
480func getLineCommentDirective(line string) string {
481 line = strings.TrimSpace(line)
482 if strings.HasPrefix(line, "Android.mk:") {
483 line = strings.TrimPrefix(line, "Android.mk:")
484 line = strings.TrimSpace(line)
485 return line
486 }
487
488 return ""
489}
490
Colin Crossb0931242015-06-29 14:18:27 -0700491func (w *androidMkWriter) write(writer io.Writer) (err error) {
492 w.Writer = writer
Andres Moralesda8706f2015-04-29 12:46:49 -0700493
Colin Crossb0931242015-06-29 14:18:27 -0700494 if err = w.handleLocalPath(); err != nil {
Colin Cross26478b72015-06-29 13:46:00 -0700495 return err
496 }
497
498 for _, block := range w.blueprint.Defs {
Andres Moralesda8706f2015-04-29 12:46:49 -0700499 switch block := block.(type) {
500 case *bpparser.Module:
Colin Crossb0931242015-06-29 14:18:27 -0700501 err = w.handleModule(block)
Andres Moralesda8706f2015-04-29 12:46:49 -0700502 case *bpparser.Assignment:
Colin Crossb3245e92015-06-30 16:27:57 -0700503 // Nothing
Colin Crossb0931242015-06-29 14:18:27 -0700504 default:
505 return fmt.Errorf("Unhandled def %v", block)
506 }
507 if err != nil {
508 return err
Andres Moralesda8706f2015-04-29 12:46:49 -0700509 }
510 }
511
Ying Wang38284902015-06-02 18:44:59 -0700512 return nil
Andres Moralesda8706f2015-04-29 12:46:49 -0700513}
514
Colin Crossb3245e92015-06-30 16:27:57 -0700515func translate(rootFile, androidBp, androidMk string) error {
Andres Moralesda8706f2015-04-29 12:46:49 -0700516
Colin Crossb3245e92015-06-30 16:27:57 -0700517 ctx := blueprint.NewContext()
518
519 var blueprintFile *bpparser.File
520
521 _, errs := ctx.WalkBlueprintsFiles(rootFile, func(file *bpparser.File) {
522 if file.Name == androidBp {
523 blueprintFile = file
524 }
525 })
Andres Moralesda8706f2015-04-29 12:46:49 -0700526 if len(errs) > 0 {
Colin Crossb0931242015-06-29 14:18:27 -0700527 return errs[0]
Andres Moralesda8706f2015-04-29 12:46:49 -0700528 }
529
Colin Crossb3245e92015-06-30 16:27:57 -0700530 if blueprintFile == nil {
531 return fmt.Errorf("File %q wasn't parsed from %q", androidBp, rootFile)
532 }
533
Andres Moralesda8706f2015-04-29 12:46:49 -0700534 writer := &androidMkWriter{
Colin Crossb3245e92015-06-30 16:27:57 -0700535 blueprint: blueprintFile,
Ying Wang38284902015-06-02 18:44:59 -0700536 path: path.Dir(androidBp),
Andres Moralesda8706f2015-04-29 12:46:49 -0700537 }
538
Colin Crossb0931242015-06-29 14:18:27 -0700539 buf := &bytes.Buffer{}
540
Colin Crossb3245e92015-06-30 16:27:57 -0700541 err := writer.write(buf)
Ying Wang38284902015-06-02 18:44:59 -0700542 if err != nil {
Colin Crossb0931242015-06-29 14:18:27 -0700543 os.Remove(androidMk)
544 return err
545 }
546
547 f, err := os.Create(androidMk)
548 if err != nil {
549 return err
550 }
551 defer f.Close()
552
553 _, err = f.Write(buf.Bytes())
554
555 return err
556}
557
558func main() {
Colin Crossb3245e92015-06-30 16:27:57 -0700559 if len(os.Args) < 4 {
560 fmt.Fprintln(os.Stderr, "Expected root Android.bp, input and output filename arguments")
Colin Crossb0931242015-06-29 14:18:27 -0700561 os.Exit(1)
562 }
563
Colin Crossb3245e92015-06-30 16:27:57 -0700564 rootFile := os.Args[1]
565 androidBp, err := filepath.Rel(filepath.Dir(rootFile), os.Args[2])
566 if err != nil {
567 fmt.Fprintf(os.Stderr, "Android.bp file %q is not relative to %q: %s\n",
568 os.Args[2], rootFile, err.Error())
569 os.Exit(1)
570 }
571 androidMk := os.Args[3]
Colin Crossb0931242015-06-29 14:18:27 -0700572
Colin Crossb3245e92015-06-30 16:27:57 -0700573 err = translate(rootFile, androidBp, androidMk)
Colin Crossb0931242015-06-29 14:18:27 -0700574 if err != nil {
575 fmt.Fprintf(os.Stderr, "Error translating %s: %s\n", androidBp, err.Error())
Ying Wang38284902015-06-02 18:44:59 -0700576 os.Exit(1)
577 }
Andres Moralesda8706f2015-04-29 12:46:49 -0700578}