From 1e27586012c47be8c8d8338df57a573116551665 Mon Sep 17 00:00:00 2001 From: Cole Faust Date: Tue, 26 Apr 2022 14:28:04 -0700 Subject: [PATCH] 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 --- mk2rbc/expr.go | 4 ++-- mk2rbc/mk2rbc.go | 42 +++++++++++++++++++++++++----------------- mk2rbc/mk2rbc_test.go | 8 +++++--- 3 files changed, 32 insertions(+), 22 deletions(-) diff --git a/mk2rbc/expr.go b/mk2rbc/expr.go index 92665207d..6a6eb460a 100644 --- a/mk2rbc/expr.go +++ b/mk2rbc/expr.go @@ -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 { diff --git a/mk2rbc/mk2rbc.go b/mk2rbc/mk2rbc.go index 8f4fea4b1..073c2ed8f 100644 --- a/mk2rbc/mk2rbc.go +++ b/mk2rbc/mk2rbc.go @@ -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 { diff --git a/mk2rbc/mk2rbc_test.go b/mk2rbc/mk2rbc_test.go index de7512927..e851278cb 100644 --- a/mk2rbc/mk2rbc_test.go +++ b/mk2rbc/mk2rbc_test.go @@ -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") `, }, {