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

@@ -7059,7 +7059,8 @@ do_build(int argc, char **argv)
}
char out[PATH_MAX];
const char *objstem = NULL;
if (outflag[0]) {
int discard_output = strcmp(outflag, "/dev/null") == 0;
if (outflag[0] && !discard_output) {
/* -o sets both the binary path and the intermediate stem so
* artifacts land beside the requested output (T3). */
memcpy(out, outflag, strlen(outflag) + 1);
@@ -7075,6 +7076,39 @@ do_build(int argc, char **argv)
basename_no_ext(resolved, out, sizeof out);
}
const char *root_identity = !literal && is_dir ? src : NULL;
if (discard_output) {
char tmpdir[PATH_MAX], tmp[PATH_MAX];
int dn = snprintf(tmpdir, sizeof tmpdir, "/tmp/ww_build_%d", getpid());
if (dn < 0 || (size_t)dn >= sizeof tmpdir
|| mkdir(tmpdir, 0700) != 0) {
fputs("ww: cannot create temporary directory\n", stderr);
free(incs);
return 1;
}
int tn = snprintf(tmp, sizeof tmp, "%s/main", tmpdir);
if (tn < 0 || (size_t)tn >= sizeof tmp) {
(void)rmdir(tmpdir);
free(incs);
return 1;
}
/* Go's null output removes installation, while command linking and
* library compilation still need request-private product paths. */
int rc = build_one_sep(resolved, is_dir, root_identity, tmp, tmp, incs,
&linkflags, 0, 0, 0, SEP_VARIANT_PRODUCTION, NULL,
emit_asm, 0, workdir);
int cleanfail = 0;
if (unlink(tmp) != 0 && errno != ENOENT) {
fputs("ww: cannot remove temporary output\n", stderr);
cleanfail = 1;
}
if (rmdir(tmpdir) != 0) {
fputs("ww: cannot remove temporary directory\n", stderr);
cleanfail = 1;
}
free(incs);
if (cleanfail && rc == 0) rc = 1;
return rc;
}
int rc = build_one_sep(resolved, is_dir, root_identity, out, objstem, incs,
&linkflags, outflag[0] != '\0', 0, 0, SEP_VARIANT_PRODUCTION, NULL,
emit_asm, 1, workdir);
@@ -7491,6 +7525,7 @@ do_test(int argc, char **argv)
}
}
}
int discard_output = strcmp(outstem, "/dev/null") == 0;
if (pattern != NULL) {
struct stat first;
if (stat(target, &first) != 0 || !S_ISREG(first.st_mode)) {
@@ -7580,8 +7615,8 @@ do_test(int argc, char **argv)
}
char tmpdir[PATH_MAX] = {0}, tmp[PATH_MAX];
const char *outp;
int owntmp = !outstem[0] && !workdir[0];
if (outstem[0]) outp = outstem;
int owntmp = (!outstem[0] || discard_output) && !workdir[0];
if (outstem[0] && !discard_output) outp = outstem;
else if (workdir[0]) {
/* The workdir owns the persistent test binary the same
* way it owns the package artifacts. */
@@ -7602,12 +7637,13 @@ do_test(int argc, char **argv)
if (tn < 0 || (size_t)tn >= sizeof tmp) return 1;
outp = tmp;
}
/* No-o redirects internal scratch to /tmp rather than beside the
* source. An explicit -o names the caller-owned artifact stem. */
/* No retained output keeps scratch private; exact /dev/null follows
* Go's no-install test action rather than naming an artifact stem. */
int br = build_one_sep(resolved, is_dir, NULL, outp,
outstem[0] ? outstem : tmp, incs, NULL, 0, 0, 1,
outstem[0] && !discard_output ? outstem : tmp,
incs, NULL, 0, 0, 1,
SEP_VARIANT_PRODUCTION, NULL, emit_asm,
outstem[0] ? 1 : 0, workdir);
outstem[0] && !discard_output ? 1 : 0, workdir);
if (br != 0) {
if (owntmp && unlink(outp) != 0 && errno != ENOENT)
fputs("ww: cannot remove temporary output\n", stderr);
@@ -7651,8 +7687,8 @@ do_test(int argc, char **argv)
}
char tmpdir[PATH_MAX] = {0}, tmp[PATH_MAX];
const char *outp;
int owntmp = !outstem[0] && !workdir[0];
if (outstem[0]) outp = outstem;
int owntmp = (!outstem[0] || discard_output) && !workdir[0];
if (outstem[0] && !discard_output) outp = outstem;
else if (workdir[0]) {
int tn = snprintf(tmp, sizeof tmp, "%s/main", workdir);
if (tn < 0 || (size_t)tn >= sizeof tmp) {
@@ -7671,10 +7707,11 @@ do_test(int argc, char **argv)
if (tn < 0 || (size_t)tn >= sizeof tmp) return 1;
outp = tmp;
}
/* See module-mode note: no-o scratch is redirected to /tmp. */
int br = build_one_sep(target, 0, NULL, outp, outstem[0] ? outstem : tmp,
/* See module-mode note: an unretained output uses private scratch. */
int br = build_one_sep(target, 0, NULL, outp,
outstem[0] && !discard_output ? outstem : tmp,
incs, NULL, 0, 0, 1, SEP_VARIANT_PRODUCTION, NULL, emit_asm,
outstem[0] ? 1 : 0, workdir);
outstem[0] && !discard_output ? 1 : 0, workdir);
if (br != 0) {
if (owntmp && unlink(outp) != 0 && errno != ENOENT)
fputs("ww: cannot remove temporary output\n", stderr);