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
71a2c2a
implements #25268; cache configuration evaluation
demotomohiro Nov 10, 2025
025e747
don't use cached config when new config file is created
demotomohiro Nov 11, 2025
fde236a
store/load ConfigRef fields
demotomohiro Nov 11, 2025
765d7c9
adds test and fixes bug
demotomohiro Nov 12, 2025
7f926c0
store/load ConfigRef fields
demotomohiro Nov 12, 2025
bd82eab
clean up code
demotomohiro Nov 12, 2025
4e47dc8
clean up code
demotomohiro Nov 12, 2025
ffb04a2
store/load ConfigRef fields
demotomohiro Nov 13, 2025
529c697
store/load ConfigRef fields
demotomohiro Nov 14, 2025
a1db184
store/load ConfigRef fields
demotomohiro Nov 14, 2025
47afa49
clean up code
demotomohiro Nov 15, 2025
4c5c37c
clean up code
demotomohiro Nov 15, 2025
73c9987
clean up code
demotomohiro Nov 15, 2025
e6b8fbb
store/load ConfigRef fields
demotomohiro Nov 16, 2025
7a3fda0
makes compile-time define pragmas works when using cache
demotomohiro Nov 16, 2025
a5494e5
clean up code
demotomohiro Nov 16, 2025
9658008
store/load ConfigRef fields
demotomohiro Nov 17, 2025
0a2a13c
updates documentations
demotomohiro Nov 18, 2025
b397650
fixes doc/advopt.txt
demotomohiro Nov 18, 2025
ad98069
temporary enable cache config by default for CI
demotomohiro Nov 28, 2025
003020b
add project name to the cache file name so that parallel build works
demotomohiro Nov 29, 2025
79131d0
makes tests/misc/trunner.nim prints more errors when failed
demotomohiro Nov 29, 2025
d3d111b
fixes cache file name
demotomohiro Nov 29, 2025
ed29ae0
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 @@ -101,6 +101,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 @@ -1009,6 +1009,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