ww: separate package identity from declared name
This commit is contained in:
@@ -17,7 +17,6 @@ import crypto.sha256;
|
||||
import hash;
|
||||
import os;
|
||||
import os.exec;
|
||||
import rt;
|
||||
import strings;
|
||||
import syntax;
|
||||
|
||||
@@ -893,6 +892,9 @@ type lflags = struct {
|
||||
type sepbind = struct {
|
||||
kind: u8,
|
||||
name: str,
|
||||
source: str,
|
||||
line: i32,
|
||||
col: i32,
|
||||
dep: i32,
|
||||
};
|
||||
|
||||
@@ -919,6 +921,7 @@ type seppkg = struct {
|
||||
root: bool, // requested usage; never package-action identity
|
||||
linkentry: bool,
|
||||
generatedmain: bool,
|
||||
generatedtarget: i32,
|
||||
failed: bool,
|
||||
testsupport: bool,
|
||||
loaded: bool,
|
||||
@@ -1609,15 +1612,13 @@ fn seprootiscommand(p: *seppkg) bool = {
|
||||
};
|
||||
|
||||
fn sepforbiddencommandimport(g: *sepgraph, importer: i32, dep: i32) bool = {
|
||||
let from: *seppkg = &g.pkg[importer];
|
||||
let to: *seppkg = &g.pkg[dep];
|
||||
if (to.name == nil || !cstreqlit(to.name, "main")
|
||||
|| to.role != SEP_ROLE_NORMAL) { return false; };
|
||||
// An external test's exact colocated production edge is variant wiring,
|
||||
// not a general source-importable command-package alias.
|
||||
return !(from.variant == SEP_VARIANT_EXTERNAL
|
||||
&& sepcommanddeclaredname(from)
|
||||
&& cstreq(from.canon, to.canon));
|
||||
return !(sepexternalproductionedge(g, importer, dep)
|
||||
&& sepexternalnamematchesproduction(g, importer, dep));
|
||||
};
|
||||
|
||||
fn sepinternalparentcount(path: *u8, parents: *u64) bool = {
|
||||
@@ -2085,6 +2086,10 @@ fn sepgraphfree(g: *sepgraph) void = {
|
||||
os.free(g.pkg[i].bindings[bi].name.ptr: *void,
|
||||
g.pkg[i].bindings[bi].name.cap: u64);
|
||||
};
|
||||
if (g.pkg[i].bindings[bi].source.ptr != nil) {
|
||||
os.free(g.pkg[i].bindings[bi].source.ptr: *void,
|
||||
g.pkg[i].bindings[bi].source.cap: u64);
|
||||
};
|
||||
bi += 1;
|
||||
};
|
||||
if (g.pkg[i].bindings.ptr != nil) {
|
||||
@@ -2556,41 +2561,41 @@ fn sepvalidateartifactpaths(g: *sepgraph, scratch: *u8) i32 = {
|
||||
return 0;
|
||||
};
|
||||
|
||||
fn sepexternalname(pkg: *seppkg, path: *u8, n: u64,
|
||||
leafonly: bool) bool = {
|
||||
fn sepexternalname(pkg: *seppkg, path: *u8, n: u64) bool = {
|
||||
if (pkg.variant != SEP_VARIANT_EXTERNAL || pkg.testpackage == nil) {
|
||||
return false;
|
||||
};
|
||||
let begin: u64 = 0u64;
|
||||
if (leafonly) {
|
||||
let i: u64 = 0u64;
|
||||
for (i < n) {
|
||||
if (path[i] == '.') { begin = i + 1u64; };
|
||||
i += 1u64;
|
||||
};
|
||||
};
|
||||
let leafn: u64 = n - begin;
|
||||
let tn: u64 = cstrlen(pkg.testpackage);
|
||||
if (tn != leafn + 5u64) { return false; };
|
||||
if (bytecmp(pkg.testpackage, leafn, path + begin, leafn) != 0) {
|
||||
if (tn != n + 5u64) { return false; };
|
||||
if (bytecmp(pkg.testpackage, n, path, n) != 0) {
|
||||
return false;
|
||||
};
|
||||
return pkg.testpackage[leafn] == '_'
|
||||
&& pkg.testpackage[leafn + 1u64] == 't'
|
||||
&& pkg.testpackage[leafn + 2u64] == 'e'
|
||||
&& pkg.testpackage[leafn + 3u64] == 's'
|
||||
&& pkg.testpackage[leafn + 4u64] == 't';
|
||||
return pkg.testpackage[n] == '_'
|
||||
&& pkg.testpackage[n + 1u64] == 't'
|
||||
&& pkg.testpackage[n + 2u64] == 'e'
|
||||
&& pkg.testpackage[n + 3u64] == 's'
|
||||
&& pkg.testpackage[n + 4u64] == 't';
|
||||
};
|
||||
|
||||
fn sepexternalproductionedge(g: *sepgraph, importer: i32, dep: i32) bool = {
|
||||
let from: *seppkg = &g.pkg[importer];
|
||||
let to: *seppkg = &g.pkg[dep];
|
||||
return from.variant == SEP_VARIANT_EXTERNAL
|
||||
&& to.variant == SEP_VARIANT_PRODUCTION
|
||||
&& to.role == SEP_ROLE_NORMAL
|
||||
&& cstreq(from.canon, to.canon);
|
||||
};
|
||||
|
||||
fn sepexternalnamematchesproduction(g: *sepgraph, importer: i32,
|
||||
dep: i32) bool = {
|
||||
let from: *seppkg = &g.pkg[importer];
|
||||
let to: *seppkg = &g.pkg[dep];
|
||||
if (from.name == nil || to.name == nil) { return false; };
|
||||
return sepexternalname(from, to.name, cstrlen(to.name));
|
||||
};
|
||||
|
||||
fn sepbindadd(bindings: *[]sepbind, kind: u8, name: str,
|
||||
dep: i32) bool = {
|
||||
let i: i32 = 0;
|
||||
for (i < len(*bindings)) {
|
||||
let b: sepbind = (*bindings)[i];
|
||||
if (b.kind == kind && b.dep == dep
|
||||
&& syntax.streq(b.name, name)) { return true; };
|
||||
i += 1;
|
||||
};
|
||||
dep: i32, source: str, line: i32, col: i32) bool = {
|
||||
if (bindings.len == SEP_COUNT_MAX) { sepfailsize(); return false; };
|
||||
if (!sepreservebinds(bindings, bindings.len + 1)) {
|
||||
return false;
|
||||
@@ -2601,9 +2606,24 @@ fn sepbindadd(bindings: *[]sepbind, kind: u8, name: str,
|
||||
case let value: str => copied = value;
|
||||
case nomem => { sepfailnomem(); return false; };
|
||||
};
|
||||
let sourceallocation: (str | nomem) = sepdupstr(source);
|
||||
let sourcecopy: str;
|
||||
match (sourceallocation) {
|
||||
case let value: str => sourcecopy = value;
|
||||
case nomem => {
|
||||
if (copied.ptr != nil) {
|
||||
os.free(copied.ptr: *void, copied.cap: u64);
|
||||
};
|
||||
sepfailnomem();
|
||||
return false;
|
||||
};
|
||||
};
|
||||
append(*bindings, sepbind {
|
||||
kind = kind,
|
||||
name = copied,
|
||||
source = sourcecopy,
|
||||
line = line,
|
||||
col = col,
|
||||
dep = dep,
|
||||
});
|
||||
return true;
|
||||
@@ -2616,6 +2636,12 @@ fn sepbindcmp(a: sepbind, b: sepbind) i32 = {
|
||||
if (a.kind > b.kind) { return 1; };
|
||||
if (a.dep < b.dep) { return -1; };
|
||||
if (a.dep > b.dep) { return 1; };
|
||||
r = strings.compare(a.source, b.source): i32;
|
||||
if (r != 0) { return r; };
|
||||
if (a.line < b.line) { return -1; };
|
||||
if (a.line > b.line) { return 1; };
|
||||
if (a.col < b.col) { return -1; };
|
||||
if (a.col > b.col) { return 1; };
|
||||
return 0;
|
||||
};
|
||||
|
||||
@@ -2633,17 +2659,63 @@ fn sepbindsort(bindings: *[]sepbind) void = {
|
||||
};
|
||||
};
|
||||
|
||||
fn sepbindsemanticsame(a: sepbind, b: sepbind) bool = {
|
||||
return a.kind == b.kind && a.dep == b.dep
|
||||
&& syntax.streq(a.name, b.name);
|
||||
};
|
||||
|
||||
fn sepbindsame(a: []sepbind, b: []sepbind) bool = {
|
||||
if (len(a) != len(b)) { return false; };
|
||||
let ai: i32 = 0;
|
||||
let bi: i32 = 0;
|
||||
for (ai < len(a) && bi < len(b)) {
|
||||
if (!sepbindsemanticsame(a[ai], b[bi])) { return false; };
|
||||
let av: sepbind = a[ai];
|
||||
let bv: sepbind = b[bi];
|
||||
ai += 1;
|
||||
for (ai < len(a) && sepbindsemanticsame(av, a[ai])) { ai += 1; };
|
||||
bi += 1;
|
||||
for (bi < len(b) && sepbindsemanticsame(bv, b[bi])) { bi += 1; };
|
||||
};
|
||||
return ai == len(a) && bi == len(b);
|
||||
};
|
||||
|
||||
fn sepvalidatebindings(g: *sepgraph, bindings: []sepbind) bool = {
|
||||
let name: str;
|
||||
let dep: i32 = -1;
|
||||
let i: i32 = 0;
|
||||
for (i < len(a)) {
|
||||
if (a[i].kind != b[i].kind || a[i].dep != b[i].dep
|
||||
|| !syntax.streq(a[i].name, b[i].name)) { return false; };
|
||||
for (i < bindings.len) {
|
||||
let b: sepbind = bindings[i];
|
||||
if (b.kind == 'D': u8) {
|
||||
if (name.len > 0 && syntax.streq(name, b.name) && dep != b.dep) {
|
||||
cerrpos(b.source, b.line, b.col);
|
||||
cerr(": error: package path "); cerr(b.name);
|
||||
cerr(" resolves to both "); cerr(pathstr(g.pkg[dep].path));
|
||||
cerr(" and "); cerr(pathstr(g.pkg[b.dep].path)); cerr("\n");
|
||||
return false;
|
||||
};
|
||||
name = b.name;
|
||||
dep = b.dep;
|
||||
};
|
||||
i += 1;
|
||||
};
|
||||
return true;
|
||||
};
|
||||
|
||||
fn sepbindneedsmap(g: *sepgraph, b: sepbind) bool = {
|
||||
return b.kind == 'D': u8 && b.dep >= 0 && b.dep < g.n
|
||||
&& !syntax.streq(b.name, pathstr(g.pkg[b.dep].path));
|
||||
};
|
||||
|
||||
fn sepbindfirstmap(g: *sepgraph, bindings: []sepbind, i: i32) bool = {
|
||||
if (!sepbindneedsmap(g, bindings[i])) { return false; };
|
||||
let j: i32 = i - 1;
|
||||
for (j >= 0 && syntax.streq(bindings[j].name, bindings[i].name)) {
|
||||
if (sepbindneedsmap(g, bindings[j])) { return false; };
|
||||
j -= 1;
|
||||
};
|
||||
return true;
|
||||
};
|
||||
|
||||
fn sepchildrenadd(children: *[]sepchild, pkg: i32, context: i32) bool = {
|
||||
let i: i32 = 0;
|
||||
for (i < children.len) {
|
||||
@@ -2780,6 +2852,18 @@ fn sepresolvesourceimport(g: *sepgraph, context: i32, name: *u8,
|
||||
return 1;
|
||||
};
|
||||
|
||||
fn sepusecmp(a: *syntax.node, b: *syntax.node) i32 = {
|
||||
let r: i32 = strings.compare(a.usepath, b.usepath): i32;
|
||||
if (r != 0) { return r; };
|
||||
r = strings.compare(a.file, b.file): i32;
|
||||
if (r != 0) { return r; };
|
||||
if (a.line < b.line) { return -1; };
|
||||
if (a.line > b.line) { return 1; };
|
||||
if (a.col < b.col) { return -1; };
|
||||
if (a.col > b.col) { return 1; };
|
||||
return 0;
|
||||
};
|
||||
|
||||
// Scan one already-selected source file for its leading package clause
|
||||
// (when it is an owned directory source) and top-level imports. A DIRECTORY
|
||||
// import is a package boundary: add as a direct dep of pi. A FILE import is an
|
||||
@@ -2880,8 +2964,7 @@ fn sepscanfile(g: *sepgraph, pi: i32, file: *u8, context: i32,
|
||||
for (si < nuse) {
|
||||
let sj: i32 = si;
|
||||
for (sj > 0) {
|
||||
if (strings.compare(uses[sj - 1].usepath,
|
||||
uses[sj].usepath) <= 0) { sj = 0; }
|
||||
if (sepusecmp(uses[sj - 1], uses[sj]) <= 0) { sj = 0; }
|
||||
else {
|
||||
let t: *syntax.node = uses[sj];
|
||||
uses[sj] = uses[sj - 1];
|
||||
@@ -2891,14 +2974,9 @@ fn sepscanfile(g: *sepgraph, pi: i32, file: *u8, context: i32,
|
||||
};
|
||||
si += 1;
|
||||
};
|
||||
let previous: str = "";
|
||||
ui = 0;
|
||||
for (ui < nuse) {
|
||||
u = uses[ui];
|
||||
let duplicate: bool = previous.len > 0
|
||||
&& syntax.streq(previous, u.usepath);
|
||||
if (!duplicate) {
|
||||
previous = u.usepath;
|
||||
let idp: *u8 = u.usepath.ptr;
|
||||
let idn: u64 = u.usepath.len: u64;
|
||||
if (reservedimport(u.usepath)) {
|
||||
@@ -2933,11 +3011,10 @@ fn sepscanfile(g: *sepgraph, pi: i32, file: *u8, context: i32,
|
||||
oi += 1u64;
|
||||
};
|
||||
let literalself: bool = routesuffix != nil
|
||||
&& cstreq(pathform, routesuffix)
|
||||
&& sepexternalname(&g.pkg[pi], idp, idn, true);
|
||||
&& cstreq(pathform, routesuffix);
|
||||
if (routesuffix == nil) {
|
||||
literalself = ordinaryleaf
|
||||
&& sepexternalname(&g.pkg[pi], idp, idn, false);
|
||||
&& sepexternalname(&g.pkg[pi], idp, idn);
|
||||
};
|
||||
if (literalself) {
|
||||
if (g.pkg[pi].importbase != nil) {
|
||||
@@ -2961,9 +3038,7 @@ fn sepscanfile(g: *sepgraph, pi: i32, file: *u8, context: i32,
|
||||
let externalproduction: bool = false;
|
||||
let self: bool = os.samefile(pathstr(resolved.entry),
|
||||
pathstr(g.pkg[pi].entry));
|
||||
if (self && (sepexternalname(&g.pkg[pi], idp, idn, true)
|
||||
|| (g.pkg[pi].variant == SEP_VARIANT_EXTERNAL
|
||||
&& sepcommanddeclaredname(&g.pkg[pi])))) {
|
||||
if (self && g.pkg[pi].variant == SEP_VARIANT_EXTERNAL) {
|
||||
externalproduction = true;
|
||||
};
|
||||
if (self && !externalproduction) {
|
||||
@@ -3010,26 +3085,19 @@ fn sepscanfile(g: *sepgraph, pi: i32, file: *u8, context: i32,
|
||||
let childcontext: i32 = sepchildcontextfor(g, context,
|
||||
resolved.entry, resolved.sourceroot);
|
||||
if (childcontext < 0
|
||||
|| !sepbindadd(bindings, 'D': u8, u.usepath, di)
|
||||
|| !sepbindadd(bindings, 'D': u8, u.usepath, di,
|
||||
u.file, u.line, u.col)
|
||||
|| !sepadddep(g, pi, di)
|
||||
|| !sepchildrenadd(children, di, childcontext)) {
|
||||
return -1;
|
||||
};
|
||||
} else {
|
||||
let lstart: u64 = 0u64;
|
||||
let lk: u64 = 0u64;
|
||||
for (lk < idn) {
|
||||
if (idp[lk] == 46u8) { lstart = lk + 1u64; }; // '.'
|
||||
lk += 1u64;
|
||||
};
|
||||
let leafp: *u8 = idp + lstart;
|
||||
let leafn: u64 = idn - lstart;
|
||||
let inlinepackage: bool = false;
|
||||
if (g.pkg[pi].isdir == 0) {
|
||||
let pm: *syntax.node = imports.body;
|
||||
for (pm != nil) {
|
||||
if (bytecmp(pm.nmod.ptr, pm.nmod.len: u64,
|
||||
leafp, leafn) == 0) { inlinepackage = true; };
|
||||
idp, idn) == 0) { inlinepackage = true; };
|
||||
pm = pm.next;
|
||||
};
|
||||
};
|
||||
@@ -3040,13 +3108,13 @@ fn sepscanfile(g: *sepgraph, pi: i32, file: *u8, context: i32,
|
||||
cerr("\n");
|
||||
return -1;
|
||||
} else {
|
||||
if (!sepbindadd(bindings, 'I': u8, u.usepath, -1)) {
|
||||
if (!sepbindadd(bindings, 'I': u8, u.usepath, -1,
|
||||
u.file, u.line, u.col)) {
|
||||
return -1;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
ui += 1;
|
||||
ui += 1;
|
||||
};
|
||||
return 0;
|
||||
};
|
||||
@@ -3160,6 +3228,7 @@ fn sepaddgeneratedmain(g: *sepgraph, product: *sepproduct, ordinal: i32,
|
||||
p.root = true;
|
||||
p.linkentry = true;
|
||||
p.generatedmain = true;
|
||||
p.generatedtarget = variant;
|
||||
p.failed = false;
|
||||
p.testsupport = false;
|
||||
p.loaded = true;
|
||||
@@ -3239,30 +3308,12 @@ fn seppreparepkgcontext(g: *sepgraph, pi: i32, context: i32,
|
||||
};
|
||||
i += 1;
|
||||
};
|
||||
if (rc == 0 && g.pkg[pi].path[0u64] != 0u8
|
||||
&& !g.pkg[pi].testsupport) {
|
||||
let plen: u64 = cstrlen(g.pkg[pi].path);
|
||||
let leaf: *u8 = g.pkg[pi].path;
|
||||
let j: u64 = 0u64;
|
||||
for (j < plen) {
|
||||
if (g.pkg[pi].path[j] == '.') { leaf = g.pkg[pi].path + j + 1u64; };
|
||||
j += 1u64;
|
||||
};
|
||||
if (!cstreq(g.pkg[pi].name, leaf)
|
||||
&& !sepcommanddeclaredname(&g.pkg[pi])) {
|
||||
cerr("ww: package ");
|
||||
cerr(pathstr(g.pkg[pi].name));
|
||||
cerr(" does not match import path ");
|
||||
cerr(pathstr(g.pkg[pi].path));
|
||||
cerr("\n");
|
||||
rc = -1;
|
||||
};
|
||||
};
|
||||
} else { if (rc == 0) {
|
||||
rc = sepscanfile(g, pi, g.pkg[pi].entry, context,
|
||||
&fv, &bindings, children, 0);
|
||||
}; };
|
||||
sepbindsort(&bindings);
|
||||
if (rc == 0 && !sepvalidatebindings(g, bindings)) { rc = -1; };
|
||||
if (rc == 0 && g.pkg[pi].emitcontext < 0) {
|
||||
g.pkg[pi].bindings = bindings;
|
||||
g.pkg[pi].emitcontext = context;
|
||||
@@ -3415,6 +3466,20 @@ fn seploadpkg(g: *sepgraph, pi: i32, context: i32) i32 = {
|
||||
if (f.pendingdep >= 0) {
|
||||
let dep: i32 = f.pendingdep;
|
||||
f.pendingdep = -1;
|
||||
if (dep != f.pkg && sepexternalproductionedge(g, f.pkg, dep)
|
||||
&& !sepexternalnamematchesproduction(g, f.pkg, dep)) {
|
||||
cerr("ww: external test package ");
|
||||
cerr(pathstr(g.pkg[f.pkg].name));
|
||||
cerr(" does not match production package ");
|
||||
cerr(pathstr(g.pkg[dep].name)); cerr("\n");
|
||||
let fi: i32 = 0;
|
||||
for (fi < nframe) {
|
||||
g.pkg[frames[fi].pkg].failed = true;
|
||||
sepclearchildren(&frames[fi].children);
|
||||
fi += 1;
|
||||
};
|
||||
return sepfinishloadframes(frames, -1);
|
||||
};
|
||||
if (dep != f.pkg && sepforbiddencommandimport(g, f.pkg, dep)) {
|
||||
cerr("ww: package ");
|
||||
if (g.pkg[dep].path[0u64] != 0u8) {
|
||||
@@ -3603,30 +3668,14 @@ fn sepreverseimportbase(g: *sepgraph, p: *seppkg, context: i32,
|
||||
return 0;
|
||||
};
|
||||
|
||||
fn sepordinarydeclaredname(p: *seppkg) *u8 = {
|
||||
if (p.name == nil || p.name[0u64] == 0u8) { return nil; };
|
||||
let n: u64 = cstrlen(p.name);
|
||||
if (p.variant == SEP_VARIANT_EXTERNAL) {
|
||||
if (n <= 5u64 || !cstrendswithlit(p.name, "_test")) {
|
||||
cerr("ww: package-test selector does not name an external package\n");
|
||||
return nil;
|
||||
};
|
||||
n -= 5u64;
|
||||
};
|
||||
return sepdupcstr(p.name, n);
|
||||
};
|
||||
|
||||
// The reserved local namespace is reversible, so filesystem identity never
|
||||
// depends on a hash, request order, output name, or another selected package.
|
||||
// depends on a hash, request order, output name, declared package name, or
|
||||
// another selected package.
|
||||
fn seplocalimportbase(p: *seppkg) *u8 = {
|
||||
let leaf: *u8 = sepordinarydeclaredname(p);
|
||||
if (leaf == nil) { return nil; };
|
||||
let need: u64 = 0u64;
|
||||
if (!sepaddbytes(&need, SEP_LOCAL_IMPORT_PREFIX.len: u64)
|
||||
|| !sepaddbytes(&need, 2u64)
|
||||
|| !sepmuladdbytes(&need, cstrlen(p.canon), 4u64)
|
||||
|| !sepaddbytes(&need, 1u64)
|
||||
|| !sepaddbytes(&need, cstrlen(leaf))
|
||||
|| !sepaddbytes(&need, 1u64)) { return nil; };
|
||||
let out: []u8;
|
||||
if (!sepmakebytes(need, &out)) { return nil; };
|
||||
@@ -3656,8 +3705,6 @@ fn seplocalimportbase(p: *seppkg) *u8 = {
|
||||
}; };
|
||||
i += 1u64;
|
||||
};
|
||||
off = byteinto(out.ptr, off, '.': u8);
|
||||
off = cstrinto(out.ptr, off, leaf);
|
||||
cstrseal(out.ptr, off);
|
||||
return out.ptr;
|
||||
};
|
||||
@@ -3725,23 +3772,6 @@ fn sepfinalizedirectoryidentities(g: *sepgraph) i32 = {
|
||||
for (pi < g.n) {
|
||||
let p: *seppkg = &g.pkg[pi];
|
||||
if (p.isdir != 0 && !p.generatedmain && !p.failed && p.loaded) {
|
||||
let plen: u64 = cstrlen(p.path);
|
||||
let leaf: *u8 = p.path;
|
||||
let j: u64 = 0u64;
|
||||
for (j < plen) {
|
||||
if (p.path[j] == '.') { leaf = p.path + j + 1u64; };
|
||||
j += 1u64;
|
||||
};
|
||||
let supportalias: bool = p.role == SEP_ROLE_TEST_SUPPORT
|
||||
&& cstreqlit(p.path, SEP_TEST_SUPPORT_MODULE)
|
||||
&& cstreqlit(p.name, "test");
|
||||
if (!supportalias && !cstreq(p.name, leaf)
|
||||
&& !sepcommanddeclaredname(p)) {
|
||||
cerr("ww: package "); cerr(pathstr(p.name));
|
||||
cerr(" does not match import path "); cerr(pathstr(p.path));
|
||||
cerr("\n");
|
||||
return -1;
|
||||
};
|
||||
p.artifact = nil;
|
||||
if (p.variant == SEP_VARIANT_SAME_TEST) {
|
||||
p.artifact = sepappendlit(p.path, "-internal-test");
|
||||
@@ -4014,8 +4044,7 @@ fn sepcomposeunit(g: *sepgraph, pi: i32, unitf: *u8) i32 = {
|
||||
let bi: i32 = 0;
|
||||
for (bi < g.pkg[pi].bindings.len && bodyrc == 0) {
|
||||
let b: sepbind = g.pkg[pi].bindings[bi];
|
||||
if (b.kind == 'D': u8 && b.dep >= 0 && b.dep < g.n
|
||||
&& !syntax.streq(b.name, pathstr(g.pkg[b.dep].path))) {
|
||||
if (sepbindfirstmap(g, g.pkg[pi].bindings, bi)) {
|
||||
let pre: str = "//ww:import-map ";
|
||||
let space: str = " ";
|
||||
let newline: str = "\n";
|
||||
@@ -4331,14 +4360,14 @@ fn validatecommandoutputpath(out: *u8) i32 = {
|
||||
fn workdirstamptext(istest: i32, emitasm: i32) str = {
|
||||
if (istest != 0) {
|
||||
if (emitasm != 0) {
|
||||
return "ww workdir fmt 12 mode test asm 1\n";
|
||||
return "ww workdir fmt 13 mode test asm 1\n";
|
||||
};
|
||||
return "ww workdir fmt 12 mode test asm 0\n";
|
||||
return "ww workdir fmt 13 mode test asm 0\n";
|
||||
};
|
||||
if (emitasm != 0) {
|
||||
return "ww workdir fmt 13 mode build asm 1\n";
|
||||
return "ww workdir fmt 14 mode build asm 1\n";
|
||||
};
|
||||
return "ww workdir fmt 13 mode build asm 0\n";
|
||||
return "ww workdir fmt 14 mode build asm 0\n";
|
||||
};
|
||||
|
||||
fn stampmatches(path: *u8, want: str) bool = {
|
||||
@@ -4434,6 +4463,22 @@ fn invalidateworkdirunits(scratch: *u8) i32 = {
|
||||
return rc;
|
||||
};
|
||||
|
||||
fn sepdiscardactionstaging(warm: bool, unit: *u8, wwi: *u8,
|
||||
assembly: *u8, object: *u8, archive: *u8) i32 = {
|
||||
if (!warm) { return 0; };
|
||||
let paths: []*u8 = [unit, wwi, assembly, object, archive];
|
||||
let i: i32 = 0;
|
||||
for (i < paths.len) {
|
||||
let rr: i32 = os.remove(pathstr(paths[i]));
|
||||
if (rr != 0 && rr != -2) {
|
||||
cerr("ww: cannot remove staged package artifacts\n");
|
||||
return -1;
|
||||
};
|
||||
i += 1;
|
||||
};
|
||||
return 0;
|
||||
};
|
||||
|
||||
type sepcreateddirs = struct {
|
||||
path: [4096]u8,
|
||||
offset: [2048]u16,
|
||||
@@ -5092,7 +5137,16 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
cu = unitnew; cw = wwinew; cs = asmnew;
|
||||
co = objnew; ca = anew;
|
||||
};
|
||||
if (sepdiscardactionstaging(warm, unitnew, wwinew, asmnew,
|
||||
objnew, anew) < 0) {
|
||||
g.pkg[pi].failed = true;
|
||||
anyfailed = true;
|
||||
oi += 1;
|
||||
continue;
|
||||
};
|
||||
if (sepcomposeunit(g, pi, cu) < 0) {
|
||||
sepdiscardactionstaging(warm, unitnew, wwinew, asmnew,
|
||||
objnew, anew);
|
||||
g.pkg[pi].failed = true;
|
||||
anyfailed = true;
|
||||
oi += 1;
|
||||
@@ -5122,7 +5176,11 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
};
|
||||
};
|
||||
};
|
||||
if (sepfatalallocation) { return 1; };
|
||||
if (sepfatalallocation) {
|
||||
sepdiscardactionstaging(warm, unitnew, wwinew, asmnew,
|
||||
objnew, anew);
|
||||
return 1;
|
||||
};
|
||||
if (fresh) {
|
||||
if (os.remove(pathstr(unitnew)) != 0) {
|
||||
cerrpath("ww: cannot remove ", unitnew, "\n");
|
||||
@@ -5144,17 +5202,19 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
let nmaps: i32 = 0;
|
||||
let mapk: i32 = 0;
|
||||
for (mapk < g.pkg[pi].bindings.len) {
|
||||
let b: sepbind = g.pkg[pi].bindings[mapk];
|
||||
if (b.kind == 'D': u8 && b.dep >= 0 && b.dep < g.n
|
||||
&& !syntax.streq(b.name,
|
||||
pathstr(g.pkg[b.dep].path))) {
|
||||
if (nmaps == SEP_COUNT_MAX) { sepfailsize(); return 1; };
|
||||
if (sepbindfirstmap(g, g.pkg[pi].bindings, mapk)) {
|
||||
if (nmaps == SEP_COUNT_MAX) {
|
||||
sepfailsize();
|
||||
sepdiscardactionstaging(warm, unitnew, wwinew,
|
||||
asmnew, objnew, anew);
|
||||
return 1;
|
||||
};
|
||||
nmaps += 1;
|
||||
};
|
||||
mapk += 1;
|
||||
};
|
||||
let alen: i32 = 8;
|
||||
if (gent) { alen += 4; }
|
||||
if (gent) { alen += 4; if (g.pkg[pi].generatedmain) { alen += 2; }; }
|
||||
else {
|
||||
if (testpkg) { alen += 1; };
|
||||
if (commandpkg) { alen += 1; };
|
||||
@@ -5163,11 +5223,15 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
};
|
||||
if (g.pkg[pi].ndeps > (SEP_COUNT_MAX - alen) / 3) {
|
||||
sepfailsize();
|
||||
sepdiscardactionstaging(warm, unitnew, wwinew, asmnew,
|
||||
objnew, anew);
|
||||
return 1;
|
||||
};
|
||||
alen += g.pkg[pi].ndeps * 3;
|
||||
if (nmaps > (SEP_COUNT_MAX - alen) / 3) {
|
||||
sepfailsize();
|
||||
sepdiscardactionstaging(warm, unitnew, wwinew, asmnew,
|
||||
objnew, anew);
|
||||
return 1;
|
||||
};
|
||||
alen += nmaps * 3;
|
||||
@@ -5175,7 +5239,12 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
let argv: []str;
|
||||
match (allocation) {
|
||||
case let value: []str => argv = value;
|
||||
case nomem => { sepfailnomem(); return 1; };
|
||||
case nomem => {
|
||||
sepfailnomem();
|
||||
sepdiscardactionstaging(warm, unitnew, wwinew, asmnew,
|
||||
objnew, anew);
|
||||
return 1;
|
||||
};
|
||||
};
|
||||
append(argv, "w6c");
|
||||
if (gent) {
|
||||
@@ -5183,6 +5252,10 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
append(argv, "--entry");
|
||||
append(argv, "--test-support-module");
|
||||
append(argv, testsupportmodule);
|
||||
if (g.pkg[pi].generatedmain) {
|
||||
append(argv, "--test-target-package");
|
||||
append(argv, pathstr(g.pkg[g.pkg[pi].generatedtarget].path));
|
||||
};
|
||||
} else {
|
||||
if (testpkg) { append(argv, "--test-package"); };
|
||||
if (commandpkg) { append(argv, "--command-package"); };
|
||||
@@ -5199,16 +5272,18 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
append(argv, "--import");
|
||||
append(argv, pathstr(g.pkg[dj].path));
|
||||
let depinterface: *u8 = sepfname(g, dj, scratch, ".wwi");
|
||||
if (depinterface == nil) { return 1; };
|
||||
if (depinterface == nil) {
|
||||
sepdiscardactionstaging(warm, unitnew, wwinew,
|
||||
asmnew, objnew, anew);
|
||||
return 1;
|
||||
};
|
||||
append(argv, pathstr(depinterface));
|
||||
importk += 1;
|
||||
};
|
||||
mapk = 0;
|
||||
for (mapk < g.pkg[pi].bindings.len) {
|
||||
let b: sepbind = g.pkg[pi].bindings[mapk];
|
||||
if (b.kind == 'D': u8 && b.dep >= 0 && b.dep < g.n
|
||||
&& !syntax.streq(b.name,
|
||||
pathstr(g.pkg[b.dep].path))) {
|
||||
if (sepbindfirstmap(g, g.pkg[pi].bindings, mapk)) {
|
||||
append(argv, "--import-map");
|
||||
append(argv, b.name);
|
||||
append(argv, pathstr(g.pkg[b.dep].path));
|
||||
@@ -5237,6 +5312,8 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
};
|
||||
g.pkg[pi].failed = true;
|
||||
anyfailed = true;
|
||||
sepdiscardactionstaging(warm, unitnew, wwinew, asmnew,
|
||||
objnew, anew);
|
||||
oi += 1;
|
||||
continue;
|
||||
};
|
||||
@@ -5244,13 +5321,22 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
if (!warm || !fileequal(wwinew, wwi)) {
|
||||
g.pkg[pi].exportchanged = true;
|
||||
};
|
||||
if (sepfatalallocation) { return 1; };
|
||||
if (sepfatalallocation) {
|
||||
sepdiscardactionstaging(warm, unitnew, wwinew, asmnew,
|
||||
objnew, anew);
|
||||
return 1;
|
||||
};
|
||||
if (emitasm == 0) {
|
||||
let argallocation: ([]str | nomem) = sepallocstrs(4);
|
||||
let argv: []str;
|
||||
match (argallocation) {
|
||||
case let value: []str => argv = value;
|
||||
case nomem => { sepfailnomem(); return 1; };
|
||||
case nomem => {
|
||||
sepfailnomem();
|
||||
sepdiscardactionstaging(warm, unitnew, wwinew, asmnew,
|
||||
objnew, anew);
|
||||
return 1;
|
||||
};
|
||||
};
|
||||
append(argv, "w6a");
|
||||
append(argv, "-o");
|
||||
@@ -5273,6 +5359,8 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
};
|
||||
g.pkg[pi].failed = true;
|
||||
anyfailed = true;
|
||||
sepdiscardactionstaging(warm, unitnew, wwinew, asmnew,
|
||||
objnew, anew);
|
||||
oi += 1;
|
||||
continue;
|
||||
};
|
||||
@@ -5284,6 +5372,8 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
cerr("ww: archive failed\n");
|
||||
g.pkg[pi].failed = true;
|
||||
anyfailed = true;
|
||||
sepdiscardactionstaging(warm, unitnew, wwinew, asmnew,
|
||||
objnew, anew);
|
||||
oi += 1;
|
||||
continue;
|
||||
};
|
||||
@@ -5328,6 +5418,8 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
};
|
||||
g.pkg[pi].failed = true;
|
||||
anyfailed = true;
|
||||
sepdiscardactionstaging(warm, unitnew, wwinew, asmnew,
|
||||
objnew, anew);
|
||||
oi += 1;
|
||||
continue;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user