deps.go 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. // Copyright 2018 Google Inc. All rights reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package makedeps
  15. import (
  16. "bytes"
  17. "fmt"
  18. "io"
  19. "strings"
  20. "android/soong/androidmk/parser"
  21. )
  22. type Deps struct {
  23. Output string
  24. Inputs []string
  25. }
  26. func Parse(filename string, r io.Reader) (*Deps, error) {
  27. p := parser.NewParser(filename, r)
  28. nodes, errs := p.Parse()
  29. if len(errs) == 1 {
  30. return nil, errs[0]
  31. } else if len(errs) > 1 {
  32. return nil, fmt.Errorf("many errors: %v", errs)
  33. }
  34. pos := func(node parser.Node) string {
  35. return p.Unpack(node.Pos()).String() + ": "
  36. }
  37. ret := &Deps{}
  38. for _, node := range nodes {
  39. switch x := node.(type) {
  40. case *parser.Comment:
  41. // Do nothing
  42. case *parser.Rule:
  43. if x.Recipe != "" {
  44. return nil, fmt.Errorf("%sunexpected recipe in rule: %v", pos(node), x)
  45. }
  46. if !x.Target.Const() {
  47. return nil, fmt.Errorf("%sunsupported variable expansion: %v", pos(node), x.Target.Dump())
  48. }
  49. outputs := x.Target.Words()
  50. if len(outputs) > 0 {
  51. ret.Output = outputs[0].Value(nil)
  52. } else {
  53. // TODO(b/141372861): put this back
  54. //return nil, fmt.Errorf("%smissing output: %v", pos(node), x)
  55. }
  56. if !x.Prerequisites.Const() {
  57. return nil, fmt.Errorf("%sunsupported variable expansion: %v", pos(node), x.Prerequisites.Dump())
  58. }
  59. for _, input := range x.Prerequisites.Words() {
  60. ret.Inputs = append(ret.Inputs, input.Value(nil))
  61. }
  62. default:
  63. return nil, fmt.Errorf("%sunexpected line: %#v", pos(node), node)
  64. }
  65. }
  66. return ret, nil
  67. }
  68. func (d *Deps) Print() []byte {
  69. // We don't really have to escape every \, but it's simpler,
  70. // and ninja will handle it.
  71. replacer := strings.NewReplacer(" ", "\\ ",
  72. ":", "\\:",
  73. "#", "\\#",
  74. "$", "$$",
  75. "\\", "\\\\")
  76. b := &bytes.Buffer{}
  77. fmt.Fprintf(b, "%s:", replacer.Replace(d.Output))
  78. for _, input := range d.Inputs {
  79. fmt.Fprintf(b, " %s", replacer.Replace(input))
  80. }
  81. fmt.Fprintln(b)
  82. return b.Bytes()
  83. }