cmd: honor package library roots in both stages

This commit is contained in:
2026-08-12 15:18:46 +09:00
parent bb71b31f81
commit 5a2e4ba28d
2 changed files with 94 additions and 41 deletions

View File

@@ -33,11 +33,18 @@ static const char *usage =
static char *self_dir; static char *self_dir;
static const char *
envpath(const char *name)
{
const char *p = getenv(name);
return p && p[0] ? p : NULL;
}
static const char * static const char *
toolpath(const char *envvar, const char *name) toolpath(const char *envvar, const char *name)
{ {
const char *p = getenv(envvar); const char *p = envpath(envvar);
if (p && p[0]) return p; if (p) return p;
static char buf[1024]; static char buf[1024];
snprintf(buf, sizeof buf, "%s/%s", self_dir, name); snprintf(buf, sizeof buf, "%s/%s", self_dir, name);
return strdup(buf); return strdup(buf);
@@ -1681,15 +1688,15 @@ build_one_sep_impl(const char *src, int entry_is_dir,
const char *c6 = toolpath("WW_W6C", "w6c"); const char *c6 = toolpath("WW_W6C", "w6c");
const char *a6 = toolpath("WW_W6A", "w6a"); const char *a6 = toolpath("WW_W6A", "w6a");
const char *l6 = toolpath("WW_W6L", "w6l"); const char *l6 = toolpath("WW_W6L", "w6l");
const char *libdir = getenv("WW_LIB"); const char *libdir = envpath("WW_LIB");
if (libdir == NULL || libdir[0] == 0) { if (libdir == NULL) {
static char libbuf[1024]; static char libbuf[1024];
snprintf(libbuf, sizeof libbuf, "%s/../lib", self_dir); snprintf(libbuf, sizeof libbuf, "%s/../lib", self_dir);
libdir = libbuf; libdir = libbuf;
} }
const char *srcdir = getenv("WW_SRCLIB"); const char *srcdir = envpath("WW_SRCLIB");
static char srcbuf[1024]; static char srcbuf[1024];
if (srcdir == NULL || srcdir[0] == 0) { if (srcdir == NULL) {
snprintf(srcbuf, sizeof srcbuf, "%s/../../lib", self_dir); snprintf(srcbuf, sizeof srcbuf, "%s/../../lib", self_dir);
if (access(srcbuf, 0) == 0) srcdir = srcbuf; if (access(srcbuf, 0) == 0) srcdir = srcbuf;
else if (access("lib", 0) == 0) srcdir = "lib"; else if (access("lib", 0) == 0) srcdir = "lib";
@@ -2267,17 +2274,17 @@ do_version(void)
return 0; return 0;
} }
/* Compose the standard module search path: cwd : <extra-includes> : $WW_LIB /* Compose the standard module search path: cwd : <extra-includes> : selected
* source dir. The `extra` string is colon-separated -I dirs from argv. */ * source library. The `extra` string is colon-separated -I dirs from argv. */
static const char * static const char *
search_path(const char *extra, char *buf, size_t bufsz) search_path(const char *extra, char *buf, size_t bufsz)
{ {
const char *libdir = getenv("WW_SRCLIB"); const char *libdir = envpath("WW_SRCLIB");
static char libbuf[1024]; static char libbuf[1024];
if (libdir == NULL || libdir[0] == 0) { if (libdir == NULL) {
libdir = getenv("WW_LIB"); libdir = envpath("WW_LIB");
} }
if (libdir == NULL || libdir[0] == 0) { if (libdir == NULL) {
snprintf(libbuf, sizeof libbuf, "%s/../../lib", self_dir); snprintf(libbuf, sizeof libbuf, "%s/../../lib", self_dir);
if (access(libbuf, 0) == 0) libdir = libbuf; if (access(libbuf, 0) == 0) libdir = libbuf;
else if (access("lib", 0) == 0) libdir = "lib"; else if (access("lib", 0) == 0) libdir = "lib";

View File

@@ -9,7 +9,7 @@
// //
// Tool paths default to siblings of $0 so a fresh build runs out of // Tool paths default to siblings of $0 so a fresh build runs out of
// out/bin/. WW_W6C / WW_W6A / WW_W6L select exact executable paths. // out/bin/. WW_W6C / WW_W6A / WW_W6L select exact executable paths.
// Source-library and runtime-library overrides are not yet supported. // WW_SRCLIB selects package sources and WW_LIB selects runtime artifacts.
package main; package main;
@@ -162,13 +162,19 @@ fn owncstr(s: str) *u8 = {
return b.ptr; return b.ptr;
}; };
fn toolpath(selfdir: *u8, envvar: str, name: str) *u8 = { fn envpath(name: str) *u8 = {
match (os.getenv(envvar)) { match (os.getenv(name)) {
case let p: str => { case let p: str => {
if (p.len != 0) { return owncstr(p); }; if (p.len != 0) { return owncstr(p); };
}; };
case void => void; case void => void;
}; };
return nil;
};
fn toolpath(selfdir: *u8, envvar: str, name: str) *u8 = {
let p: *u8 = envpath(envvar);
if (p != nil) { return p; };
return joinpathlit(selfdir, name); return joinpathlit(selfdir, name);
}; };
@@ -285,6 +291,11 @@ fn importpathform(name: *u8, namelen: u64) *u8 = {
// `foo/foo.ha` fallback; a module IS the directory). // `foo/foo.ha` fallback; a module IS the directory).
fn locatein(dir: *u8, dirlen: u64, fn locatein(dir: *u8, dirlen: u64,
pathform: *u8, pflen: u64, isdir: *i32, wantdir: i32) *u8 = { pathform: *u8, pflen: u64, isdir: *i32, wantdir: i32) *u8 = {
let tail: u64 = 1u64; // NUL for the directory form
if (wantdir == 0i32) { tail = 4u64; }; // ".ww" + NUL
if (dirlen + 1u64 + pflen + tail > os.PATH_MAX: u64) {
return nil;
};
let buf: []u8 = alloc([], (os.PATH_MAX: u64))!; let buf: []u8 = alloc([], (os.PATH_MAX: u64))!;
let off: u64 = 0u64; let off: u64 = 0u64;
let i: u64 = 0u64; let i: u64 = 0u64;
@@ -2031,13 +2042,18 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
let c6: *u8 = toolpath(selfdir, "WW_W6C", "w6c_ww"); let c6: *u8 = toolpath(selfdir, "WW_W6C", "w6c_ww");
let a6: *u8 = toolpath(selfdir, "WW_W6A", "w6a_ww"); let a6: *u8 = toolpath(selfdir, "WW_W6A", "w6a_ww");
let l6: *u8 = toolpath(selfdir, "WW_W6L", "w6l_ww"); let l6: *u8 = toolpath(selfdir, "WW_W6L", "w6l_ww");
let libdir: *u8 = envpath("WW_LIB");
let dotdotlib: []u8 = alloc([], (os.PATH_MAX: u64))!; if (libdir == nil) { libdir = joinpathlit(selfdir, "../lib"); };
dotdotlib.len = os.PATH_MAX; let toolsrcdir: *u8 = envpath("WW_SRCLIB");
{ if (toolsrcdir == nil) {
let off: u64 = cstrinto(dotdotlib.ptr, 0u64, selfdir); let candidate: *u8 = joinpathlit(selfdir, "../../lib");
off = strinto(dotdotlib.ptr, off, "/../../lib"); if (os.access(pathstr(candidate), 0i32) == 0) {
cstrseal(dotdotlib.ptr, off); toolsrcdir = candidate;
} else { if (os.access("lib", 0i32) == 0) {
toolsrcdir = "lib\0".ptr;
} else {
toolsrcdir = libdir;
}; };
}; };
let srcd: []u8 = alloc([], (os.PATH_MAX: u64))!; let srcd: []u8 = alloc([], (os.PATH_MAX: u64))!;
@@ -2144,12 +2160,21 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
if (staleall && invalidateworkdirunits(scratch) != 0) { return 1; }; if (staleall && invalidateworkdirunits(scratch) != 0) { return 1; };
}; };
let libwwrt: []u8 = alloc([], (os.PATH_MAX: u64))!; let rtpaths: []*u8 = alloc([], 2u64)!;
libwwrt.len = os.PATH_MAX; rtpaths.len = 2;
{ let nrt: i32 = 1;
let off: u64 = cstrinto(libwwrt.ptr, 0u64, selfdir); let havearchive: bool = false;
off = strinto(libwwrt.ptr, off, "/../lib/libwwrt.a"); if (cstrlen(libdir) + 1u64 + "libwwrt.a".len: u64 + 1u64
cstrseal(libwwrt.ptr, off); <= os.PATH_MAX: u64) {
rtpaths[0] = joinpathlit(libdir, "libwwrt.a");
if (os.access(pathstr(rtpaths[0]), 0i32) == 0) {
havearchive = true;
};
};
if (!havearchive) {
nrt = 2;
rtpaths[0] = joinpathlit(selfdir, "../obj/rt/start.o");
rtpaths[1] = joinpathlit(selfdir, "../obj/rt/syscall.o");
}; };
let pkgslot: []seppkg = alloc([], SEP_MAXPKG: u64)!; let pkgslot: []seppkg = alloc([], SEP_MAXPKG: u64)!;
@@ -2175,7 +2200,7 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
let contextroot: *u8 = entry; let contextroot: *u8 = entry;
if (entryisdir == 0) { contextroot = srcd.ptr; }; if (entryisdir == 0) { contextroot = srcd.ptr; };
products[producti].context = sepcontextfor(g, contextroot, products[producti].context = sepcontextfor(g, contextroot,
incs, dotdotlib.ptr); incs, toolsrcdir);
if (products[producti].context < 0) { return 1; }; if (products[producti].context < 0) { return 1; };
products[producti].root = sepfindoraddvariant(g, rootpath, entry, products[producti].root = sepfindoraddvariant(g, rootpath, entry,
entryisdir, products[producti].variant, entryisdir, products[producti].variant,
@@ -2192,11 +2217,11 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
// it distinct. The linker receives the same support archive closure. // it distinct. The linker receives the same support archive closure.
if (istest != 0) { if (istest != 0) {
let td: i32 = 0; let td: i32 = 0;
let tp: *u8 = locateimport(dotdotlib.ptr, "test".ptr, let tp: *u8 = locateimport(toolsrcdir, "test".ptr,
"test".len: u64, &td); "test".len: u64, &td);
if (tp != nil) { if (tp != nil) {
g.supportcontext = sepcontextfor(g, dotdotlib.ptr, nil, g.supportcontext = sepcontextfor(g, toolsrcdir, nil,
dotdotlib.ptr); toolsrcdir);
if (g.supportcontext < 0) { return 1; }; if (g.supportcontext < 0) { return 1; };
let collision: bool = false; let collision: bool = false;
producti = 0; producti = 0;
@@ -2629,8 +2654,8 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
let nlink: i32 = 0; let nlink: i32 = 0;
if (septopovisit(g, root, linkorder, &nlink, if (septopovisit(g, root, linkorder, &nlink,
linkstack, 0) < 0) { return 1; }; linkstack, 0) < 0) { return 1; };
// argv: 3 fixed + closure + libwwrt + joined flags + nil. // argv: 3 fixed + closure + runtime inputs + joined flags + nil.
let total: i32 = 3 + nlink + 1 + nldirs + nllibs + 1; let total: i32 = 3 + nlink + nrt + nldirs + nllibs + 1;
let largv: []*u8 = alloc([], total: u64)!; let largv: []*u8 = alloc([], total: u64)!;
largv.len = total; largv.len = total;
largv[0] = "w6l\0".ptr; largv[0] = "w6l\0".ptr;
@@ -2655,7 +2680,12 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
pos += 1; pos += 1;
li -= 1; li -= 1;
}; };
largv[pos] = libwwrt.ptr; pos += 1; let ri: i32 = 0;
for (ri < nrt) {
largv[pos] = rtpaths[ri];
pos += 1;
ri += 1;
};
let k: i32 = 0; let k: i32 = 0;
for (k < nldirs) { for (k < nldirs) {
let n: u64 = cstrlen(ldirs[k]); let n: u64 = cstrlen(ldirs[k]);
@@ -2817,9 +2847,26 @@ fn arenadupcstr(src: *u8, plen: u64) *u8 = {
return buf.ptr; return buf.ptr;
}; };
// resolvemodule search-path order: "." : <incs> : <selfdir>/../../lib // resolvemodule search-path order: "." : <incs> : selected source library.
fn buildsearchpath(selfdir: *u8, incs: *u8) *u8 = { fn buildsearchpath(selfdir: *u8, incs: *u8) *u8 = {
let buf: []u8 = alloc([], (os.PATH_MAX: u64) * 2u64)!; let libdir: *u8 = envpath("WW_SRCLIB");
if (libdir == nil) { libdir = envpath("WW_LIB"); };
if (libdir == nil) {
let candidate: *u8 = joinpathlit(selfdir, "../../lib");
if (os.access(pathstr(candidate), 0i32) == 0) {
libdir = candidate;
} else { if (os.access("lib", 0i32) == 0) {
libdir = "lib\0".ptr;
} else {
libdir = joinpathlit(selfdir, "../lib");
}; };
};
let need: u64 = 1u64 + 1u64 + cstrlen(libdir) + 1u64;
if (incs != nil && incs[0u64] != 0u8) {
need += cstrlen(incs) + 1u64;
};
let buf: []u8 = alloc([], need)!;
buf.len = need: i32;
let off: u64 = 0u64; let off: u64 = 0u64;
buf[off] = 46u8; off += 1u64; // '.' buf[off] = 46u8; off += 1u64; // '.'
if (incs != nil) { if (incs != nil) {
@@ -2829,8 +2876,7 @@ fn buildsearchpath(selfdir: *u8, incs: *u8) *u8 = {
}; };
}; };
buf[off] = 58u8; off += 1u64; buf[off] = 58u8; off += 1u64;
off = cstrinto(buf.ptr, off, selfdir); off = cstrinto(buf.ptr, off, libdir);
off = strinto(buf.ptr, off, "/../../lib");
cstrseal(buf.ptr, off); cstrseal(buf.ptr, off);
return buf.ptr; return buf.ptr;
}; };
@@ -3038,7 +3084,7 @@ fn dobuild(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
let isdir: i32 = 0; let isdir: i32 = 0;
let resolved: *u8 = resolvemodule(selfdir, src, incs.ptr, &isdir); let resolved: *u8 = resolvemodule(selfdir, src, incs.ptr, &isdir);
if (resolved == nil) { if (resolved == nil) {
cerr("ww build: cannot find module\n"); cerrpath("ww build: cannot find module ", src, "\n");
return 1; return 1;
}; };
if (packageonly != 0 && isdir == 0) { if (packageonly != 0 && isdir == 0) {
@@ -3225,7 +3271,7 @@ fn dorun(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
let isdir: i32 = 0; let isdir: i32 = 0;
let resolved: *u8 = resolvemodule(selfdir, src, incs.ptr, &isdir); let resolved: *u8 = resolvemodule(selfdir, src, incs.ptr, &isdir);
if (resolved == nil) { if (resolved == nil) {
cerr("ww run: cannot find module\n"); cerrpath("ww run: cannot find module ", src, "\n");
return 1; return 1;
}; };