The linker is told once, not twice

novox/hq 04-ISSUES/161. A repeated flag is not a merged one. The Go
command takes the last -ldflags and drops the first, so passing the
toolchain's flags and then the system stamp as a second one produced a
binary that knew its system and had lost -s -w: 12.2MB against 8.5MB,
with its debug info intact.

My own comment said the linker "accepts and merges" them. It does not,
and I found out by reading the file the build produced rather than by
reading the comment again.

Linker flags are now the toolchain's own list, composed into one flag with
the stamp. A test refuses a compile line that carries -ldflags itself,
because that is what makes two.
This commit is contained in:
2026-09-30 12:54:29 +02:00
parent ffe176f6d1
commit 3fc1feff38
3 changed files with 53 additions and 8 deletions
+13 -6
View File
@@ -877,13 +877,20 @@ func compile(ctx context.Context, run Runner, tree string, chain Toolchain,
base,
}
invocation = append(invocation, chain.Compile...)
// What it was built for, linked in. The compile line carries `-ldflags` already; this appends a
// second one, which the Go linker accepts and merges. A host with no system refuses every
// declaration before it applies anything (novox/hq 04-ISSUES/161), and it is the artifact that
// knows — the target is a property of the artifact rather than of the recipe (ADR 0142).
// **One `-ldflags`, composed here.** A repeated flag is not a merged one: the Go command takes
// the last and drops the first, so passing the toolchain's flags and then the system stamp as a
// second `-ldflags` produced a binary that knew its system and had lost `-s -w` — half again the
// size, with its debug info (novox/hq 04-ISSUES/161).
//
// What it was built for is the one thing taken from the artifact, and ADR 0142 says why: the
// target is a property of the artifact rather than of the recipe. A host with no system refuses
// every declaration before it applies anything.
linker := append([]string(nil), chain.LinkerFlags...)
if chain.SystemStamp != "" && strings.TrimSpace(a.System) != "" {
invocation = append(invocation, "-ldflags",
"-X "+chain.SystemStamp+"="+strings.TrimSpace(a.System))
linker = append(linker, "-X", chain.SystemStamp+"="+strings.TrimSpace(a.System))
}
if len(linker) > 0 {
invocation = append(invocation, "-ldflags", strings.Join(linker, " "))
}
if chain.OutputFlag != "" {
// A compiler pointed at a package is told the file to write, not the directory: the name a