Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
fad12cb
implements #25268; cache configuration evaluation
demotomohiro Nov 10, 2025
256763a
don't use cached config when new config file is created
demotomohiro Nov 11, 2025
3c939ab
store/load ConfigRef fields
demotomohiro Nov 11, 2025
7c54e27
adds test and fixes bug
demotomohiro Nov 12, 2025
68b3e5d
store/load ConfigRef fields
demotomohiro Nov 12, 2025
04b2111
clean up code
demotomohiro Nov 12, 2025
a2f0299
clean up code
demotomohiro Nov 12, 2025
6844d03
store/load ConfigRef fields
demotomohiro Nov 13, 2025
ffa830e
store/load ConfigRef fields
demotomohiro Nov 14, 2025
532c893
store/load ConfigRef fields
demotomohiro Nov 14, 2025
198d06c
clean up code
demotomohiro Nov 15, 2025
dc5d574
clean up code
demotomohiro Nov 15, 2025
760bbb6
clean up code
demotomohiro Nov 15, 2025
42e39e5
store/load ConfigRef fields
demotomohiro Nov 16, 2025
1979f6c
makes compile-time define pragmas works when using cache
demotomohiro Nov 16, 2025
b78da5b
clean up code
demotomohiro Nov 16, 2025
93fb9b4
store/load ConfigRef fields
demotomohiro Nov 17, 2025
016bdbd
updates documentations
demotomohiro Nov 18, 2025
8eb0814
fixes doc/advopt.txt
demotomohiro Nov 18, 2025
b9ca60b
temporary enable cache config by default for CI
demotomohiro Nov 28, 2025
e88ad18
add project name to the cache file name so that parallel build works
demotomohiro Nov 29, 2025
09dabe4
makes tests/misc/trunner.nim prints more errors when failed
demotomohiro Nov 29, 2025
ed04084
fixes cache file name
demotomohiro Nov 29, 2025
848e69f
load nimblePaths so that conf.lazyPaths is initialized
demotomohiro Nov 30, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ errors.

## Compiler changes

- Added `--cachecfg` command line option that caches the result of evaluation of cfg/NimScript configuration files to reduces the compile time.

## Tool changes

Expand Down
2 changes: 2 additions & 0 deletions compiler/commands.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1016,6 +1016,8 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
processOnOffSwitchG(conf, {optSkipUserConfigFile}, arg, pass, info)
of "skipparentcfg":
processOnOffSwitchG(conf, {optSkipParentConfigFiles}, arg, pass, info)
of "cachecfg":
processOnOffSwitchG(conf, {optCacheConfig}, arg, pass, info)
of "genscript", "gendeps":
if switch.normalize == "gendeps": deprecatedAlias(switch, "genscript")
processOnOffSwitchG(conf, {optGenScript}, arg, pass, info)
Expand Down
77 changes: 62 additions & 15 deletions compiler/nimconf.nim
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@

import
llstream, commands, msgs, lexer, ast,
options, idents, wordrecg, lineinfos, pathutils, scriptconfig
options, idents, wordrecg, lineinfos, pathutils, scriptconfig, nimconfcache

import std/[os, strutils, strtabs]
import std/[os, strutils, strtabs, sets, times]

when defined(nimPreviewSlimSystem):
import std/syncio
Expand Down Expand Up @@ -244,25 +244,39 @@ proc getSystemConfigPath*(conf: ConfigRef; filename: RelativeFile): AbsoluteFile
if not fileExists(result): result = p / RelativeDir"etc/nim" / filename
if not fileExists(result): result = AbsoluteDir"/etc/nim" / filename

proc loadConfigs*(cfg: RelativeFile; cache: IdentCache; conf: ConfigRef; idgen: IdGenerator) =
proc loadConfigsImpl(cfg: RelativeFile; cache: IdentCache; conf: ConfigRef; idgen: IdGenerator; cachedCfgFiles: var HashSet[string]) =
# `cachedCfgFiles` is used to detect newly created config files.
# if cachedCfgFiles.len == 0, evaluate config files,
# if not, doesn't evaluate but find newly created config files.
# clears `cachedCfgFiles` if found.
setDefaultLibpath(conf)
template readConfigFile(path) =
let configPath = path
conf.currentConfigDir = configPath.splitFile.dir.string
setConfigVar(conf, "selfDir", conf.currentConfigDir)
if readConfigFile(configPath, cache, conf):
conf.configFiles.add(configPath)
if cachedCfgFiles.len == 0:
conf.currentConfigDir = configPath.splitFile.dir.string
setConfigVar(conf, "selfDir", conf.currentConfigDir)
if readConfigFile(configPath, cache, conf):
conf.configFiles.add(configPath)
elif configPath.string notin cachedCfgFiles and configPath.fileExists:
#echo "config file was created ", configPath
cachedCfgFiles = HashSet[string]()
return

template runNimScriptIfExists(path: AbsoluteFile, isMain = false) =
let p = path # eval once
var s: PLLStream = nil
if isMain and optWasNimscript in conf.globalOptions:
if conf.projectIsStdin: s = stdin.llStreamOpen
elif conf.projectIsCmd: s = llStreamOpen(conf.cmdInput)
if s == nil and fileExists(p): s = llStreamOpen(p, fmRead)
if s != nil:
conf.configFiles.add(p)
runNimScript(cache, p, idgen, freshDefines = false, conf, s)
if cachedCfgFiles.len == 0:
var s: PLLStream = nil
if isMain and optWasNimscript in conf.globalOptions:
if conf.projectIsStdin: s = stdin.llStreamOpen
elif conf.projectIsCmd: s = llStreamOpen(conf.cmdInput)
if s == nil and fileExists(p): s = llStreamOpen(p, fmRead)
if s != nil:
conf.configFiles.add(p)
runNimScript(cache, p, idgen, freshDefines = false, conf, s)
elif p.string notin cachedCfgFiles and p.fileExists:
#echo "config file was created ", p
cachedCfgFiles = HashSet[string]()
return

if optSkipSystemConfigFile notin conf.globalOptions:
readConfigFile(getSystemConfigPath(conf, cfg))
Expand Down Expand Up @@ -319,3 +333,36 @@ proc loadConfigs*(cfg: RelativeFile; cache: IdentCache; conf: ConfigRef; idgen:
# `nim check foo.nims' means to check the syntax of the NimScript file
discard
showHintConf()

proc canUseCache(cfg: RelativeFile; cache: IdentCache; conf: ConfigRef; idgen: IdGenerator; cachedCfgFiles: var HashSet[string]): bool =
if optForceFullMake in conf.globalOptions or optCacheConfig notin conf.globalOptions:
result = false
elif conf.cmd == cmdNimscript:
# loadConfigsImpl runs Nim script
result = false
else:
# Don't use cached config when:
# - cache doesn't exists
# - command line parameter is changed (config file can depend it)
# - config file is changed, removed or created
cachedCfgFiles = sourceChanged(conf)
if cachedCfgFiles.len == 0:
result = false
else:
#echo formatFloat(epochTime() - conf.lastCmdTime, ffDecimal, 3), " checking added config"
loadConfigsImpl(cfg, cache, conf, idgen, cachedCfgFiles)
#echo formatFloat(epochTime() - conf.lastCmdTime, ffDecimal, 3), " done checking added config"
result = cachedCfgFiles.len != 0

proc loadConfigs*(cfg: RelativeFile; cache: IdentCache; conf: ConfigRef; idgen: IdGenerator) =
#conf.lastCmdTime = epochTime()
var cachedCfgFiles = HashSet[string]()
if canUseCache(cfg, cache, conf, idgen, cachedCfgFiles):
#echo formatFloat(epochTime() - conf.lastCmdTime, ffDecimal, 3), " loading cached config"
loadConfigsFromCache(conf)
#echo formatFloat(epochTime() - conf.lastCmdTime, ffDecimal, 3), " done loading cached config"
else:
#echo formatFloat(epochTime() - conf.lastCmdTime, ffDecimal, 3), " evaluating config files"
loadConfigsImpl(cfg, cache, conf, idgen, cachedCfgFiles)
#echo formatFloat(epochTime() - conf.lastCmdTime, ffDecimal, 3), " done evaluating config files"
storeConfigs(conf)
Loading
Loading