ww build: honor output directories
This commit is contained in:
@@ -1465,6 +1465,7 @@ type seppkg = struct {
|
||||
generatedtargets: []i32,
|
||||
ngeneratedtargets: i32,
|
||||
failed: bool,
|
||||
action: bool, // reached by this request's semantic action list
|
||||
testsupport: bool,
|
||||
loaded: bool,
|
||||
exportchanged: bool,
|
||||
@@ -1513,6 +1514,7 @@ type sepproduct = struct {
|
||||
variant: i32,
|
||||
directoryproduct: bool,
|
||||
notests: bool,
|
||||
buildaction: bool, // loaded product retained in the action list
|
||||
context: i32,
|
||||
root: i32,
|
||||
variantroot: i32,
|
||||
@@ -2973,6 +2975,7 @@ fn sepfindoraddvariant(g: *sepgraph, path: *u8, entry: *u8,
|
||||
g.pkg[g.n].generatedtargets = emptytargets;
|
||||
g.pkg[g.n].ngeneratedtargets = 0;
|
||||
g.pkg[g.n].failed = false;
|
||||
g.pkg[g.n].action = false;
|
||||
g.pkg[g.n].testsupport = false;
|
||||
g.pkg[g.n].loaded = false;
|
||||
g.pkg[g.n].exportchanged = false;
|
||||
@@ -3537,7 +3540,9 @@ fn sepfname(g: *sepgraph, pi: i32, scratch: *u8, suffix: str) *u8 = {
|
||||
fn sepvalidateartifactpaths(g: *sepgraph, scratch: *u8) i32 = {
|
||||
let i: i32 = 0;
|
||||
for (i < g.n) {
|
||||
if (g.pkg[i].failed || !g.pkg[i].loaded) { i += 1; continue; };
|
||||
if (g.pkg[i].failed || !g.pkg[i].loaded || !g.pkg[i].action) {
|
||||
i += 1; continue;
|
||||
};
|
||||
if (g.pkg[i].storage == nil
|
||||
&& sepassignstorage(&g.pkg[i], scratch) < 0) { return -1; };
|
||||
i += 1;
|
||||
@@ -3547,10 +3552,12 @@ fn sepvalidateartifactpaths(g: *sepgraph, scratch: *u8) i32 = {
|
||||
changed = false;
|
||||
i = 0;
|
||||
for (i < g.n && !changed) {
|
||||
if (g.pkg[i].failed || !g.pkg[i].loaded) { i += 1; continue; };
|
||||
if (g.pkg[i].failed || !g.pkg[i].loaded || !g.pkg[i].action) {
|
||||
i += 1; continue;
|
||||
};
|
||||
let j: i32 = i + 1;
|
||||
for (j < g.n) {
|
||||
if (g.pkg[j].failed || !g.pkg[j].loaded
|
||||
if (g.pkg[j].failed || !g.pkg[j].loaded || !g.pkg[j].action
|
||||
|| !cstreq(g.pkg[i].storage, g.pkg[j].storage)) {
|
||||
j += 1; continue;
|
||||
};
|
||||
@@ -4350,6 +4357,7 @@ fn sepaddgeneratedmain(g: *sepgraph, product: *sepproduct, ordinal: i32,
|
||||
ti += 1;
|
||||
};
|
||||
p.failed = false;
|
||||
p.action = false;
|
||||
p.testsupport = false;
|
||||
p.loaded = true;
|
||||
p.exportchanged = false;
|
||||
@@ -4473,6 +4481,7 @@ fn sepclonefortest(g: *sepgraph, original: i32, owner: *u8,
|
||||
p.generatedtargets = emptytargets;
|
||||
p.ngeneratedtargets = 0;
|
||||
p.failed = src.failed;
|
||||
p.action = false;
|
||||
p.testsupport = src.testsupport;
|
||||
p.loaded = src.loaded;
|
||||
p.exportchanged = false;
|
||||
@@ -4501,6 +4510,15 @@ fn sepclonefortest(g: *sepgraph, original: i32, owner: *u8,
|
||||
seppkgfreeowned(&p);
|
||||
return -1;
|
||||
};
|
||||
// A test copy is product-scoped even when its replaced source node is not
|
||||
// in the final action closure. Preserve the complete-action locator without
|
||||
// relying on a storage collision with that inactive source node.
|
||||
p.storage = sepstoragedigest(&p);
|
||||
p.storagehashed = true;
|
||||
if (p.storage == nil) {
|
||||
seppkgfreeowned(&p);
|
||||
return -1;
|
||||
};
|
||||
|
||||
if (src.nsources > 0) {
|
||||
let sources: []*u8;
|
||||
@@ -5856,7 +5874,7 @@ fn sepvalidateunitowner(g: *sepgraph, pi: i32, scratch: *u8) i32 = {
|
||||
fn sepvalidateworkdirowners(g: *sepgraph, scratch: *u8) i32 = {
|
||||
let i: i32 = 0;
|
||||
for (i < g.n) {
|
||||
if (!g.pkg[i].failed && g.pkg[i].loaded
|
||||
if (!g.pkg[i].failed && g.pkg[i].loaded && g.pkg[i].action
|
||||
&& sepvalidateunitowner(g, i, scratch) < 0) { return -1; };
|
||||
i += 1;
|
||||
};
|
||||
@@ -6035,7 +6053,7 @@ fn sepvalidaterequeststaging(g: *sepgraph, scratch: *u8, warm: bool,
|
||||
".a.new", ".init.unit.new", ".init.s.new", ".init.o.new"];
|
||||
let pi: i32 = 0;
|
||||
for (pi < g.n) {
|
||||
if (!g.pkg[pi].failed && g.pkg[pi].loaded) {
|
||||
if (!g.pkg[pi].failed && g.pkg[pi].loaded && g.pkg[pi].action) {
|
||||
let si: i32 = 0;
|
||||
for (si < suffix.len) {
|
||||
let path: *u8 = sepfname(g, pi, scratch, suffix[si]);
|
||||
@@ -6437,6 +6455,7 @@ fn sepdiscardrequeststaging(g: *sepgraph, scratch: *u8, warm: bool,
|
||||
let rc: i32 = 0;
|
||||
let pi: i32 = 0;
|
||||
for (pi < g.n) {
|
||||
if (!g.pkg[pi].action) { pi += 1; continue; };
|
||||
let si: i32 = 0;
|
||||
for (si < suffix.len) {
|
||||
let path: *u8 = sepfname(g, pi, scratch, suffix[si]);
|
||||
@@ -6941,10 +6960,12 @@ fn sepfinishrequest(selfdir: *u8, l6: *u8, c6: *u8, a6: *u8,
|
||||
};
|
||||
|
||||
fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
out: *u8, objstem: *u8, incs: *u8, lf: *lflags,
|
||||
publishpackage: i32, requirecommand: i32, istest: i32,
|
||||
products: *sepproduct, nproducts: i32, emitasm: i32,
|
||||
workdir: *u8, createworkdir: bool, createoutputdir: *u8,
|
||||
out: *u8, objstem: *u8, incs: *u8, lf: *lflags,
|
||||
publishpackage: i32, requirecommand: i32, istest: i32,
|
||||
products: *sepproduct, nproducts: i32, emitasm: i32,
|
||||
workdir: *u8, createworkdir: bool, createoutputdir: *u8,
|
||||
defaultoutputdir: *u8, outputpatherror: bool,
|
||||
outputcollisionbase: *u8, outputcollisiondir: *u8,
|
||||
scratchout: **u8,
|
||||
graphout: **sepgraph) i32 = {
|
||||
sepfatalallocation = false;
|
||||
@@ -7511,9 +7532,6 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
let rootpackage: bool = istest == 0 && nproducts == 1
|
||||
&& !g.pkg[products[0].root].failed
|
||||
&& !seprootiscommand(&g.pkg[products[0].root]);
|
||||
if (sepvalidateartifactpaths(g, scratch) < 0) { return 1; };
|
||||
if (warm && workdirexists
|
||||
&& sepvalidateworkdirowners(g, scratch) < 0) { return 1; };
|
||||
let ci: i32 = 0;
|
||||
let order: []i32;
|
||||
let stack: []i32;
|
||||
@@ -7572,6 +7590,22 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
return 1;
|
||||
};
|
||||
};
|
||||
if (istest == 0 && createoutputdir != nil) {
|
||||
let actions: i32 = 0;
|
||||
producti = 0;
|
||||
for (producti < nproducts) {
|
||||
let root: i32 = products[producti].root;
|
||||
if (g.pkg[root].failed) { return 1; };
|
||||
products[producti].buildaction =
|
||||
seprootiscommand(&g.pkg[root]);
|
||||
if (products[producti].buildaction) { actions += 1; };
|
||||
producti += 1;
|
||||
};
|
||||
if (actions == 0) {
|
||||
cerr("ww: no main packages to build\n");
|
||||
return 1;
|
||||
};
|
||||
};
|
||||
if (!g.pkg[products[0].root].failed
|
||||
&& rootpackage && publishpackage != 0 && emitasm == 0
|
||||
&& validatepackageoutputpath(out) < 0) { return 1; };
|
||||
@@ -7580,12 +7614,25 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
producti = 0;
|
||||
for (producti < nproducts) {
|
||||
let root: i32 = products[producti].root;
|
||||
if (!g.pkg[root].failed) {
|
||||
if (products[producti].buildaction && !g.pkg[root].failed) {
|
||||
if (septopovisit(g, root, order,
|
||||
&norder, stack, 0) < 0) { return 1; };
|
||||
};
|
||||
producti += 1;
|
||||
};
|
||||
let actionpi: i32 = 0;
|
||||
for (actionpi < g.n) {
|
||||
g.pkg[actionpi].action = false;
|
||||
actionpi += 1;
|
||||
};
|
||||
let actionoi: i32 = 0;
|
||||
for (actionoi < norder) {
|
||||
g.pkg[order[actionoi]].action = true;
|
||||
actionoi += 1;
|
||||
};
|
||||
if (sepvalidateartifactpaths(g, scratch) < 0) { return 1; };
|
||||
if (warm && workdirexists
|
||||
&& sepvalidateworkdirowners(g, scratch) < 0) { return 1; };
|
||||
// Propagate already-known package-load failures before scratch or status
|
||||
// acquisition. Good sibling roots may remain viable for deterministic
|
||||
// staging/diagnosis, but any failure rejects publication; an entirely failed
|
||||
@@ -7605,12 +7652,31 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
let viableproduct: bool = false;
|
||||
producti = 0;
|
||||
for (producti < nproducts) {
|
||||
if (!g.pkg[products[producti].root].failed) {
|
||||
if (products[producti].buildaction
|
||||
&& !g.pkg[products[producti].root].failed) {
|
||||
viableproduct = true;
|
||||
};
|
||||
producti += 1;
|
||||
};
|
||||
if (!viableproduct) { return 1; };
|
||||
if (istest == 0 && emitasm == 0 && outputpatherror) {
|
||||
cerr("ww: command output path is too long\n");
|
||||
return 1;
|
||||
};
|
||||
if (istest == 0 && emitasm == 0 && outputcollisionbase != nil) {
|
||||
cerr("ww: multiple commands produce output basename ");
|
||||
sepputquoted(outputcollisionbase);
|
||||
cerr(" in directory ");
|
||||
sepputquoted(outputcollisiondir);
|
||||
cerr("\n");
|
||||
return 1;
|
||||
};
|
||||
if (istest == 0 && emitasm == 0 && defaultoutputdir != nil && nproducts == 1
|
||||
&& seprootiscommand(&g.pkg[products[0].root])) {
|
||||
cerrpath("ww: build output \"", defaultoutputdir,
|
||||
"\" already exists and is a directory\n");
|
||||
return 1;
|
||||
};
|
||||
if (sepvalidaterequeststaging(g, scratch, warm, products, nproducts,
|
||||
rootpackage, publishpackage, emitasm, istest) < 0) {
|
||||
sepfreeproductstaging(products, nproducts);
|
||||
@@ -7622,10 +7688,8 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
let createdwork: sepcreateddirs;
|
||||
createdoutput.n = 0;
|
||||
createdwork.n = 0;
|
||||
let outputmode: i32 = 448;
|
||||
if (istest != 0) { outputmode = 511; };
|
||||
if (createoutputdir != nil
|
||||
&& sepmkdirsrecord(createoutputdir, outputmode, &createdoutput) != 0) {
|
||||
if (emitasm == 0 && createoutputdir != nil
|
||||
&& sepmkdirsrecord(createoutputdir, 511, &createdoutput) != 0) {
|
||||
if (istest != 0) {
|
||||
cerrpath("ww: cannot create test output directory ",
|
||||
createoutputdir, "\n");
|
||||
@@ -8149,7 +8213,8 @@ fn buildonesep(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
objstem: *u8, incs: *u8, lf: *lflags, publishpackage: i32,
|
||||
requirecommand: i32, istest: i32,
|
||||
rootvariant: i32, testpackage: *u8, emitasm: i32,
|
||||
keepscratch: i32, workdir: *u8) i32 = {
|
||||
keepscratch: i32, workdir: *u8, createoutputdir: *u8,
|
||||
defaultoutputdir: *u8, outputpatherror: bool) i32 = {
|
||||
let scratch: *u8 = nil;
|
||||
let g: *sepgraph = nil;
|
||||
let product: sepproduct;
|
||||
@@ -8169,12 +8234,15 @@ fn buildonesep(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
product.variant = rootvariant;
|
||||
product.directoryproduct = false;
|
||||
product.notests = false;
|
||||
product.buildaction = true;
|
||||
product.root = -1;
|
||||
product.variantroot = -1;
|
||||
product.support = -1;
|
||||
let r: i32 = buildonesepimpl(selfdir, src, entryisdir, out, objstem,
|
||||
incs, lf, publishpackage, requirecommand, istest, &product, 1,
|
||||
emitasm, workdir, false, nil, &scratch, &g);
|
||||
emitasm, workdir, false, createoutputdir, defaultoutputdir,
|
||||
outputpatherror, nil, nil,
|
||||
&scratch, &g);
|
||||
sepgraphfree(g);
|
||||
if (keepscratch == 0 && scratch != nil) {
|
||||
if (cstrendswithlit(scratch, ".sepwork")) {
|
||||
@@ -8205,7 +8273,9 @@ fn buildonesep(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
fn buildpackagetests(selfdir: *u8, src: *u8, rootidentity: *u8,
|
||||
incs: *u8, workdir: *u8, products: *sepproduct, nproducts: i32,
|
||||
istest: i32, publishpackage: i32, lf: *lflags, emitasm: i32,
|
||||
createworkdir: bool, createoutputdir: *u8) i32 = {
|
||||
createworkdir: bool, createoutputdir: *u8, defaultoutputdir: *u8,
|
||||
outputpatherror: bool, outputcollisionbase: *u8,
|
||||
outputcollisiondir: *u8) i32 = {
|
||||
let scratch: *u8 = nil;
|
||||
let g: *sepgraph = nil;
|
||||
let i: i32 = 0;
|
||||
@@ -8217,7 +8287,8 @@ fn buildpackagetests(selfdir: *u8, src: *u8, rootidentity: *u8,
|
||||
products[0].out, products[0].out, incs, lf,
|
||||
publishpackage, 0, istest,
|
||||
products, nproducts, emitasm, workdir, createworkdir,
|
||||
createoutputdir, &scratch, &g);
|
||||
createoutputdir, defaultoutputdir, outputpatherror,
|
||||
outputcollisionbase, outputcollisiondir, &scratch, &g);
|
||||
sepgraphfree(g);
|
||||
return r;
|
||||
};
|
||||
@@ -8313,7 +8384,7 @@ fn resolvemodule(selfdir: *u8, name: *u8, incs: *u8, isdir: *i32) *u8 = {
|
||||
};
|
||||
|
||||
fn writeusage(fd: i32) void = {
|
||||
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 local package graphs\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 eligible package under lib, recursively\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|DIR] [path ...] build local package graphs\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 FILE publishes a non-main archive FILE + FILE.wwi\n -o DIR publishes each selected command beneath DIR\n lib/... every eligible package under lib, recursively\n . build the cwd's <basename>.ww\n";
|
||||
os.write(fd, s.ptr, s.len: u64);
|
||||
};
|
||||
|
||||
@@ -8352,6 +8423,54 @@ fn defaultoutpath(src: *u8) *u8 = {
|
||||
return out.ptr;
|
||||
};
|
||||
|
||||
// Go's build -o directory branch follows an existing destination through
|
||||
// stat, and a trailing platform separator declares a directory which the
|
||||
// request may need to create. WW's platform separator is '/'.
|
||||
fn buildoutputdir(path: *u8) bool = {
|
||||
if (cstrendswithlit(path, "/")) { return true; };
|
||||
let fi: os.filestat;
|
||||
match (os.stat(&fi, pathstr(path))) {
|
||||
case void => {
|
||||
let typ: u32 = (fi.mode: u32) & 61440u32;
|
||||
return typ == os.mode.DIR: u32;
|
||||
};
|
||||
case let e: os.oserror => return false;
|
||||
};
|
||||
};
|
||||
|
||||
fn buildoutputpath(dir: *u8, src: *u8) *u8 = {
|
||||
let base: *u8 = defaultoutpath(src);
|
||||
let need: u64 = 0u64;
|
||||
if (!sepaddbytes(&need, cstrlen(dir))
|
||||
|| (!cstrendswithlit(dir, "/") && !sepaddbytes(&need, 1u64))
|
||||
|| !sepaddbytes(&need, cstrlen(base))
|
||||
|| !sepaddbytes(&need, 1u64)
|
||||
|| need > os.PATH_MAX: u64) {
|
||||
return nil;
|
||||
};
|
||||
if (cstrendswithlit(dir, "/")) {
|
||||
return sepappendlit(dir, pathstr(base));
|
||||
};
|
||||
return sepjoinpath(dir, base);
|
||||
};
|
||||
|
||||
fn defaultimportoutpath(identity: *u8) *u8 = {
|
||||
let n: u64 = cstrlen(identity);
|
||||
let start: u64 = 0u64;
|
||||
let i: u64 = 0u64;
|
||||
for (i < n) {
|
||||
if (identity[i] == 46u8) { start = i + 1u64; };
|
||||
i += 1u64;
|
||||
};
|
||||
let out: []u8 = alloc([], (os.PATH_MAX: u64))!;
|
||||
out.len = os.PATH_MAX;
|
||||
let off: u64 = 0u64;
|
||||
i = start;
|
||||
for (i < n) { out[off] = identity[i]; off += 1u64; i += 1u64; };
|
||||
cstrseal(out.ptr, off);
|
||||
return out.ptr;
|
||||
};
|
||||
|
||||
fn dobuild(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
|
||||
let src: *u8 = nil;
|
||||
let srcindex: i32 = -1;
|
||||
@@ -8504,11 +8623,34 @@ fn dobuild(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
|
||||
let objstem: *u8 = nil;
|
||||
let discardoutput: bool = outflag != nil
|
||||
&& cstreqlit(outflag, "/dev/null");
|
||||
let outputdir: bool = outflag != nil && outflag[0u64] != 0u8
|
||||
&& !discardoutput && buildoutputdir(outflag);
|
||||
let rootidentity: *u8 = nil;
|
||||
if (!requestedliteral && isdir != 0) { rootidentity = src; };
|
||||
if (outputdir && isdir != 0) {
|
||||
let coordinatortarget: *u8 = resolved;
|
||||
if (srcindex < 0) { coordinatortarget = nil; };
|
||||
return execpackagetests(selfdir, argv, argc, start, srcindex,
|
||||
coordinatortarget, rootidentity, srcindex < 0, true);
|
||||
};
|
||||
let createoutputdir: *u8 = nil;
|
||||
let outputpatherror: bool = false;
|
||||
if (outflag != nil && outflag[0u64] != 0u8 && !discardoutput) {
|
||||
// -o sets both the binary path and the intermediate stem so
|
||||
// artifacts land beside the requested output (T3).
|
||||
out = outflag;
|
||||
objstem = outflag;
|
||||
if (outputdir) {
|
||||
out = buildoutputpath(outflag, resolved);
|
||||
if (out == nil) {
|
||||
outputpatherror = true;
|
||||
out = defaultoutpath(resolved);
|
||||
};
|
||||
createoutputdir = outflag;
|
||||
} else {
|
||||
out = outflag;
|
||||
};
|
||||
objstem = out;
|
||||
} else { if (isdir != 0 && rootidentity != nil) {
|
||||
out = defaultimportoutpath(rootidentity);
|
||||
} else { if (isdir != 0) {
|
||||
let rlen: u64 = cstrlen(resolved);
|
||||
for (rlen > 1u64) {
|
||||
@@ -8525,14 +8667,16 @@ fn dobuild(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
|
||||
cstrseal(out, off);
|
||||
} else {
|
||||
out = defaultoutpath(resolved);
|
||||
}; };
|
||||
}; }; };
|
||||
let defaultoutputdir: *u8 = nil;
|
||||
if ((outflag == nil || outflag[0u64] == 0u8) && buildoutputdir(out)) {
|
||||
defaultoutputdir = out;
|
||||
};
|
||||
let lf: lflags;
|
||||
lf.libdirs = &libdirs[0];
|
||||
lf.nlibdirs = nlibdirs;
|
||||
lf.libs = &libs[0];
|
||||
lf.nlibs = nlibs;
|
||||
let rootidentity: *u8 = nil;
|
||||
if (!requestedliteral && isdir != 0) { rootidentity = src; };
|
||||
if (discardoutput) {
|
||||
let tmp: []u8 = alloc([], (os.PATH_MAX: u64))!;
|
||||
tmp.len = os.PATH_MAX;
|
||||
@@ -8547,7 +8691,7 @@ fn dobuild(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
|
||||
let rc: i32 = buildonesep(selfdir, resolved, isdir, rootidentity,
|
||||
outp, outp, incs.ptr, &lf,
|
||||
0i32, 0i32, 0i32, SEP_VARIANT_PRODUCTION, nil,
|
||||
emitasm, 0i32, workdir);
|
||||
emitasm, 0i32, workdir, nil, nil, false);
|
||||
let cleanbad: bool = false;
|
||||
let cleanrc: i32 = os.remove(pathstr(outp));
|
||||
if (cleanrc != 0 && cleanrc != -2i32) {
|
||||
@@ -8566,7 +8710,8 @@ fn dobuild(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
|
||||
return buildonesep(selfdir, resolved, isdir, rootidentity,
|
||||
out, objstem, incs.ptr, &lf,
|
||||
publishpackage, 0i32, 0i32, SEP_VARIANT_PRODUCTION, nil,
|
||||
emitasm, 1i32, workdir);
|
||||
emitasm, 1i32, workdir, createoutputdir, defaultoutputdir,
|
||||
outputpatherror);
|
||||
};
|
||||
|
||||
// Format the owned driver workspace /tmp/<prefix><pid> into buf. Pid is
|
||||
@@ -8748,7 +8893,7 @@ fn dorun(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
|
||||
if (buildonesep(selfdir, resolved, isdir, rootidentity,
|
||||
outp, outp, incs.ptr, &lf,
|
||||
0i32, 1i32, 0i32, SEP_VARIANT_PRODUCTION, nil,
|
||||
0i32, 0i32, nil) != 0) {
|
||||
0i32, 0i32, nil, nil, nil, false) != 0) {
|
||||
let cleanrc: i32 = os.remove(pathstr(outp));
|
||||
if (cleanrc != 0 && cleanrc != -2i32) {
|
||||
cerr("ww: cannot remove temporary output\n");
|
||||
@@ -8841,7 +8986,7 @@ fn runsingletest(selfdir: *u8, src: *u8, incs: *u8, compileonly: i32,
|
||||
if (retainout) { keep = 1; };
|
||||
let bres: i32 = buildonesep(selfdir, src, 0, nil, outp, objstem, incs, &lf,
|
||||
0i32, 0i32, 1i32, SEP_VARIANT_PRODUCTION, nil,
|
||||
emitasm, keep, workdir);
|
||||
emitasm, keep, workdir, nil, nil, false);
|
||||
if (bres != 0) {
|
||||
if (owntmp) {
|
||||
let cleanrc: i32 = os.remove(pathstr(outp));
|
||||
@@ -8942,6 +9087,10 @@ fn dotest(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
|
||||
let packagepublish: bool = false;
|
||||
let packagecreateworkdir: bool = false;
|
||||
let packagecreateoutputdir: *u8 = nil;
|
||||
let packageoutputpatherror: bool = false;
|
||||
let packagedefaultoutputdir: *u8 = nil;
|
||||
let packageoutputcollisionbase: *u8 = nil;
|
||||
let packageoutputcollisiondir: *u8 = nil;
|
||||
let maxpackagelflags: i32 = 32;
|
||||
let packagelibdirs: [32]*u8;
|
||||
let packagelibs: [32]*u8;
|
||||
@@ -9008,6 +9157,37 @@ fn dotest(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
|
||||
i += 2;
|
||||
continue;
|
||||
};
|
||||
if (cstreqlit(p, "--ww-command-output-path-error")) {
|
||||
if (packageoutputpatherror) {
|
||||
cerr("ww test: invalid --ww-command-output-path-error\n");
|
||||
return 2;
|
||||
};
|
||||
packageoutputpatherror = true;
|
||||
i += 1;
|
||||
continue;
|
||||
};
|
||||
if (cstreqlit(p, "--ww-default-output-dir")) {
|
||||
if (i + 1 >= argc || packagedefaultoutputdir != nil
|
||||
|| argv[i + 1][0u64] == 0u8) {
|
||||
cerr("ww test: invalid --ww-default-output-dir\n");
|
||||
return 2;
|
||||
};
|
||||
packagedefaultoutputdir = argv[i + 1];
|
||||
i += 2;
|
||||
continue;
|
||||
};
|
||||
if (cstreqlit(p, "--ww-command-output-collision")) {
|
||||
if (i + 2 >= argc || packageoutputcollisionbase != nil
|
||||
|| argv[i + 1][0u64] == 0u8
|
||||
|| argv[i + 2][0u64] == 0u8) {
|
||||
cerr("ww test: invalid --ww-command-output-collision\n");
|
||||
return 2;
|
||||
};
|
||||
packageoutputcollisionbase = argv[i + 1];
|
||||
packageoutputcollisiondir = argv[i + 2];
|
||||
i += 3;
|
||||
continue;
|
||||
};
|
||||
if (cstreqlit(p, "--ww-package-test")) {
|
||||
if (i + 9 >= argc) {
|
||||
cerr("ww test: --ww-package-test needs kind, package, production, internal, external, directory, output, publication, and status\n");
|
||||
@@ -9067,6 +9247,7 @@ fn dotest(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
|
||||
if (buildproduct) { product.variant = SEP_VARIANT_PRODUCTION; };
|
||||
product.directoryproduct = true;
|
||||
product.notests = testproduct && !hasinternal && !hasexternal;
|
||||
product.buildaction = true;
|
||||
product.root = -1;
|
||||
product.variantroot = -1;
|
||||
product.productionroot = -1;
|
||||
@@ -9243,6 +9424,12 @@ fn dotest(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
|
||||
cerr("ww test: invalid private directory creation\n");
|
||||
return 2;
|
||||
};
|
||||
if ((packageoutputpatherror || packagedefaultoutputdir != nil
|
||||
|| packageoutputcollisionbase != nil)
|
||||
&& (!packagebuild || products.len == 0)) {
|
||||
cerr("ww test: invalid private output preflight\n");
|
||||
return 2;
|
||||
};
|
||||
if (packagecreateworkdir && products.len == 0) {
|
||||
cerr("ww test: invalid private directory creation\n");
|
||||
return 2;
|
||||
@@ -9388,7 +9575,9 @@ fn dotest(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
|
||||
incs.ptr, workdir,
|
||||
products.ptr, products.len, packagemode, publishmode,
|
||||
&packagelinks, emitasm, packagecreateworkdir,
|
||||
packagecreateoutputdir);
|
||||
packagecreateoutputdir, packagedefaultoutputdir,
|
||||
packageoutputpatherror, packageoutputcollisionbase,
|
||||
packageoutputcollisiondir);
|
||||
};
|
||||
let replacement: *u8 = nil;
|
||||
if (resolved != target) { replacement = resolved; };
|
||||
|
||||
Reference in New Issue
Block a user