ww: build intermediates follow -o output stem, not the source dir (test-perf T3a)
build_one/buildone gain an explicit objstem: 'ww build -o X' derives
main.{combined.ww,s,o} beside X; 'ww run' uses its per-pid /tmp stem;
default no--o stays next-to-source (load-bearing for the make regen of
tracked combined.ww and the freshness gate). Realizes the redirect TODO
in 995_self_rebuild.c. Kills the concurrent-test torn-read race on
selfhost/cmd/<tool>/main.* (the 991 transient). 993/995/949 pass -o
into their per-pid workdirs; 949's '-o /dev/null' relied on the old
driver ignoring -o (audited: the only live driver case). Atomic
combined write (os.rename) deferred to its own commit - lib/os lacks
rename and that addition is an import-floor regen.
This commit is contained in:
@@ -375,9 +375,15 @@ expand(FILE *out, const char *path, struct ImportSet *visited,
|
||||
fclose(in);
|
||||
}
|
||||
|
||||
/* objstem (when non-NULL/non-empty) redirects the .s/.o/.combined.ww
|
||||
* side files to live beside the build's OUTPUT instead of next to the
|
||||
* source (task #15/T3). `ww run` and `ww build -o` pass it so concurrent
|
||||
* builds never share the next-to-source fixed paths; the default
|
||||
* (objstem == NULL) keeps the old next-to-source layout, load-bearing
|
||||
* for make's tracked-combined.ww regen + the #110 freshness gate. */
|
||||
static int
|
||||
build_one(const char *src, int entry_is_dir, const char *out,
|
||||
const char *extra_includes, const char *extra_libs,
|
||||
const char *objstem, const char *extra_includes, const char *extra_libs,
|
||||
const char *extra_libdirs)
|
||||
{
|
||||
const char *c6 = toolpath("WW_W6C", "w6c");
|
||||
@@ -447,10 +453,11 @@ build_one(const char *src, int entry_is_dir, const char *out,
|
||||
if (dot && strcmp(dot, ".ww") == 0) *dot = '\0';
|
||||
}
|
||||
|
||||
const char *ostem = (objstem && objstem[0]) ? objstem : stem;
|
||||
char asmf[1024], obj[1024], combined[1024];
|
||||
snprintf(asmf, sizeof asmf, "%s.s", stem);
|
||||
snprintf(obj, sizeof obj, "%s.o", stem);
|
||||
snprintf(combined, sizeof combined, "%s.combined.ww", stem);
|
||||
snprintf(asmf, sizeof asmf, "%s.s", ostem);
|
||||
snprintf(obj, sizeof obj, "%s.o", ostem);
|
||||
snprintf(combined, sizeof combined, "%s.combined.ww", ostem);
|
||||
|
||||
/* Resolve imports by concatenating sources into a temp file. The
|
||||
* compiler then sees one flat source. Dir entry → enumerate the
|
||||
@@ -629,6 +636,7 @@ parse_build_flags(int argc, char **argv,
|
||||
char *incs, size_t incsz,
|
||||
char *libdirs, size_t libdirsz,
|
||||
char *libs, size_t libsz,
|
||||
char *outpath, size_t outsz,
|
||||
const char **src_out)
|
||||
{
|
||||
*src_out = NULL;
|
||||
@@ -658,6 +666,10 @@ parse_build_flags(int argc, char **argv,
|
||||
size_t n = strlen(incs);
|
||||
snprintf(incs + n, incsz - n,
|
||||
"%s%s", n ? ":" : "", argv[i] + 2);
|
||||
} else if (strcmp(argv[i], "-o") == 0 && i + 1 < argc) {
|
||||
snprintf(outpath, outsz, "%s", argv[++i]);
|
||||
} else if (strncmp(argv[i], "-o", 2) == 0 && argv[i][2]) {
|
||||
snprintf(outpath, outsz, "%s", argv[i] + 2);
|
||||
} else if (*src_out == NULL) {
|
||||
*src_out = argv[i];
|
||||
} else {
|
||||
@@ -674,8 +686,10 @@ do_build(int argc, char **argv)
|
||||
char libs[2048] = {0};
|
||||
char libdirs[2048] = {0};
|
||||
char incs[2048] = {0};
|
||||
char outflag[1024] = {0};
|
||||
parse_build_flags(argc, argv, incs, sizeof incs,
|
||||
libdirs, sizeof libdirs, libs, sizeof libs, &src);
|
||||
libdirs, sizeof libdirs, libs, sizeof libs,
|
||||
outflag, sizeof outflag, &src);
|
||||
if (src == NULL) src = "."; /* default: build cwd */
|
||||
char resolved[1024];
|
||||
int is_dir = 0;
|
||||
@@ -684,7 +698,13 @@ do_build(int argc, char **argv)
|
||||
return 1;
|
||||
}
|
||||
char out[1024];
|
||||
if (is_dir) {
|
||||
const char *objstem = NULL;
|
||||
if (outflag[0]) {
|
||||
/* -o sets both the binary path and the intermediate stem so
|
||||
* artifacts land beside the requested output (T3). */
|
||||
snprintf(out, sizeof out, "%s", outflag);
|
||||
objstem = out;
|
||||
} else if (is_dir) {
|
||||
char tmp[1024];
|
||||
snprintf(tmp, sizeof tmp, "%s", resolved);
|
||||
size_t n = strlen(tmp);
|
||||
@@ -694,7 +714,7 @@ do_build(int argc, char **argv)
|
||||
} else {
|
||||
basename_no_ext(resolved, out, sizeof out);
|
||||
}
|
||||
return build_one(resolved, is_dir, out, incs, libs, libdirs);
|
||||
return build_one(resolved, is_dir, out, objstem, incs, libs, libdirs);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -704,8 +724,10 @@ do_run(int argc, char **argv)
|
||||
char libs[2048] = {0};
|
||||
char libdirs[2048] = {0};
|
||||
char incs[2048] = {0};
|
||||
char outflag[1024] = {0}; /* -o accepted+ignored: run always uses the temp */
|
||||
int next = parse_build_flags(argc, argv, incs, sizeof incs,
|
||||
libdirs, sizeof libdirs, libs, sizeof libs, &src);
|
||||
libdirs, sizeof libdirs, libs, sizeof libs,
|
||||
outflag, sizeof outflag, &src);
|
||||
if (src == NULL) src = ".";
|
||||
char resolved[1024];
|
||||
int is_dir = 0;
|
||||
@@ -715,7 +737,9 @@ do_run(int argc, char **argv)
|
||||
}
|
||||
char tmp[1024];
|
||||
snprintf(tmp, sizeof tmp, "/tmp/ww_run_%d", getpid());
|
||||
if (build_one(resolved, is_dir, tmp, incs, libs, libdirs) != 0)
|
||||
/* objstem = tmp → intermediates land at /tmp/ww_run_<pid>.{s,o,
|
||||
* combined.ww}, never next to the source (T3). */
|
||||
if (build_one(resolved, is_dir, tmp, tmp, incs, libs, libdirs) != 0)
|
||||
return 1;
|
||||
/* exec the built binary with any trailing argv as its argv. */
|
||||
pid_t pid = fork();
|
||||
@@ -754,7 +778,7 @@ do_test(int argc, char **argv)
|
||||
}
|
||||
char tmp[1024];
|
||||
snprintf(tmp, sizeof tmp, "/tmp/ww_test_%d", getpid());
|
||||
if (build_one(resolved, is_dir, tmp, "", "", "") != 0) return 1;
|
||||
if (build_one(resolved, is_dir, tmp, NULL, "", "", "") != 0) return 1;
|
||||
int rc = run(tmp);
|
||||
unlink(tmp);
|
||||
return rc;
|
||||
@@ -763,7 +787,7 @@ do_test(int argc, char **argv)
|
||||
/* single .ww file — build+run it. */
|
||||
char tmp[1024];
|
||||
snprintf(tmp, sizeof tmp, "/tmp/ww_test_%d", getpid());
|
||||
if (build_one(target, 0, tmp, "", "", "") != 0) return 1;
|
||||
if (build_one(target, 0, tmp, NULL, "", "", "") != 0) return 1;
|
||||
int rc = run(tmp);
|
||||
unlink(tmp);
|
||||
return rc;
|
||||
@@ -789,7 +813,7 @@ do_test(int argc, char **argv)
|
||||
snprintf(tmp, sizeof tmp, "/tmp/ww_test_%d_%d", getpid(), i);
|
||||
const char *label = strrchr(files[i], '/');
|
||||
label = label ? label + 1 : files[i];
|
||||
int rc = build_one(files[i], 0, tmp, target, "", "");
|
||||
int rc = build_one(files[i], 0, tmp, NULL, target, "", "");
|
||||
if (rc != 0) {
|
||||
fprintf(stderr, "FAIL %s (build)\n", label);
|
||||
fail++;
|
||||
|
||||
Reference in New Issue
Block a user