This commit is contained in:
Araq
2026-06-10 19:51:25 +02:00
parent b72affa1a1
commit 0457ebc170
3 changed files with 43 additions and 8 deletions

View File

@@ -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"

View File

@@ -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]

View File

@@ -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):