Skip to content

Commit

Permalink
new cmd: nim r main [args...] to compile & run, saving binary under…
Browse files Browse the repository at this point in the history
… $nimcache/main (#13382)

* implement `nim r main` to compile and run, saving binary to $nimcache
* remove outFileAbs for now
  • Loading branch information
timotheecour authored Apr 23, 2020
1 parent 4b43d42 commit 5c534b2
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 16 deletions.
11 changes: 11 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,17 @@

- Specific warnings can now be turned into errors via `--warningAsError[X]:on|off`.
- The `define` and `undef` pragmas have been de-deprecated.
- New command: `nim r main.nim [args...]` which compiles and runs main.nim, saving
the binary to $nimcache/main$exeExt, using the same logic as `nim c -r` to
avoid recompiling when sources don't change. This is now the preferred way to
run tests, avoiding the usual pain of clobbering your repo with binaries or
using tricky gitignore rules on posix. Example:
```nim
nim r compiler/nim.nim --help # only compiled the first time
echo 'import os; echo getCurrentCompilerExe()' | nim r - # this works too
nim r compiler/nim.nim --fullhelp # no recompilation
nim r --nimcache:/tmp main # binary saved to /tmp/main
```

## Tool changes

25 changes: 17 additions & 8 deletions compiler/main.nim
Original file line number Diff line number Diff line change
Expand Up @@ -66,16 +66,22 @@ when not defined(leanCompiler):
compileProject(graph)
finishDoc2Pass(graph.config.projectName)

proc setOutDir(conf: ConfigRef) =
if conf.outDir.isEmpty:
if optUseNimcache in conf.globalOptions:
conf.outDir = getNimcacheDir(conf)
else:
conf.outDir = conf.projectPath

proc commandCompileToC(graph: ModuleGraph) =
let conf = graph.config

if conf.outDir.isEmpty:
conf.outDir = conf.projectPath
setOutDir(conf)
if conf.outFile.isEmpty:
let base = conf.projectName
let targetName = if optGenDynLib in conf.globalOptions:
platform.OS[conf.target.targetOS].dllFrmt % conf.projectName
platform.OS[conf.target.targetOS].dllFrmt % base
else:
conf.projectName & platform.OS[conf.target.targetOS].exeExt
base & platform.OS[conf.target.targetOS].exeExt
conf.outFile = RelativeFile targetName

extccomp.initVars(conf)
Expand Down Expand Up @@ -181,13 +187,13 @@ proc mainCommand*(graph: ModuleGraph) =
conf.lastCmdTime = epochTime()
conf.searchPaths.add(conf.libpath)
setId(100)
case conf.command.normalize
of "c", "cc", "compile", "compiletoc":
# compile means compileToC currently
template handleC() =
conf.cmd = cmdCompileToC
if conf.exc == excNone: conf.exc = excSetjmp
defineSymbol(graph.config.symbols, "c")
commandCompileToC(graph)
case conf.command.normalize
of "c", "cc", "compile", "compiletoc": handleC() # compile means compileToC currently
of "cpp", "compiletocpp":
conf.cmd = cmdCompileToCpp
if conf.exc == excNone: conf.exc = excCpp
Expand All @@ -197,6 +203,9 @@ proc mainCommand*(graph: ModuleGraph) =
conf.cmd = cmdCompileToOC
defineSymbol(graph.config.symbols, "objc")
commandCompileToC(graph)
of "r": # different from `"run"`!
conf.globalOptions.incl {optRun, optUseNimcache}
handleC()
of "run":
conf.cmd = cmdRun
when hasTinyCBackend:
Expand Down
2 changes: 1 addition & 1 deletion compiler/nim.nim
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ proc processCmdLine(pass: TCmdLinePass, cmd: string; config: ConfigRef) =
if processArgument(pass, p, argsCount, config): break
if pass == passCmd2:
if {optRun, optWasNimscript} * config.globalOptions == {} and
config.arguments.len > 0 and config.command.normalize notin ["run", "e"]:
config.arguments.len > 0 and config.command.normalize notin ["run", "e", "r"]:
rawMessage(config, errGenerated, errArgsNeedRunOption)

proc handleCmdLine(cache: IdentCache; conf: ConfigRef) =
Expand Down
16 changes: 9 additions & 7 deletions compiler/options.nim
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ type # please make sure we have under 32 options
optGenScript, # generate a script file to compile the *.c files
optGenMapping, # generate a mapping file
optRun, # run the compiled project
optUseNimcache, # save artifacts (including binary) in $nimcache
optStyleHint, # check that the names adhere to NEP-1
optStyleError, # enforce that the names adhere to NEP-1
optSkipSystemConfigFile, # skip the system's cfg/nims config file
Expand Down Expand Up @@ -524,18 +525,19 @@ proc getOutFile*(conf: ConfigRef; filename: RelativeFile, ext: string): Absolute
conf.outDir / changeFileExt(filename, ext)

proc absOutFile*(conf: ConfigRef): AbsoluteFile =
if false:
doAssert not conf.outDir.isEmpty
doAssert not conf.outFile.isEmpty
# xxx: fix this pre-existing bug causing `SuccessX` error messages to lie
# for `jsonscript`
result = conf.outDir / conf.outFile
when defined(posix):
if dirExists(result.string):
result.string.add ".out"
if dirExists(result.string): result.string.add ".out"

proc prepareToWriteOutput*(conf: ConfigRef): AbsoluteFile =
## Create the output directory and returns a full path to the output file
createDir conf.outDir
result = conf.outDir / conf.outFile
when defined(posix):
if dirExists(result.string):
result.string.add ".out"
result = conf.absOutFile
createDir result.string.parentDir

proc getPrefixDir*(conf: ConfigRef): AbsoluteDir =
## Gets the prefix dir, usually the parent directory where the binary resides.
Expand Down
1 change: 1 addition & 0 deletions doc/basicopt.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

Command:
//compile, c compile project with default code generator (C)
//r compile & run $nimcach/projname [arguments]
//doc generate the documentation for inputfile

Arguments:
Expand Down

0 comments on commit 5c534b2

Please sign in to comment.