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") `, }, {