Recognize some unsupported functions

Some functions are called without the use of $(call),
since $(call) is not necessary when the function doesn't
take any arguments. mk2rbc thinks these function calls
are local variables, and converts them as such. This
leads to undefined variable errors when trying to load
(before even executing) the starlark file.

Hardcode a known function that should not be converted
to a local variable.

Bug: 226974242
Test: go test
Change-Id: I5567a34fcc282b181a7e78ac3d5cc9b40bd025a2
This commit is contained in:
Cole Faust 2022-04-26 14:28:04 -07:00
parent 12097e3109
commit 1e27586012
3 changed files with 32 additions and 22 deletions

View file

@ -741,8 +741,8 @@ func (_ *badExpr) typ() starlarkType {
return starlarkTypeUnknown
}
func (_ *badExpr) emitListVarCopy(_ *generationContext) {
panic("implement me")
func (b *badExpr) emitListVarCopy(gctx *generationContext) {
b.emit(gctx)
}
func (b *badExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {

View file

@ -130,6 +130,14 @@ var knownNodeFunctions = map[string]interface {
"foreach": &foreachCallNodeParser{},
}
// These look like variables, but are actually functions, and would give
// undefined variable errors if we converted them as variables. Instead,
// emit an error instead of converting them.
var unsupportedFunctions = map[string]bool{
"local-generated-sources-dir": true,
"local-intermediates-dir": true,
}
// These are functions that we don't implement conversions for, but
// we allow seeing their definitions in the product config files.
var ignoredDefines = map[string]bool{
@ -556,9 +564,6 @@ func (ctx *parseContext) handleAssignment(a *mkparser.Assignment) []starlarkNode
if lhs.valueType() == starlarkTypeUnknown {
// Try to divine variable type from the RHS
asgn.value = ctx.parseMakeString(a, a.Value)
if xBad, ok := asgn.value.(*badExpr); ok {
return []starlarkNode{&exprNode{xBad}}
}
inferred_type := asgn.value.typ()
if inferred_type != starlarkTypeUnknown {
lhs.setValueType(inferred_type)
@ -567,21 +572,19 @@ func (ctx *parseContext) handleAssignment(a *mkparser.Assignment) []starlarkNode
if lhs.valueType() == starlarkTypeList {
xConcat, xBad := ctx.buildConcatExpr(a)
if xBad != nil {
return []starlarkNode{&exprNode{expr: xBad}}
}
switch len(xConcat.items) {
case 0:
asgn.value = &listExpr{}
case 1:
asgn.value = xConcat.items[0]
default:
asgn.value = xConcat
asgn.value = xBad
} else {
switch len(xConcat.items) {
case 0:
asgn.value = &listExpr{}
case 1:
asgn.value = xConcat.items[0]
default:
asgn.value = xConcat
}
}
} else {
asgn.value = ctx.parseMakeString(a, a.Value)
if xBad, ok := asgn.value.(*badExpr); ok {
return []starlarkNode{&exprNode{expr: xBad}}
}
}
if asgn.lhs.valueType() == starlarkTypeString &&
@ -1262,6 +1265,12 @@ func (ctx *parseContext) parseReference(node mkparser.Node, ref *mkparser.MakeSt
return ctx.newBadExpr(node, "reference is too complex: %s", refDump)
}
if name, _, ok := ctx.maybeParseFunctionCall(node, ref); ok {
if _, unsupported := unsupportedFunctions[name]; unsupported {
return ctx.newBadExpr(node, "%s is not supported", refDump)
}
}
// If it is a single word, it can be a simple variable
// reference or a function call
if len(words) == 1 && !isMakeControlFunc(refDump) && refDump != "shell" && refDump != "eval" {
@ -1309,9 +1318,8 @@ func (ctx *parseContext) parseReference(node mkparser.Node, ref *mkparser.MakeSt
} else {
return ctx.newBadExpr(node, "cannot handle invoking %s", name)
}
} else {
return ctx.newBadExpr(node, "cannot handle %s", refDump)
}
return ctx.newBadExpr(node, "cannot handle %s", refDump)
}
type simpleCallParser struct {

View file

@ -117,8 +117,8 @@ PRODUCT_NAME := $(call foo0)
def init(g, handle):
cfg = rblf.cfg(handle)
rblf.mk2rbc_error("product.mk:2", "cannot handle invoking foo1")
rblf.mk2rbc_error("product.mk:3", "cannot handle invoking foo0")
cfg["PRODUCT_NAME"] = rblf.mk2rbc_error("product.mk:2", "cannot handle invoking foo1")
cfg["PRODUCT_NAME"] = rblf.mk2rbc_error("product.mk:3", "cannot handle invoking foo0")
`,
},
{
@ -975,7 +975,7 @@ def init(g, handle):
rblf.soong_config_namespace(g, "cvd")
rblf.soong_config_set(g, "cvd", "launch_configs", "cvd_config_auto.json")
rblf.soong_config_append(g, "cvd", "grub_config", "grub.cfg")
rblf.mk2rbc_error("product.mk:7", "SOONG_CONFIG_ variables cannot be referenced, use soong_config_get instead: SOONG_CONFIG_cvd_grub_config")
_x = rblf.mk2rbc_error("product.mk:7", "SOONG_CONFIG_ variables cannot be referenced, use soong_config_get instead: SOONG_CONFIG_cvd_grub_config")
`,
}, {
desc: "soong namespace accesses",
@ -1269,6 +1269,7 @@ def init(g, handle):
in: `
ifeq (,$(call foobar))
endif
my_sources := $(local-generated-sources-dir)
`,
expected: `load("//build/make/core:product_config.rbc", "rblf")
@ -1276,6 +1277,7 @@ def init(g, handle):
cfg = rblf.cfg(handle)
if rblf.mk2rbc_error("build/product.mk:2", "cannot handle invoking foobar"):
pass
_my_sources = rblf.mk2rbc_error("build/product.mk:4", "local-generated-sources-dir is not supported")
`,
},
{