diff --git a/mk2rbc/mk2rbc.go b/mk2rbc/mk2rbc.go index e317cadff..ebb463b09 100644 --- a/mk2rbc/mk2rbc.go +++ b/mk2rbc/mk2rbc.go @@ -829,11 +829,7 @@ func (ctx *parseContext) handleSubConfig( pathPattern = append(pathPattern, chunk) } } - if pathPattern[0] == "" { - if len(ctx.includeTops) == 0 { - ctx.errorf(v, "inherit-product/include statements must not be prefixed with a variable, or must include a #RBC# include_top comment beforehand giving a root directory to search.") - return - } + if pathPattern[0] == "" && len(ctx.includeTops) > 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 { @@ -849,14 +845,20 @@ func (ctx *parseContext) handleSubConfig( ctx.errorf(v, "there are >%d files matching the pattern, please rewrite it", maxMatchingFiles) return } - res := inheritedDynamicModule{*varPath, []*moduleInfo{}, loadAlways} - for _, p := range matchingPaths { - // A product configuration files discovered dynamically may attempt to inherit - // from another one which does not exist in this source tree. Prevent load errors - // by always loading the dynamic files as optional. - res.candidateModules = append(res.candidateModules, ctx.newDependentModule(p, true)) + if len(matchingPaths) == 1 { + res := inheritedStaticModule{ctx.newDependentModule(matchingPaths[0], loadAlways && ctx.ifNestLevel == 0), loadAlways} + processModule(res) + } else { + needsWarning := pathPattern[0] == "" && len(ctx.includeTops) == 0 + res := inheritedDynamicModule{*varPath, []*moduleInfo{}, loadAlways, ctx.errorLocation(v), needsWarning} + for _, p := range matchingPaths { + // A product configuration files discovered dynamically may attempt to inherit + // from another one which does not exist in this source tree. Prevent load errors + // by always loading the dynamic files as optional. + res.candidateModules = append(res.candidateModules, ctx.newDependentModule(p, true)) + } + processModule(res) } - processModule(res) } func (ctx *parseContext) findMatchingPaths(pattern []string) []string { diff --git a/mk2rbc/mk2rbc_test.go b/mk2rbc/mk2rbc_test.go index c4f7da33c..20f198af8 100644 --- a/mk2rbc/mk2rbc_test.go +++ b/mk2rbc/mk2rbc_test.go @@ -1072,13 +1072,7 @@ def init(g, handle): cfg = rblf.cfg(handle) g["MY_PATH"] = "foo" #RBC# include_top vendor/foo1 - _entry = { - "vendor/foo1/cfg.mk": ("vendor/foo1/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("product.mk", "Cannot find %s" % ("%s/cfg.mk" % g["MY_PATH"])) - rblf.inherit(handle, _varmod, _varmod_init) + rblf.inherit(handle, "vendor/foo1/cfg", _cfg_init) `, }, { @@ -1098,25 +1092,13 @@ def init(g, handle): cfg = rblf.cfg(handle) g["MY_PATH"] = "foo" #RBC# include_top vendor/foo1 - _entry = { - "vendor/foo1/cfg.mk": ("vendor/foo1/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("product.mk", "Cannot find %s" % ("%s/cfg.mk" % g["MY_PATH"])) - rblf.inherit(handle, _varmod, _varmod_init) + rblf.inherit(handle, "vendor/foo1/cfg", _cfg_init) #RBC# include_top vendor/foo1 - _entry = { - "vendor/foo1/cfg.mk": ("vendor/foo1/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("product.mk", "Cannot find %s" % ("%s/cfg.mk" % g["MY_PATH"])) - rblf.inherit(handle, _varmod, _varmod_init) + rblf.inherit(handle, "vendor/foo1/cfg", _cfg_init) `, }, { - desc: "Dynamic inherit path that lacks necessary hint", + desc: "Dynamic inherit path that lacks hint", mkname: "product.mk", in: ` #RBC# include_top foo @@ -1133,26 +1115,23 @@ $(call inherit-product,$(MY_VAR)/font.mk) expected: `#RBC# include_top foo load("//build/make/core:product_config.rbc", "rblf") load("//foo:font.star|init", _font_init = "init") +load("//bar:font.star|init", _font1_init = "init") def init(g, handle): cfg = rblf.cfg(handle) - _entry = { - "foo/font.mk": ("foo/font", _font_init), - }.get("%s/font.mk" % g.get("MY_VAR", "")) - (_varmod, _varmod_init) = _entry if _entry else (None, None) - if not _varmod_init: - rblf.mkerror("product.mk", "Cannot find %s" % ("%s/font.mk" % g.get("MY_VAR", ""))) - rblf.inherit(handle, _varmod, _varmod_init) + rblf.inherit(handle, "foo/font", _font_init) #RBC# include_top foo # There's some space and even this comment between the include_top and the inherit-product + rblf.inherit(handle, "foo/font", _font_init) + rblf.mkwarning("product.mk:11", "Including a path with a non-constant prefix, please convert this to a simple literal to generate cleaner starlark.") _entry = { "foo/font.mk": ("foo/font", _font_init), + "bar/font.mk": ("bar/font", _font1_init), }.get("%s/font.mk" % g.get("MY_VAR", "")) (_varmod, _varmod_init) = _entry if _entry else (None, None) if not _varmod_init: rblf.mkerror("product.mk", "Cannot find %s" % ("%s/font.mk" % g.get("MY_VAR", ""))) rblf.inherit(handle, _varmod, _varmod_init) - rblf.mk2rbc_error("product.mk:11", "inherit-product/include statements must not be prefixed with a variable, or must include a #RBC# include_top comment beforehand giving a root directory to search.") `, }, { diff --git a/mk2rbc/node.go b/mk2rbc/node.go index 4f7c4f0f0..dea4dc84b 100644 --- a/mk2rbc/node.go +++ b/mk2rbc/node.go @@ -86,6 +86,8 @@ type inheritedDynamicModule struct { path interpolateExpr candidateModules []*moduleInfo loadAlways bool + location ErrorLocation + needsWarning bool } func (i inheritedDynamicModule) name() string { @@ -97,6 +99,10 @@ func (i inheritedDynamicModule) entryName() string { } func (i inheritedDynamicModule) emitSelect(gctx *generationContext) { + if i.needsWarning { + gctx.newLine() + gctx.writef("%s.mkwarning(%q, %q)", baseName, i.location, "Including a path with a non-constant prefix, please convert this to a simple literal to generate cleaner starlark.") + } gctx.newLine() gctx.writef("_entry = {") gctx.indentLevel++