ww: select build action from package declaration
This commit is contained in:
148
cmd/ww/main.c
148
cmd/ww/main.c
@@ -24,7 +24,7 @@
|
|||||||
static const char *usage =
|
static const char *usage =
|
||||||
"usage: ww [-V] <subcommand> [args...]\n"
|
"usage: ww [-V] <subcommand> [args...]\n"
|
||||||
" -V print version and exit\n"
|
" -V print version and exit\n"
|
||||||
" build [-p] [-S] [-w DIR] [-I DIR] [-o FILE] [path] build a local package graph\n"
|
" build [-S] [-w DIR] [-I DIR] [-o FILE] [path] build a local package graph\n"
|
||||||
" run [path] ... build then exec, passing extra args to the program\n"
|
" run [path] ... build then exec, passing extra args to the program\n"
|
||||||
" test [-S -o STEM] [-w DIR] [options] [path] build/run tests; -S emits package asm\n"
|
" test [-S -o STEM] [-w DIR] [options] [path] build/run tests; -S emits package asm\n"
|
||||||
" version print version and exit\n"
|
" version print version and exit\n"
|
||||||
@@ -33,7 +33,7 @@ static const char *usage =
|
|||||||
" foo.ww literal file\n"
|
" foo.ww literal file\n"
|
||||||
" foo search cwd, -I dirs, then the source library for foo.ww or foo/\n"
|
" foo search cwd, -I dirs, then the source library for foo.ww or foo/\n"
|
||||||
" lib/foo directory: build its package sources\n"
|
" lib/foo directory: build its package sources\n"
|
||||||
" -p emits a non-main archive FILE + FILE.wwi\n"
|
" -o publishes a non-main archive FILE + FILE.wwi\n"
|
||||||
" lib/... every package under lib, recursively (test only)\n"
|
" lib/... every package under lib, recursively (test only)\n"
|
||||||
" . build the cwd's <basename>.ww\n";
|
" . build the cwd's <basename>.ww\n";
|
||||||
|
|
||||||
@@ -969,6 +969,17 @@ sep_command_declared_name(const struct seppkg *p)
|
|||||||
? strcmp(p->name, "main_test") == 0
|
? strcmp(p->name, "main_test") == 0
|
||||||
: strcmp(p->name, "main") == 0;
|
: strcmp(p->name, "main") == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Directory-package action kind comes only from the loaded declaration.
|
||||||
|
* An explicit package-less file is the retained raw-unit compatibility path;
|
||||||
|
* it has no directory package declaration and remains a command unit. */
|
||||||
|
static int
|
||||||
|
sep_root_is_command(const struct seppkg *p)
|
||||||
|
{
|
||||||
|
if (p->name == NULL) return !p->is_dir;
|
||||||
|
return strcmp(p->name, "main") == 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
sep_forbidden_command_import(const struct sepgraph *g, int importer, int dep)
|
sep_forbidden_command_import(const struct sepgraph *g, int importer, int dep)
|
||||||
{
|
{
|
||||||
@@ -2663,6 +2674,20 @@ copy_file_atomic(const char *src, const char *dst)
|
|||||||
return rename(tmp, dst);
|
return rename(tmp, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* A package publication writes OUT, OUT.new, OUT.wwi, and OUT.wwi.new.
|
||||||
|
* Validate the longest spelling before any producer tool can run. */
|
||||||
|
static int
|
||||||
|
validate_package_output_path(const char *out)
|
||||||
|
{
|
||||||
|
size_t n = strlen(out);
|
||||||
|
if ((size_t)PATH_MAX < sizeof ".wwi.new"
|
||||||
|
|| n > (size_t)PATH_MAX - sizeof ".wwi.new") {
|
||||||
|
fprintf(stderr, "ww: package output path is too long\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* A coordinator-private completion marker distinguishes a newly linked
|
/* A coordinator-private completion marker distinguishes a newly linked
|
||||||
* product from a caller-owned binary left behind by an earlier invocation. */
|
* product from a caller-owned binary left behind by an earlier invocation. */
|
||||||
static int
|
static int
|
||||||
@@ -2681,13 +2706,13 @@ record_product_status(const char *path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* The stamp pins the non-content build inputs a unit compare cannot see:
|
/* The stamp pins the non-content build inputs a unit compare cannot see:
|
||||||
* the -T/-S shape of the producer pass and the artifact protocol
|
* the -T/-S/root-action shape of the producer pass and the artifact protocol
|
||||||
* revision (bump "fmt" when the unit/archive/commit format changes). */
|
* revision (bump "fmt" when the unit/archive/commit format changes). */
|
||||||
static void
|
static void
|
||||||
workdir_stamp_text(char *buf, size_t bufsz, int is_test, int emit_asm)
|
workdir_stamp_text(char *buf, size_t bufsz, int is_test, int emit_asm)
|
||||||
{
|
{
|
||||||
snprintf(buf, bufsz, "ww workdir fmt %d mode %s asm %d\n",
|
snprintf(buf, bufsz, "ww workdir fmt %d mode %s asm %d\n",
|
||||||
is_test ? 11 : 10, is_test ? "test" : "build", emit_asm);
|
is_test ? 11 : 12, is_test ? "test" : "build", emit_asm);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* A stale global builder identity invalidates every committed unit voucher in
|
/* A stale global builder identity invalidates every committed unit voucher in
|
||||||
@@ -2732,7 +2757,8 @@ invalidate_workdir_units(const char *scratch)
|
|||||||
static int
|
static int
|
||||||
build_one_sep_impl(const char *src, int entry_is_dir,
|
build_one_sep_impl(const char *src, int entry_is_dir,
|
||||||
const char *out, const char *objstem, const char *extra_includes,
|
const char *out, const char *objstem, const char *extra_includes,
|
||||||
const struct seplinkflags *linkflags, int package_only, int is_test,
|
const struct seplinkflags *linkflags, int publish_package,
|
||||||
|
int require_command, int is_test,
|
||||||
struct sepproduct *products, int nproducts, int emit_asm,
|
struct sepproduct *products, int nproducts, int emit_asm,
|
||||||
const char *workdir, char *scratchout, size_t scratchoutsz,
|
const char *workdir, char *scratchout, size_t scratchoutsz,
|
||||||
struct sepgraph **graphout)
|
struct sepgraph **graphout)
|
||||||
@@ -2895,8 +2921,6 @@ build_one_sep_impl(const char *src, int entry_is_dir,
|
|||||||
SEP_ROLE_NORMAL, products[i].artifact, 1);
|
SEP_ROLE_NORMAL, products[i].artifact, 1);
|
||||||
if (products[i].root < 0) return 1;
|
if (products[i].root < 0) return 1;
|
||||||
products[i].variant_root = products[i].root;
|
products[i].variant_root = products[i].root;
|
||||||
if (!is_test && !package_only)
|
|
||||||
g->pkg[products[i].root].link_entry = 1;
|
|
||||||
}
|
}
|
||||||
const char *test_support_module = "test";
|
const char *test_support_module = "test";
|
||||||
/* -T generates a dispatcher whose support qualifier is selected by the
|
/* -T generates a dispatcher whose support qualifier is selected by the
|
||||||
@@ -3016,6 +3040,14 @@ build_one_sep_impl(const char *src, int entry_is_dir,
|
|||||||
}
|
}
|
||||||
if (g->identity_failed) return 1;
|
if (g->identity_failed) return 1;
|
||||||
if (sep_finalize_directory_identities(g) < 0) return 1;
|
if (sep_finalize_directory_identities(g) < 0) return 1;
|
||||||
|
if (!is_test) {
|
||||||
|
for (int i = 0; i < nproducts; i++) {
|
||||||
|
int root = products[i].variant_root;
|
||||||
|
if (!g->pkg[root].failed)
|
||||||
|
g->pkg[root].link_entry =
|
||||||
|
sep_root_is_command(&g->pkg[root]);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (is_test && entry_is_dir) {
|
if (is_test && entry_is_dir) {
|
||||||
for (int i = 0; i < nproducts; i++) {
|
for (int i = 0; i < nproducts; i++) {
|
||||||
int variant = products[i].variant_root;
|
int variant = products[i].variant_root;
|
||||||
@@ -3031,18 +3063,15 @@ build_one_sep_impl(const char *src, int entry_is_dir,
|
|||||||
products[i].root = mainpkg;
|
products[i].root = mainpkg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
int root_package = !is_test
|
||||||
|
&& !g->pkg[products[0].root].failed
|
||||||
|
&& !sep_root_is_command(&g->pkg[products[0].root]);
|
||||||
if (sep_validate_artifact_paths(g, scratch) < 0)
|
if (sep_validate_artifact_paths(g, scratch) < 0)
|
||||||
return 1;
|
return 1;
|
||||||
if (warm && sep_validate_workdir_owners(g, scratch) < 0)
|
if (warm && sep_validate_workdir_owners(g, scratch) < 0)
|
||||||
return 1;
|
return 1;
|
||||||
if (warm && stale_all && invalidate_workdir_units(scratch) != 0)
|
if (warm && stale_all && invalidate_workdir_units(scratch) != 0)
|
||||||
return 1;
|
return 1;
|
||||||
int root_package = package_only;
|
|
||||||
if (root_package && !g->pkg[products[0].root].failed
|
|
||||||
&& strcmp(g->pkg[products[0].root].name, "main") == 0) {
|
|
||||||
fprintf(stderr, "ww: -p requires a non-main package\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
int *order = calloc((size_t)g->n, sizeof *order);
|
int *order = calloc((size_t)g->n, sizeof *order);
|
||||||
int *stack = calloc((size_t)g->n, sizeof *stack);
|
int *stack = calloc((size_t)g->n, sizeof *stack);
|
||||||
int norder = 0;
|
int norder = 0;
|
||||||
@@ -3065,6 +3094,23 @@ build_one_sep_impl(const char *src, int entry_is_dir,
|
|||||||
|| sep_validate_module_closure(g, order, ignored, 1) < 0)
|
|| sep_validate_module_closure(g, order, ignored, 1) < 0)
|
||||||
g->pkg[root].failed = 1;
|
g->pkg[root].failed = 1;
|
||||||
}
|
}
|
||||||
|
if (!is_test && require_command) {
|
||||||
|
int root = products[0].root;
|
||||||
|
if (!g->pkg[root].failed
|
||||||
|
&& !sep_root_is_command(&g->pkg[root])) {
|
||||||
|
fprintf(stderr, "ww: package %s is not a main package\n",
|
||||||
|
g->pkg[root].path[0] ? g->pkg[root].path
|
||||||
|
: g->pkg[root].canon);
|
||||||
|
free(stack); free(order);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!g->pkg[products[0].root].failed
|
||||||
|
&& root_package && publish_package && !emit_asm
|
||||||
|
&& validate_package_output_path(out) < 0) {
|
||||||
|
free(stack); free(order);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
for (int pi = 0; pi < g->n; pi++) g->pkg[pi].color = 0;
|
for (int pi = 0; pi < g->n; pi++) g->pkg[pi].color = 0;
|
||||||
for (int i = 0; i < nproducts; i++) {
|
for (int i = 0; i < nproducts; i++) {
|
||||||
int root = products[i].root;
|
int root = products[i].root;
|
||||||
@@ -3277,21 +3323,24 @@ build_one_sep_impl(const char *src, int entry_is_dir,
|
|||||||
if (root_package) {
|
if (root_package) {
|
||||||
int root = products[0].root;
|
int root = products[0].root;
|
||||||
if (g->pkg[root].failed) { free(order); return 1; }
|
if (g->pkg[root].failed) { free(order); return 1; }
|
||||||
char archive[SEP_ARTIFACT_MAX], iface[SEP_ARTIFACT_MAX];
|
if (publish_package) {
|
||||||
char outiface[SEP_ARTIFACT_MAX];
|
char archive[SEP_ARTIFACT_MAX], iface[SEP_ARTIFACT_MAX];
|
||||||
sep_fname(g, root, scratch, ".a", archive, sizeof archive);
|
char outiface[SEP_ARTIFACT_MAX];
|
||||||
sep_fname(g, root, scratch, ".wwi", iface, sizeof iface);
|
sep_fname(g, root, scratch, ".a", archive, sizeof archive);
|
||||||
int on = snprintf(outiface, sizeof outiface, "%s.wwi", out);
|
sep_fname(g, root, scratch, ".wwi", iface, sizeof iface);
|
||||||
if (on < 0 || (size_t)on >= sizeof outiface) {
|
int on = snprintf(outiface, sizeof outiface, "%s.wwi", out);
|
||||||
fprintf(stderr, "ww: package output path is too long\n");
|
if (on < 0 || (size_t)on >= sizeof outiface) {
|
||||||
free(order);
|
fprintf(stderr, "ww: package output path is too long\n");
|
||||||
return 1;
|
free(order);
|
||||||
}
|
return 1;
|
||||||
if (copy_file_atomic(archive, out) != 0
|
}
|
||||||
|| copy_file_atomic(iface, outiface) != 0) {
|
if (copy_file_atomic(archive, out) != 0
|
||||||
fprintf(stderr, "ww: cannot write package artifact %s\n", out);
|
|| copy_file_atomic(iface, outiface) != 0) {
|
||||||
free(order);
|
fprintf(stderr,
|
||||||
return 1;
|
"ww: cannot write package artifact %s\n", out);
|
||||||
|
free(order);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
free(order);
|
free(order);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -3414,7 +3463,8 @@ static int
|
|||||||
build_one_sep(const char *src, int entry_is_dir, const char *root_identity,
|
build_one_sep(const char *src, int entry_is_dir, const char *root_identity,
|
||||||
const char *out,
|
const char *out,
|
||||||
const char *objstem, const char *extra_includes,
|
const char *objstem, const char *extra_includes,
|
||||||
const struct seplinkflags *linkflags, int package_only, int is_test,
|
const struct seplinkflags *linkflags, int publish_package,
|
||||||
|
int require_command, int is_test,
|
||||||
int root_variant, const char *test_package, int emit_asm,
|
int root_variant, const char *test_package, int emit_asm,
|
||||||
int keepscratch, const char *workdir)
|
int keepscratch, const char *workdir)
|
||||||
{
|
{
|
||||||
@@ -3432,10 +3482,10 @@ build_one_sep(const char *src, int entry_is_dir, const char *root_identity,
|
|||||||
.variant_root = -1,
|
.variant_root = -1,
|
||||||
.support = -1,
|
.support = -1,
|
||||||
};
|
};
|
||||||
if (!package_only && !entry_is_dir)
|
if (!entry_is_dir)
|
||||||
product.artifact = "__root";
|
product.artifact = "__root";
|
||||||
int r = build_one_sep_impl(src, entry_is_dir, out, objstem,
|
int r = build_one_sep_impl(src, entry_is_dir, out, objstem,
|
||||||
extra_includes, linkflags, package_only, is_test,
|
extra_includes, linkflags, publish_package, require_command, is_test,
|
||||||
&product, 1, emit_asm, workdir, scratch,
|
&product, 1, emit_asm, workdir, scratch,
|
||||||
sizeof scratch, &g);
|
sizeof scratch, &g);
|
||||||
sep_graph_free(g);
|
sep_graph_free(g);
|
||||||
@@ -3477,7 +3527,7 @@ build_package_tests(const char *src, const char *root_identity,
|
|||||||
for (int i = 0; i < nproducts; i++)
|
for (int i = 0; i < nproducts; i++)
|
||||||
products[i].identity = root_identity;
|
products[i].identity = root_identity;
|
||||||
int r = build_one_sep_impl(src, 1, products[0].out,
|
int r = build_one_sep_impl(src, 1, products[0].out,
|
||||||
products[0].out, extra_includes, NULL, 0, 1,
|
products[0].out, extra_includes, NULL, 0, 0, 1,
|
||||||
products, nproducts, 0, workdir, scratch, sizeof scratch, &g);
|
products, nproducts, 0, workdir, scratch, sizeof scratch, &g);
|
||||||
sep_graph_free(g);
|
sep_graph_free(g);
|
||||||
return r;
|
return r;
|
||||||
@@ -3621,11 +3671,10 @@ parse_build_flags(const char *cmd, int argc, char **argv,
|
|||||||
struct seplinkflags *linkflags,
|
struct seplinkflags *linkflags,
|
||||||
char *outpath, size_t outsz,
|
char *outpath, size_t outsz,
|
||||||
char *workdir, size_t workdirsz,
|
char *workdir, size_t workdirsz,
|
||||||
const char **src_out, int *emit_asm_out, int *package_out)
|
const char **src_out, int *emit_asm_out)
|
||||||
{
|
{
|
||||||
*src_out = NULL;
|
*src_out = NULL;
|
||||||
if (emit_asm_out) *emit_asm_out = 0;
|
if (emit_asm_out) *emit_asm_out = 0;
|
||||||
if (package_out) *package_out = 0;
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (; i < argc; i++) {
|
for (; i < argc; i++) {
|
||||||
if (strcmp(argv[i], "-S") == 0) {
|
if (strcmp(argv[i], "-S") == 0) {
|
||||||
@@ -3634,12 +3683,6 @@ parse_build_flags(const char *cmd, int argc, char **argv,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
*emit_asm_out = 1;
|
*emit_asm_out = 1;
|
||||||
} else if (strcmp(argv[i], "-p") == 0) {
|
|
||||||
if (package_out == NULL) {
|
|
||||||
fprintf(stderr, "ww %s: unknown flag\n", cmd);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
*package_out = 1;
|
|
||||||
} else if (strcmp(argv[i], "-w") == 0) {
|
} else if (strcmp(argv[i], "-w") == 0) {
|
||||||
if (workdir == NULL) {
|
if (workdir == NULL) {
|
||||||
fprintf(stderr, "ww %s: unknown flag\n", cmd);
|
fprintf(stderr, "ww %s: unknown flag\n", cmd);
|
||||||
@@ -3738,20 +3781,14 @@ do_build(int argc, char **argv)
|
|||||||
char outflag[PATH_MAX] = {0};
|
char outflag[PATH_MAX] = {0};
|
||||||
char workdir[PATH_MAX] = {0};
|
char workdir[PATH_MAX] = {0};
|
||||||
int emit_asm = 0;
|
int emit_asm = 0;
|
||||||
int package_only = 0;
|
|
||||||
if (parse_build_flags("build", argc, argv, incs, incsz,
|
if (parse_build_flags("build", argc, argv, incs, incsz,
|
||||||
&linkflags,
|
&linkflags,
|
||||||
outflag, sizeof outflag, workdir, sizeof workdir,
|
outflag, sizeof outflag, workdir, sizeof workdir,
|
||||||
&src, &emit_asm, &package_only) < 0) {
|
&src, &emit_asm) < 0) {
|
||||||
free(incs);
|
free(incs);
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
if (src == NULL) src = ".";
|
if (src == NULL) src = ".";
|
||||||
if (package_only && emit_asm) {
|
|
||||||
fprintf(stderr, "ww build: -p and -S cannot be combined\n");
|
|
||||||
free(incs);
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
struct stat requested;
|
struct stat requested;
|
||||||
int literal = stat(src, &requested) == 0;
|
int literal = stat(src, &requested) == 0;
|
||||||
char resolved[PATH_MAX];
|
char resolved[PATH_MAX];
|
||||||
@@ -3761,11 +3798,6 @@ do_build(int argc, char **argv)
|
|||||||
free(incs);
|
free(incs);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (package_only && !is_dir) {
|
|
||||||
fprintf(stderr, "ww build: -p needs a package directory\n");
|
|
||||||
free(incs);
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
char out[PATH_MAX];
|
char out[PATH_MAX];
|
||||||
const char *objstem = NULL;
|
const char *objstem = NULL;
|
||||||
if (outflag[0]) {
|
if (outflag[0]) {
|
||||||
@@ -3785,8 +3817,8 @@ do_build(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
const char *root_identity = !literal && is_dir ? src : NULL;
|
const char *root_identity = !literal && is_dir ? src : NULL;
|
||||||
int rc = build_one_sep(resolved, is_dir, root_identity, out, objstem, incs,
|
int rc = build_one_sep(resolved, is_dir, root_identity, out, objstem, incs,
|
||||||
&linkflags, package_only, 0, SEP_VARIANT_PRODUCTION, NULL, emit_asm,
|
&linkflags, outflag[0] != '\0', 0, 0, SEP_VARIANT_PRODUCTION, NULL,
|
||||||
1, workdir);
|
emit_asm, 1, workdir);
|
||||||
free(incs);
|
free(incs);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@@ -3802,7 +3834,7 @@ do_run(int argc, char **argv)
|
|||||||
char outflag[PATH_MAX] = {0}; /* -o accepted+ignored: run always uses the temp */
|
char outflag[PATH_MAX] = {0}; /* -o accepted+ignored: run always uses the temp */
|
||||||
int next = parse_build_flags("run", argc, argv, incs, incsz,
|
int next = parse_build_flags("run", argc, argv, incs, incsz,
|
||||||
&linkflags,
|
&linkflags,
|
||||||
outflag, sizeof outflag, NULL, 0, &src, NULL, NULL);
|
outflag, sizeof outflag, NULL, 0, &src, NULL);
|
||||||
if (next < 0) { free(incs); return 2; }
|
if (next < 0) { free(incs); return 2; }
|
||||||
if (src == NULL) src = ".";
|
if (src == NULL) src = ".";
|
||||||
struct stat requested;
|
struct stat requested;
|
||||||
@@ -3831,7 +3863,7 @@ do_run(int argc, char **argv)
|
|||||||
const char *root_identity = !literal && is_dir ? src : NULL;
|
const char *root_identity = !literal && is_dir ? src : NULL;
|
||||||
int buildrc = build_one_sep(resolved, is_dir, root_identity, tmp, tmp, incs,
|
int buildrc = build_one_sep(resolved, is_dir, root_identity, tmp, tmp, incs,
|
||||||
&linkflags,
|
&linkflags,
|
||||||
0, 0, SEP_VARIANT_PRODUCTION, NULL, 0, 0, NULL);
|
0, 1, 0, SEP_VARIANT_PRODUCTION, NULL, 0, 0, NULL);
|
||||||
free(incs);
|
free(incs);
|
||||||
if (buildrc != 0) {
|
if (buildrc != 0) {
|
||||||
if (unlink(tmp) != 0 && errno != ENOENT)
|
if (unlink(tmp) != 0 && errno != ENOENT)
|
||||||
@@ -4181,7 +4213,7 @@ do_test(int argc, char **argv)
|
|||||||
/* No-o redirects internal scratch to /tmp rather than beside the
|
/* No-o redirects internal scratch to /tmp rather than beside the
|
||||||
* source. An explicit -o names the caller-owned artifact stem. */
|
* source. An explicit -o names the caller-owned artifact stem. */
|
||||||
int br = build_one_sep(resolved, is_dir, NULL, outp,
|
int br = build_one_sep(resolved, is_dir, NULL, outp,
|
||||||
outstem[0] ? outstem : tmp, incs, NULL, 0, 1,
|
outstem[0] ? outstem : tmp, incs, NULL, 0, 0, 1,
|
||||||
SEP_VARIANT_PRODUCTION, NULL, emit_asm,
|
SEP_VARIANT_PRODUCTION, NULL, emit_asm,
|
||||||
outstem[0] ? 1 : 0, workdir);
|
outstem[0] ? 1 : 0, workdir);
|
||||||
if (br != 0) {
|
if (br != 0) {
|
||||||
@@ -4249,7 +4281,7 @@ do_test(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
/* See module-mode note: no-o scratch is redirected to /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,
|
int br = build_one_sep(target, 0, NULL, outp, outstem[0] ? outstem : tmp,
|
||||||
incs, NULL, 0, 1, SEP_VARIANT_PRODUCTION, NULL, emit_asm,
|
incs, NULL, 0, 0, 1, SEP_VARIANT_PRODUCTION, NULL, emit_asm,
|
||||||
outstem[0] ? 1 : 0, workdir);
|
outstem[0] ? 1 : 0, workdir);
|
||||||
if (br != 0) {
|
if (br != 0) {
|
||||||
if (owntmp && unlink(outp) != 0 && errno != ENOENT)
|
if (owntmp && unlink(outp) != 0 && errno != ENOENT)
|
||||||
|
|||||||
@@ -2843,34 +2843,78 @@ source-like `.wwi` syntax remains a transitional export encoding pending the
|
|||||||
binary `.wwe` format described above, but the separate direct-input ownership
|
binary `.wwe` format described above, but the separate direct-input ownership
|
||||||
boundary is live in production Cstage and WWstage compilers and drivers.
|
boundary is live in production Cstage and WWstage compilers and drivers.
|
||||||
|
|
||||||
An ordinary executable directory root is one normal package action. Its
|
A selected production root is one normal package action. Its finalized
|
||||||
finalized canonical import identity tags its owner-only unit; it receives only
|
canonical import identity tags its owner-only unit; it receives only direct
|
||||||
direct exports, emits `.wwi`, `.o`, and a deterministic `.a`, and is compiled
|
exports, emits `.wwi`, `.o`, and a deterministic `.a`, and is compiled exactly
|
||||||
exactly once. The declared package name validates the last component of that
|
once. The declared package name validates the last component of that identity
|
||||||
identity for ordinary importable packages. A selected command root may declare
|
for ordinary importable packages. After loading and identity finalization, the
|
||||||
`package main`; `main` validates its executable role and never replaces or
|
declaration also selects the terminal build action: `package main` is a command
|
||||||
truncates an identity such as `cmd.tool`. The narrow compiler `--entry` flag
|
and every other valid declaration is a compile-only library. A command root
|
||||||
both classifies that primary unit as a command and controls bare `main` codegen;
|
receives the narrow compiler `--entry` flag, which controls bare `main` codegen,
|
||||||
the package driver uses the parser-only `--command-package` marker for command
|
then the linker receives that root archive first, the complete reachable
|
||||||
test variants that must remain ordinary archive code. Neither flag changes
|
package-archive closure, and the runtime archive; it never receives `.wwi`. A
|
||||||
export identity, and imported interfaces remain under strict leaf validation.
|
non-main root receives no `--entry` and never enters the linker. `main` validates
|
||||||
The linker receives that root archive first, then the complete reachable
|
command kind but never replaces or truncates an identity such as `cmd.tool`.
|
||||||
package-archive closure and runtime archive; it never receives `.wwi`. The
|
The explicit package-less single-file compatibility path has no directory
|
||||||
linkers seed `main` before archive selection, so the existing WWAR member
|
package declaration to classify and remains a raw command unit; it does not
|
||||||
protocol needs no special root object or format change.
|
participate in canonical directory-package interning.
|
||||||
|
The package driver still uses the parser-only `--command-package` marker for
|
||||||
|
command test variants that must remain ordinary archive code. Neither marker
|
||||||
|
changes export identity, and imported interfaces remain under strict leaf
|
||||||
|
validation. The linkers seed `main` before archive selection, so the existing
|
||||||
|
WWAR member protocol needs no special root object or format change.
|
||||||
|
|
||||||
`ww build -p -o lib.a DIR` explicitly requests a non-main package product: it
|
Publication is separate from that semantic action choice. `ww build -o lib.a
|
||||||
emits a deterministic archive at `lib.a` and its compiler interface at
|
DIR` or `ww build -I ROOT -o bar.a foo.bar` automatically publishes a non-main
|
||||||
`lib.a.wwi`, without invoking the linker. A logical target retains its full
|
root's deterministic archive and self-contained compiler export at
|
||||||
identity (`ww build -p -I ROOT -o bar.a foo.bar` emits `foo.bar.*` symbols),
|
`FILE.wwi`, without invoking the linker; the latter retains `foo.bar.*` symbols.
|
||||||
while a literal directory is reverse-resolved through the active source roots
|
Without `-o`, a non-main root and its dependencies are compiled in the selected
|
||||||
or receives the deterministic local identity described below. Its declared
|
scratch or persistent work directory and no cwd product is invented. For a
|
||||||
leaf can never invent or truncate that identity. Package output requires a
|
command, `-o` continues to name the executable publication path. Output names,
|
||||||
directory and `-p` cannot be combined with assembly-only `-S`. Two cold builds
|
request order, and whether publication was requested never enter package or
|
||||||
with identical inputs are required to produce byte-identical requested
|
action identity. The historical action-selecting `-p` exception is removed and
|
||||||
products. Compiler intrinsics keep their package-mode runtime ABI independent
|
rejected as an unknown build flag. Assembly-only `-S` still stops before object,
|
||||||
of transitive source interfaces (for example, `alloc` lowers to the runtime
|
archive, publication, or link production. A literal directory is
|
||||||
allocator without requiring an `rt.wwi` compiler input).
|
reverse-resolved through the active source roots or receives the deterministic
|
||||||
|
local identity described below; its declared leaf can never invent or truncate
|
||||||
|
that identity. Two cold builds with identical inputs are required to produce
|
||||||
|
byte-identical requested products. Compiler intrinsics keep their package-mode
|
||||||
|
runtime ABI independent of transitive source interfaces (for example, `alloc`
|
||||||
|
lowers to the runtime allocator without requiring an `rt.wwi` compiler input).
|
||||||
|
|
||||||
|
This rule follows the pinned official Go 1.26.5 source at commit
|
||||||
|
`c19862e5f8415b4f24b189d065ed739517c548ba`. `go/build.Package` stores source
|
||||||
|
directory, declared name, and import path independently, and defines a command
|
||||||
|
solely as a package named `main`
|
||||||
|
([`go/build/build.go`, lines 436–449](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L436-L449),
|
||||||
|
[`go/build/build.go`, lines 514–519](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L514-L519)).
|
||||||
|
The Go builder's `AutoAction` links only `main` and returns the archive compile
|
||||||
|
action for every other package
|
||||||
|
([`cmd/go/internal/work/action.go`, lines 450–456](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/action.go#L450-L456)).
|
||||||
|
The build command invents a default output only for one `main`, applies an
|
||||||
|
explicit `-o` to either AutoAction result, and otherwise builds each requested
|
||||||
|
package without conflating publication and semantic kind
|
||||||
|
([`cmd/go/internal/work/build.go`, lines 473–478](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/build.go#L473-L478),
|
||||||
|
[`cmd/go/internal/work/build.go`, lines 508–548](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/build.go#L508-L548),
|
||||||
|
[`cmd/go/internal/work/build.go`, lines 551–558](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/build.go#L551-L558)).
|
||||||
|
|
||||||
|
Both WW stages represent the rule with the existing loaded declaration and
|
||||||
|
stable root action index; no package, dependency, ownership, locator, traversal,
|
||||||
|
or closure allocation is added. `ww run` adds only a command-kind requirement:
|
||||||
|
a successfully loaded, cycle-free non-main root produces the deterministic
|
||||||
|
`package PATH is not a main package` diagnostic before any compiler, assembler,
|
||||||
|
or linker invocation; package and graph failures retain precedence. Before a
|
||||||
|
non-main `-o` build invokes a producer, both stages validate the longest atomic
|
||||||
|
publication spelling, `FILE.wwi.new`, so an incomplete archive/export pair is
|
||||||
|
never caused by a late path-overflow failure. Package loading, cycle detection,
|
||||||
|
and closure validation retain diagnostic precedence over this publication-only
|
||||||
|
check, and `-S` does not validate a publication path it never consumes.
|
||||||
|
Build workdir format 12 invalidates older build-mode unit vouchers before reuse
|
||||||
|
because root compiler argv changed; test workdir format 11 is unchanged because
|
||||||
|
test variants still link only their explicit generated-main action. Thereafter
|
||||||
|
an equivalent warm library build invokes no tools, a private dependency change
|
||||||
|
stops at its unchanged export, and an export change recompiles its direct
|
||||||
|
importer under the existing propagation rule.
|
||||||
|
|
||||||
### 11.7 Implemented directory package-test slice
|
### 11.7 Implemented directory package-test slice
|
||||||
|
|
||||||
@@ -2939,7 +2983,7 @@ invocation, each still-unbound directory is finalized by this exact algorithm:
|
|||||||
invalidates a name inferred from a later or nested root.
|
invalidates a name inferred from a later or nested root.
|
||||||
3. Bind the first precedence-valid candidate from each reaching context through
|
3. Bind the first precedence-valid candidate from each reaching context through
|
||||||
the command-global bidirectional interner. An identity supplied by successful
|
the command-global bidirectional interner. An identity supplied by successful
|
||||||
logical package lookup, such as `-p encoding.utf8`, is already bound and is
|
logical package lookup, such as `encoding.utf8`, is already bound and is
|
||||||
preserved exactly. That forward-selected identity is authoritative: reverse
|
preserved exactly. That forward-selected identity is authoritative: reverse
|
||||||
derivation applies only to still-unbound literal roots, so a nested active
|
derivation applies only to still-unbound literal roots, so a nested active
|
||||||
root cannot rename an explicitly resolved package.
|
root cannot rename an explicitly resolved package.
|
||||||
|
|||||||
@@ -1402,6 +1402,14 @@ fn sepcommanddeclaredname(p: *seppkg) bool = {
|
|||||||
return cstreqlit(p.name, "main");
|
return cstreqlit(p.name, "main");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Directory-package action kind comes only from the loaded declaration. An
|
||||||
|
// explicit package-less file is the retained raw-unit compatibility path and
|
||||||
|
// remains a command unit.
|
||||||
|
fn seprootiscommand(p: *seppkg) bool = {
|
||||||
|
if (p.name == nil) { return p.isdir == 0; };
|
||||||
|
return cstreqlit(p.name, "main");
|
||||||
|
};
|
||||||
|
|
||||||
fn sepforbiddencommandimport(g: *sepgraph, importer: i32, dep: i32) bool = {
|
fn sepforbiddencommandimport(g: *sepgraph, importer: i32, dep: i32) bool = {
|
||||||
let from: *seppkg = &g.pkg[importer];
|
let from: *seppkg = &g.pkg[importer];
|
||||||
let to: *seppkg = &g.pkg[dep];
|
let to: *seppkg = &g.pkg[dep];
|
||||||
@@ -3324,8 +3332,20 @@ fn copyfileatomic(src: *u8, dst: *u8) i32 = {
|
|||||||
return os.rename(pathstr(tmpp), pathstr(dst));
|
return os.rename(pathstr(tmpp), pathstr(dst));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Package publication writes OUT, OUT.new, OUT.wwi, and OUT.wwi.new. Check
|
||||||
|
// the longest spelling before any producer tool can run.
|
||||||
|
fn validatepackageoutputpath(out: *u8) i32 = {
|
||||||
|
let suffix: u64 = ".wwi.new".len: u64 + 1u64;
|
||||||
|
let limit: u64 = os.PATH_MAX: u64;
|
||||||
|
if (suffix > limit || cstrlen(out) > limit - suffix) {
|
||||||
|
cerr("ww: package output path is too long\n");
|
||||||
|
return -1;
|
||||||
|
};
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
// The stamp pins the non-content build inputs a unit compare cannot see:
|
// The stamp pins the non-content build inputs a unit compare cannot see:
|
||||||
// the -T/-S shape of the producer pass and the artifact protocol
|
// the -T/-S/root-action shape of the producer pass and the artifact protocol
|
||||||
// revision (bump "fmt" when the unit/archive/commit format changes).
|
// revision (bump "fmt" when the unit/archive/commit format changes).
|
||||||
fn workdirstamptext(istest: i32, emitasm: i32) str = {
|
fn workdirstamptext(istest: i32, emitasm: i32) str = {
|
||||||
if (istest != 0) {
|
if (istest != 0) {
|
||||||
@@ -3335,9 +3355,9 @@ fn workdirstamptext(istest: i32, emitasm: i32) str = {
|
|||||||
return "ww workdir fmt 11 mode test asm 0\n";
|
return "ww workdir fmt 11 mode test asm 0\n";
|
||||||
};
|
};
|
||||||
if (emitasm != 0) {
|
if (emitasm != 0) {
|
||||||
return "ww workdir fmt 10 mode build asm 1\n";
|
return "ww workdir fmt 12 mode build asm 1\n";
|
||||||
};
|
};
|
||||||
return "ww workdir fmt 10 mode build asm 0\n";
|
return "ww workdir fmt 12 mode build asm 0\n";
|
||||||
};
|
};
|
||||||
|
|
||||||
fn stampmatches(path: *u8, want: str) bool = {
|
fn stampmatches(path: *u8, want: str) bool = {
|
||||||
@@ -3444,7 +3464,7 @@ fn cerrpath(head: str, path: *u8, tail: str) void = {
|
|||||||
|
|
||||||
fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||||
out: *u8, objstem: *u8, incs: *u8, lf: *lflags,
|
out: *u8, objstem: *u8, incs: *u8, lf: *lflags,
|
||||||
packageonly: i32, istest: i32,
|
publishpackage: i32, requirecommand: i32, istest: i32,
|
||||||
products: *sepproduct, nproducts: i32, emitasm: i32,
|
products: *sepproduct, nproducts: i32, emitasm: i32,
|
||||||
workdir: *u8, scratchout: **u8,
|
workdir: *u8, scratchout: **u8,
|
||||||
graphout: **sepgraph) i32 = {
|
graphout: **sepgraph) i32 = {
|
||||||
@@ -3663,9 +3683,6 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
|||||||
SEP_ROLE_NORMAL, products[producti].artifact, true);
|
SEP_ROLE_NORMAL, products[producti].artifact, true);
|
||||||
if (products[producti].root < 0) { return 1; };
|
if (products[producti].root < 0) { return 1; };
|
||||||
products[producti].variantroot = products[producti].root;
|
products[producti].variantroot = products[producti].root;
|
||||||
if (istest == 0 && packageonly == 0) {
|
|
||||||
g.pkg[products[producti].root].linkentry = true;
|
|
||||||
};
|
|
||||||
producti += 1;
|
producti += 1;
|
||||||
};
|
};
|
||||||
let testsupportmodule: str = "test";
|
let testsupportmodule: str = "test";
|
||||||
@@ -3785,6 +3802,17 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
|||||||
};
|
};
|
||||||
if (g.identityfailed) { return 1; };
|
if (g.identityfailed) { return 1; };
|
||||||
if (sepfinalizedirectoryidentities(g) < 0) { return 1; };
|
if (sepfinalizedirectoryidentities(g) < 0) { return 1; };
|
||||||
|
if (istest == 0) {
|
||||||
|
producti = 0;
|
||||||
|
for (producti < nproducts) {
|
||||||
|
let root: i32 = products[producti].variantroot;
|
||||||
|
if (!g.pkg[root].failed) {
|
||||||
|
g.pkg[root].linkentry =
|
||||||
|
seprootiscommand(&g.pkg[root]);
|
||||||
|
};
|
||||||
|
producti += 1;
|
||||||
|
};
|
||||||
|
};
|
||||||
if (istest != 0 && entryisdir != 0) {
|
if (istest != 0 && entryisdir != 0) {
|
||||||
producti = 0;
|
producti = 0;
|
||||||
for (producti < nproducts) {
|
for (producti < nproducts) {
|
||||||
@@ -3803,16 +3831,12 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
|||||||
producti += 1;
|
producti += 1;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
let rootpackage: bool = istest == 0
|
||||||
|
&& !g.pkg[products[0].root].failed
|
||||||
|
&& !seprootiscommand(&g.pkg[products[0].root]);
|
||||||
if (sepvalidateartifactpaths(g, scratch) < 0) { return 1; };
|
if (sepvalidateartifactpaths(g, scratch) < 0) { return 1; };
|
||||||
if (warm && sepvalidateworkdirowners(g, scratch) < 0) { return 1; };
|
if (warm && sepvalidateworkdirowners(g, scratch) < 0) { return 1; };
|
||||||
if (warm && staleall && invalidateworkdirunits(scratch) != 0) { return 1; };
|
if (warm && staleall && invalidateworkdirunits(scratch) != 0) { return 1; };
|
||||||
let rootpackage: bool = packageonly != 0;
|
|
||||||
if (rootpackage && !g.pkg[products[0].root].failed
|
|
||||||
&& cstreqlit(g.pkg[products[0].root].name, "main")) {
|
|
||||||
cerr("ww: -p requires a non-main package\n");
|
|
||||||
return 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
let ci: i32 = 0;
|
let ci: i32 = 0;
|
||||||
let order: []i32;
|
let order: []i32;
|
||||||
let stack: []i32;
|
let stack: []i32;
|
||||||
@@ -3839,6 +3863,21 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
|||||||
};
|
};
|
||||||
producti += 1;
|
producti += 1;
|
||||||
};
|
};
|
||||||
|
if (istest == 0 && requirecommand != 0) {
|
||||||
|
let root: i32 = products[0].root;
|
||||||
|
if (!g.pkg[root].failed && !seprootiscommand(&g.pkg[root])) {
|
||||||
|
let identity: *u8 = g.pkg[root].canon;
|
||||||
|
if (g.pkg[root].path[0u64] != 0u8) {
|
||||||
|
identity = g.pkg[root].path;
|
||||||
|
};
|
||||||
|
cerrpath("ww: package ", identity,
|
||||||
|
" is not a main package\n");
|
||||||
|
return 1;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
if (!g.pkg[products[0].root].failed
|
||||||
|
&& rootpackage && publishpackage != 0 && emitasm == 0
|
||||||
|
&& validatepackageoutputpath(out) < 0) { return 1; };
|
||||||
ci = 0;
|
ci = 0;
|
||||||
for (ci < g.n) { g.pkg[ci].color = 0; ci += 1; };
|
for (ci < g.n) { g.pkg[ci].color = 0; ci += 1; };
|
||||||
producti = 0;
|
producti = 0;
|
||||||
@@ -4149,14 +4188,18 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
|||||||
if (rootpackage) {
|
if (rootpackage) {
|
||||||
let root: i32 = products[0].root;
|
let root: i32 = products[0].root;
|
||||||
if (g.pkg[root].failed) { return 1; };
|
if (g.pkg[root].failed) { return 1; };
|
||||||
let archive: *u8 = sepfname(g, root, scratch, ".a");
|
if (publishpackage != 0) {
|
||||||
let iface: *u8 = sepfname(g, root, scratch, ".wwi");
|
let archive: *u8 = sepfname(g, root, scratch, ".a");
|
||||||
let outiface: *u8 = sepappendlit(out, ".wwi");
|
let iface: *u8 = sepfname(g, root, scratch, ".wwi");
|
||||||
if (archive == nil || iface == nil || outiface == nil) { return 1; };
|
let outiface: *u8 = sepappendlit(out, ".wwi");
|
||||||
if (copyfileatomic(archive, out) != 0
|
if (archive == nil || iface == nil || outiface == nil) {
|
||||||
|| copyfileatomic(iface, outiface) != 0) {
|
return 1;
|
||||||
cerrpath("ww: cannot write package artifact ", out, "\n");
|
};
|
||||||
return 1;
|
if (copyfileatomic(archive, out) != 0
|
||||||
|
|| copyfileatomic(iface, outiface) != 0) {
|
||||||
|
cerrpath("ww: cannot write package artifact ", out, "\n");
|
||||||
|
return 1;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
@@ -4305,7 +4348,8 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
|||||||
// exact tree. Twin of the cstage build_one_sep wrapper.
|
// exact tree. Twin of the cstage build_one_sep wrapper.
|
||||||
fn buildonesep(selfdir: *u8, src: *u8, entryisdir: i32,
|
fn buildonesep(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||||
rootidentity: *u8, out: *u8,
|
rootidentity: *u8, out: *u8,
|
||||||
objstem: *u8, incs: *u8, lf: *lflags, packageonly: i32, istest: i32,
|
objstem: *u8, incs: *u8, lf: *lflags, publishpackage: i32,
|
||||||
|
requirecommand: i32, istest: i32,
|
||||||
rootvariant: i32, testpackage: *u8, emitasm: i32,
|
rootvariant: i32, testpackage: *u8, emitasm: i32,
|
||||||
keepscratch: i32, workdir: *u8) i32 = {
|
keepscratch: i32, workdir: *u8) i32 = {
|
||||||
let scratch: *u8 = nil;
|
let scratch: *u8 = nil;
|
||||||
@@ -4317,7 +4361,7 @@ fn buildonesep(selfdir: *u8, src: *u8, entryisdir: i32,
|
|||||||
product.testpackage = testpackage;
|
product.testpackage = testpackage;
|
||||||
product.status = nil;
|
product.status = nil;
|
||||||
product.artifact = nil;
|
product.artifact = nil;
|
||||||
if (packageonly == 0 && entryisdir == 0) {
|
if (entryisdir == 0) {
|
||||||
product.artifact = "__root\0".ptr;
|
product.artifact = "__root\0".ptr;
|
||||||
};
|
};
|
||||||
product.variant = rootvariant;
|
product.variant = rootvariant;
|
||||||
@@ -4325,7 +4369,7 @@ fn buildonesep(selfdir: *u8, src: *u8, entryisdir: i32,
|
|||||||
product.variantroot = -1;
|
product.variantroot = -1;
|
||||||
product.support = -1;
|
product.support = -1;
|
||||||
let r: i32 = buildonesepimpl(selfdir, src, entryisdir, out, objstem,
|
let r: i32 = buildonesepimpl(selfdir, src, entryisdir, out, objstem,
|
||||||
incs, lf, packageonly, istest, &product, 1,
|
incs, lf, publishpackage, requirecommand, istest, &product, 1,
|
||||||
emitasm, workdir, &scratch, &g);
|
emitasm, workdir, &scratch, &g);
|
||||||
sepgraphfree(g);
|
sepgraphfree(g);
|
||||||
if (keepscratch == 0 && scratch != nil) {
|
if (keepscratch == 0 && scratch != nil) {
|
||||||
@@ -4367,7 +4411,7 @@ fn buildpackagetests(selfdir: *u8, src: *u8, rootidentity: *u8,
|
|||||||
i += 1;
|
i += 1;
|
||||||
};
|
};
|
||||||
let r: i32 = buildonesepimpl(selfdir, src, 1,
|
let r: i32 = buildonesepimpl(selfdir, src, 1,
|
||||||
products[0].out, products[0].out, incs, &lf, 0, 1,
|
products[0].out, products[0].out, incs, &lf, 0, 0, 1,
|
||||||
products, nproducts, 0, workdir, &scratch, &g);
|
products, nproducts, 0, workdir, &scratch, &g);
|
||||||
sepgraphfree(g);
|
sepgraphfree(g);
|
||||||
return r;
|
return r;
|
||||||
@@ -4464,7 +4508,7 @@ fn resolvemodule(selfdir: *u8, name: *u8, incs: *u8, isdir: *i32) *u8 = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
fn writeusage(fd: i32) void = {
|
fn writeusage(fd: i32) void = {
|
||||||
let s: str = "usage: ww [-V] <subcommand> [args...]\n -V print version and exit\n build [-p] [-S] [-w DIR] [-I DIR] [-o FILE] [path] build a local package graph\n run [path] ... build then exec, passing extra args to the program\n test [-S -o STEM] [-w DIR] [options] [path] build/run tests; -S emits package asm\n version print version and exit\n\n path forms:\n foo.ww literal file\n foo search cwd, -I dirs, then the source library for foo.ww or foo/\n lib/foo directory: build its package sources\n -p emits a non-main archive FILE + FILE.wwi\n lib/... every package under lib, recursively (test only)\n . build the cwd's <basename>.ww\n";
|
let s: str = "usage: ww [-V] <subcommand> [args...]\n -V print version and exit\n build [-S] [-w DIR] [-I DIR] [-o FILE] [path] build a local package graph\n run [path] ... build then exec, passing extra args to the program\n test [-S -o STEM] [-w DIR] [options] [path] build/run tests; -S emits package asm\n version print version and exit\n\n path forms:\n foo.ww literal file\n foo search cwd, -I dirs, then the source library for foo.ww or foo/\n lib/foo directory: build its package sources\n -o publishes a non-main archive FILE + FILE.wwi\n lib/... every package under lib, recursively (test only)\n . build the cwd's <basename>.ww\n";
|
||||||
os.write(fd, s.ptr, s.len: u64);
|
os.write(fd, s.ptr, s.len: u64);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -4508,7 +4552,6 @@ fn dobuild(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
|
|||||||
let outflag: *u8 = nil; // -o target (binary + intermediate stem); T3
|
let outflag: *u8 = nil; // -o target (binary + intermediate stem); T3
|
||||||
let workdir: *u8 = nil; // -w persistent package-artifact workdir
|
let workdir: *u8 = nil; // -w persistent package-artifact workdir
|
||||||
let emitasm: i32 = 0;
|
let emitasm: i32 = 0;
|
||||||
let packageonly: i32 = 0;
|
|
||||||
let inccap: u64 = 1u64;
|
let inccap: u64 = 1u64;
|
||||||
let capi: i32 = start;
|
let capi: i32 = start;
|
||||||
for (capi < argc) {
|
for (capi < argc) {
|
||||||
@@ -4535,8 +4578,6 @@ fn dobuild(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
|
|||||||
if (p[0u64] == 45u8) { // '-'
|
if (p[0u64] == 45u8) { // '-'
|
||||||
if (cstreqlit(p, "-S")) {
|
if (cstreqlit(p, "-S")) {
|
||||||
emitasm = 1;
|
emitasm = 1;
|
||||||
} else { if (cstreqlit(p, "-p")) {
|
|
||||||
packageonly = 1;
|
|
||||||
} else { if (p[1u64] == 73u8) { // '-I'
|
} else { if (p[1u64] == 73u8) { // '-I'
|
||||||
let dir: *u8 = nil;
|
let dir: *u8 = nil;
|
||||||
if (p[2u64] != 0u8) {
|
if (p[2u64] != 0u8) {
|
||||||
@@ -4616,7 +4657,7 @@ fn dobuild(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
|
|||||||
} else {
|
} else {
|
||||||
cerr("ww build: unknown flag\n");
|
cerr("ww build: unknown flag\n");
|
||||||
return 2;
|
return 2;
|
||||||
}; }; }; }; }; }; };
|
}; }; }; }; }; };
|
||||||
} else {
|
} else {
|
||||||
if (src == nil) { src = p; };
|
if (src == nil) { src = p; };
|
||||||
};
|
};
|
||||||
@@ -4627,10 +4668,6 @@ fn dobuild(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
|
|||||||
let dot: [2]u8 = ['.': u8, 0u8];
|
let dot: [2]u8 = ['.': u8, 0u8];
|
||||||
src = &dot[0];
|
src = &dot[0];
|
||||||
};
|
};
|
||||||
if (packageonly != 0 && emitasm != 0) {
|
|
||||||
cerr("ww build: -p and -S cannot be combined\n");
|
|
||||||
return 2;
|
|
||||||
};
|
|
||||||
let requestedliteral: bool = false;
|
let requestedliteral: bool = false;
|
||||||
let requestedstat: os.filestat;
|
let requestedstat: os.filestat;
|
||||||
match (os.stat(&requestedstat, pathstr(src))) {
|
match (os.stat(&requestedstat, pathstr(src))) {
|
||||||
@@ -4643,13 +4680,9 @@ fn dobuild(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
|
|||||||
cerrpath("ww build: cannot find module ", src, "\n");
|
cerrpath("ww build: cannot find module ", src, "\n");
|
||||||
return 1;
|
return 1;
|
||||||
};
|
};
|
||||||
if (packageonly != 0 && isdir == 0) {
|
|
||||||
cerr("ww build: -p needs a package directory\n");
|
|
||||||
return 2;
|
|
||||||
};
|
|
||||||
let out: *u8 = nil;
|
let out: *u8 = nil;
|
||||||
let objstem: *u8 = nil;
|
let objstem: *u8 = nil;
|
||||||
if (outflag != nil) {
|
if (outflag != nil && outflag[0u64] != 0u8) {
|
||||||
// -o sets both the binary path and the intermediate stem so
|
// -o sets both the binary path and the intermediate stem so
|
||||||
// artifacts land beside the requested output (T3).
|
// artifacts land beside the requested output (T3).
|
||||||
out = outflag;
|
out = outflag;
|
||||||
@@ -4678,9 +4711,11 @@ fn dobuild(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
|
|||||||
lf.nlibs = nlibs;
|
lf.nlibs = nlibs;
|
||||||
let rootidentity: *u8 = nil;
|
let rootidentity: *u8 = nil;
|
||||||
if (!requestedliteral && isdir != 0) { rootidentity = src; };
|
if (!requestedliteral && isdir != 0) { rootidentity = src; };
|
||||||
|
let publishpackage: i32 = 0;
|
||||||
|
if (outflag != nil && outflag[0u64] != 0u8) { publishpackage = 1; };
|
||||||
return buildonesep(selfdir, resolved, isdir, rootidentity,
|
return buildonesep(selfdir, resolved, isdir, rootidentity,
|
||||||
out, objstem, incs.ptr, &lf,
|
out, objstem, incs.ptr, &lf,
|
||||||
packageonly, 0i32, SEP_VARIANT_PRODUCTION, nil,
|
publishpackage, 0i32, 0i32, SEP_VARIANT_PRODUCTION, nil,
|
||||||
emitasm, 1i32, workdir);
|
emitasm, 1i32, workdir);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -4862,7 +4897,8 @@ fn dorun(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
|
|||||||
if (!requestedliteral && isdir != 0) { rootidentity = src; };
|
if (!requestedliteral && isdir != 0) { rootidentity = src; };
|
||||||
if (buildonesep(selfdir, resolved, isdir, rootidentity,
|
if (buildonesep(selfdir, resolved, isdir, rootidentity,
|
||||||
outp, outp, incs.ptr, &lf,
|
outp, outp, incs.ptr, &lf,
|
||||||
0i32, 0i32, SEP_VARIANT_PRODUCTION, nil, 0i32, 0i32, nil) != 0) {
|
0i32, 1i32, 0i32, SEP_VARIANT_PRODUCTION, nil,
|
||||||
|
0i32, 0i32, nil) != 0) {
|
||||||
let cleanrc: i32 = os.remove(pathstr(outp));
|
let cleanrc: i32 = os.remove(pathstr(outp));
|
||||||
if (cleanrc != 0 && cleanrc != -2i32) {
|
if (cleanrc != 0 && cleanrc != -2i32) {
|
||||||
cerr("ww: cannot remove temporary output\n");
|
cerr("ww: cannot remove temporary output\n");
|
||||||
@@ -4952,7 +4988,8 @@ fn runsingletest(selfdir: *u8, src: *u8, incs: *u8, compileonly: i32,
|
|||||||
let keep: i32 = 0;
|
let keep: i32 = 0;
|
||||||
if (outstem != nil) { keep = 1; };
|
if (outstem != nil) { keep = 1; };
|
||||||
let bres: i32 = buildonesep(selfdir, src, 0, nil, outp, objstem, incs, &lf,
|
let bres: i32 = buildonesep(selfdir, src, 0, nil, outp, objstem, incs, &lf,
|
||||||
0i32, 1i32, SEP_VARIANT_PRODUCTION, nil, emitasm, keep, workdir);
|
0i32, 0i32, 1i32, SEP_VARIANT_PRODUCTION, nil,
|
||||||
|
emitasm, keep, workdir);
|
||||||
if (bres != 0) {
|
if (bres != 0) {
|
||||||
if (owntmp) {
|
if (owntmp) {
|
||||||
let cleanrc: i32 = os.remove(pathstr(outp));
|
let cleanrc: i32 = os.remove(pathstr(outp));
|
||||||
|
|||||||
@@ -984,7 +984,7 @@ fn mkdirall(path: str) void = {
|
|||||||
" assert(pkg.second() == 9);\n};\n"));
|
" assert(pkg.second() == 9);\n};\n"));
|
||||||
|
|
||||||
let prodout: str = strings.concat(root, "/production.a");
|
let prodout: str = strings.concat(root, "/production.a");
|
||||||
let prodav: []str = [driver("ww"), "build", "-p", "-I", root,
|
let prodav: []str = [driver("ww"), "build", "-I", root,
|
||||||
"-o", prodout, pkg];
|
"-o", prodout, pkg];
|
||||||
let out: commandout;
|
let out: commandout;
|
||||||
runcommand(root, "production-build", prodav,
|
runcommand(root, "production-build", prodav,
|
||||||
@@ -2094,7 +2094,7 @@ fn mkdirall(path: str) void = {
|
|||||||
if (rsi == 1) { uniondriver = wwtracedriver; };
|
if (rsi == 1) { uniondriver = wwtracedriver; };
|
||||||
let rootout: str = strings.concat(root, "/root-only-",
|
let rootout: str = strings.concat(root, "/root-only-",
|
||||||
rootstages[rsi], ".a");
|
rootstages[rsi], ".a");
|
||||||
let rootav: []str = [driver(rootstages[rsi]), "build", "-p",
|
let rootav: []str = [driver(rootstages[rsi]), "build",
|
||||||
"-I", root, "-o", rootout, aaroot];
|
"-I", root, "-o", rootout, aaroot];
|
||||||
runcommand(root, strings.concat("root-only-", rootstages[rsi]), rootav,
|
runcommand(root, strings.concat("root-only-", rootstages[rsi]), rootav,
|
||||||
(60i64 * (time.second: i64)): time.duration, &out);
|
(60i64 * (time.second: i64)): time.duration, &out);
|
||||||
@@ -3942,7 +3942,7 @@ fn mkdirall(path: str) void = {
|
|||||||
let rootout: str = strings.concat(root, "/long-root-",
|
let rootout: str = strings.concat(root, "/long-root-",
|
||||||
rootlabels[ri], "-", tags[si], ".a");
|
rootlabels[ri], "-", tags[si], ".a");
|
||||||
clean(compilertrace); writefile(compilertrace, "");
|
clean(compilertrace); writefile(compilertrace, "");
|
||||||
let rootav: []str = [driver(stages[si]), "build", "-p", "-I",
|
let rootav: []str = [driver(stages[si]), "build", "-I",
|
||||||
source, "-o", rootout, rootspellings[ri]];
|
source, "-o", rootout, rootspellings[ri]];
|
||||||
runcommandenv(root, strings.concat("long-root-", rootlabels[ri],
|
runcommandenv(root, strings.concat("long-root-", rootlabels[ri],
|
||||||
"-", tags[si]), rootav, env,
|
"-", tags[si]), rootav, env,
|
||||||
@@ -4232,7 +4232,7 @@ fn mkdirall(path: str) void = {
|
|||||||
clean(trace);
|
clean(trace);
|
||||||
writefile(trace, "");
|
writefile(trace, "");
|
||||||
let importout: str = strings.concat(root, "/importer-", stages[si], ".a");
|
let importout: str = strings.concat(root, "/importer-", stages[si], ".a");
|
||||||
let importav: []str = [driver(stages[si]), "build", "-p", "-I", source,
|
let importav: []str = [driver(stages[si]), "build", "-I", source,
|
||||||
"-o", importout, importer];
|
"-o", importout, importer];
|
||||||
runcommandenv(root, strings.concat("command-import-", stages[si]),
|
runcommandenv(root, strings.concat("command-import-", stages[si]),
|
||||||
importav, env, (60i64 * (time.second: i64)): time.duration, &out);
|
importav, env, (60i64 * (time.second: i64)): time.duration, &out);
|
||||||
@@ -4351,7 +4351,7 @@ fn mkdirall(path: str) void = {
|
|||||||
let identitydiagnostics: []str = ["", ""];
|
let identitydiagnostics: []str = ["", ""];
|
||||||
i = 0;
|
i = 0;
|
||||||
for (i < stages.len) {
|
for (i < stages.len) {
|
||||||
let av: []str = [driver(stages[i]), "build", "-p", "-I", root,
|
let av: []str = [driver(stages[i]), "build", "-I", root,
|
||||||
"-o", strings.concat(root, "/bad-identity-", stages[i], ".a"),
|
"-o", strings.concat(root, "/bad-identity-", stages[i], ".a"),
|
||||||
identityroot];
|
identityroot];
|
||||||
runcommandenv(root, strings.concat("duplicate-directory-identity-",
|
runcommandenv(root, strings.concat("duplicate-directory-identity-",
|
||||||
@@ -4372,7 +4372,7 @@ fn mkdirall(path: str) void = {
|
|||||||
let reserveddiagnostics: []str = ["", ""];
|
let reserveddiagnostics: []str = ["", ""];
|
||||||
i = 0;
|
i = 0;
|
||||||
for (i < stages.len) {
|
for (i < stages.len) {
|
||||||
let av: []str = [driver(stages[i]), "build", "-p", "-I", root,
|
let av: []str = [driver(stages[i]), "build", "-I", root,
|
||||||
"-o", strings.concat(root, "/bad-reserved-", stages[i], ".a"),
|
"-o", strings.concat(root, "/bad-reserved-", stages[i], ".a"),
|
||||||
reserved];
|
reserved];
|
||||||
runcommandenv(root, strings.concat("reserved-local-import-", stages[i]),
|
runcommandenv(root, strings.concat("reserved-local-import-", stages[i]),
|
||||||
@@ -4843,7 +4843,7 @@ fn runtimepath(relative: str) str = {
|
|||||||
writefile(strings.concat(extra, "/extra.ww"),
|
writefile(strings.concat(extra, "/extra.ww"),
|
||||||
"package extra;\nexport fn marker() i32 = { return 7; };\n");
|
"package extra;\nexport fn marker() i32 = { return 7; };\n");
|
||||||
let extralib: str = strings.concat(root, "/libextra.a");
|
let extralib: str = strings.concat(root, "/libextra.a");
|
||||||
let libav: []str = [driver("ww"), "build", "-p", "-o", extralib,
|
let libav: []str = [driver("ww"), "build", "-o", extralib,
|
||||||
extra];
|
extra];
|
||||||
let out: commandout;
|
let out: commandout;
|
||||||
runcommand(root, "link-flags-library", libav,
|
runcommand(root, "link-flags-library", libav,
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ fn samefile(a: str, b: str, why: str) void = {
|
|||||||
"late/example/foo", "late/example/foo", fooalias, fooalias];
|
"late/example/foo", "late/example/foo", fooalias, fooalias];
|
||||||
i = 0;
|
i = 0;
|
||||||
for (i < rootouts.len) {
|
for (i < rootouts.len) {
|
||||||
let rav: []str = [testenv.driver(rootdrivers[i]), "build", "-p",
|
let rav: []str = [testenv.driver(rootdrivers[i]), "build",
|
||||||
"-I", early, "-I", late, "-o", rootouts[i], roottargets[i]];
|
"-I", early, "-I", late, "-o", rootouts[i], roottargets[i]];
|
||||||
expectcode(td, strings.concat("foo_root_", roottags[i]), rav, 0);
|
expectcode(td, strings.concat("foo_root_", roottags[i]), rav, 0);
|
||||||
let rw: str = strings.concat(rootouts[i], ".sepwork/");
|
let rw: str = strings.concat(rootouts[i], ".sepwork/");
|
||||||
|
|||||||
@@ -166,9 +166,9 @@ fn rejectstable(dir: str, label: str, target: str, needle: str) void = {
|
|||||||
"fn hidden() i32 = { return 99; };\n"));
|
"fn hidden() i32 = { return 99; };\n"));
|
||||||
let ca: str = strings.concat(td, "/libonly-c.a");
|
let ca: str = strings.concat(td, "/libonly-c.a");
|
||||||
let wa: str = strings.concat(td, "/libonly-w.a");
|
let wa: str = strings.concat(td, "/libonly-w.a");
|
||||||
let cav: []str = [testenv.driver("ww"), "build", "-p", "-I", td,
|
let cav: []str = [testenv.driver("ww"), "build", "-I", td,
|
||||||
"-o", ca, lib];
|
"-o", ca, lib];
|
||||||
let wav: []str = [testenv.driver("ww_ww"), "build", "-p", "-I", td,
|
let wav: []str = [testenv.driver("ww_ww"), "build", "-I", td,
|
||||||
"-o", wa, lib];
|
"-o", wa, lib];
|
||||||
if (code(td, "build_package_c", cav) != 0
|
if (code(td, "build_package_c", cav) != 0
|
||||||
|| code(td, "build_package_w", wav) != 0) {
|
|| code(td, "build_package_w", wav) != 0) {
|
||||||
@@ -302,10 +302,10 @@ fn rejectstable(dir: str, label: str, target: str, needle: str) void = {
|
|||||||
strings.concat(td, "/api-c2.a"), strings.concat(td, "/api-w.a")];
|
strings.concat(td, "/api-c2.a"), strings.concat(td, "/api-w.a")];
|
||||||
i = 0;
|
i = 0;
|
||||||
for (i < packages.len) {
|
for (i < packages.len) {
|
||||||
let pav: []str = [testenv.driver(drivers[i]), "build", "-p", "-I", td,
|
let pav: []str = [testenv.driver(drivers[i]), "build", "-I", td,
|
||||||
"-o", packages[i], api];
|
"-o", packages[i], api];
|
||||||
if (code(td, strings.concat("package_", tags[i]), pav) != 0) {
|
if (code(td, strings.concat("package_", tags[i]), pav) != 0) {
|
||||||
fail("self-contained", "ww build -p api failed");
|
fail("self-contained", "ww build api failed");
|
||||||
};
|
};
|
||||||
i += 1;
|
i += 1;
|
||||||
};
|
};
|
||||||
@@ -907,7 +907,7 @@ fn writediamond(td: str, reverse: bool) str = {
|
|||||||
"/.wwtool.w6a")), testenv.readfile(assembler))
|
"/.wwtool.w6a")), testenv.readfile(assembler))
|
||||||
|| !testenv.same(testenv.readfile(strings.concat(work,
|
|| !testenv.same(testenv.readfile(strings.concat(work,
|
||||||
"/.wwtool.stamp")),
|
"/.wwtool.stamp")),
|
||||||
"ww workdir fmt 10 mode build asm 0\n")) {
|
"ww workdir fmt 12 mode build asm 0\n")) {
|
||||||
fail("driver-identity", "persistent artifacts or identities are incomplete");
|
fail("driver-identity", "persistent artifacts or identities are incomplete");
|
||||||
};
|
};
|
||||||
let coldwwi: str = testenv.readfile(strings.concat(work, "/dep.wwi"));
|
let coldwwi: str = testenv.readfile(strings.concat(work, "/dep.wwi"));
|
||||||
@@ -1224,9 +1224,9 @@ fn writediamond(td: str, reverse: bool) str = {
|
|||||||
"export fn nestedvalue() i32 = { return 41; };\n"));
|
"export fn nestedvalue() i32 = { return 41; };\n"));
|
||||||
let ca: str = strings.concat(td, "/nested-c.a");
|
let ca: str = strings.concat(td, "/nested-c.a");
|
||||||
let wa: str = strings.concat(td, "/nested-w.a");
|
let wa: str = strings.concat(td, "/nested-w.a");
|
||||||
let cav: []str = [testenv.driver("ww"), "build", "-p", "-I", root,
|
let cav: []str = [testenv.driver("ww"), "build", "-I", root,
|
||||||
"-o", ca, "foo.bar"];
|
"-o", ca, "foo.bar"];
|
||||||
let wav: []str = [testenv.driver("ww_ww"), "build", "-p", "-I", root,
|
let wav: []str = [testenv.driver("ww_ww"), "build", "-I", root,
|
||||||
"-o", wa, "foo.bar"];
|
"-o", wa, "foo.bar"];
|
||||||
if (code(td, "nested_package_c", cav) != 0
|
if (code(td, "nested_package_c", cav) != 0
|
||||||
|| code(td, "nested_package_w", wav) != 0) {
|
|| code(td, "nested_package_w", wav) != 0) {
|
||||||
@@ -1247,22 +1247,575 @@ fn writediamond(td: str, reverse: bool) str = {
|
|||||||
let i: i32 = 0;
|
let i: i32 = 0;
|
||||||
for (i < drivers.len) {
|
for (i < drivers.len) {
|
||||||
let badout: str = strings.concat(td, "/bad-flags-", drivers[i]);
|
let badout: str = strings.concat(td, "/bad-flags-", drivers[i]);
|
||||||
let av: []str = [testenv.driver(drivers[i]), "build", "-p", "-S",
|
let av: []str = [testenv.driver(drivers[i]), "build", "-p",
|
||||||
"-I", root, "-o", badout, "foo.bar"];
|
"-I", root, "-o", badout, "foo.bar"];
|
||||||
let co: testenv.commandout;
|
let co: testenv.commandout;
|
||||||
command(td, strings.concat("package_flag_contract_", drivers[i]),
|
command(td, strings.concat("package_flag_contract_", drivers[i]),
|
||||||
av, &co);
|
av, &co);
|
||||||
if (co.termination != exec.termination.EXIT || co.code == 0
|
if (co.termination != exec.termination.EXIT || co.code == 0
|
||||||
|| !testenv.has(co.stderr,
|
|| !testenv.has(co.stderr, "ww build: unknown flag")) {
|
||||||
"ww build: -p and -S cannot be combined")) {
|
|
||||||
fail("package-flags", strings.concat(drivers[i],
|
fail("package-flags", strings.concat(drivers[i],
|
||||||
" accepted -p -S"));
|
" accepted the removed package-action flag"));
|
||||||
};
|
};
|
||||||
i += 1;
|
i += 1;
|
||||||
};
|
};
|
||||||
testenv.clean(td);
|
testenv.clean(td);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@test fn package_kind_selects_build_action() void = {
|
||||||
|
let td: str = testenv.fresh();
|
||||||
|
let source: str = strings.concat(td, "/source");
|
||||||
|
let foo: str = strings.concat(source, "/foo");
|
||||||
|
let dep: str = strings.concat(foo, "/dep");
|
||||||
|
let bar: str = strings.concat(foo, "/bar");
|
||||||
|
let commanddir: str = strings.concat(foo, "/cmd");
|
||||||
|
let cyclea: str = strings.concat(foo, "/cyclea");
|
||||||
|
let cycleb: str = strings.concat(foo, "/cycleb");
|
||||||
|
let tools: str = strings.concat(td, "/tools");
|
||||||
|
mkdir(source); mkdir(foo); mkdir(dep); mkdir(bar); mkdir(commanddir);
|
||||||
|
mkdir(cyclea); mkdir(cycleb); mkdir(tools);
|
||||||
|
let depsrc: str = strings.concat(dep, "/dep.ww");
|
||||||
|
let depbase: str = strings.concat(
|
||||||
|
"package dep;\n",
|
||||||
|
"// DEP_SOURCE\n",
|
||||||
|
"fn hidden() i32 = { return 40; };\n",
|
||||||
|
"export fn value() i32 = { return hidden(); };\n");
|
||||||
|
let depprivate: str = strings.concat(
|
||||||
|
"package dep;\n",
|
||||||
|
"// DEP_SOURCE\n",
|
||||||
|
"fn hidden() i32 = { return 41; };\n",
|
||||||
|
"export fn value() i32 = { return hidden(); };\n");
|
||||||
|
let depexported: str = strings.concat(depprivate,
|
||||||
|
"export fn additional() i32 = { return 1; };\n");
|
||||||
|
testenv.writefile(depsrc, depbase);
|
||||||
|
testenv.writefile(strings.concat(bar, "/a.ww"), strings.concat(
|
||||||
|
"package bar;\nimport foo.dep;\n",
|
||||||
|
"// ROOT_A\n",
|
||||||
|
"export fn value() i32 = { return dep.value() + 2; };\n"));
|
||||||
|
testenv.writefile(strings.concat(bar, "/z.ww"), strings.concat(
|
||||||
|
"package bar;\nimport foo.dep;\n",
|
||||||
|
"// ROOT_Z\n",
|
||||||
|
"export fn other() i32 = { return 9; };\n"));
|
||||||
|
testenv.writefile(strings.concat(commanddir, "/main.ww"), strings.concat(
|
||||||
|
"package main;\nimport foo.bar;\n",
|
||||||
|
"// COMMAND_OWNER\n",
|
||||||
|
"fn main() i32 = { return bar.value(); };\n"));
|
||||||
|
testenv.writefile(strings.concat(cyclea, "/a.ww"), strings.concat(
|
||||||
|
"package cyclea;\nimport foo.cycleb;\n",
|
||||||
|
"export fn value() i32 = { return cycleb.value(); };\n"));
|
||||||
|
testenv.writefile(strings.concat(cycleb, "/b.ww"), strings.concat(
|
||||||
|
"package cycleb;\nimport foo.cyclea;\n",
|
||||||
|
"export fn value() i32 = { return cyclea.value(); };\n"));
|
||||||
|
|
||||||
|
let compiler: str = strings.concat(tools, "/w6c.sh");
|
||||||
|
let assembler: str = strings.concat(tools, "/w6a.sh");
|
||||||
|
let linker: str = strings.concat(tools, "/w6l.sh");
|
||||||
|
testenv.writeexecutable(compiler, strings.concat(
|
||||||
|
"#!/bin/sh\n",
|
||||||
|
"printf 'BEGIN' >> \"$WW_ROOT_COMPILER_TRACE\"\n",
|
||||||
|
"for arg in \"$@\"; do printf '<%s>' \"$arg\" >> ",
|
||||||
|
"\"$WW_ROOT_COMPILER_TRACE\"; done\n",
|
||||||
|
"printf '\\n' >> \"$WW_ROOT_COMPILER_TRACE\"\n",
|
||||||
|
"exec \"$WW_ROOT_REAL_COMPILER\" \"$@\"\n"));
|
||||||
|
testenv.writeexecutable(assembler, strings.concat(
|
||||||
|
"#!/bin/sh\n",
|
||||||
|
"printf 'BEGIN' >> \"$WW_ROOT_ASSEMBLER_TRACE\"\n",
|
||||||
|
"for arg in \"$@\"; do printf '<%s>' \"$arg\" >> ",
|
||||||
|
"\"$WW_ROOT_ASSEMBLER_TRACE\"; done\n",
|
||||||
|
"printf '\\n' >> \"$WW_ROOT_ASSEMBLER_TRACE\"\n",
|
||||||
|
"exec \"$WW_ROOT_REAL_ASSEMBLER\" \"$@\"\n"));
|
||||||
|
testenv.writeexecutable(linker, strings.concat(
|
||||||
|
"#!/bin/sh\n",
|
||||||
|
"printf 'BEGIN' >> \"$WW_ROOT_LINKER_TRACE\"\n",
|
||||||
|
"for arg in \"$@\"; do printf '<%s>' \"$arg\" >> ",
|
||||||
|
"\"$WW_ROOT_LINKER_TRACE\"; done\n",
|
||||||
|
"printf '\\n' >> \"$WW_ROOT_LINKER_TRACE\"\n",
|
||||||
|
"exec \"$WW_ROOT_REAL_LINKER\" \"$@\"\n"));
|
||||||
|
|
||||||
|
let stages: []str = ["ww", "ww_ww"];
|
||||||
|
let compilers: []str = ["w6c", "w6c_ww"];
|
||||||
|
let assemblers: []str = ["w6a", "w6a_ww"];
|
||||||
|
let linkers: []str = ["w6l", "w6l_ww"];
|
||||||
|
let tags: []str = ["c", "ww"];
|
||||||
|
let suffixes: []str = [".unit.ww", ".wwi", ".s", ".o", ".a"];
|
||||||
|
let rootreference: []str = ["", "", "", "", ""];
|
||||||
|
let depreference: []str = ["", "", "", "", ""];
|
||||||
|
let commandreference: []str = ["", "", "", "", ""];
|
||||||
|
let nooutrootreference: []str = ["", "", "", "", ""];
|
||||||
|
let nooutdepreference: []str = ["", "", "", "", ""];
|
||||||
|
let publishreference: str = "";
|
||||||
|
let exportreference: str = "";
|
||||||
|
let binaryreference: str = "";
|
||||||
|
let diagnosticreference: str = "";
|
||||||
|
let cyclediagreference: str = "";
|
||||||
|
let cyclepathdiagreference: str = "";
|
||||||
|
let pathdiagreference: str = "";
|
||||||
|
let runtime: str = strings.concat(testenv.repo(), "/out/lib");
|
||||||
|
let si: i32 = 0;
|
||||||
|
for (si < stages.len) {
|
||||||
|
let work: str = strings.concat(td, "/work-", tags[si]);
|
||||||
|
let outpath: str = strings.concat(td, "/libbar-", tags[si], ".a");
|
||||||
|
let compilertrace: str = strings.concat(td, "/compiler-", tags[si]);
|
||||||
|
let assemblertrace: str = strings.concat(td, "/assembler-", tags[si]);
|
||||||
|
let linkertrace: str = strings.concat(td, "/linker-", tags[si]);
|
||||||
|
mkdir(work);
|
||||||
|
testenv.writefile(compilertrace, "");
|
||||||
|
testenv.writefile(assemblertrace, "");
|
||||||
|
testenv.writefile(linkertrace, "");
|
||||||
|
let env: []str = roottraceenv(source, runtime,
|
||||||
|
compiler, assembler, linker,
|
||||||
|
compilertrace, assemblertrace, linkertrace,
|
||||||
|
testenv.driver(compilers[si]),
|
||||||
|
testenv.driver(assemblers[si]),
|
||||||
|
testenv.driver(linkers[si]));
|
||||||
|
let av: []str = [testenv.driver(stages[si]), "build",
|
||||||
|
"-w", work, "-I", source, "-o", outpath, "foo.bar"];
|
||||||
|
let out: testenv.commandout;
|
||||||
|
testenv.runcommandenv(td, td, strings.concat("auto-cold-", tags[si]),
|
||||||
|
av, env, tmo(), &out);
|
||||||
|
if (out.termination != exec.termination.EXIT || out.code != 0
|
||||||
|
|| out.stderr.len != 0) {
|
||||||
|
fail("package-autoaction", strings.concat(tags[si],
|
||||||
|
" cold library build failed: ", out.stderr));
|
||||||
|
};
|
||||||
|
let ctrace: str = testenv.readfile(compilertrace);
|
||||||
|
let atrace: str = testenv.readfile(assemblertrace);
|
||||||
|
let wantcompiler: str = strings.concat(
|
||||||
|
"BEGIN<-c><-I><", work,
|
||||||
|
"/foo.dep.wwi.new><-o><", work,
|
||||||
|
"/foo.dep.s.new><", work, "/foo.dep.unit.new>\n",
|
||||||
|
"BEGIN<-c><--import><foo.dep><", work,
|
||||||
|
"/foo.dep.wwi><-I><", work,
|
||||||
|
"/foo.bar.wwi.new><-o><", work,
|
||||||
|
"/foo.bar.s.new><", work, "/foo.bar.unit.new>\n");
|
||||||
|
let wantassembler: str = strings.concat(
|
||||||
|
"BEGIN<-o><", work, "/foo.dep.o.new><", work,
|
||||||
|
"/foo.dep.s.new>\n",
|
||||||
|
"BEGIN<-o><", work, "/foo.bar.o.new><", work,
|
||||||
|
"/foo.bar.s.new>\n");
|
||||||
|
if (!testenv.same(ctrace, wantcompiler)
|
||||||
|
|| !testenv.same(atrace, wantassembler)
|
||||||
|
|| testenv.readfile(linkertrace).len != 0) {
|
||||||
|
fail("package-autoaction",
|
||||||
|
"library action tool arguments are not compile-only/direct");
|
||||||
|
};
|
||||||
|
let rootunit: str = testenv.readfile(strings.concat(work,
|
||||||
|
"/foo.bar.unit.ww"));
|
||||||
|
if (testenv.pos(rootunit, "// ROOT_A") < 0
|
||||||
|
|| testenv.pos(rootunit, "// ROOT_Z")
|
||||||
|
<= testenv.pos(rootunit, "// ROOT_A")
|
||||||
|
|| testenv.has(rootunit, "DEP_SOURCE")
|
||||||
|
|| testenv.occurrences(rootunit,
|
||||||
|
"//ww:module-reset foo.bar\n") != 2) {
|
||||||
|
fail("package-autoaction",
|
||||||
|
"library unit is not owner-only and byte-sorted");
|
||||||
|
};
|
||||||
|
if (!testenv.exists(outpath)
|
||||||
|
|| !testenv.exists(strings.concat(outpath, ".wwi"))
|
||||||
|
|| !testenv.same(testenv.readfile(outpath),
|
||||||
|
testenv.readfile(strings.concat(work, "/foo.bar.a")))
|
||||||
|
|| !testenv.same(testenv.readfile(strings.concat(outpath, ".wwi")),
|
||||||
|
testenv.readfile(strings.concat(work, "/foo.bar.wwi")))) {
|
||||||
|
fail("package-autoaction", "explicit package publication changed bytes");
|
||||||
|
};
|
||||||
|
let ai: i32 = 0;
|
||||||
|
for (ai < suffixes.len) {
|
||||||
|
let rootbytes: str = testenv.readfile(strings.concat(work,
|
||||||
|
"/foo.bar", suffixes[ai]));
|
||||||
|
let depbytes: str = testenv.readfile(strings.concat(work,
|
||||||
|
"/foo.dep", suffixes[ai]));
|
||||||
|
if (si == 0) {
|
||||||
|
rootreference[ai] = strings.dup(rootbytes);
|
||||||
|
depreference[ai] = strings.dup(depbytes);
|
||||||
|
} else { if (!testenv.same(rootreference[ai], rootbytes)
|
||||||
|
|| !testenv.same(depreference[ai], depbytes)) {
|
||||||
|
fail("package-autoaction",
|
||||||
|
"Cstage and WWstage package artifacts differ");
|
||||||
|
}; };
|
||||||
|
ai += 1;
|
||||||
|
};
|
||||||
|
if (si == 0) {
|
||||||
|
publishreference = strings.dup(testenv.readfile(outpath));
|
||||||
|
exportreference = strings.dup(testenv.readfile(strings.concat(
|
||||||
|
outpath, ".wwi")));
|
||||||
|
} else { if (!testenv.same(publishreference,
|
||||||
|
testenv.readfile(outpath)) || !testenv.same(exportreference,
|
||||||
|
testenv.readfile(strings.concat(outpath, ".wwi")))) {
|
||||||
|
fail("package-autoaction", "published stage artifacts differ");
|
||||||
|
}; };
|
||||||
|
|
||||||
|
// The other AutoAction half remains declaration-selected: package main
|
||||||
|
// alone receives --entry and its complete archive-only link closure.
|
||||||
|
testenv.clean(compilertrace); testenv.writefile(compilertrace, "");
|
||||||
|
testenv.clean(assemblertrace); testenv.writefile(assemblertrace, "");
|
||||||
|
testenv.clean(linkertrace); testenv.writefile(linkertrace, "");
|
||||||
|
let commandwork: str = strings.concat(td, "/command-work-", tags[si]);
|
||||||
|
let commandbin: str = strings.concat(td, "/command-", tags[si]);
|
||||||
|
mkdir(commandwork);
|
||||||
|
let commandav: []str = [testenv.driver(stages[si]), "build",
|
||||||
|
"-w", commandwork, "-I", source, "-o", commandbin, "foo.cmd"];
|
||||||
|
testenv.runcommandenv(td, td, strings.concat("auto-command-", tags[si]),
|
||||||
|
commandav, env, tmo(), &out);
|
||||||
|
ctrace = testenv.readfile(compilertrace);
|
||||||
|
atrace = testenv.readfile(assemblertrace);
|
||||||
|
let commandlink: str = testenv.readfile(linkertrace);
|
||||||
|
let wantcommandcompiler: str = strings.concat(
|
||||||
|
"BEGIN<-c><-I><", commandwork,
|
||||||
|
"/foo.dep.wwi.new><-o><", commandwork,
|
||||||
|
"/foo.dep.s.new><", commandwork, "/foo.dep.unit.new>\n",
|
||||||
|
"BEGIN<-c><--import><foo.dep><", commandwork,
|
||||||
|
"/foo.dep.wwi><-I><", commandwork,
|
||||||
|
"/foo.bar.wwi.new><-o><", commandwork,
|
||||||
|
"/foo.bar.s.new><", commandwork, "/foo.bar.unit.new>\n",
|
||||||
|
"BEGIN<--entry><-c><--import><foo.bar><", commandwork,
|
||||||
|
"/foo.bar.wwi><-I><", commandwork,
|
||||||
|
"/foo.cmd.wwi.new><-o><", commandwork,
|
||||||
|
"/foo.cmd.s.new><", commandwork, "/foo.cmd.unit.new>\n");
|
||||||
|
let wantcommandassembler: str = strings.concat(
|
||||||
|
"BEGIN<-o><", commandwork, "/foo.dep.o.new><", commandwork,
|
||||||
|
"/foo.dep.s.new>\n",
|
||||||
|
"BEGIN<-o><", commandwork, "/foo.bar.o.new><", commandwork,
|
||||||
|
"/foo.bar.s.new>\n",
|
||||||
|
"BEGIN<-o><", commandwork, "/foo.cmd.o.new><", commandwork,
|
||||||
|
"/foo.cmd.s.new>\n");
|
||||||
|
let wantcommandlink: str = strings.concat("BEGIN<-o><", commandbin,
|
||||||
|
"><", commandwork, "/foo.cmd.a><", commandwork,
|
||||||
|
"/foo.bar.a><", commandwork, "/foo.dep.a><", runtime,
|
||||||
|
"/libwwrt.a>\n");
|
||||||
|
if (out.termination != exec.termination.EXIT || out.code != 0
|
||||||
|
|| out.stderr.len != 0
|
||||||
|
|| !testenv.same(ctrace, wantcommandcompiler)
|
||||||
|
|| !testenv.same(atrace, wantcommandassembler)
|
||||||
|
|| !testenv.same(commandlink, wantcommandlink)
|
||||||
|
|| testenv.has(commandlink, ".wwi>")) {
|
||||||
|
fail("package-autoaction",
|
||||||
|
"main action arguments or archive closure changed");
|
||||||
|
};
|
||||||
|
let commandunit: str = testenv.readfile(strings.concat(commandwork,
|
||||||
|
"/foo.cmd.unit.ww"));
|
||||||
|
if (!testenv.has(commandunit, "// COMMAND_OWNER")
|
||||||
|
|| testenv.has(commandunit, "// ROOT_A")
|
||||||
|
|| testenv.has(commandunit, "// DEP_SOURCE")) {
|
||||||
|
fail("package-autoaction", "command unit contains foreign sources");
|
||||||
|
};
|
||||||
|
ai = 0;
|
||||||
|
for (ai < suffixes.len) {
|
||||||
|
let commandbytes: str = testenv.readfile(strings.concat(commandwork,
|
||||||
|
"/foo.cmd", suffixes[ai]));
|
||||||
|
if (si == 0) { commandreference[ai] = strings.dup(commandbytes); }
|
||||||
|
else { if (!testenv.same(commandreference[ai], commandbytes)) {
|
||||||
|
fail("package-autoaction",
|
||||||
|
"Cstage and WWstage command artifacts differ");
|
||||||
|
}; };
|
||||||
|
ai += 1;
|
||||||
|
};
|
||||||
|
let commandrun: []str = [commandbin];
|
||||||
|
if (code(td, strings.concat("auto-command-run-", tags[si]),
|
||||||
|
commandrun) != 42) {
|
||||||
|
fail("package-autoaction", "main action binary returned wrong value");
|
||||||
|
};
|
||||||
|
// The public run command must make the same declaration-driven choice;
|
||||||
|
// its private temp paths make exact argv intentionally inapplicable here.
|
||||||
|
let drivercommandrun: []str = [testenv.driver(stages[si]), "run",
|
||||||
|
"-I", source, "foo.cmd"];
|
||||||
|
testenv.runcommand(td, td, strings.concat("auto-driver-command-run-",
|
||||||
|
tags[si]), drivercommandrun, tmo(), &out);
|
||||||
|
if (out.termination != exec.termination.EXIT || out.code != 42
|
||||||
|
|| out.stdout.len != 0 || out.stderr.len != 0) {
|
||||||
|
fail("package-autoaction", "ww run rejected or misran package main");
|
||||||
|
};
|
||||||
|
if (si == 0) {
|
||||||
|
binaryreference = strings.dup(testenv.readfile(commandbin));
|
||||||
|
} else { if (!testenv.same(binaryreference,
|
||||||
|
testenv.readfile(commandbin))) {
|
||||||
|
fail("package-autoaction", "linked stage binaries differ");
|
||||||
|
}; };
|
||||||
|
|
||||||
|
testenv.clean(compilertrace); testenv.writefile(compilertrace, "");
|
||||||
|
testenv.clean(assemblertrace); testenv.writefile(assemblertrace, "");
|
||||||
|
testenv.clean(linkertrace); testenv.writefile(linkertrace, "");
|
||||||
|
let nooutwork: str = strings.concat(td, "/no-output-work-", tags[si]);
|
||||||
|
mkdir(nooutwork);
|
||||||
|
let noout: []str = [testenv.driver(stages[si]), "build",
|
||||||
|
"-w", nooutwork, "-I", source, "foo.bar"];
|
||||||
|
testenv.runcommandenv(td, td, strings.concat("auto-no-output-", tags[si]),
|
||||||
|
noout, env, tmo(), &out);
|
||||||
|
ctrace = testenv.readfile(compilertrace);
|
||||||
|
atrace = testenv.readfile(assemblertrace);
|
||||||
|
let wantnooutcompiler: str = strings.concat(
|
||||||
|
"BEGIN<-c><-I><", nooutwork,
|
||||||
|
"/foo.dep.wwi.new><-o><", nooutwork,
|
||||||
|
"/foo.dep.s.new><", nooutwork, "/foo.dep.unit.new>\n",
|
||||||
|
"BEGIN<-c><--import><foo.dep><", nooutwork,
|
||||||
|
"/foo.dep.wwi><-I><", nooutwork,
|
||||||
|
"/foo.bar.wwi.new><-o><", nooutwork,
|
||||||
|
"/foo.bar.s.new><", nooutwork, "/foo.bar.unit.new>\n");
|
||||||
|
let wantnooutassembler: str = strings.concat(
|
||||||
|
"BEGIN<-o><", nooutwork, "/foo.dep.o.new><", nooutwork,
|
||||||
|
"/foo.dep.s.new>\n",
|
||||||
|
"BEGIN<-o><", nooutwork, "/foo.bar.o.new><", nooutwork,
|
||||||
|
"/foo.bar.s.new>\n");
|
||||||
|
if (out.termination != exec.termination.EXIT || out.code != 0
|
||||||
|
|| out.stderr.len != 0 || testenv.exists(strings.concat(td, "/bar"))
|
||||||
|
|| !testenv.same(ctrace, wantnooutcompiler)
|
||||||
|
|| !testenv.same(atrace, wantnooutassembler)
|
||||||
|
|| testenv.readfile(linkertrace).len != 0) {
|
||||||
|
fail("package-autoaction",
|
||||||
|
"cold no-output library build did not remain compile-only");
|
||||||
|
};
|
||||||
|
ai = 0;
|
||||||
|
for (ai < suffixes.len) {
|
||||||
|
let nooutroot: str = testenv.readfile(strings.concat(nooutwork,
|
||||||
|
"/foo.bar", suffixes[ai]));
|
||||||
|
let nooutdep: str = testenv.readfile(strings.concat(nooutwork,
|
||||||
|
"/foo.dep", suffixes[ai]));
|
||||||
|
if (!testenv.same(nooutroot, rootreference[ai])
|
||||||
|
|| !testenv.same(nooutdep, depreference[ai])) {
|
||||||
|
fail("package-autoaction",
|
||||||
|
"publication request changed package artifact bytes");
|
||||||
|
};
|
||||||
|
if (si == 0) {
|
||||||
|
nooutrootreference[ai] = strings.dup(nooutroot);
|
||||||
|
nooutdepreference[ai] = strings.dup(nooutdep);
|
||||||
|
} else { if (!testenv.same(nooutrootreference[ai], nooutroot)
|
||||||
|
|| !testenv.same(nooutdepreference[ai], nooutdep)) {
|
||||||
|
fail("package-autoaction",
|
||||||
|
"cold no-output artifacts differ by stage");
|
||||||
|
}; };
|
||||||
|
ai += 1;
|
||||||
|
};
|
||||||
|
// An explicitly empty -o is observably the same no-publication request
|
||||||
|
// in both drivers and therefore reuses the same semantic actions.
|
||||||
|
testenv.clean(compilertrace); testenv.writefile(compilertrace, "");
|
||||||
|
testenv.clean(assemblertrace); testenv.writefile(assemblertrace, "");
|
||||||
|
testenv.clean(linkertrace); testenv.writefile(linkertrace, "");
|
||||||
|
let emptyout: []str = [testenv.driver(stages[si]), "build",
|
||||||
|
"-w", nooutwork, "-I", source, "-o", "", "foo.bar"];
|
||||||
|
testenv.runcommandenv(td, td, strings.concat("auto-empty-output-",
|
||||||
|
tags[si]), emptyout, env, tmo(), &out);
|
||||||
|
if (out.termination != exec.termination.EXIT || out.code != 0
|
||||||
|
|| out.stderr.len != 0
|
||||||
|
|| testenv.readfile(compilertrace).len != 0
|
||||||
|
|| testenv.readfile(assemblertrace).len != 0
|
||||||
|
|| testenv.readfile(linkertrace).len != 0) {
|
||||||
|
fail("package-autoaction",
|
||||||
|
"empty -o changed no-publication action semantics");
|
||||||
|
};
|
||||||
|
|
||||||
|
// Publication is not semantic action identity: an already-populated
|
||||||
|
// package workdir is reusable when the next request omits -o.
|
||||||
|
testenv.clean(compilertrace); testenv.writefile(compilertrace, "");
|
||||||
|
testenv.clean(assemblertrace); testenv.writefile(assemblertrace, "");
|
||||||
|
testenv.clean(linkertrace); testenv.writefile(linkertrace, "");
|
||||||
|
let warmnoout: []str = [testenv.driver(stages[si]), "build",
|
||||||
|
"-w", work, "-I", source, "foo.bar"];
|
||||||
|
testenv.runcommandenv(td, td, strings.concat("auto-warm-no-output-",
|
||||||
|
tags[si]), warmnoout, env, tmo(), &out);
|
||||||
|
if (out.termination != exec.termination.EXIT || out.code != 0
|
||||||
|
|| out.stderr.len != 0
|
||||||
|
|| testenv.readfile(compilertrace).len != 0
|
||||||
|
|| testenv.readfile(assemblertrace).len != 0
|
||||||
|
|| testenv.readfile(linkertrace).len != 0) {
|
||||||
|
fail("package-autoaction",
|
||||||
|
"publication request entered persistent action identity");
|
||||||
|
};
|
||||||
|
|
||||||
|
testenv.clean(compilertrace); testenv.writefile(compilertrace, "");
|
||||||
|
testenv.clean(assemblertrace); testenv.writefile(assemblertrace, "");
|
||||||
|
testenv.clean(linkertrace); testenv.writefile(linkertrace, "");
|
||||||
|
let pathwork: str = strings.concat(td, "/path-work-", tags[si]);
|
||||||
|
mkdir(pathwork);
|
||||||
|
let longout: str = strings.concat(td, "/");
|
||||||
|
for (longout.len < 4090) { longout = strings.concat(longout, "x"); };
|
||||||
|
let pathav: []str = [testenv.driver(stages[si]), "build",
|
||||||
|
"-w", pathwork, "-I", source, "-o", longout, "foo.bar"];
|
||||||
|
testenv.runcommandenv(td, td, strings.concat("auto-output-path-", tags[si]),
|
||||||
|
pathav, env, tmo(), &out);
|
||||||
|
let wantpathdiag: str = "ww: package output path is too long\n";
|
||||||
|
if (out.termination != exec.termination.EXIT || out.code != 1
|
||||||
|
|| !testenv.same(out.stderr, wantpathdiag)
|
||||||
|
|| testenv.readfile(compilertrace).len != 0
|
||||||
|
|| testenv.readfile(assemblertrace).len != 0
|
||||||
|
|| testenv.readfile(linkertrace).len != 0
|
||||||
|
|| testenv.exists(strings.concat(pathwork, "/foo.dep.unit.ww"))
|
||||||
|
|| testenv.exists(strings.concat(pathwork, "/foo.bar.unit.ww"))) {
|
||||||
|
fail("package-autoaction",
|
||||||
|
"package publication path failed after the tool boundary");
|
||||||
|
};
|
||||||
|
if (si == 0) { pathdiagreference = strings.dup(out.stderr); }
|
||||||
|
else { if (!testenv.same(pathdiagreference, out.stderr)) {
|
||||||
|
fail("package-autoaction", "output path diagnostics differ by stage");
|
||||||
|
}; };
|
||||||
|
|
||||||
|
// Output publication is unused under -S, so even this spelling must not
|
||||||
|
// participate in an assembly-only action or its failure behavior.
|
||||||
|
testenv.clean(compilertrace); testenv.writefile(compilertrace, "");
|
||||||
|
testenv.clean(assemblertrace); testenv.writefile(assemblertrace, "");
|
||||||
|
testenv.clean(linkertrace); testenv.writefile(linkertrace, "");
|
||||||
|
let asmwork: str = strings.concat(td, "/asm-work-", tags[si]);
|
||||||
|
mkdir(asmwork);
|
||||||
|
let asmav: []str = [testenv.driver(stages[si]), "build", "-S",
|
||||||
|
"-w", asmwork, "-I", source, "-o", longout, "foo.bar"];
|
||||||
|
testenv.runcommandenv(td, td, strings.concat("auto-asm-long-output-",
|
||||||
|
tags[si]), asmav, env, tmo(), &out);
|
||||||
|
let wantasmcompiler: str = strings.concat(
|
||||||
|
"BEGIN<-c><-I><", asmwork,
|
||||||
|
"/foo.dep.wwi.new><-o><", asmwork,
|
||||||
|
"/foo.dep.s.new><", asmwork, "/foo.dep.unit.new>\n",
|
||||||
|
"BEGIN<-c><--import><foo.dep><", asmwork,
|
||||||
|
"/foo.dep.wwi><-I><", asmwork,
|
||||||
|
"/foo.bar.wwi.new><-o><", asmwork,
|
||||||
|
"/foo.bar.s.new><", asmwork, "/foo.bar.unit.new>\n");
|
||||||
|
if (out.termination != exec.termination.EXIT || out.code != 0
|
||||||
|
|| out.stderr.len != 0
|
||||||
|
|| !testenv.same(testenv.readfile(compilertrace), wantasmcompiler)
|
||||||
|
|| testenv.readfile(assemblertrace).len != 0
|
||||||
|
|| testenv.readfile(linkertrace).len != 0
|
||||||
|
|| testenv.exists(strings.concat(asmwork, "/foo.dep.o"))
|
||||||
|
|| testenv.exists(strings.concat(asmwork, "/foo.dep.a"))
|
||||||
|
|| testenv.exists(strings.concat(asmwork, "/foo.bar.o"))
|
||||||
|
|| testenv.exists(strings.concat(asmwork, "/foo.bar.a"))) {
|
||||||
|
fail("package-autoaction",
|
||||||
|
"assembly-only action consumed an unused publication path");
|
||||||
|
};
|
||||||
|
|
||||||
|
testenv.clean(compilertrace); testenv.writefile(compilertrace, "");
|
||||||
|
testenv.clean(assemblertrace); testenv.writefile(assemblertrace, "");
|
||||||
|
testenv.clean(linkertrace); testenv.writefile(linkertrace, "");
|
||||||
|
let runav: []str = [testenv.driver(stages[si]), "run",
|
||||||
|
"-I", source, "foo.bar"];
|
||||||
|
testenv.runcommandenv(td, td, strings.concat("auto-run-reject-", tags[si]),
|
||||||
|
runav, env, tmo(), &out);
|
||||||
|
let wantdiag: str = "ww: package foo.bar is not a main package\n";
|
||||||
|
if (out.termination != exec.termination.EXIT || out.code != 1
|
||||||
|
|| !testenv.same(out.stderr, wantdiag)
|
||||||
|
|| testenv.readfile(compilertrace).len != 0
|
||||||
|
|| testenv.readfile(assemblertrace).len != 0
|
||||||
|
|| testenv.readfile(linkertrace).len != 0) {
|
||||||
|
fail("package-autoaction", "run crossed the non-main tool boundary");
|
||||||
|
};
|
||||||
|
if (si == 0) { diagnosticreference = strings.dup(out.stderr); }
|
||||||
|
else { if (!testenv.same(diagnosticreference, out.stderr)) {
|
||||||
|
fail("package-autoaction", "run diagnostics differ by stage");
|
||||||
|
}; };
|
||||||
|
|
||||||
|
let cyclerun: []str = [testenv.driver(stages[si]), "run",
|
||||||
|
"-I", source, "foo.cyclea"];
|
||||||
|
testenv.runcommandenv(td, td, strings.concat("auto-run-cycle-", tags[si]),
|
||||||
|
cyclerun, env, tmo(), &out);
|
||||||
|
if (out.termination != exec.termination.EXIT || out.code != 1
|
||||||
|
|| !testenv.has(out.stderr,
|
||||||
|
"ww: dependency cycle: foo.cyclea -> foo.cycleb -> foo.cyclea\n")
|
||||||
|
|| testenv.has(out.stderr, "is not a main package")
|
||||||
|
|| testenv.readfile(compilertrace).len != 0
|
||||||
|
|| testenv.readfile(assemblertrace).len != 0
|
||||||
|
|| testenv.readfile(linkertrace).len != 0) {
|
||||||
|
fail("package-autoaction",
|
||||||
|
"run command-kind validation masked a graph failure");
|
||||||
|
};
|
||||||
|
if (si == 0) { cyclediagreference = strings.dup(out.stderr); }
|
||||||
|
else { if (!testenv.same(cyclediagreference, out.stderr)) {
|
||||||
|
fail("package-autoaction", "run cycle diagnostics differ by stage");
|
||||||
|
}; };
|
||||||
|
|
||||||
|
let cyclepathwork: str = strings.concat(td, "/cycle-path-work-",
|
||||||
|
tags[si]);
|
||||||
|
mkdir(cyclepathwork);
|
||||||
|
let cyclepathav: []str = [testenv.driver(stages[si]), "build",
|
||||||
|
"-w", cyclepathwork, "-I", source, "-o", longout,
|
||||||
|
"foo.cyclea"];
|
||||||
|
testenv.runcommandenv(td, td, strings.concat("auto-cycle-path-", tags[si]),
|
||||||
|
cyclepathav, env, tmo(), &out);
|
||||||
|
if (out.termination != exec.termination.EXIT || out.code != 1
|
||||||
|
|| !testenv.has(out.stderr, "ww: dependency cycle: ")
|
||||||
|
|| !testenv.has(out.stderr, "foo.cyclea")
|
||||||
|
|| !testenv.has(out.stderr, "foo.cycleb")
|
||||||
|
|| testenv.has(out.stderr, "package output path is too long")
|
||||||
|
|| testenv.readfile(compilertrace).len != 0
|
||||||
|
|| testenv.readfile(assemblertrace).len != 0
|
||||||
|
|| testenv.readfile(linkertrace).len != 0) {
|
||||||
|
fail("package-autoaction",
|
||||||
|
strings.concat("publication path validation masked a graph failure: ",
|
||||||
|
out.stderr));
|
||||||
|
};
|
||||||
|
if (si == 0) { cyclepathdiagreference = strings.dup(out.stderr); }
|
||||||
|
else { if (!testenv.same(cyclepathdiagreference, out.stderr)) {
|
||||||
|
fail("package-autoaction",
|
||||||
|
"cycle/output-path diagnostic differs by stage");
|
||||||
|
}; };
|
||||||
|
|
||||||
|
assert(os.remove(depsrc) == 0);
|
||||||
|
testenv.writefile(depsrc, depprivate);
|
||||||
|
testenv.runcommandenv(td, td, strings.concat("auto-private-", tags[si]),
|
||||||
|
av, env, tmo(), &out);
|
||||||
|
ctrace = testenv.readfile(compilertrace);
|
||||||
|
atrace = testenv.readfile(assemblertrace);
|
||||||
|
let wantprivatecompiler: str = strings.concat(
|
||||||
|
"BEGIN<-c><-I><", work,
|
||||||
|
"/foo.dep.wwi.new><-o><", work,
|
||||||
|
"/foo.dep.s.new><", work, "/foo.dep.unit.new>\n");
|
||||||
|
let wantprivateassembler: str = strings.concat(
|
||||||
|
"BEGIN<-o><", work, "/foo.dep.o.new><", work,
|
||||||
|
"/foo.dep.s.new>\n");
|
||||||
|
if (out.termination != exec.termination.EXIT || out.code != 0
|
||||||
|
|| !testenv.same(ctrace, wantprivatecompiler)
|
||||||
|
|| !testenv.same(atrace, wantprivateassembler)
|
||||||
|
|| testenv.readfile(linkertrace).len != 0
|
||||||
|
|| !testenv.same(rootreference[4], testenv.readfile(strings.concat(
|
||||||
|
work, "/foo.bar.a")))) {
|
||||||
|
fail("package-autoaction",
|
||||||
|
"private dependency change escaped its export boundary");
|
||||||
|
};
|
||||||
|
|
||||||
|
testenv.clean(compilertrace); testenv.writefile(compilertrace, "");
|
||||||
|
testenv.clean(assemblertrace); testenv.writefile(assemblertrace, "");
|
||||||
|
testenv.clean(linkertrace); testenv.writefile(linkertrace, "");
|
||||||
|
assert(os.remove(depsrc) == 0);
|
||||||
|
testenv.writefile(depsrc, depexported);
|
||||||
|
testenv.runcommandenv(td, td, strings.concat("auto-export-", tags[si]),
|
||||||
|
av, env, tmo(), &out);
|
||||||
|
ctrace = testenv.readfile(compilertrace);
|
||||||
|
atrace = testenv.readfile(assemblertrace);
|
||||||
|
let wantexportcompiler: str = strings.concat(
|
||||||
|
"BEGIN<-c><-I><", work,
|
||||||
|
"/foo.dep.wwi.new><-o><", work,
|
||||||
|
"/foo.dep.s.new><", work, "/foo.dep.unit.new>\n",
|
||||||
|
"BEGIN<-c><--import><foo.dep><", work,
|
||||||
|
"/foo.dep.wwi><-I><", work,
|
||||||
|
"/foo.bar.wwi.new><-o><", work,
|
||||||
|
"/foo.bar.s.new><", work, "/foo.bar.unit.new>\n");
|
||||||
|
let wantexportassembler: str = strings.concat(
|
||||||
|
"BEGIN<-o><", work, "/foo.dep.o.new><", work,
|
||||||
|
"/foo.dep.s.new>\n",
|
||||||
|
"BEGIN<-o><", work, "/foo.bar.o.new><", work,
|
||||||
|
"/foo.bar.s.new>\n");
|
||||||
|
if (out.termination != exec.termination.EXIT || out.code != 0
|
||||||
|
|| !testenv.same(ctrace, wantexportcompiler)
|
||||||
|
|| !testenv.same(atrace, wantexportassembler)
|
||||||
|
|| testenv.readfile(linkertrace).len != 0) {
|
||||||
|
fail("package-autoaction",
|
||||||
|
"exported dependency change did not reach its direct importer");
|
||||||
|
};
|
||||||
|
|
||||||
|
testenv.clean(compilertrace); testenv.writefile(compilertrace, "");
|
||||||
|
testenv.clean(assemblertrace); testenv.writefile(assemblertrace, "");
|
||||||
|
testenv.clean(linkertrace); testenv.writefile(linkertrace, "");
|
||||||
|
testenv.runcommandenv(td, td, strings.concat("auto-warm-", tags[si]),
|
||||||
|
av, env, tmo(), &out);
|
||||||
|
if (out.termination != exec.termination.EXIT || out.code != 0
|
||||||
|
|| out.stderr.len != 0
|
||||||
|
|| testenv.readfile(compilertrace).len != 0
|
||||||
|
|| testenv.readfile(assemblertrace).len != 0
|
||||||
|
|| testenv.readfile(linkertrace).len != 0) {
|
||||||
|
fail("package-autoaction", "warm library build did not fully reuse");
|
||||||
|
};
|
||||||
|
assert(os.remove(depsrc) == 0);
|
||||||
|
testenv.writefile(depsrc, depbase);
|
||||||
|
si += 1;
|
||||||
|
};
|
||||||
|
testenv.clean(td);
|
||||||
|
};
|
||||||
|
|
||||||
@test fn generated_test_hook_is_not_a_user_exemption() void = {
|
@test fn generated_test_hook_is_not_a_user_exemption() void = {
|
||||||
let td: str = testenv.fresh();
|
let td: str = testenv.fresh();
|
||||||
let src: str = strings.concat(td, "/case.ww");
|
let src: str = strings.concat(td, "/case.ww");
|
||||||
|
|||||||
@@ -249,6 +249,7 @@ fn runrootargv(dir: str, root: str, name: str, drv: str,
|
|||||||
let td: str = testenv.fresh();
|
let td: str = testenv.fresh();
|
||||||
let src: str = strings.concat(td, "/inline.ww");
|
let src: str = strings.concat(td, "/inline.ww");
|
||||||
testenv.writefile(src, strings.concat(
|
testenv.writefile(src, strings.concat(
|
||||||
|
"package main;\n",
|
||||||
"package aa;\n",
|
"package aa;\n",
|
||||||
"export fn getv() i32 = { return 7; };\n",
|
"export fn getv() i32 = { return 7; };\n",
|
||||||
"package main;\n",
|
"package main;\n",
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ package rejects_test;
|
|||||||
// paramshadow (#19/#16) — value names and module names are disjoint:
|
// paramshadow (#19/#16) — value names and module names are disjoint:
|
||||||
// a param/let/mlet/for-range/match-case binding named `shadowmod` in
|
// a param/let/mlet/for-range/match-case binding named `shadowmod` in
|
||||||
// a file importing module shadowmod is rejected at the decl site; the
|
// a file importing module shadowmod is rejected at the decl site; the
|
||||||
// renamed binding builds+runs 42 (no over-trigger); a param named
|
// renamed binding in a real `package main` builds+runs 42 (no over-trigger); a param named
|
||||||
// like a module a SIBLING module imports does not trip (src_imports
|
// like a module a SIBLING module imports does not trip (src_imports
|
||||||
// filters by the binding's own module — build+run exit 2). The
|
// filters by the binding's own module — build+run exit 2). The
|
||||||
// carrier's neg_selfimp leg is DROPPED here:
|
// carrier's neg_selfimp leg is DROPPED here:
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
// p2() = mod2.ping = 31
|
// p2() = mod2.ping = 31
|
||||||
// total = 112
|
// total = 112
|
||||||
|
|
||||||
package fnlabelmangle;
|
package main;
|
||||||
|
|
||||||
import mod1;
|
import mod1;
|
||||||
import mod2;
|
import mod2;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
// own module — must NOT trip crossmod's param, even though a sibling
|
// own module — must NOT trip crossmod's param, even though a sibling
|
||||||
// module in the same bundle imports that leaf. Build + run; exit = 2.
|
// module in the same bundle imports that leaf. Build + run; exit = 2.
|
||||||
|
|
||||||
package paramshadowmod;
|
package main;
|
||||||
|
|
||||||
import shadowmod;
|
import shadowmod;
|
||||||
import crossmod;
|
import crossmod;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
// imported module's bareword, so the rule doesn't fire and the body
|
// imported module's bareword, so the rule doesn't fire and the body
|
||||||
// can call `shadowmod.say()` cleanly. Built + run; exit code = 42.
|
// can call `shadowmod.say()` cleanly. Built + run; exit code = 42.
|
||||||
|
|
||||||
package paramshadowmod;
|
package main;
|
||||||
|
|
||||||
import shadowmod;
|
import shadowmod;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//ww:run-exit 26
|
//ww:run-exit 26
|
||||||
|
package main;
|
||||||
// migrated from test/wcc/696_modtype_leaf_collision.c: same-leaf cross-module `type stream` must stay mod-tagged (pre-fix sym smash cross-bound the fields).
|
// migrated from test/wcc/696_modtype_leaf_collision.c: same-leaf cross-module `type stream` must stay mod-tagged (pre-fix sym smash cross-bound the fields).
|
||||||
package mod1;
|
package mod1;
|
||||||
export type stream = struct {
|
export type stream = struct {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//ww:run-exit 42
|
//ww:run-exit 42
|
||||||
|
package main;
|
||||||
// migrated from test/wcc/699_use_promote_alias.c: SK_USE->SK_DEF promotion must keep use_alias so `defmod.flag` resolves.
|
// migrated from test/wcc/699_use_promote_alias.c: SK_USE->SK_DEF promotion must keep use_alias so `defmod.flag` resolves.
|
||||||
package defmod;
|
package defmod;
|
||||||
export def defmod: i32 = 0i32;
|
export def defmod: i32 = 0i32;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//ww:run-exit 42
|
//ww:run-exit 42
|
||||||
|
package main;
|
||||||
// migrated from test/wcc/699_use_promote_alias.c: SK_USE->SK_FN promotion (the original bug) must keep use_alias or `fnmod.flag` fails "unknown type".
|
// migrated from test/wcc/699_use_promote_alias.c: SK_USE->SK_FN promotion (the original bug) must keep use_alias or `fnmod.flag` fails "unknown type".
|
||||||
package fnmod;
|
package fnmod;
|
||||||
export type flag = enum i32 {
|
export type flag = enum i32 {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//ww:run-exit 42
|
//ww:run-exit 42
|
||||||
|
package main;
|
||||||
// migrated from test/wcc/699_use_promote_alias.c: SK_USE->SK_TYPE in-place promotion keeps use_alias so `typmod.flag` resolves (check.c self-import branch).
|
// migrated from test/wcc/699_use_promote_alias.c: SK_USE->SK_TYPE in-place promotion keeps use_alias so `typmod.flag` resolves (check.c self-import branch).
|
||||||
package typmod;
|
package typmod;
|
||||||
export type typmod = struct {
|
export type typmod = struct {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//ww:run-exit 42
|
//ww:run-exit 42
|
||||||
|
package main;
|
||||||
// migrated from test/wcc/699_use_promote_alias.c: SK_USE->SK_VAR promotion must keep use_alias so `varmod.flag` resolves.
|
// migrated from test/wcc/699_use_promote_alias.c: SK_USE->SK_VAR promotion must keep use_alias so `varmod.flag` resolves.
|
||||||
package varmod;
|
package varmod;
|
||||||
export let varmod: i32 = 0i32;
|
export let varmod: i32 = 0i32;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//ww:run-exit 107
|
//ww:run-exit 107
|
||||||
|
package main;
|
||||||
// Migrated from 700_e2e row 40.
|
// Migrated from 700_e2e row 40.
|
||||||
package myos;
|
package myos;
|
||||||
fn alloc(n: i64) i64 = { return n + 100; };
|
fn alloc(n: i64) i64 = { return n + 100; };
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//ww:run-exit 42
|
//ww:run-exit 42
|
||||||
|
package main;
|
||||||
// Migrated from 700_e2e row 123.
|
// Migrated from 700_e2e row 123.
|
||||||
package pkg;
|
package pkg;
|
||||||
export type base = enum i32 { DEC = 10, HEX = 16 };
|
export type base = enum i32 { DEC = 10, HEX = 16 };
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//ww:run-exit 1
|
//ww:run-exit 1
|
||||||
|
package main;
|
||||||
// Migrated from 700_e2e row 118.
|
// Migrated from 700_e2e row 118.
|
||||||
package pkg;
|
package pkg;
|
||||||
type dir = enum { NORTH, SOUTH, EAST, WEST };
|
type dir = enum { NORTH, SOUTH, EAST, WEST };
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//ww:run-exit 42
|
//ww:run-exit 42
|
||||||
|
package main;
|
||||||
// migrated from test/wcc/732_def_const_fold.c: cross-module def-RHS fold (`def K = a.J + 1`) must emit the folded DATA row; run-exit links AND reads the value.
|
// migrated from test/wcc/732_def_const_fold.c: cross-module def-RHS fold (`def K = a.J + 1`) must emit the folded DATA row; run-exit links AND reads the value.
|
||||||
package a;
|
package a;
|
||||||
export def J: i32 = 41;
|
export def J: i32 = 41;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//ww:run-exit 5
|
//ww:run-exit 5
|
||||||
|
package main;
|
||||||
package aa;
|
package aa;
|
||||||
export def K: i32 = 5;
|
export def K: i32 = 5;
|
||||||
export fn getk() i32 = { return K; };
|
export fn getk() i32 = { return K; };
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//ww:run-exit 7
|
//ww:run-exit 7
|
||||||
|
package main;
|
||||||
package aa;
|
package aa;
|
||||||
export let v: i32 = 7;
|
export let v: i32 = 7;
|
||||||
package main;
|
package main;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//ww:run-exit 7
|
//ww:run-exit 7
|
||||||
|
package main;
|
||||||
package aa;
|
package aa;
|
||||||
export let v: i32 = 7;
|
export let v: i32 = 7;
|
||||||
package main;
|
package main;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//ww:run-exit 2
|
//ww:run-exit 2
|
||||||
|
package main;
|
||||||
package aa;
|
package aa;
|
||||||
export let f: f64 = 2.5;
|
export let f: f64 = 2.5;
|
||||||
export fn getf() f64 = { return f; };
|
export fn getf() f64 = { return f; };
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//ww:run-exit 7
|
//ww:run-exit 7
|
||||||
|
package main;
|
||||||
package aa;
|
package aa;
|
||||||
export let v: i32 = 7;
|
export let v: i32 = 7;
|
||||||
export fn getv() i32 = { return v; };
|
export fn getv() i32 = { return v; };
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//ww:run
|
//ww:run
|
||||||
|
package main;
|
||||||
// migrated from test/wcc/839_xmod_nominal_typeeqast.c: A6 — concrete e.myerr returned into e.res (bare-vs-qualified nominal forward), both stages accept.
|
// migrated from test/wcc/839_xmod_nominal_typeeqast.c: A6 — concrete e.myerr returned into e.res (bare-vs-qualified nominal forward), both stages accept.
|
||||||
package e;
|
package e;
|
||||||
export type myerr = !i64;
|
export type myerr = !i64;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//ww:run-exit 42
|
//ww:run-exit 42
|
||||||
|
package main;
|
||||||
// migrated from test/wcc/839_xmod_nominal_typeeqast.c: bare-spelled union variants matched via QUALIFIED case patterns (`case let x: e.myerr`) — cross-module nominal cover.
|
// migrated from test/wcc/839_xmod_nominal_typeeqast.c: bare-spelled union variants matched via QUALIFIED case patterns (`case let x: e.myerr`) — cross-module nominal cover.
|
||||||
package e;
|
package e;
|
||||||
export type myerr = !i64;
|
export type myerr = !i64;
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
//ww:run-exit 7
|
//ww:run-exit 7
|
||||||
|
package main;
|
||||||
package cmatrix;
|
package cmatrix;
|
||||||
fn main() i32 = { return 7; };
|
fn main() i32 = { return 7; };
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//ww:run-exit 37
|
//ww:run-exit 37
|
||||||
|
package main;
|
||||||
package pkg;
|
package pkg;
|
||||||
export type point = struct { x: i64, y: i64 };
|
export type point = struct { x: i64, y: i64 };
|
||||||
export type rect = struct { lo: point, hi: point };
|
export type rect = struct { lo: point, hi: point };
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//ww:run-exit 18
|
//ww:run-exit 18
|
||||||
|
package main;
|
||||||
package pkg;
|
package pkg;
|
||||||
export type point = struct { x: i64, y: i64 };
|
export type point = struct { x: i64, y: i64 };
|
||||||
export type rect = struct { lo: point, hi: point };
|
export type rect = struct { lo: point, hi: point };
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//ww:run-exit 27
|
//ww:run-exit 27
|
||||||
|
package main;
|
||||||
package pkg;
|
package pkg;
|
||||||
export type point = struct { x: i64, y: i64 };
|
export type point = struct { x: i64, y: i64 };
|
||||||
export type rect = struct { lo: point, hi: point };
|
export type rect = struct { lo: point, hi: point };
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//ww:run
|
//ww:run
|
||||||
|
package main;
|
||||||
// migrated from test/wcc/915_arr_module_index_run.c: cross-package mod.arr[0] — LEAQ base + u16 load width (#128b).
|
// migrated from test/wcc/915_arr_module_index_run.c: cross-package mod.arr[0] — LEAQ base + u16 load width (#128b).
|
||||||
package wcmodarr;
|
package wcmodarr;
|
||||||
export let probe_table: [8]u16 = [0u16, 0x0800u16, 0x0801u16, 0x0803u16, 0x1006u16, 0x1009u16, 0x100Du16, 0x1812u16];
|
export let probe_table: [8]u16 = [0u16, 0x0800u16, 0x0801u16, 0x0803u16, 0x1006u16, 0x1009u16, 0x100Du16, 0x1812u16];
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//ww:run-exit 1
|
//ww:run-exit 1
|
||||||
|
package main;
|
||||||
// migrated from test/wcc/915_arr_module_index_run.c: nontrivial index — the pre-fix MOVQ-not-LEAQ segfault repro; 0x0801 mod 256 = 1.
|
// migrated from test/wcc/915_arr_module_index_run.c: nontrivial index — the pre-fix MOVQ-not-LEAQ segfault repro; 0x0801 mod 256 = 1.
|
||||||
package wcmodarr;
|
package wcmodarr;
|
||||||
export let probe_table: [8]u16 = [0u16, 0x0800u16, 0x0801u16, 0x0803u16, 0x1006u16, 0x1009u16, 0x100Du16, 0x1812u16];
|
export let probe_table: [8]u16 = [0u16, 0x0800u16, 0x0801u16, 0x0803u16, 0x1006u16, 0x1009u16, 0x100Du16, 0x1812u16];
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//ww:run-exit 6
|
//ww:run-exit 6
|
||||||
|
package main;
|
||||||
// migrated from test/wcc/915_arr_module_index_run.c: per-element stride pin; 0x1006 mod 256 = 6.
|
// migrated from test/wcc/915_arr_module_index_run.c: per-element stride pin; 0x1006 mod 256 = 6.
|
||||||
package wcmodarr;
|
package wcmodarr;
|
||||||
export let probe_table: [8]u16 = [0u16, 0x0800u16, 0x0801u16, 0x0803u16, 0x1006u16, 0x1009u16, 0x100Du16, 0x1812u16];
|
export let probe_table: [8]u16 = [0u16, 0x0800u16, 0x0801u16, 0x0803u16, 0x1006u16, 0x1009u16, 0x100Du16, 0x1812u16];
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//ww:run-exit 18
|
//ww:run-exit 18
|
||||||
|
package main;
|
||||||
package myf;
|
package myf;
|
||||||
export type pt = struct { x: i32, y: i32 };
|
export type pt = struct { x: i32, y: i32 };
|
||||||
export def P: pt = pt{x=7, y=11};
|
export def P: pt = pt{x=7, y=11};
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//ww:run-exit 7
|
//ww:run-exit 7
|
||||||
|
package main;
|
||||||
package myf;
|
package myf;
|
||||||
export fn helper() i32 = { return 42; };
|
export fn helper() i32 = { return 42; };
|
||||||
package main;
|
package main;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//ww:run-exit 18
|
//ww:run-exit 18
|
||||||
|
package main;
|
||||||
package myf;
|
package myf;
|
||||||
export type pt = struct { x: i32, y: i32 };
|
export type pt = struct { x: i32, y: i32 };
|
||||||
export let L: pt = pt{x=7, y=11};
|
export let L: pt = pt{x=7, y=11};
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//ww:run-exit 42
|
//ww:run-exit 42
|
||||||
|
package main;
|
||||||
package myf;
|
package myf;
|
||||||
export let S: i32 = 42;
|
export let S: i32 = 42;
|
||||||
package main;
|
package main;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//ww:run
|
//ww:run
|
||||||
|
package main;
|
||||||
// migrated from test/wcc/929_match_4arm_cross_module_run.c: 3-arm boundary — arm 2 must reach its body under the shadowed callee.
|
// migrated from test/wcc/929_match_4arm_cross_module_run.c: 3-arm boundary — arm 2 must reach its body under the shadowed callee.
|
||||||
package a;
|
package a;
|
||||||
export type more = void;
|
export type more = void;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//ww:run
|
//ww:run
|
||||||
|
package main;
|
||||||
// migrated from test/wcc/929_match_4arm_cross_module_run.c: mixed variant kinds (i32|str|rune|u8) — the shadowed-resolution fix is not shape-specific.
|
// migrated from test/wcc/929_match_4arm_cross_module_run.c: mixed variant kinds (i32|str|rune|u8) — the shadowed-resolution fix is not shape-specific.
|
||||||
package a;
|
package a;
|
||||||
export fn next(k: i32) (i32 | str | rune | u8) = {
|
export fn next(k: i32) (i32 | str | rune | u8) = {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//ww:run
|
//ww:run
|
||||||
|
package main;
|
||||||
// migrated from test/wcc/929_match_4arm_cross_module_run.c: canonical 4-arm — caller fn `next` shadows callee a.next; every arm body must fire (#31 fnretlookupmod).
|
// migrated from test/wcc/929_match_4arm_cross_module_run.c: canonical 4-arm — caller fn `next` shadows callee a.next; every arm body must fire (#31 fnretlookupmod).
|
||||||
package a;
|
package a;
|
||||||
export type more = void;
|
export type more = void;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//ww:run
|
//ww:run
|
||||||
|
package main;
|
||||||
// migrated from test/wcc/929_match_4arm_cross_module_run.c: reverse arm order — dispatch follows the callee's variant indices, not source order.
|
// migrated from test/wcc/929_match_4arm_cross_module_run.c: reverse arm order — dispatch follows the callee's variant indices, not source order.
|
||||||
package a;
|
package a;
|
||||||
export type more = void;
|
export type more = void;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//ww:run
|
//ww:run
|
||||||
|
package main;
|
||||||
// migrated from test/wcc/929_match_4arm_cross_module_run.c: 5-arm scaling — arms 3 and 4 must each reach their body.
|
// migrated from test/wcc/929_match_4arm_cross_module_run.c: 5-arm scaling — arms 3 and 4 must each reach their body.
|
||||||
package a;
|
package a;
|
||||||
export type more = void;
|
export type more = void;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//ww:run
|
//ww:run
|
||||||
|
package main;
|
||||||
// migrated from test/wcc/929_match_4arm_cross_module_run.c: 6-arm — every arm beyond the caller's variant count was broken, not just arm 2/3.
|
// migrated from test/wcc/929_match_4arm_cross_module_run.c: 6-arm — every arm beyond the caller's variant count was broken, not just arm 2/3.
|
||||||
package a;
|
package a;
|
||||||
export type more = void;
|
export type more = void;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//ww:run
|
//ww:run
|
||||||
|
package main;
|
||||||
// migrated from test/wcc/949_xmod_fnptr_const_run.c: cross-module &cc.fn inside const table + scalar emits the &fn->DATAR reloc (#124); DISTINCT predicates catch a swapped reloc.
|
// migrated from test/wcc/949_xmod_fnptr_const_run.c: cross-module &cc.fn inside const table + scalar emits the &fn->DATAR reloc (#124); DISTINCT predicates catch a swapped reloc.
|
||||||
package cc;
|
package cc;
|
||||||
export fn isa(c: rune) bool = { return c == 'a'; };
|
export fn isa(c: rune) bool = { return c == 'a'; };
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//ww:run-exit 249
|
//ww:run-exit 249
|
||||||
|
package main;
|
||||||
package myf;
|
package myf;
|
||||||
export fn g() f64 = { return -7.0; };
|
export fn g() f64 = { return -7.0; };
|
||||||
package main;
|
package main;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//ww:run-exit 253
|
//ww:run-exit 253
|
||||||
|
package main;
|
||||||
package myf;
|
package myf;
|
||||||
export fn g() f64 = { return -3.9; };
|
export fn g() f64 = { return -3.9; };
|
||||||
package main;
|
package main;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//ww:run-exit 3
|
//ww:run-exit 3
|
||||||
|
package main;
|
||||||
package myf;
|
package myf;
|
||||||
export fn g() f64 = { return 3.9; };
|
export fn g() f64 = { return 3.9; };
|
||||||
package main;
|
package main;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//ww:run-exit 242
|
//ww:run-exit 242
|
||||||
|
package main;
|
||||||
package myf;
|
package myf;
|
||||||
export fn g() f64 = { return -7.0; };
|
export fn g() f64 = { return -7.0; };
|
||||||
package main;
|
package main;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//ww:run-exit 8
|
//ww:run-exit 8
|
||||||
|
package main;
|
||||||
package myf;
|
package myf;
|
||||||
export fn g() f64 = { return -7.0; };
|
export fn g() f64 = { return -7.0; };
|
||||||
package main;
|
package main;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//ww:run
|
//ww:run
|
||||||
|
package main;
|
||||||
package myf;
|
package myf;
|
||||||
export fn frexp(n: f64) (f64, i64) = {
|
export fn frexp(n: f64) (f64, i64) = {
|
||||||
if (n == 0.0) { return (0.0, 0i64); };
|
if (n == 0.0) { return (0.0, 0i64); };
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//ww:run-exit 4
|
//ww:run-exit 4
|
||||||
|
package main;
|
||||||
package myf;
|
package myf;
|
||||||
export fn fs(n: f64) (f64, str) = {
|
export fn fs(n: f64) (f64, str) = {
|
||||||
if (n == 0.0) { return (n, "x"); };
|
if (n == 0.0) { return (n, "x"); };
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//ww:run-exit 15
|
//ww:run-exit 15
|
||||||
|
package main;
|
||||||
package myf;
|
package myf;
|
||||||
export fn addi64(a: i64, b: i64) (i64, bool) = {
|
export fn addi64(a: i64, b: i64) (i64, bool) = {
|
||||||
let s: i64 = a + b;
|
let s: i64 = a + b;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//ww:run-exit 10
|
//ww:run-exit 10
|
||||||
|
package main;
|
||||||
package beta;
|
package beta;
|
||||||
export fn dup() (i64, i64) = { return (3i64, 7i64); };
|
export fn dup() (i64, i64) = { return (3i64, 7i64); };
|
||||||
package main;
|
package main;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//ww:run-exit 42
|
//ww:run-exit 42
|
||||||
|
package main;
|
||||||
package m;
|
package m;
|
||||||
export fn f() i32 = {
|
export fn f() i32 = {
|
||||||
assert(3 > 2, "m.f invariant");
|
assert(3 > 2, "m.f invariant");
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//ww:run-exit 42
|
//ww:run-exit 42
|
||||||
|
package main;
|
||||||
package m;
|
package m;
|
||||||
export fn assert(b: bool, msg: str) void = { };
|
export fn assert(b: bool, msg: str) void = { };
|
||||||
package main;
|
package main;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//ww:run-exit 42
|
//ww:run-exit 42
|
||||||
|
package main;
|
||||||
// Current-module &fn lookup must beat a later same-leaf declaration.
|
// Current-module &fn lookup must beat a later same-leaf declaration.
|
||||||
package beta;
|
package beta;
|
||||||
export type hfn = fn(x: i32) i32;
|
export type hfn = fn(x: i32) i32;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//ww:run-exit 42
|
//ww:run-exit 42
|
||||||
|
package main;
|
||||||
package beta;
|
package beta;
|
||||||
export type berr = !void;
|
export type berr = !void;
|
||||||
export fn op() (i32 | berr) = { return 5; };
|
export fn op() (i32 | berr) = { return 5; };
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//ww:run-exit 42
|
//ww:run-exit 42
|
||||||
|
package main;
|
||||||
package beta;
|
package beta;
|
||||||
export type berr = !void;
|
export type berr = !void;
|
||||||
export fn op() (i32 | berr) = { return 5; };
|
export fn op() (i32 | berr) = { return 5; };
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
// task; until then we exercise polymorphism via ctx pointers, which
|
// task; until then we exercise polymorphism via ctx pointers, which
|
||||||
// is what the real port wants anyway.
|
// is what the real port wants anyway.
|
||||||
|
|
||||||
package test;
|
package main;
|
||||||
|
|
||||||
import os;
|
import os;
|
||||||
import strconv;
|
import strconv;
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ package direnum_test;
|
|||||||
// Both stages must FAIL with "conflicting package names", and the
|
// Both stages must FAIL with "conflicting package names", and the
|
||||||
// two stages' diagnostics must be byte-identical.
|
// two stages' diagnostics must be byte-identical.
|
||||||
//
|
//
|
||||||
// rootorder — a private rootok/ dir built DIRECTLY (z.ww ORDER-Z
|
// rootorder — a private rootok/ command dir built DIRECTLY (z.ww ORDER-Z
|
||||||
// value()=17 vs a.ww ORDER-A leading comment + main): build exit 0,
|
// value()=17 vs a.ww ORDER-A leading comment + main): build exit 0,
|
||||||
// the binary exits 17, and the driver's local-identity owner unit
|
// the binary exits 17, and the driver's local-identity owner unit
|
||||||
// stores ORDER-A strictly before ORDER-Z (byte-sorted deterministic
|
// stores ORDER-A strictly before ORDER-Z (byte-sorted deterministic
|
||||||
@@ -121,14 +121,14 @@ fn rejectpair(label: str, td: str, target: str, needle: str) void = {
|
|||||||
let rootok: str = strings.concat(td, "/rootok");
|
let rootok: str = strings.concat(td, "/rootok");
|
||||||
assert(os.mkdir(rootok, 493) == 0);
|
assert(os.mkdir(rootok, 493) == 0);
|
||||||
testenv.writefile(strings.concat(rootok, "/z.ww"), strings.concat(
|
testenv.writefile(strings.concat(rootok, "/z.ww"), strings.concat(
|
||||||
"package rootok;\n// ORDER-Z\n",
|
"package main;\n// ORDER-Z\n",
|
||||||
"fn value() i32 = { return 17; };\n"));
|
"fn value() i32 = { return 17; };\n"));
|
||||||
testenv.writefile(strings.concat(rootok, "/a.ww"), strings.concat(
|
testenv.writefile(strings.concat(rootok, "/a.ww"), strings.concat(
|
||||||
"// leading comment is part of the loader grammar\n",
|
"// leading comment is part of the loader grammar\n",
|
||||||
"package rootok;\n// ORDER-A\n",
|
"package main;\n// ORDER-A\n",
|
||||||
"fn main() i32 = { return value(); };\n"));
|
"fn main() i32 = { return value(); };\n"));
|
||||||
let drvs: []str = ["ww", "ww_ww"];
|
let drvs: []str = ["ww", "ww_ww"];
|
||||||
let identity: str = testenv.localpackageidentity(rootok, "rootok");
|
let identity: str = testenv.localpackageidentity(rootok, "main");
|
||||||
let units: []str = ["", ""];
|
let units: []str = ["", ""];
|
||||||
let s: i32 = 0;
|
let s: i32 = 0;
|
||||||
for (s < 2) {
|
for (s < 2) {
|
||||||
|
|||||||
Reference in New Issue
Block a user