cmd: compile packages from direct exports

This commit is contained in:
2026-08-12 01:12:50 +09:00
parent 9b970eb16a
commit 0ac0fd68ec
4 changed files with 265 additions and 108 deletions

View File

@@ -331,14 +331,10 @@ enumerate_dir_ww(const char *dirpath, char ***out_files)
* definer's qualified symbol (#53) equals the consumer's qualified
* reference (#40) and the sep `.o`s link. A dep is NEVER bare-embedded.
*
* The prepend is the TRANSITIVE closure of a package's deps (lead-
* ratified, superseding rob-c3-spec §1.3 "direct deps"): a dep's public
* interface can name a transitive dep's type (os exposes time.instant),
* so the consuming unit needs the whole closure for name RESOLUTION —
* direct-deps-only does not type-check. This mirrors harec reading the
* transitive `.td` closure. The checker still scopes qualifier lookup to
* each source package's direct N_USE declarations, so carrying those type
* facts does not make a transitive package source-visible.
* Only DIRECT dependency artifacts are prepended. A `.wwi` relocates the
* recursively reachable public foreign type/const facts required by its own
* API, retaining their origin modules without turning them into source
* imports. Full transitive reachability remains a linker concern.
*/
#define SEP_MAXPKG 256
@@ -749,15 +745,6 @@ sep_topo_visit(struct sepgraph *g, int pi, int *order, int *no,
return 0;
}
static void
sep_mark_deps(struct sepgraph *g, int pi, char *inset)
{
for (int k = 0; k < g->pkg[pi].ndeps; k++) {
int di = g->pkg[pi].deps[k];
if (!inset[di]) { inset[di] = 1; sep_mark_deps(g, di, inset); }
}
}
/* Emit one of pi's own source files into the sep-unit under the
* //ww:module-reset primary boundary (so -c emits its decls, imported
* ==0). DIRECTORY imports are skipped (provided as `.wwi` ahead of the
@@ -839,24 +826,21 @@ sep_emit_body(FILE *out, const char *path, struct ImportSet *visited,
return 0;
}
/* Compose pi's sep-unit at `unitf`: the transitive-closure `.wwi`s
* (reverse-topo order, each tagged by its dotted path), then pi's own
* body under //ww:module-reset. Directory membership comes only from the
* package node loaded before planning. */
/* Compose pi's sep-unit at `unitf`: its byte-sorted DIRECT dependency
* `.wwi`s, each tagged by its dotted path, then pi's own body under
* //ww:module-reset. Compiler exports are self-contained for public type
* facts; the linker separately retains the reachable archive closure. */
static int
sep_compose_unit(struct sepgraph *g, int pi, const char *scratch,
const int *order, int norder, const char *searchpath, const char *unitf)
const char *searchpath, const char *unitf)
{
FILE *u = fopen(unitf, "wb");
if (u == NULL) {
fprintf(stderr, "ww: cannot open %s\n", unitf);
return -1;
}
char inset[SEP_MAXPKG] = {0};
sep_mark_deps(g, pi, inset);
for (int oi = 0; oi < norder; oi++) {
int dj = order[oi];
if (dj == pi || !inset[dj]) continue;
for (int k = 0; k < g->pkg[pi].ndeps; k++) {
int dj = g->pkg[pi].deps[k];
char wwi[1024];
sep_fname(g, dj, scratch, ".wwi", wwi, sizeof wwi);
FILE *wf = fopen(wwi, "rb");
@@ -1043,7 +1027,7 @@ copy_file_atomic(const char *src, const char *dst)
static void
workdir_stamp_text(char *buf, size_t bufsz, int is_test, int emit_asm)
{
snprintf(buf, bufsz, "ww workdir fmt 1 mode %s asm %d\n",
snprintf(buf, bufsz, "ww workdir fmt 2 mode %s asm %d\n",
is_test ? "test" : "build", emit_asm);
}
@@ -1222,7 +1206,7 @@ build_one_sep_impl(const char *src, int entry_is_dir,
const char *ca = warm ? anew : apath;
int needs_export = pi != root || root_package;
int needs_archive = pi != root || root_package;
if (sep_compose_unit(g, pi, scratch, order, norder, srcdir,
if (sep_compose_unit(g, pi, scratch, srcdir,
cu) < 0) { free(order); return 1; }
if (warm && !stale_all && file_equal(unitnew, unitf)
&& file_is_reg(asmf)