build: make executable and test roots package actions
This commit is contained in:
246
cmd/ww/main.c
246
cmd/ww/main.c
@@ -322,9 +322,11 @@ source_has_test_decl(const char *path)
|
||||
#define SEP_VARIANT_PRODUCTION 0
|
||||
#define SEP_VARIANT_SAME_TEST 1
|
||||
#define SEP_VARIANT_EXTERNAL 2
|
||||
#define SEP_VARIANT_TEST_MAIN 3
|
||||
#define SEP_ROLE_NORMAL 0
|
||||
#define SEP_ROLE_EXTERNAL_PRODUCTION 1
|
||||
#define SEP_ROLE_TEST_SUPPORT 2
|
||||
#define SEP_ROLE_GENERATED_MAIN 3
|
||||
#define SEP_TEST_SUPPORT_MODULE "__wwtest"
|
||||
#define SEP_MAXPRODUCT 256
|
||||
#define SEP_MAXCONTEXT (SEP_MAXPRODUCT + 1)
|
||||
@@ -508,7 +510,7 @@ enumerate_dir_ww(const char *dirpath, int variant, const char *test_package,
|
||||
#define SEP_MAXPKG 256
|
||||
|
||||
struct seppkg {
|
||||
char path[256]; /* dotted import path; "" == root/primary */
|
||||
char path[256]; /* canonical dotted package identity */
|
||||
char entry[1024]; /* resolved package dir (or file, for a file root) */
|
||||
char canon[1024]; /* canonical location; never package identity */
|
||||
char artifact[64]; /* non-importable product-root artifact key */
|
||||
@@ -519,7 +521,9 @@ struct seppkg {
|
||||
int is_dir;
|
||||
int variant; /* SEP_VARIANT_*; dependencies are production */
|
||||
int role; /* normal, external-production, or test support */
|
||||
int root; /* independently compiled/linkable product root */
|
||||
int root; /* requested package action (possibly a test variant) */
|
||||
int link_entry; /* package supplies the executable's bare main */
|
||||
int generated_main; /* compiler-owned generated test-main package */
|
||||
int failed; /* discovery/compile failure reaches this action */
|
||||
int test_support; /* compiler-generated -T support package */
|
||||
int loaded; /* directory membership/name loaded exactly once */
|
||||
@@ -554,6 +558,7 @@ struct sepproduct {
|
||||
int variant;
|
||||
int context;
|
||||
int root;
|
||||
int variant_root; /* production-plus-test or external test package */
|
||||
};
|
||||
|
||||
#define SEP_MAXLFLAGS 32
|
||||
@@ -591,8 +596,17 @@ sep_find_or_add_variant(struct sepgraph *g, const char *path,
|
||||
if (root && g->pkg[i].root) {
|
||||
if (!same_location) continue;
|
||||
if (variant != g->pkg[i].variant) continue;
|
||||
if (g->pkg[i].role == role
|
||||
&& strcmp(g->pkg[i].path, path) == 0
|
||||
&& strcmp(g->pkg[i].test_package,
|
||||
test_package ? test_package : "") == 0) {
|
||||
/* One canonical directory variant is one compile action,
|
||||
* even when more than one product requests it. */
|
||||
free(canon);
|
||||
return i;
|
||||
}
|
||||
fprintf(stderr,
|
||||
"ww: duplicate package-test root %s\n", entry);
|
||||
"ww: incompatible package-test roots %s\n", entry);
|
||||
free(canon);
|
||||
return -1;
|
||||
}
|
||||
@@ -693,6 +707,8 @@ sep_find_or_add_variant(struct sepgraph *g, const char *path,
|
||||
p->variant = variant;
|
||||
p->role = role;
|
||||
p->root = root;
|
||||
p->link_entry = 0;
|
||||
p->generated_main = 0;
|
||||
p->failed = 0;
|
||||
p->test_support = 0;
|
||||
p->loaded = 0;
|
||||
@@ -1135,6 +1151,62 @@ sep_dep_cmp(const struct sepgraph *g, int a, int b)
|
||||
return strcmp(g->pkg[a].artifact, g->pkg[b].artifact);
|
||||
}
|
||||
|
||||
/* Add the compiler-owned test main as a real package action. Its semantic
|
||||
* identity and artifact key are distinct from every directory variant; its
|
||||
* only dependencies are the selected test variant and dispatcher support. */
|
||||
static int
|
||||
sep_add_generated_main(struct sepgraph *g, struct sepproduct *product,
|
||||
int ordinal, int support)
|
||||
{
|
||||
if (g->n >= SEP_MAXPKG) {
|
||||
fprintf(stderr, "ww: too many packages (limit %d)\n", SEP_MAXPKG);
|
||||
return -1;
|
||||
}
|
||||
int variant = product->variant_root;
|
||||
if (variant < 0 || variant >= g->n) return -1;
|
||||
char variantcanon[sizeof g->pkg[0].canon];
|
||||
char variantentry[sizeof g->pkg[0].entry];
|
||||
snprintf(variantcanon, sizeof variantcanon, "%s", g->pkg[variant].canon);
|
||||
snprintf(variantentry, sizeof variantentry, "%s", g->pkg[variant].entry);
|
||||
struct seppkg *p = &g->pkg[g->n];
|
||||
memset(p, 0, sizeof *p);
|
||||
int pn = snprintf(p->path, sizeof p->path,
|
||||
"__wwtestmain.%03d.main", ordinal);
|
||||
int an = snprintf(p->artifact, sizeof p->artifact,
|
||||
"__ww-test-%03d-main", ordinal);
|
||||
int cn = snprintf(p->canon, sizeof p->canon, "%s#test-main-%03d",
|
||||
variantcanon, ordinal);
|
||||
if (pn < 0 || (size_t)pn >= sizeof p->path
|
||||
|| an < 0 || (size_t)an >= sizeof p->artifact
|
||||
|| cn < 0 || (size_t)cn >= sizeof p->canon) {
|
||||
fprintf(stderr, "ww: generated test-main identity is too long\n");
|
||||
return -1;
|
||||
}
|
||||
snprintf(p->entry, sizeof p->entry, "%s", variantentry);
|
||||
snprintf(p->name, sizeof p->name, "main");
|
||||
p->variant = SEP_VARIANT_TEST_MAIN;
|
||||
p->role = SEP_ROLE_GENERATED_MAIN;
|
||||
p->root = 1;
|
||||
p->link_entry = 1;
|
||||
p->generated_main = 1;
|
||||
p->loaded = 1;
|
||||
p->emit_context = product->context;
|
||||
p->context_state[product->context] = 2;
|
||||
p->deps[p->ndeps++] = variant;
|
||||
if (support >= 0 && support != variant)
|
||||
p->deps[p->ndeps++] = support;
|
||||
for (int i = 1; i < p->ndeps; i++) {
|
||||
int v = p->deps[i];
|
||||
int j = i;
|
||||
while (j > 0 && sep_dep_cmp(g, p->deps[j - 1], v) > 0) {
|
||||
p->deps[j] = p->deps[j - 1];
|
||||
j--;
|
||||
}
|
||||
p->deps[j] = v;
|
||||
}
|
||||
return g->n++;
|
||||
}
|
||||
|
||||
/* Load one canonical package under one selected-root resolution context.
|
||||
* Source membership is owned once, but a shared package's imports are checked
|
||||
* under every context that reaches it. The first canonical binding set owns
|
||||
@@ -1224,10 +1296,11 @@ sep_load_pkg(struct sepgraph *g, int pi, int context)
|
||||
g->pkg[pi].failed = 1;
|
||||
return -1;
|
||||
}
|
||||
/* Give a non-main root its declared identity before recursively loading
|
||||
* dependencies. A back-edge can then reuse the root and reach the normal
|
||||
* cycle detector instead of looking like a location alias. */
|
||||
if (g->pkg[pi].root && g->pkg[pi].path[0] == '\0'
|
||||
/* Give a directory root its declared package identity before recursively
|
||||
* loading dependencies. Explicit raw single-file compiler fixtures retain
|
||||
* their historical anonymous multi-package boundary. */
|
||||
if (g->pkg[pi].root && g->pkg[pi].is_dir
|
||||
&& g->pkg[pi].path[0] == '\0'
|
||||
&& g->pkg[pi].name[0] != '\0') {
|
||||
size_t n = strlen(g->pkg[pi].name);
|
||||
memcpy(g->pkg[pi].path, g->pkg[pi].name, n + 1);
|
||||
@@ -1358,7 +1431,15 @@ sep_compose_unit(struct sepgraph *g, int pi, const char *unitf)
|
||||
return -1;
|
||||
}
|
||||
int bodyrc = 0;
|
||||
if (g->pkg[pi].is_dir) {
|
||||
if (g->pkg[pi].generated_main) {
|
||||
if (fprintf(u, "//ww:module-reset %s\npackage main;\n",
|
||||
g->pkg[pi].path) < 0)
|
||||
bodyrc = -1;
|
||||
for (int i = 0; i < g->pkg[pi].ndeps && bodyrc == 0; i++)
|
||||
if (fprintf(u, "import %s;\n",
|
||||
g->pkg[g->pkg[pi].deps[i]].path) < 0)
|
||||
bodyrc = -1;
|
||||
} else if (g->pkg[pi].is_dir) {
|
||||
for (int i = 0; i < g->pkg[pi].nsources && bodyrc == 0; i++)
|
||||
bodyrc = sep_emit_body(u, g->pkg[pi].sources[i],
|
||||
g->pkg[pi].path);
|
||||
@@ -1536,7 +1617,7 @@ static void
|
||||
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",
|
||||
is_test ? 7 : 6, is_test ? "test" : "build", emit_asm);
|
||||
is_test ? 8 : 7, is_test ? "test" : "build", emit_asm);
|
||||
}
|
||||
|
||||
/* A stale global builder identity invalidates every committed unit voucher in
|
||||
@@ -1574,8 +1655,8 @@ invalidate_workdir_units(const char *scratch)
|
||||
* package universe, compile the dependency-first union once, then link each
|
||||
* root from its own complete reachable archive closure. The dependency-first
|
||||
* producer loop (one `w6c -c -I` per package,
|
||||
* each DEP `.o` wrapped in its own deterministic `.a`), then a
|
||||
* reverse-topo `w6l` of each root `.o` + dep `.a` set + libwwrt.a. Side
|
||||
* each package `.o` wrapped in its own deterministic `.a`), then a
|
||||
* reverse-topo `w6l` of each root `.a` + reachable `.a` set + libwwrt.a. Side
|
||||
* files land in a cold `<stem>.sepwork` dir, or under the persistent
|
||||
* `-w` workdir with content-identity package reuse. */
|
||||
static int
|
||||
@@ -1696,6 +1777,8 @@ build_one_sep_impl(const char *src, int entry_is_dir,
|
||||
if (graphout) *graphout = g;
|
||||
const char *rootpath = package_only && root_identity
|
||||
? root_identity : "";
|
||||
int support_for[SEP_MAXPRODUCT];
|
||||
for (int i = 0; i < nproducts; i++) support_for[i] = -1;
|
||||
for (int i = 0; i < nproducts; i++) {
|
||||
const char *entry = products[i].dir != NULL
|
||||
? products[i].dir : src;
|
||||
@@ -1720,11 +1803,15 @@ build_one_sep_impl(const char *src, int entry_is_dir,
|
||||
entry_is_dir, products[i].variant, products[i].test_package,
|
||||
SEP_ROLE_NORMAL, products[i].artifact, 1);
|
||||
if (products[i].root < 0) return 1;
|
||||
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";
|
||||
/* -T generates a dispatcher whose support qualifier is selected by the
|
||||
* command. Represent that compiler-generated requirement as a direct root
|
||||
* edge. It normally coalesces with an explicit toolchain `import test`;
|
||||
* command. Represent that compiler-generated requirement as a direct edge
|
||||
* of the generated-main action. It normally coalesces with an explicit
|
||||
* toolchain `import test`;
|
||||
* when user source occupies that identity, the reserved graph alias keeps
|
||||
* it distinct. The linker receives the same support archive closure. */
|
||||
if (is_test) {
|
||||
@@ -1770,8 +1857,10 @@ build_one_sep_impl(const char *src, int entry_is_dir,
|
||||
* colocated production node, which is also its support dep. */
|
||||
if (root_is_support
|
||||
&& strcmp(test_support_module, "test") == 0
|
||||
&& products[i].variant != SEP_VARIANT_EXTERNAL)
|
||||
&& products[i].variant != SEP_VARIANT_EXTERNAL) {
|
||||
support_for[i] = root;
|
||||
continue;
|
||||
}
|
||||
int ti;
|
||||
if (strcmp(test_support_module,
|
||||
SEP_TEST_SUPPORT_MODULE) == 0)
|
||||
@@ -1782,19 +1871,27 @@ build_one_sep_impl(const char *src, int entry_is_dir,
|
||||
tdir);
|
||||
if (ti < 0) return 1;
|
||||
g->pkg[ti].test_support = 1;
|
||||
int seen = 0;
|
||||
for (int k = 0; k < g->pkg[root].ndeps; k++)
|
||||
if (g->pkg[root].deps[k] == ti) {
|
||||
seen = 1; break;
|
||||
}
|
||||
if (!seen && g->pkg[root].ndeps < SEP_MAXPKG)
|
||||
g->pkg[root].deps[g->pkg[root].ndeps++] = ti;
|
||||
support_for[i] = ti;
|
||||
}
|
||||
free(tc);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < nproducts; i++) {
|
||||
int root = products[i].root;
|
||||
int root = products[i].variant_root;
|
||||
/* Raw single-file test fixtures are the one retained non-directory
|
||||
* exception: keep compiler-owned test-main synthesis in that action.
|
||||
* Its support export is still an exact direct input. */
|
||||
if (is_test && !entry_is_dir) {
|
||||
int support = support_for[i];
|
||||
if (support >= 0 && support != root) {
|
||||
int seen = 0;
|
||||
for (int k = 0; k < g->pkg[root].ndeps; k++)
|
||||
if (g->pkg[root].deps[k] == support) seen = 1;
|
||||
if (!seen)
|
||||
g->pkg[root].deps[g->pkg[root].ndeps++] = support;
|
||||
}
|
||||
g->pkg[root].link_entry = 1;
|
||||
}
|
||||
if (sep_load_pkg(g, root, products[i].context) < 0) {
|
||||
g->pkg[root].failed = 1;
|
||||
continue;
|
||||
@@ -1808,6 +1905,22 @@ build_one_sep_impl(const char *src, int entry_is_dir,
|
||||
g->pkg[root].failed = 1;
|
||||
}
|
||||
}
|
||||
if (is_test && entry_is_dir) {
|
||||
for (int i = 0; i < nproducts; i++) {
|
||||
int variant = products[i].variant_root;
|
||||
int support = support_for[i];
|
||||
if (support >= 0 && support != variant
|
||||
&& sep_load_pkg(g, support, products[i].context) < 0)
|
||||
g->pkg[variant].failed = 1;
|
||||
int mainpkg = sep_add_generated_main(g, &products[i], i,
|
||||
support);
|
||||
if (mainpkg < 0) return 1;
|
||||
if (g->pkg[variant].failed
|
||||
|| (support >= 0 && g->pkg[support].failed))
|
||||
g->pkg[mainpkg].failed = 1;
|
||||
products[i].root = mainpkg;
|
||||
}
|
||||
}
|
||||
if (sep_validate_artifact_paths(g, scratch) < 0)
|
||||
return 1;
|
||||
int root_package = package_only;
|
||||
@@ -1830,8 +1943,7 @@ build_one_sep_impl(const char *src, int entry_is_dir,
|
||||
for (int pi = 0; pi < g->n; pi++) g->pkg[pi].color = 0;
|
||||
int ignored = 0;
|
||||
if (sep_topo_visit(g, root, order, &ignored, stack, 0) < 0
|
||||
|| sep_validate_module_closure(g, order, ignored,
|
||||
root_package) < 0)
|
||||
|| sep_validate_module_closure(g, order, ignored, 1) < 0)
|
||||
g->pkg[root].failed = 1;
|
||||
}
|
||||
for (int pi = 0; pi < g->n; pi++) g->pkg[pi].color = 0;
|
||||
@@ -1843,11 +1955,6 @@ build_one_sep_impl(const char *src, int entry_is_dir,
|
||||
}
|
||||
}
|
||||
free(stack);
|
||||
if (!root_package)
|
||||
for (int i = 0; i < nproducts; i++)
|
||||
if (g->pkg[products[i].root].path[0] != '\0')
|
||||
g->pkg[products[i].root].path[0] = '\0';
|
||||
|
||||
int any_failed = 0;
|
||||
for (int i = 0; i < nproducts; i++)
|
||||
if (g->pkg[products[i].root].failed) any_failed = 1;
|
||||
@@ -1882,8 +1989,6 @@ build_one_sep_impl(const char *src, int entry_is_dir,
|
||||
const char *cs = warm ? asmnew : asmf;
|
||||
const char *co = warm ? objnew : obj;
|
||||
const char *ca = warm ? anew : apath;
|
||||
int needs_export = !g->pkg[pi].root || root_package;
|
||||
int needs_archive = !g->pkg[pi].root || root_package;
|
||||
if (sep_compose_unit(g, pi, cu) < 0) {
|
||||
g->pkg[pi].failed = 1;
|
||||
any_failed = 1;
|
||||
@@ -1896,9 +2001,9 @@ build_one_sep_impl(const char *src, int entry_is_dir,
|
||||
if (warm && !stale_all && !deps_changed
|
||||
&& file_equal(unitnew, unitf)
|
||||
&& file_is_reg(asmf)
|
||||
&& (!needs_export || file_is_reg(wwi))
|
||||
&& file_is_reg(wwi)
|
||||
&& (emit_asm || (file_size_nonzero(obj)
|
||||
&& (!needs_archive || file_size_nonzero(apath))))) {
|
||||
&& file_size_nonzero(apath)))) {
|
||||
if (unlink(unitnew) != 0) {
|
||||
fprintf(stderr, "ww: cannot remove %s\n",
|
||||
unitnew);
|
||||
@@ -1907,13 +2012,6 @@ build_one_sep_impl(const char *src, int entry_is_dir,
|
||||
}
|
||||
continue;
|
||||
}
|
||||
/* BUG-1 (#69): -I <wwi> is purely the root's UNUSED
|
||||
* `.wwi` output path, but it triggers wwi_emit →
|
||||
* check_exported_type on the root. A terminal binary's
|
||||
* root legitimately has `export fn` over an unexported
|
||||
* LOCAL type (the root is never imported), which the
|
||||
* export-check rejects. Skip -I for the root; its `.wwi`
|
||||
* is never consumed. */
|
||||
size_t cargvcap = (size_t)(12 + 3 * g->pkg[pi].ndeps);
|
||||
char **cargv = calloc(cargvcap, sizeof *cargv);
|
||||
char (*importfiles)[SEP_ARTIFACT_MAX] = NULL;
|
||||
@@ -1930,16 +2028,21 @@ build_one_sep_impl(const char *src, int entry_is_dir,
|
||||
}
|
||||
int cpos = 0;
|
||||
cargv[cpos++] = "w6c";
|
||||
if (!needs_export && is_test && g->pkg[pi].root) {
|
||||
/* #79: the root carries -T under `ww test`
|
||||
* so w6c synthesizes the test main. Deps never
|
||||
* get -T. */
|
||||
if (g->pkg[pi].generated_main
|
||||
|| (is_test && g->pkg[pi].root && !g->pkg[pi].is_dir)) {
|
||||
cargv[cpos++] = "-T";
|
||||
cargv[cpos++] = "--entry";
|
||||
cargv[cpos++] = "--test-support-module";
|
||||
cargv[cpos++] = (char *)test_support_module;
|
||||
} else if (needs_export && g->pkg[pi].test_support) {
|
||||
cargv[cpos++] = "--test-support-module";
|
||||
cargv[cpos++] = (char *)test_support_module;
|
||||
} else {
|
||||
if (is_test && g->pkg[pi].root)
|
||||
cargv[cpos++] = "--test-package";
|
||||
if (g->pkg[pi].link_entry)
|
||||
cargv[cpos++] = "--entry";
|
||||
if (g->pkg[pi].test_support) {
|
||||
cargv[cpos++] = "--test-support-module";
|
||||
cargv[cpos++] = (char *)test_support_module;
|
||||
}
|
||||
}
|
||||
cargv[cpos++] = "-c";
|
||||
for (int k = 0; k < g->pkg[pi].ndeps; k++) {
|
||||
@@ -1950,10 +2053,8 @@ build_one_sep_impl(const char *src, int entry_is_dir,
|
||||
cargv[cpos++] = g->pkg[dj].path;
|
||||
cargv[cpos++] = importfiles[k];
|
||||
}
|
||||
if (needs_export) {
|
||||
cargv[cpos++] = "-I";
|
||||
cargv[cpos++] = (char *)cw;
|
||||
}
|
||||
cargv[cpos++] = "-I";
|
||||
cargv[cpos++] = (char *)cw;
|
||||
cargv[cpos++] = "-o";
|
||||
cargv[cpos++] = (char *)cs;
|
||||
cargv[cpos++] = (char *)cu;
|
||||
@@ -1968,9 +2069,8 @@ build_one_sep_impl(const char *src, int entry_is_dir,
|
||||
any_failed = 1;
|
||||
continue;
|
||||
}
|
||||
if (needs_export)
|
||||
g->pkg[pi].export_changed = !warm
|
||||
|| !file_equal(wwinew, wwi);
|
||||
g->pkg[pi].export_changed = !warm
|
||||
|| !file_equal(wwinew, wwi);
|
||||
if (!emit_asm) {
|
||||
char *aargv[] = {"w6a", "-o", (char *)co,
|
||||
(char *)cs, NULL};
|
||||
@@ -1982,12 +2082,9 @@ build_one_sep_impl(const char *src, int entry_is_dir,
|
||||
continue;
|
||||
}
|
||||
}
|
||||
/* wrap each DEP package's `.o` in its own deterministic `.a`
|
||||
* (5a). The ROOT stays a positional `.o` (force-loaded — it's
|
||||
* the build target, always fully linked), so `main` is defined
|
||||
* before any archive is processed. The link consumes `.o`/`.a`,
|
||||
* never `.wwi`. */
|
||||
if (!emit_asm && needs_archive) {
|
||||
/* Every package action, including executable and generated-test roots,
|
||||
* produces the existing deterministic single-member archive. */
|
||||
if (!emit_asm) {
|
||||
if (archive_o(co, ca) != 0) {
|
||||
fprintf(stderr, "ww: archive failed for %s\n",
|
||||
g->pkg[pi].path[0] ? g->pkg[pi].path : "(root)");
|
||||
@@ -1999,11 +2096,10 @@ build_one_sep_impl(const char *src, int entry_is_dir,
|
||||
/* Commit order: artifacts before the unit that vouches for
|
||||
* them, unit strictly last. */
|
||||
if (warm) {
|
||||
if ((needs_export && rename(wwinew, wwi) != 0)
|
||||
if (rename(wwinew, wwi) != 0
|
||||
|| rename(asmnew, asmf) != 0
|
||||
|| (!emit_asm && rename(objnew, obj) != 0)
|
||||
|| (!emit_asm && needs_archive
|
||||
&& rename(anew, apath) != 0)
|
||||
|| (!emit_asm && rename(anew, apath) != 0)
|
||||
|| rename(unitnew, unitf) != 0) {
|
||||
fprintf(stderr, "ww: cannot commit %s\n",
|
||||
g->pkg[pi].path[0] ? g->pkg[pi].path : "(root)");
|
||||
@@ -2066,10 +2162,10 @@ build_one_sep_impl(const char *src, int entry_is_dir,
|
||||
}
|
||||
|
||||
free(order);
|
||||
/* Each product gets its own reverse-topological closure: root `.o` first,
|
||||
* then every transitively reachable dependency `.a`, then libwwrt.a. A
|
||||
* same-test root already contains its production sources, so its colocated
|
||||
* production archive is omitted without dropping that node's dependencies. */
|
||||
/* Each product gets its own reverse-topological archive closure: root `.a`
|
||||
* first, then every transitively reachable package `.a`, then libwwrt.a. An
|
||||
* internal test variant already contains production sources, so its
|
||||
* colocated production archive is omitted without dropping dependencies. */
|
||||
char rtpaths[2][1024];
|
||||
int nrt = 1;
|
||||
snprintf(rtpaths[0], sizeof rtpaths[0], "%s/libwwrt.a", libdir);
|
||||
@@ -2084,6 +2180,7 @@ build_one_sep_impl(const char *src, int entry_is_dir,
|
||||
int nlibs = linkflags ? linkflags->nlibs : 0;
|
||||
for (int i = 0; i < nproducts; i++) {
|
||||
int root = products[i].root;
|
||||
int variant_root = products[i].variant_root;
|
||||
if (g->pkg[root].failed) { any_failed = 1; continue; }
|
||||
for (int pi = 0; pi < g->n; pi++) g->pkg[pi].color = 0;
|
||||
int *linkorder = calloc((size_t)g->n, sizeof *linkorder);
|
||||
@@ -2110,14 +2207,15 @@ build_one_sep_impl(const char *src, int entry_is_dir,
|
||||
largv[pos++] = (char *)products[i].out;
|
||||
for (int oi = nlink - 1; oi >= 0; oi--) {
|
||||
int pi = linkorder[oi];
|
||||
if (g->pkg[root].variant == SEP_VARIANT_SAME_TEST
|
||||
&& pi != root
|
||||
if (variant_root >= 0
|
||||
&& g->pkg[variant_root].variant == SEP_VARIANT_SAME_TEST
|
||||
&& pi != variant_root
|
||||
&& g->pkg[pi].variant == SEP_VARIANT_PRODUCTION
|
||||
&& g->pkg[pi].role != SEP_ROLE_TEST_SUPPORT
|
||||
&& strcmp(g->pkg[pi].canon, g->pkg[root].canon) == 0)
|
||||
&& strcmp(g->pkg[pi].canon,
|
||||
g->pkg[variant_root].canon) == 0)
|
||||
continue;
|
||||
sep_fname(g, pi, scratch,
|
||||
pi == root ? ".o" : ".a", linkpaths[npath],
|
||||
sep_fname(g, pi, scratch, ".a", linkpaths[npath],
|
||||
sizeof linkpaths[npath]);
|
||||
largv[pos++] = linkpaths[npath++];
|
||||
}
|
||||
@@ -2174,7 +2272,10 @@ build_one_sep(const char *src, int entry_is_dir, const char *root_identity,
|
||||
.artifact = {0},
|
||||
.variant = root_variant,
|
||||
.root = -1,
|
||||
.variant_root = -1,
|
||||
};
|
||||
if (!package_only)
|
||||
snprintf(product.artifact, sizeof product.artifact, "__root");
|
||||
int r = build_one_sep_impl(src, entry_is_dir, root_identity, out, objstem,
|
||||
extra_includes, linkflags, package_only, is_test,
|
||||
&product, 1, emit_asm, workdir, scratch,
|
||||
@@ -2612,6 +2713,7 @@ do_test(int argc, char **argv)
|
||||
products[nproducts].artifact[0] = '\0';
|
||||
products[nproducts].variant = variant;
|
||||
products[nproducts].root = -1;
|
||||
products[nproducts].variant_root = -1;
|
||||
nproducts++;
|
||||
} else if (strcmp(argv[i], "-S") == 0) {
|
||||
emit_asm = 1;
|
||||
|
||||
Reference in New Issue
Block a user