From 0457ebc1703d57c03e09fd6281c852cfc25bca5d Mon Sep 17 00:00:00 2001 From: Araq Date: Wed, 10 Jun 2026 19:51:25 +0200 Subject: [PATCH] progress --- compiler/deps.nim | 36 +++++++++++++++++++++++++++++------- koch.nim | 10 ++++++++++ lib/system/mmdisp.nim | 5 ++++- 3 files changed, 43 insertions(+), 8 deletions(-) diff --git a/compiler/deps.nim b/compiler/deps.nim index d8e6632d10..dd69e096a8 100644 --- a/compiler/deps.nim +++ b/compiler/deps.nim @@ -156,6 +156,25 @@ proc skipSubtree(s: var Stream; first: PackedToken) = elif t.kind == ParRi: dec depth elif t.kind == EofToken: return +proc evalCondIdent(c: DepContext; v: string): bool = + ## Truth value of a bare identifier appearing in a `when` condition. + case v + of "false": false + of "hasThreadSupport": + # system.nim's `hasThreadSupport` is `compileOption("threads") and + # not defined(nimscript)`; the conservative `true` would schedule the + # threads-only modules (syslocks, threadtypes, sharedlist, locks) + # whose NIFs a --threads:off compile never produces — nifmake then + # sees missing outputs and re-runs the system rule (and everything + # downstream) on every rerun. + optThreads in c.config.globalOptions + of "usesDestructors": + # system.nim's `usesDestructors = defined(gcDestructors) or + # defined(gcHooks)`; guards mmdisp.nim's `include "system/gc"` whose + # transitive imports (sharedlist, locks) an orc compile never produces. + isDefined(c.config, "gcDestructors") or isDefined(c.config, "gcHooks") + else: true + proc evalCondExpr(c: DepContext; s: var Stream): bool = ## Read exactly one condition expression from `s` and return its truth ## value. Consumes tokens whether the expression is recognised or not so @@ -167,10 +186,7 @@ proc evalCondExpr(c: DepContext; s: var Stream): bool = let t = next(s) case t.kind of Ident: - case pool.strings[t.litId] - of "true": result = true - of "false": result = false - else: result = true + result = evalCondIdent(c, pool.strings[t.litId]) of ParLe: let tag = pool.tags[t.tagId] case tag @@ -319,9 +335,8 @@ proc whenMarkerHolds(c: DepContext; s: var Stream): bool = # Unknown — treat as true and skip. skipSubtree(s, t) elif t.kind == Ident: - let v = pool.strings[t.litId] - if v == "false": result = false - # else (true / unknown ident): keep result + if not evalCondIdent(c, pool.strings[t.litId]): result = false + # a true / unknown ident keeps the current result proc parseImportPath(s: var Stream; t: var PackedToken): seq[string] = ## Parse an import path expression and return the list of module paths it @@ -549,6 +564,13 @@ proc generateBuildFile(c: DepContext): string = forwardedArgs.add "--define:" & k & (if v == "true": "" else: "=" & v) sort forwardedArgs forwardedArgs.add "--threads:" & (if optThreads in c.config.globalOptions: "on" else: "off") + # Forward the memory-management mode too: the children would otherwise + # compile with the default GC while the dependency graph here was computed + # with the selected one (e.g. under --mm:refc the scanner keeps + # system/gc's transitive imports but default-orc children never compile + # them — phantom outputs that re-fire the build on every rerun). + if c.config.selectedGC != gcUnselected: + forwardedArgs.add "--mm:" & $c.config.selectedGC # Define nifler command b.addTree "cmd" diff --git a/koch.nim b/koch.nim index 6fff0de5af..bf295c62f9 100644 --- a/koch.nim +++ b/koch.nim @@ -427,8 +427,18 @@ proc bootic(args: string, skipIntegrityCheck: bool) = let nimStart = findStartNim().quoteShell() let times = 2 - ord(skipIntegrityCheck) + # `boot` shares the `compiler/nim` output path; remove it so a fully warm + # cache still relinks and iteration 1 cannot adopt a stale foreign binary. + removeFile output for i in 0..times: echo "iteration: ", i+1 + # Iteration 1 may build incrementally (that's the point of IC), but every + # later iteration must start from a clean cache: with a warm cache a + # no-change rerun correctly rebuilds nothing, so iteration i+1 would just + # keep iteration i's binary and the fixed-point check would be vacuous. + # The check is only meaningful if the freshly built compiler re-translates + # everything. + if i > 0: removeDir smartNimcache let nimi = if i == 0: nimStart else: i.thVersion exec "$# ic --nimcache:$# $# compiler" / "nim.nim" % [nimi, smartNimcache, args] diff --git a/lib/system/mmdisp.nim b/lib/system/mmdisp.nim index 7fd61e0dc3..100ae442ca 100644 --- a/lib/system/mmdisp.nim +++ b/lib/system/mmdisp.nim @@ -91,7 +91,10 @@ else: elif defined(gcMarkAndSweep): # XXX use 'compileOption' here include "system/gc_ms" - else: + elif not (defined(nimV2) or usesDestructors): + # equivalent to a plain `else` here, but spelled out so that the IC + # dependency scanner (which sees `else` imports/includes unguarded) + # doesn't schedule system/gc's transitive imports under --mm:orc include "system/gc" when not declared(nimNewSeqOfCap) and not defined(nimSeqsV2):