Pin the export/override prefix and ?= first-wins with tests
Some checks failed
check / check (push) Failing after 7s

This commit is contained in:
user
2026-09-04 11:18:19 +00:00
parent 18226d345b
commit 18b0f039b5

View File

@@ -826,6 +826,81 @@ describe("the resolver reads what the shell would run", () => {
expect(recipes.get("check")?.recipe).toEqual(["script/fmt-check"]); expect(recipes.get("check")?.recipe).toEqual(["script/fmt-check"]);
}); });
// `export FMT := script/fmt-check` is an assignment make honours and the
// pattern anchored at the name, so the whole line read as neither an
// assignment nor a target and `@$(FMT)` stood unresolved: `make -n check`
// printed `script/check` and `script/fmt-check` while this file scored
// one. `override` reaches the same place by the same route.
it("expands a variable assigned through an export or override prefix", () => {
expect(
parseMakefile(
[
"export FMT := script/fmt-check",
"check:",
"\t@$(FMT)",
"\t@script/check",
].join("\n"),
).get("check")?.recipe,
).toEqual(["script/fmt-check", "script/check"]);
expect(
parseMakefile(
["override FMT = script/fmt-check", "check:", "\t@$(FMT)"].join(
"\n",
),
).get("check")?.recipe,
).toEqual(["script/fmt-check"]);
// `export` on its own line names a variable without assigning one, and
// is not read as an assignment of the empty string.
expect(
parseMakefile(
["FMT := script/fmt-check", "export FMT", "check:", "\t@$(FMT)"].join(
"\n",
),
).get("check")?.recipe,
).toEqual(["script/fmt-check"]);
});
// `?=` assigns only when the name has no value yet, so among assignments
// to one name the first `?=` wins where `:=` and `=` let the last one win.
// Reading every operator as last-wins resolved `@$(FMT)` to the value make
// discards: the file counted an invocation that never happens and missed
// the one that does, with the suite green either way.
it("keeps the first value when a later assignment is conditional", () => {
expect(
parseMakefile(
[
"FMT := script/fmt-check",
"FMT ?= script/build",
"check:",
"\t@$(FMT)",
].join("\n"),
).get("check")?.recipe,
).toEqual(["script/fmt-check"]);
// A `?=` that is itself the first assignment does assign, and a `?=`
// after it does not.
expect(
parseMakefile(
[
"FMT ?= script/fmt-check",
"FMT ?= script/build",
"check:",
"\t@$(FMT)",
].join("\n"),
).get("check")?.recipe,
).toEqual(["script/fmt-check"]);
// `:=` and `=` stay last-wins, which is what make does.
expect(
parseMakefile(
[
"FMT := script/build",
"FMT := script/fmt-check",
"check:",
"\t@$(FMT)",
].join("\n"),
).get("check")?.recipe,
).toEqual(["script/fmt-check"]);
});
// The edges of the expansion, asserted so the header's not-followed list // The edges of the expansion, asserted so the header's not-followed list
// is the code's behaviour rather than a claim about it. Each of these // is the code's behaviour rather than a claim about it. Each of these
// leaves the reference standing verbatim, which reaches nothing — the same // leaves the reference standing verbatim, which reaches nothing — the same