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
This commit is contained in:
@@ -40,7 +40,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
baseUri = "//build/make/core:product_config.rbc"
|
annotationCommentPrefix = "RBC#"
|
||||||
|
baseUri = "//build/make/core:product_config.rbc"
|
||||||
// The name of the struct exported by the product_config.rbc
|
// The name of the struct exported by the product_config.rbc
|
||||||
// that contains the functions and variables available to
|
// that contains the functions and variables available to
|
||||||
// product configuration Starlark files.
|
// product configuration Starlark files.
|
||||||
@@ -407,6 +408,7 @@ type parseContext struct {
|
|||||||
outputDir string
|
outputDir string
|
||||||
dependentModules map[string]*moduleInfo
|
dependentModules map[string]*moduleInfo
|
||||||
soongNamespaces map[string]map[string]bool
|
soongNamespaces map[string]map[string]bool
|
||||||
|
includeTops []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func newParseContext(ss *StarlarkScript, nodes []mkparser.Node) *parseContext {
|
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),
|
variables: make(map[string]variable),
|
||||||
dependentModules: make(map[string]*moduleInfo),
|
dependentModules: make(map[string]*moduleInfo),
|
||||||
soongNamespaces: make(map[string]map[string]bool),
|
soongNamespaces: make(map[string]map[string]bool),
|
||||||
|
includeTops: []string{"vendor/google-devices"},
|
||||||
}
|
}
|
||||||
ctx.pushVarAssignments()
|
ctx.pushVarAssignments()
|
||||||
for _, item := range predefined {
|
for _, item := range predefined {
|
||||||
@@ -810,21 +813,15 @@ func (ctx *parseContext) handleSubConfig(
|
|||||||
pathPattern = append(pathPattern, chunk)
|
pathPattern = append(pathPattern, chunk)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if pathPattern[0] != "" {
|
if pathPattern[0] == "" {
|
||||||
matchingPaths = ctx.findMatchingPaths(pathPattern)
|
// If pattern starts from the top. restrict it to the directories where
|
||||||
} else {
|
// we know inherit-product uses dynamically calculated path.
|
||||||
// Heuristics -- if pattern starts from top, restrict it to the directories where
|
for _, p := range ctx.includeTops {
|
||||||
// we know inherit-product uses dynamically calculated path. Restrict it even further
|
pathPattern[0] = p
|
||||||
// for certain path which would yield too many useless matches
|
matchingPaths = append(matchingPaths, ctx.findMatchingPaths(pathPattern)...)
|
||||||
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
|
|
||||||
matchingPaths = append(matchingPaths, ctx.findMatchingPaths(pathPattern)...)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
matchingPaths = ctx.findMatchingPaths(pathPattern)
|
||||||
}
|
}
|
||||||
// Safeguard against $(call inherit-product,$(PRODUCT_PATH))
|
// Safeguard against $(call inherit-product,$(PRODUCT_PATH))
|
||||||
const maxMatchingFiles = 150
|
const maxMatchingFiles = 150
|
||||||
@@ -1453,6 +1450,7 @@ func (ctx *parseContext) handleSimpleStatement(node mkparser.Node) bool {
|
|||||||
handled := true
|
handled := true
|
||||||
switch x := node.(type) {
|
switch x := node.(type) {
|
||||||
case *mkparser.Comment:
|
case *mkparser.Comment:
|
||||||
|
ctx.maybeHandleAnnotation(x)
|
||||||
ctx.insertComment("#" + x.Comment)
|
ctx.insertComment("#" + x.Comment)
|
||||||
case *mkparser.Assignment:
|
case *mkparser.Assignment:
|
||||||
ctx.handleAssignment(x)
|
ctx.handleAssignment(x)
|
||||||
@@ -1473,6 +1471,28 @@ func (ctx *parseContext) handleSimpleStatement(node mkparser.Node) bool {
|
|||||||
return handled
|
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) {
|
func (ctx *parseContext) insertComment(s string) {
|
||||||
ctx.receiver.newNode(&commentNode{strings.TrimSpace(s)})
|
ctx.receiver.newNode(&commentNode{strings.TrimSpace(s)})
|
||||||
}
|
}
|
||||||
|
@@ -919,7 +919,7 @@ def init(g, handle):
|
|||||||
desc: "Dynamic inherit path",
|
desc: "Dynamic inherit path",
|
||||||
mkname: "product.mk",
|
mkname: "product.mk",
|
||||||
in: `
|
in: `
|
||||||
MY_PATH=foo
|
MY_PATH:=foo
|
||||||
$(call inherit-product,vendor/$(MY_PATH)/cfg.mk)
|
$(call inherit-product,vendor/$(MY_PATH)/cfg.mk)
|
||||||
`,
|
`,
|
||||||
expected: `load("//build/make/core:product_config.rbc", "rblf")
|
expected: `load("//build/make/core:product_config.rbc", "rblf")
|
||||||
@@ -937,6 +937,30 @@ def init(g, handle):
|
|||||||
if not _varmod_init:
|
if not _varmod_init:
|
||||||
rblf.mkerror("cannot")
|
rblf.mkerror("cannot")
|
||||||
rblf.inherit(handle, _varmod, _varmod_init)
|
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)
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user