ww build: discard exact null outputs

This commit is contained in:
2026-08-20 23:17:23 +09:00
parent 84f5e68709
commit 71a9da2058
7 changed files with 751 additions and 31 deletions

View File

@@ -8502,7 +8502,9 @@ fn dobuild(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
};
let out: *u8 = nil;
let objstem: *u8 = nil;
if (outflag != nil && outflag[0u64] != 0u8) {
let discardoutput: bool = outflag != nil
&& cstreqlit(outflag, "/dev/null");
if (outflag != nil && outflag[0u64] != 0u8 && !discardoutput) {
// -o sets both the binary path and the intermediate stem so
// artifacts land beside the requested output (T3).
out = outflag;
@@ -8531,6 +8533,34 @@ fn dobuild(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
lf.nlibs = nlibs;
let rootidentity: *u8 = nil;
if (!requestedliteral && isdir != 0) { rootidentity = src; };
if (discardoutput) {
let tmp: []u8 = alloc([], (os.PATH_MAX: u64))!;
tmp.len = os.PATH_MAX;
makedrivertmp(tmp.ptr, "ww_build_");
if (os.mkdir(pathstr(tmp.ptr), 448i32) != 0) {
cerr("ww: cannot create temporary directory\n");
return 1;
};
let outp: *u8 = joinpathlit(tmp.ptr, "main");
// Go's null output removes installation, while command linking and
// library compilation still need request-private product paths.
let rc: i32 = buildonesep(selfdir, resolved, isdir, rootidentity,
outp, outp, incs.ptr, &lf,
0i32, 0i32, 0i32, SEP_VARIANT_PRODUCTION, nil,
emitasm, 0i32, workdir);
let cleanbad: bool = false;
let cleanrc: i32 = os.remove(pathstr(outp));
if (cleanrc != 0 && cleanrc != -2i32) {
cerr("ww: cannot remove temporary output\n");
cleanbad = true;
};
if (os.rmdir(pathstr(tmp.ptr)) != 0) {
cerr("ww: cannot remove temporary directory\n");
cleanbad = true;
};
if (cleanbad && rc == 0) { rc = 1; };
return rc;
};
let publishpackage: i32 = 0;
if (outflag != nil && outflag[0u64] != 0u8) { publishpackage = 1; };
return buildonesep(selfdir, resolved, isdir, rootidentity,
@@ -8774,14 +8804,16 @@ fn runsingletest(selfdir: *u8, src: *u8, incs: *u8, compileonly: i32,
emitasm: i32, outstem: *u8, workdir: *u8, pattern: *u8) i32 = {
let tmp: []u8 = alloc([], (os.PATH_MAX: u64))!;
tmp.len = os.PATH_MAX;
// -o redirects the binary + its caller-owned sepwork intermediates
// (objstem, T3) to <stem>; without -o both are driver-owned /tmp paths.
// A retained -o redirects the binary and sepwork intermediates to its stem;
// exact /dev/null needs the no-install path used by Go's test builder.
let outp: *u8 = nil;
let objstem: *u8 = nil;
// owntmp: the driver owns (and must clean) the /tmp workspace; with
// -o or -w the binary lands in a caller-owned location instead.
// A retained output or -w has caller-owned storage; every other binary is
// request-private and must be removed here.
let owntmp: bool = false;
if (outstem != nil) {
let retainout: bool = outstem != nil
&& !cstreqlit(outstem, "/dev/null");
if (retainout) {
outp = outstem;
objstem = outstem;
} else { if (workdir != nil) {
@@ -8806,7 +8838,7 @@ fn runsingletest(selfdir: *u8, src: *u8, incs: *u8, compileonly: i32,
lf.libs = nil;
lf.nlibs = 0;
let keep: i32 = 0;
if (outstem != nil) { keep = 1; };
if (retainout) { keep = 1; };
let bres: i32 = buildonesep(selfdir, src, 0, nil, outp, objstem, incs, &lf,
0i32, 0i32, 1i32, SEP_VARIANT_PRODUCTION, nil,
emitasm, keep, workdir);