Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6d852dd1 authored by Sasha Smundak's avatar Sasha Smundak
Browse files

Implement include path annotation.

Include top annotation is a specially formatted comment line providing
the include/inhherit file location hint. E.g., adding
```
```
before
```
$(call inherit-product $(SRC)/foo.mk
```
is a hint to the converter to look for the `foo.mk` files under
`vendor/my_vendor/` in addition to `vendor/google_devices/'

Bug: 193566316
Test: internal
Change-Id: I01c5dde2504f1a9eb724098b1cc03d2176ca2cf9
parent 65b547ed
Loading
Loading
Loading
Loading
+35 −15
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ import (
)

const (
	annotationCommentPrefix = "RBC#"
	baseUri                 = "//build/make/core:product_config.rbc"
	// The name of the struct exported by the product_config.rbc
	// that contains the functions and variables available to
@@ -407,6 +408,7 @@ type parseContext struct {
	outputDir        string
	dependentModules map[string]*moduleInfo
	soongNamespaces  map[string]map[string]bool
	includeTops      []string
}

func newParseContext(ss *StarlarkScript, nodes []mkparser.Node) *parseContext {
@@ -452,6 +454,7 @@ func newParseContext(ss *StarlarkScript, nodes []mkparser.Node) *parseContext {
		variables:        make(map[string]variable),
		dependentModules: make(map[string]*moduleInfo),
		soongNamespaces:  make(map[string]map[string]bool),
		includeTops:      []string{"vendor/google-devices"},
	}
	ctx.pushVarAssignments()
	for _, item := range predefined {
@@ -810,21 +813,15 @@ func (ctx *parseContext) handleSubConfig(
			pathPattern = append(pathPattern, chunk)
		}
	}
	if pathPattern[0] != "" {
		matchingPaths = ctx.findMatchingPaths(pathPattern)
	} else {
		// Heuristics -- if pattern starts from top, restrict it to the directories where
		// we know inherit-product uses dynamically calculated path. Restrict it even further
		// for certain path which would yield too many useless matches
		if len(varPath.chunks) == 2 && varPath.chunks[1] == "/BoardConfigVendor.mk" {
			pathPattern[0] = "vendor/google_devices"
			matchingPaths = ctx.findMatchingPaths(pathPattern)
		} else {
			for _, t := range []string{"vendor/qcom", "vendor/google_devices"} {
				pathPattern[0] = t
	if pathPattern[0] == "" {
		// If pattern starts from the top. restrict it to the directories where
		// we know inherit-product uses dynamically calculated path.
		for _, p := range ctx.includeTops {
			pathPattern[0] = p
			matchingPaths = append(matchingPaths, ctx.findMatchingPaths(pathPattern)...)
		}
		}
	} else {
		matchingPaths = ctx.findMatchingPaths(pathPattern)
	}
	// Safeguard against $(call inherit-product,$(PRODUCT_PATH))
	const maxMatchingFiles = 150
@@ -1453,6 +1450,7 @@ func (ctx *parseContext) handleSimpleStatement(node mkparser.Node) bool {
	handled := true
	switch x := node.(type) {
	case *mkparser.Comment:
		ctx.maybeHandleAnnotation(x)
		ctx.insertComment("#" + x.Comment)
	case *mkparser.Assignment:
		ctx.handleAssignment(x)
@@ -1473,6 +1471,28 @@ func (ctx *parseContext) handleSimpleStatement(node mkparser.Node) bool {
	return handled
}

// Processes annotation. An annotation is a comment that starts with #RBC# and provides
// a conversion hint -- say, where to look for the dynamically calculated inherit/include
// paths.
func (ctx *parseContext) maybeHandleAnnotation(cnode *mkparser.Comment) {
	maybeTrim := func(s, prefix string) (string, bool) {
		if strings.HasPrefix(s, prefix) {
			return strings.TrimSpace(strings.TrimPrefix(s, prefix)), true
		}
		return s, false
	}
	annotation, ok := maybeTrim(cnode.Comment, annotationCommentPrefix)
	if !ok {
		return
	}
	if p, ok := maybeTrim(annotation, "include_top"); ok {
		ctx.includeTops = append(ctx.includeTops, p)
		return
	}
	ctx.errorf(cnode, "unsupported annotation %s", cnode.Comment)

}

func (ctx *parseContext) insertComment(s string) {
	ctx.receiver.newNode(&commentNode{strings.TrimSpace(s)})
}
+25 −1
Original line number Diff line number Diff line
@@ -919,7 +919,7 @@ def init(g, handle):
		desc:   "Dynamic inherit path",
		mkname: "product.mk",
		in: `
MY_PATH=foo
MY_PATH:=foo
$(call inherit-product,vendor/$(MY_PATH)/cfg.mk)
`,
		expected: `load("//build/make/core:product_config.rbc", "rblf")
@@ -937,6 +937,30 @@ def init(g, handle):
  if not _varmod_init:
    rblf.mkerror("cannot")
  rblf.inherit(handle, _varmod, _varmod_init)
`,
	},
	{
		desc:   "Dynamic inherit with hint",
		mkname: "product.mk",
		in: `
MY_PATH:=foo
#RBC# include_top vendor/foo1
$(call inherit-product,$(MY_PATH)/cfg.mk)
`,
		expected: `load("//build/make/core:product_config.rbc", "rblf")
load("//vendor/foo1:cfg.star|init", _cfg_init = "init")

def init(g, handle):
  cfg = rblf.cfg(handle)
  g["MY_PATH"] = "foo"
  #RBC# include_top vendor/foo1
  _entry = {
    "vendor/foo1/cfg.mk": ("_cfg", _cfg_init),
  }.get("%s/cfg.mk" % g["MY_PATH"])
  (_varmod, _varmod_init) = _entry if _entry else (None, None)
  if not _varmod_init:
    rblf.mkerror("cannot")
  rblf.inherit(handle, _varmod, _varmod_init)
`,
	},
}