build: make executable and test roots package actions
This commit is contained in:
@@ -447,9 +447,11 @@ fn dirfileattest(dirpath: *u8, name: *u8) i32 = {
|
||||
def SEP_VARIANT_PRODUCTION: i32 = 0;
|
||||
def SEP_VARIANT_SAME_TEST: i32 = 1;
|
||||
def SEP_VARIANT_EXTERNAL: i32 = 2;
|
||||
def SEP_VARIANT_TEST_MAIN: i32 = 3;
|
||||
def SEP_ROLE_NORMAL: i32 = 0;
|
||||
def SEP_ROLE_EXTERNAL_PRODUCTION: i32 = 1;
|
||||
def SEP_ROLE_TEST_SUPPORT: i32 = 2;
|
||||
def SEP_ROLE_GENERATED_MAIN: i32 = 3;
|
||||
def SEP_TEST_SUPPORT_MODULE: str = "__wwtest";
|
||||
def SEP_MAXPRODUCT: i32 = 256;
|
||||
def SEP_MAXCONTEXT: i32 = 257;
|
||||
@@ -757,7 +759,7 @@ type sepbind = struct {
|
||||
};
|
||||
|
||||
type seppkg = struct {
|
||||
path: *u8, // dotted import path, NUL-term; root path[0]==0
|
||||
path: *u8, // canonical dotted package identity, NUL-term
|
||||
entry: *u8, // resolved package dir (or file, file root), NUL-term
|
||||
artifact: *u8, // non-importable product-root artifact key
|
||||
name: *u8, // validated declared name; directory packages only
|
||||
@@ -768,6 +770,8 @@ type seppkg = struct {
|
||||
variant: i32,
|
||||
role: i32,
|
||||
root: bool,
|
||||
linkentry: bool,
|
||||
generatedmain: bool,
|
||||
failed: bool,
|
||||
testsupport: bool,
|
||||
loaded: bool,
|
||||
@@ -802,6 +806,7 @@ type sepproduct = struct {
|
||||
variant: i32,
|
||||
context: i32,
|
||||
root: i32,
|
||||
variantroot: i32,
|
||||
};
|
||||
|
||||
fn sepfindoraddvariant(g: *sepgraph, path: *u8, entry: *u8,
|
||||
@@ -819,7 +824,17 @@ fn sepfindoraddvariant(g: *sepgraph, path: *u8, entry: *u8,
|
||||
if (root && g.pkg[i].root) {
|
||||
if (!samelocation) { i += 1; continue; };
|
||||
if (variant != g.pkg[i].variant) { i += 1; continue; };
|
||||
cerr("ww: duplicate package-test root ");
|
||||
let sametest: bool = testpackage == nil
|
||||
&& g.pkg[i].testpackage == nil;
|
||||
if (testpackage != nil && g.pkg[i].testpackage != nil) {
|
||||
sametest = cstreq(testpackage, g.pkg[i].testpackage);
|
||||
};
|
||||
if (g.pkg[i].role == role && cstreq(g.pkg[i].path, path)
|
||||
&& sametest) {
|
||||
// One directory variant is one compile action across products.
|
||||
return i;
|
||||
};
|
||||
cerr("ww: incompatible package-test roots ");
|
||||
cerr(pathstr(entry)); cerr("\n");
|
||||
return -1;
|
||||
};
|
||||
@@ -923,6 +938,8 @@ fn sepfindoraddvariant(g: *sepgraph, path: *u8, entry: *u8,
|
||||
g.pkg[g.n].variant = variant;
|
||||
g.pkg[g.n].role = role;
|
||||
g.pkg[g.n].root = root;
|
||||
g.pkg[g.n].linkentry = false;
|
||||
g.pkg[g.n].generatedmain = false;
|
||||
g.pkg[g.n].failed = false;
|
||||
g.pkg[g.n].testsupport = false;
|
||||
g.pkg[g.n].loaded = false;
|
||||
@@ -1356,6 +1373,79 @@ fn sepdepcmp(g: *sepgraph, a: i32, b: i32) i32 = {
|
||||
pathstr(g.pkg[b].artifact)): i32;
|
||||
};
|
||||
|
||||
fn generatedmainpath(index: i32) *u8 = {
|
||||
let buf: []u8 = alloc([], 64u64)!;
|
||||
buf.len = 64;
|
||||
let off: u64 = strinto(buf.ptr, 0u64, "__wwtestmain.");
|
||||
buf[off] = (((index / 100) % 10) + 48): u8; off += 1u64;
|
||||
buf[off] = (((index / 10) % 10) + 48): u8; off += 1u64;
|
||||
buf[off] = ((index % 10) + 48): u8; off += 1u64;
|
||||
off = strinto(buf.ptr, off, ".main");
|
||||
cstrseal(buf.ptr, off);
|
||||
return buf.ptr;
|
||||
};
|
||||
|
||||
// Materialize the generated test dispatcher as a normal package action. It
|
||||
// owns a generated source unit and imports exactly its test variant/support.
|
||||
fn sepaddgeneratedmain(g: *sepgraph, product: *sepproduct, ordinal: i32,
|
||||
support: i32) i32 = {
|
||||
if (g.n >= SEP_MAXPKG) {
|
||||
cerr("ww: too many packages\n");
|
||||
return -1;
|
||||
};
|
||||
let variant: i32 = product.variantroot;
|
||||
if (variant < 0 || variant >= g.n) { return -1; };
|
||||
let p: *seppkg = &g.pkg[g.n];
|
||||
p.path = generatedmainpath(ordinal);
|
||||
p.entry = g.pkg[variant].entry;
|
||||
p.artifact = productartifact(ordinal, SEP_VARIANT_TEST_MAIN);
|
||||
p.name = arenadupcstr("main\0".ptr, 4u64);
|
||||
p.testpackage = nil;
|
||||
p.sources = nil;
|
||||
p.nsources = 0;
|
||||
p.isdir = 0;
|
||||
p.variant = SEP_VARIANT_TEST_MAIN;
|
||||
p.role = SEP_ROLE_GENERATED_MAIN;
|
||||
p.root = true;
|
||||
p.linkentry = true;
|
||||
p.generatedmain = true;
|
||||
p.failed = false;
|
||||
p.testsupport = false;
|
||||
p.loaded = true;
|
||||
p.exportchanged = false;
|
||||
p.emitcontext = product.context;
|
||||
let cslot: []u8 = alloc([], SEP_MAXCONTEXT: u64)!;
|
||||
cslot.len = SEP_MAXCONTEXT;
|
||||
p.contextstate = cslot;
|
||||
p.contextstate[product.context] = 2u8;
|
||||
let emptybindings: []sepbind;
|
||||
p.bindings = emptybindings;
|
||||
let dslot: []i32 = alloc([], SEP_MAXPKG: u64)!;
|
||||
dslot.len = SEP_MAXPKG;
|
||||
p.deps = dslot;
|
||||
p.ndeps = 1;
|
||||
p.deps[0] = variant;
|
||||
if (support >= 0 && support != variant) {
|
||||
p.deps[p.ndeps] = support;
|
||||
p.ndeps += 1;
|
||||
};
|
||||
let i: i32 = 1;
|
||||
for (i < p.ndeps) {
|
||||
let v: i32 = p.deps[i];
|
||||
let j: i32 = i;
|
||||
for (j > 0 && sepdepcmp(g, p.deps[j - 1], v) > 0) {
|
||||
p.deps[j] = p.deps[j - 1];
|
||||
j -= 1;
|
||||
};
|
||||
p.deps[j] = v;
|
||||
i += 1;
|
||||
};
|
||||
p.color = 0;
|
||||
let r: i32 = g.n;
|
||||
g.n += 1;
|
||||
return r;
|
||||
};
|
||||
|
||||
// Load pi once: a directory node takes ownership of its sorted production
|
||||
// paths, then every selected-root context verifies the same canonical import
|
||||
// bindings before the package is compiled once.
|
||||
@@ -1450,7 +1540,10 @@ fn seploadpkg(g: *sepgraph, pi: i32, context: i32) i32 = {
|
||||
g.pkg[pi].failed = true;
|
||||
return rc;
|
||||
};
|
||||
if (g.pkg[pi].root && g.pkg[pi].path[0u64] == 0u8
|
||||
// Directory roots acquire their canonical package identity. Explicit raw
|
||||
// single-file compiler fixtures retain their anonymous multi-package reset.
|
||||
if (g.pkg[pi].root && g.pkg[pi].isdir != 0
|
||||
&& g.pkg[pi].path[0u64] == 0u8
|
||||
&& g.pkg[pi].name != nil) {
|
||||
g.pkg[pi].path = arenadupcstr(g.pkg[pi].name,
|
||||
cstrlen(g.pkg[pi].name));
|
||||
@@ -1598,7 +1691,27 @@ fn sepcomposeunit(g: *sepgraph, pi: i32, unitf: *u8) i32 = {
|
||||
return -1;
|
||||
};
|
||||
let bodyrc: i32 = 0;
|
||||
if (g.pkg[pi].isdir != 0) {
|
||||
if (g.pkg[pi].generatedmain) {
|
||||
let head: str = "//ww:module-reset ";
|
||||
let pkg: str = "\npackage main;\n";
|
||||
if (!sepwriteall(u, head.ptr, head.len: u64)
|
||||
|| !sepwriteall(u, g.pkg[pi].path, cstrlen(g.pkg[pi].path))
|
||||
|| !sepwriteall(u, pkg.ptr, pkg.len: u64)) {
|
||||
bodyrc = -1;
|
||||
};
|
||||
let i: i32 = 0;
|
||||
for (i < g.pkg[pi].ndeps && bodyrc == 0) {
|
||||
let pre: str = "import ";
|
||||
let end: str = ";\n";
|
||||
let dep: *u8 = g.pkg[g.pkg[pi].deps[i]].path;
|
||||
if (!sepwriteall(u, pre.ptr, pre.len: u64)
|
||||
|| !sepwriteall(u, dep, cstrlen(dep))
|
||||
|| !sepwriteall(u, end.ptr, end.len: u64)) {
|
||||
bodyrc = -1;
|
||||
};
|
||||
i += 1;
|
||||
};
|
||||
} else { if (g.pkg[pi].isdir != 0) {
|
||||
let i: i32 = 0;
|
||||
for (i < g.pkg[pi].nsources && bodyrc == 0) {
|
||||
bodyrc = sepemitbody(u, g.pkg[pi].sources[i], g.pkg[pi].path);
|
||||
@@ -1606,7 +1719,7 @@ fn sepcomposeunit(g: *sepgraph, pi: i32, unitf: *u8) i32 = {
|
||||
};
|
||||
} else {
|
||||
bodyrc = sepemitbody(u, g.pkg[pi].entry, g.pkg[pi].path);
|
||||
};
|
||||
}; };
|
||||
if (os.close(u) != 0) {
|
||||
cerr("ww: cannot close package unit\n");
|
||||
return -1;
|
||||
@@ -1691,8 +1804,8 @@ fn archiveo(objpath: *u8, apath: *u8) i32 = {
|
||||
|
||||
// buildonesep — discover deps, reverse-topo,
|
||||
// the dependency-first producer loop (one `w6c -c -I` per package,
|
||||
// each dependency `.o` wrapped in its own deterministic per-package `.a`), then a
|
||||
// reverse-topo `w6l` of the root `.o` + dependency `.a` set + libwwrt.a.
|
||||
// each package `.o` wrapped in its own deterministic per-package `.a`), then a
|
||||
// reverse-topo `w6l` of the root `.a` + reachable `.a` set + libwwrt.a.
|
||||
// Side files land in a cold `<stem>.sepwork` scratch dir. Twin of cstage
|
||||
// build_one_sep.
|
||||
|
||||
@@ -1811,14 +1924,14 @@ fn copyfileatomic(src: *u8, dst: *u8) i32 = {
|
||||
fn workdirstamptext(istest: i32, emitasm: i32) str = {
|
||||
if (istest != 0) {
|
||||
if (emitasm != 0) {
|
||||
return "ww workdir fmt 7 mode test asm 1\n";
|
||||
return "ww workdir fmt 8 mode test asm 1\n";
|
||||
};
|
||||
return "ww workdir fmt 7 mode test asm 0\n";
|
||||
return "ww workdir fmt 8 mode test asm 0\n";
|
||||
};
|
||||
if (emitasm != 0) {
|
||||
return "ww workdir fmt 6 mode build asm 1\n";
|
||||
return "ww workdir fmt 7 mode build asm 1\n";
|
||||
};
|
||||
return "ww workdir fmt 6 mode build asm 0\n";
|
||||
return "ww workdir fmt 7 mode build asm 0\n";
|
||||
};
|
||||
|
||||
fn stampmatches(path: *u8, want: str) bool = {
|
||||
@@ -2097,7 +2210,11 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
if (graphout != nil) { *graphout = g; };
|
||||
let rootpath: *u8 = "\0".ptr;
|
||||
if (packageonly != 0 && rootidentity != nil) { rootpath = rootidentity; };
|
||||
let supportfor: []i32 = alloc([], nproducts: u64)!;
|
||||
supportfor.len = nproducts;
|
||||
let producti: i32 = 0;
|
||||
for (producti < nproducts) { supportfor[producti] = -1; producti += 1; };
|
||||
producti = 0;
|
||||
for (producti < nproducts) {
|
||||
let entry: *u8 = src;
|
||||
if (products[producti].dir != nil) {
|
||||
@@ -2113,12 +2230,16 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
products[producti].testpackage,
|
||||
SEP_ROLE_NORMAL, products[producti].artifact, true);
|
||||
if (products[producti].root < 0) { return 1; };
|
||||
products[producti].variantroot = products[producti].root;
|
||||
if (istest == 0 && packageonly == 0) {
|
||||
g.pkg[products[producti].root].linkentry = true;
|
||||
};
|
||||
producti += 1;
|
||||
};
|
||||
let testsupportmodule: str = "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 requirement as a direct generated-main edge. 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 (istest != 0) {
|
||||
@@ -2168,6 +2289,7 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
if (rootissupport
|
||||
&& syntax.streq(testsupportmodule, "test")
|
||||
&& products[producti].variant != SEP_VARIANT_EXTERNAL) {
|
||||
supportfor[producti] = root;
|
||||
producti += 1;
|
||||
continue;
|
||||
};
|
||||
@@ -2181,25 +2303,32 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
};
|
||||
if (ti < 0) { return 1; };
|
||||
g.pkg[ti].testsupport = true;
|
||||
let seen: bool = false;
|
||||
let m: i32 = 0;
|
||||
for (m < g.pkg[root].ndeps) {
|
||||
if (g.pkg[root].deps[m] == ti) { seen = true; };
|
||||
m += 1;
|
||||
};
|
||||
if (!seen) {
|
||||
if (g.pkg[root].ndeps < SEP_MAXPKG) {
|
||||
g.pkg[root].deps[g.pkg[root].ndeps] = ti;
|
||||
g.pkg[root].ndeps += 1;
|
||||
};
|
||||
};
|
||||
supportfor[producti] = ti;
|
||||
producti += 1;
|
||||
};
|
||||
};
|
||||
};
|
||||
producti = 0;
|
||||
for (producti < nproducts) {
|
||||
let root: i32 = products[producti].root;
|
||||
let root: i32 = products[producti].variantroot;
|
||||
// Raw single-file tests retain the explicit fixture exception: test-main
|
||||
// synthesis stays in that action and support remains a direct export.
|
||||
if (istest != 0 && entryisdir == 0) {
|
||||
let support: i32 = supportfor[producti];
|
||||
if (support >= 0 && support != root) {
|
||||
let seen: bool = false;
|
||||
let sk: i32 = 0;
|
||||
for (sk < g.pkg[root].ndeps) {
|
||||
if (g.pkg[root].deps[sk] == support) { seen = true; };
|
||||
sk += 1;
|
||||
};
|
||||
if (!seen) {
|
||||
g.pkg[root].deps[g.pkg[root].ndeps] = support;
|
||||
g.pkg[root].ndeps += 1;
|
||||
};
|
||||
};
|
||||
g.pkg[root].linkentry = true;
|
||||
};
|
||||
if (seploadpkg(g, root, products[producti].context) < 0) {
|
||||
g.pkg[root].failed = true;
|
||||
producti += 1;
|
||||
@@ -2214,6 +2343,27 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
};
|
||||
producti += 1;
|
||||
};
|
||||
if (istest != 0 && entryisdir != 0) {
|
||||
producti = 0;
|
||||
for (producti < nproducts) {
|
||||
let variant: i32 = products[producti].variantroot;
|
||||
let support: i32 = supportfor[producti];
|
||||
if (support >= 0 && support != variant) {
|
||||
if (seploadpkg(g, support, products[producti].context) < 0) {
|
||||
g.pkg[variant].failed = true;
|
||||
};
|
||||
};
|
||||
let mainpkg: i32 = sepaddgeneratedmain(g, &products[producti],
|
||||
producti, support);
|
||||
if (mainpkg < 0) { return 1; };
|
||||
if (g.pkg[variant].failed
|
||||
|| (support >= 0 && g.pkg[support].failed)) {
|
||||
g.pkg[mainpkg].failed = true;
|
||||
};
|
||||
products[producti].root = mainpkg;
|
||||
producti += 1;
|
||||
};
|
||||
};
|
||||
if (sepvalidateartifactpaths(g, scratch) < 0) { return 1; };
|
||||
let rootpackage: bool = packageonly != 0;
|
||||
if (rootpackage && !g.pkg[products[0].root].failed
|
||||
@@ -2239,8 +2389,7 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
let ignored: i32 = 0;
|
||||
if (septopovisit(g, root, order,
|
||||
&ignored, stack, 0) < 0
|
||||
|| sepvalidatemoduleclosure(g, order, ignored,
|
||||
rootpackage) < 0) {
|
||||
|| sepvalidatemoduleclosure(g, order, ignored, true) < 0) {
|
||||
g.pkg[root].failed = true;
|
||||
};
|
||||
};
|
||||
@@ -2257,14 +2406,6 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
};
|
||||
producti += 1;
|
||||
};
|
||||
if (!rootpackage) {
|
||||
producti = 0;
|
||||
for (producti < nproducts) {
|
||||
g.pkg[products[producti].root].path = "\0".ptr;
|
||||
producti += 1;
|
||||
};
|
||||
};
|
||||
|
||||
let anyfailed: bool = false;
|
||||
producti = 0;
|
||||
for (producti < nproducts) {
|
||||
@@ -2307,8 +2448,6 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
cu = unitnew; cw = wwinew; cs = asmnew;
|
||||
co = objnew; ca = anew;
|
||||
};
|
||||
let needsexport: bool = !g.pkg[pi].root || rootpackage;
|
||||
let needsarchive: bool = !g.pkg[pi].root || rootpackage;
|
||||
if (sepcomposeunit(g, pi, cu) < 0) {
|
||||
g.pkg[pi].failed = true;
|
||||
anyfailed = true;
|
||||
@@ -2328,20 +2467,14 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
if (!staleall && !depschanged) {
|
||||
fresh = fileequal(unitnew, unitf);
|
||||
if (fresh) { fresh = fileisreg(asmf); };
|
||||
if (fresh) {
|
||||
if (needsexport) {
|
||||
fresh = fileisreg(wwi);
|
||||
};
|
||||
};
|
||||
if (fresh) { fresh = fileisreg(wwi); };
|
||||
if (fresh) {
|
||||
if (emitasm == 0) {
|
||||
fresh = filesizenonzero(objf);
|
||||
};
|
||||
};
|
||||
if (fresh) {
|
||||
if (emitasm == 0 && needsarchive) {
|
||||
fresh = filesizenonzero(apath);
|
||||
};
|
||||
if (fresh && emitasm == 0) {
|
||||
fresh = filesizenonzero(apath);
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -2355,31 +2488,34 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
continue;
|
||||
};
|
||||
{
|
||||
// BUG-1 (#69): -I <wwi> is purely the root's UNUSED
|
||||
// `.wwi` output path, but it triggers wwiemit ->
|
||||
// checkexportedtype 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. Build a shorter root argv
|
||||
// without the -I/wwi pair; root's `.wwi` is unconsumed.
|
||||
// #79: the root carries -T under `ww test` so w6c
|
||||
// synthesizes the test main; deps never get -T.
|
||||
let roott: bool = g.pkg[pi].root && (istest != 0);
|
||||
let supportt: bool = g.pkg[pi].testsupport;
|
||||
let rawtest: bool = (istest != 0) && g.pkg[pi].root
|
||||
&& g.pkg[pi].isdir == 0;
|
||||
let gent: bool = g.pkg[pi].generatedmain || rawtest;
|
||||
let testpkg: bool = g.pkg[pi].root && (istest != 0) && !gent;
|
||||
let entry: bool = g.pkg[pi].linkentry;
|
||||
let supportpkg: bool = g.pkg[pi].testsupport;
|
||||
let alen: u64 = 8u64;
|
||||
if (!needsexport) { alen = 6u64; if (roott) { alen = 9u64; }; };
|
||||
if (supportt) { alen += 2u64; };
|
||||
if (gent) { alen += 4u64; }
|
||||
else {
|
||||
if (testpkg) { alen += 1u64; };
|
||||
if (entry) { alen += 1u64; };
|
||||
if (supportpkg) { alen += 2u64; };
|
||||
};
|
||||
alen += (g.pkg[pi].ndeps: u64) * 3u64;
|
||||
let argv: []str = alloc([], alen)!;
|
||||
append(argv, "w6c");
|
||||
if (roott) {
|
||||
if (gent) {
|
||||
append(argv, "-T");
|
||||
append(argv, "--entry");
|
||||
append(argv, "--test-support-module");
|
||||
append(argv, testsupportmodule);
|
||||
};
|
||||
if (supportt) {
|
||||
append(argv, "--test-support-module");
|
||||
append(argv, testsupportmodule);
|
||||
} else {
|
||||
if (testpkg) { append(argv, "--test-package"); };
|
||||
if (entry) { append(argv, "--entry"); };
|
||||
if (supportpkg) {
|
||||
append(argv, "--test-support-module");
|
||||
append(argv, testsupportmodule);
|
||||
};
|
||||
};
|
||||
append(argv, "-c");
|
||||
let importk: i32 = 0;
|
||||
@@ -2390,10 +2526,8 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
append(argv, pathstr(sepfname(g, dj, scratch, ".wwi")));
|
||||
importk += 1;
|
||||
};
|
||||
if (needsexport) {
|
||||
append(argv, "-I");
|
||||
append(argv, pathstr(cw));
|
||||
};
|
||||
append(argv, "-I");
|
||||
append(argv, pathstr(cw));
|
||||
append(argv, "-o");
|
||||
append(argv, pathstr(cs));
|
||||
append(argv, pathstr(cu));
|
||||
@@ -2418,10 +2552,8 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
continue;
|
||||
};
|
||||
};
|
||||
if (needsexport) {
|
||||
if (!warm || !fileequal(wwinew, wwi)) {
|
||||
g.pkg[pi].exportchanged = true;
|
||||
};
|
||||
if (!warm || !fileequal(wwinew, wwi)) {
|
||||
g.pkg[pi].exportchanged = true;
|
||||
};
|
||||
if (emitasm == 0) {
|
||||
let argv: []str = alloc([], 4u64)!;
|
||||
@@ -2450,12 +2582,9 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
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), so `main` is defined before any archive is
|
||||
// processed. The link
|
||||
// consumes `.o`/`.a`, never `.wwi`.
|
||||
if (emitasm == 0 && needsarchive) {
|
||||
// Every package action, including executable/generated roots, produces
|
||||
// the existing deterministic single-member archive.
|
||||
if (emitasm == 0) {
|
||||
if (archiveo(co, ca) != 0) {
|
||||
cerr("ww: archive failed\n");
|
||||
g.pkg[pi].failed = true;
|
||||
@@ -2468,10 +2597,8 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
// them, unit strictly last.
|
||||
if (warm) {
|
||||
let bad: bool = false;
|
||||
if (needsexport) {
|
||||
if (os.rename(pathstr(wwinew), pathstr(wwi)) != 0) {
|
||||
bad = true;
|
||||
};
|
||||
if (os.rename(pathstr(wwinew), pathstr(wwi)) != 0) {
|
||||
bad = true;
|
||||
};
|
||||
if (!bad) {
|
||||
if (os.rename(pathstr(asmnew), pathstr(asmf)) != 0) {
|
||||
@@ -2486,7 +2613,7 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
};
|
||||
};
|
||||
if (!bad) {
|
||||
if (emitasm == 0 && needsarchive) {
|
||||
if (emitasm == 0) {
|
||||
if (os.rename(pathstr(anew), pathstr(apath)) != 0) {
|
||||
bad = true;
|
||||
};
|
||||
@@ -2573,6 +2700,7 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
producti = 0;
|
||||
for (producti < nproducts) {
|
||||
let root: i32 = products[producti].root;
|
||||
let variantroot: i32 = products[producti].variantroot;
|
||||
if (g.pkg[root].failed) {
|
||||
anyfailed = true;
|
||||
producti += 1;
|
||||
@@ -2598,18 +2726,17 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
let li: i32 = nlink - 1;
|
||||
for (li >= 0) {
|
||||
let pi: i32 = linkorder[li];
|
||||
if (g.pkg[root].variant == SEP_VARIANT_SAME_TEST
|
||||
&& pi != root
|
||||
if (variantroot >= 0
|
||||
&& g.pkg[variantroot].variant == SEP_VARIANT_SAME_TEST
|
||||
&& pi != variantroot
|
||||
&& g.pkg[pi].variant == SEP_VARIANT_PRODUCTION
|
||||
&& g.pkg[pi].role != SEP_ROLE_TEST_SUPPORT
|
||||
&& os.samefile(pathstr(g.pkg[pi].entry),
|
||||
pathstr(g.pkg[root].entry))) {
|
||||
pathstr(g.pkg[variantroot].entry))) {
|
||||
li -= 1;
|
||||
continue;
|
||||
};
|
||||
let suf: str = ".a";
|
||||
if (pi == root) { suf = ".o"; };
|
||||
largv[pos] = sepfname(g, pi, scratch, suf);
|
||||
largv[pos] = sepfname(g, pi, scratch, ".a");
|
||||
pos += 1;
|
||||
li -= 1;
|
||||
};
|
||||
@@ -2694,8 +2821,10 @@ fn buildonesep(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
product.testpackage = testpackage;
|
||||
product.status = nil;
|
||||
product.artifact = nil;
|
||||
if (packageonly == 0) { product.artifact = "__root\0".ptr; };
|
||||
product.variant = rootvariant;
|
||||
product.root = -1;
|
||||
product.variantroot = -1;
|
||||
let r: i32 = buildonesepimpl(selfdir, src, entryisdir, rootidentity,
|
||||
out, objstem,
|
||||
incs, lf, packageonly, istest, &product, 1,
|
||||
@@ -2755,9 +2884,11 @@ fn productartifact(index: i32, variant: i32) *u8 = {
|
||||
off = byteinto(buf.ptr, off, '-': u8);
|
||||
if (variant == SEP_VARIANT_SAME_TEST) {
|
||||
off = strinto(buf.ptr, off, "same");
|
||||
} else { if (variant == SEP_VARIANT_TEST_MAIN) {
|
||||
off = strinto(buf.ptr, off, "main");
|
||||
} else {
|
||||
off = strinto(buf.ptr, off, "external");
|
||||
};
|
||||
}; };
|
||||
cstrseal(buf.ptr, off);
|
||||
return buf.ptr;
|
||||
};
|
||||
@@ -3446,6 +3577,7 @@ fn dotest(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
|
||||
product.artifact = nil;
|
||||
product.variant = variant;
|
||||
product.root = -1;
|
||||
product.variantroot = -1;
|
||||
append(products, product);
|
||||
i += 6;
|
||||
continue;
|
||||
|
||||
Reference in New Issue
Block a user