diff options
-rw-r--r-- | changelog.md | 10 | ||||
-rw-r--r-- | compiler/cmdlinehelper.nim | 8 | ||||
-rw-r--r-- | compiler/commands.nim | 4 | ||||
-rw-r--r-- | compiler/docgen.nim | 21 | ||||
-rw-r--r-- | compiler/extccomp.nim | 15 | ||||
-rw-r--r-- | compiler/main.nim | 77 | ||||
-rw-r--r-- | compiler/options.nim | 4 | ||||
-rw-r--r-- | lib/packages/docutils/rstgen.nim | 2 | ||||
-rw-r--r-- | tests/misc/mbackend.nim | 31 | ||||
-rw-r--r-- | tests/nimdoc/m13129.nim | 2 | ||||
-rw-r--r-- | tests/trunner.nim | 10 |
11 files changed, 125 insertions, 59 deletions
diff --git a/changelog.md b/changelog.md index a93a7e651..986186356 100644 --- a/changelog.md +++ b/changelog.md @@ -160,8 +160,8 @@ proc mydiv(a, b): int {.raises: [].} = - 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 +- New command: `nim r main.nim [args...]` which compiles and runs main.nim, and implies `--usenimcache` + so that output is saved 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: @@ -178,6 +178,12 @@ proc mydiv(a, b): int {.raises: [].} = - new hint: `--hint:msgOrigin` will show where a compiler msg (hint|warning|error) was generated; this helps in particular when it's non obvious where it came from either because multiple locations generate the same message, or because the message involves runtime formatting. +- new flag `--backend:js|c|cpp|objc (or -b:js etc), to change backend; can be used with any command + (eg nim r, doc, check etc); safe to re-assign. +- new flag `--doccmd:cmd` to pass additional flags for runnableExamples, eg: `--doccmd:-d:foo --threads` + use `--doccmd:skip` to skip runnableExamples and rst test snippets. +- new flag `--usenimcache` to output to nimcache (whatever it resolves to after all commands are processed) + and avoids polluting both $pwd and $projectdir. It can be used with any command. ## Tool changes diff --git a/compiler/cmdlinehelper.nim b/compiler/cmdlinehelper.nim index dd74f54dc..4777af8df 100644 --- a/compiler/cmdlinehelper.nim +++ b/compiler/cmdlinehelper.nim @@ -75,14 +75,6 @@ proc loadConfigsAndRunMainCommand*(self: NimProg, cache: IdentCache; conf: Confi # now process command line arguments again, because some options in the # command line can overwrite the config file's settings extccomp.initVars(conf) - # XXX This is hacky. We need to find a better way. - case conf.command - of "cpp", "compiletocpp": - conf.backend = backendCpp - conf.cmd = cmdCompileToBackend - else: - discard - self.processCmdLine(passCmd2, "", conf) if conf.command == "": rawMessage(conf, errGenerated, "command missing") diff --git a/compiler/commands.nim b/compiler/commands.nim index 2ab79f14a..340180378 100644 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -502,8 +502,6 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; defineSymbol(conf.symbols, "gcmarkandsweep") of "destructors", "arc": conf.selectedGC = gcArc - if conf.backend != backendCpp: - conf.exc = excGoto defineSymbol(conf.symbols, "gcdestructors") defineSymbol(conf.symbols, "gcarc") incl conf.globalOptions, optSeqDestructors @@ -513,8 +511,6 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; defineSymbol(conf.symbols, "nimV2") of "orc": conf.selectedGC = gcOrc - if conf.backend != backendCpp: - conf.exc = excGoto defineSymbol(conf.symbols, "gcdestructors") defineSymbol(conf.symbols, "gcorc") incl conf.globalOptions, optSeqDestructors diff --git a/compiler/docgen.nim b/compiler/docgen.nim index d774fd508..b594921ae 100644 --- a/compiler/docgen.nim +++ b/compiler/docgen.nim @@ -216,13 +216,20 @@ proc newDocumentor*(filename: AbsoluteFile; cache: IdentCache; conf: ConfigRef, # Include the current file if we're parsing a nim file let importStmt = if d.isPureRst: "" else: "import \"$1\"\n" % [d.filename.replace("\\", "/")] writeFile(outp, importStmt & content) - let c = if cmd.startsWith("nim <backend> "): os.getAppFilename() & " " & $conf.backend & cmd.substr("nim <backend>".len) - elif cmd.startsWith("nim "): os.getAppFilename() & cmd.substr("nim".len) - else: cmd - let c2 = c % quoteShell(outp) - rawMessage(conf, hintExecuting, c2) - if execShellCmd(c2) != status: - rawMessage(conf, errGenerated, "executing of external program failed: " & c2) + + proc interpSnippetCmd(cmd: string): string = + # backward compatibility hacks; interpolation commands should explicitly use `$` + if cmd.startsWith "nim ": result = "$nim " & cmd[4..^1] + else: result = cmd + result = result.replace("$1", "$options") % [ + "nim", os.getAppFilename().quoteShell, + "backend", $d.conf.backend, + "options", outp.quoteShell, + ] + let cmd = cmd.interpSnippetCmd + rawMessage(conf, hintExecuting, cmd) + if execShellCmd(cmd) != status: + rawMessage(conf, errGenerated, "executing of external program failed: " & cmd) result.emitted = initIntSet() result.destFile = getOutFile2(conf, presentationPath(conf, filename), outExt, htmldocsDir, false) diff --git a/compiler/extccomp.nim b/compiler/extccomp.nim index 3c2435bec..4c5b195ab 100644 --- a/compiler/extccomp.nim +++ b/compiler/extccomp.nim @@ -306,13 +306,14 @@ proc isVSCompatible*(conf: ConfigRef): bool = proc getConfigVar(conf: ConfigRef; c: TSystemCC, suffix: string): string = # use ``cpu.os.cc`` for cross compilation, unless ``--compileOnly`` is given # for niminst support - let fullSuffix = - case conf.backend - of backendCpp, backendJs, backendObjc: "." & $conf.backend & suffix - of backendC: suffix - else: - doAssert false - "" + var fullSuffix = suffix + case conf.backend + of backendCpp, backendJs, backendObjc: fullSuffix = "." & $conf.backend & suffix + of backendC: discard + of backendInvalid: + # during parsing of cfg files; we don't know the backend yet, no point in + # guessing wrong thing + return "" if (conf.target.hostOS != conf.target.targetOS or conf.target.hostCPU != conf.target.targetCPU) and optCompileOnly notin conf.globalOptions: diff --git a/compiler/main.nim b/compiler/main.nim index 00bc579df..21c0695f6 100644 --- a/compiler/main.nim +++ b/compiler/main.nim @@ -114,8 +114,10 @@ proc commandJsonScript(graph: ModuleGraph) = let proj = changeFileExt(graph.config.projectFull, "") extccomp.runJsonBuildInstructions(graph.config, proj) -when not defined(leanCompiler): - proc commandCompileToJS(graph: ModuleGraph) = +proc commandCompileToJS(graph: ModuleGraph) = + when defined(leanCompiler): + globalError(graph.config, unknownLineInfo, "compiler wasn't built with JS code generator") + else: let conf = graph.config conf.exc = excCpp @@ -194,47 +196,65 @@ proc mainCommand*(graph: ModuleGraph) = when false: setOutDir(conf) if optUseNimcache in conf.globalOptions: setOutDir(conf) - template handleBackend(backend2: TBackend) = - conf.backend = backend2 - conf.cmd = cmdCompileToBackend - defineSymbol(graph.config.symbols, $backend2) - case backend2 + proc customizeForBackend(backend: TBackend) = + ## Sets backend specific options but don't compile to backend yet in + ## case command doesn't require it. This must be called by all commands. + if conf.backend == backendInvalid: + # only set if wasn't already set, to allow override via `nim c -b:cpp` + conf.backend = backend + + defineSymbol(graph.config.symbols, $conf.backend) + case conf.backend of backendC: if conf.exc == excNone: conf.exc = excSetjmp - commandCompileToC(graph) of backendCpp: if conf.exc == excNone: conf.exc = excCpp - commandCompileToC(graph) - of backendObjc: - commandCompileToC(graph) + of backendObjc: discard of backendJs: - when defined(leanCompiler): - globalError(conf, unknownLineInfo, "compiler wasn't built with JS code generator") - else: - if conf.hcrOn: - # XXX: At the moment, system.nim cannot be compiled in JS mode - # with "-d:useNimRtl". The HCR option has been processed earlier - # and it has added this define implictly, so we must undo that here. - # A better solution might be to fix system.nim - undefSymbol(conf.symbols, "useNimRtl") - commandCompileToJS(graph) + if conf.hcrOn: + # XXX: At the moment, system.nim cannot be compiled in JS mode + # with "-d:useNimRtl". The HCR option has been processed earlier + # and it has added this define implictly, so we must undo that here. + # A better solution might be to fix system.nim + undefSymbol(conf.symbols, "useNimRtl") + of backendInvalid: doAssert false + if conf.selectedGC in {gcArc, gcOrc} and conf.backend != backendCpp: + conf.exc = excGoto + + var commandAlreadyProcessed = false + + proc compileToBackend(backend: TBackend, cmd = cmdCompileToBackend) = + commandAlreadyProcessed = true + conf.cmd = cmd + customizeForBackend(backend) + case conf.backend + of backendC: commandCompileToC(graph) + of backendCpp: commandCompileToC(graph) + of backendObjc: commandCompileToC(graph) + of backendJs: commandCompileToJS(graph) of backendInvalid: doAssert false + ## process all backend commands case conf.command.normalize - of "c", "cc", "compile", "compiletoc": handleBackend(backendC) # compile means compileToC currently - of "cpp", "compiletocpp": handleBackend(backendCpp) - of "objc", "compiletooc": handleBackend(backendObjc) - of "js", "compiletojs": handleBackend(backendJs) + of "c", "cc", "compile", "compiletoc": compileToBackend(backendC) # compile means compileToC currently + of "cpp", "compiletocpp": compileToBackend(backendCpp) + of "objc", "compiletooc": compileToBackend(backendObjc) + of "js", "compiletojs": compileToBackend(backendJs) of "r": # different from `"run"`! conf.globalOptions.incl {optRun, optUseNimcache} - handleBackend(conf.backend) + compileToBackend(backendC) of "run": - conf.cmd = cmdRun when hasTinyCBackend: extccomp.setCC(conf, "tcc", unknownLineInfo) - commandCompileToC(graph) + if conf.backend notin {backendC, backendInvalid}: + rawMessage(conf, errGenerated, "'run' requires c backend, got: '$1'" % $conf.backend) + compileToBackend(backendC, cmd = cmdRun) else: rawMessage(conf, errGenerated, "'run' command not available; rebuild with -d:tinyc") + else: customizeForBackend(backendC) # fallback for other commands + + ## process all other commands + case conf.command.normalize of "doc0": when defined(leanCompiler): quit "compiler wasn't built with documentation generator" @@ -383,6 +403,7 @@ proc mainCommand*(graph: ModuleGraph) = of "jsonscript": conf.cmd = cmdJsonScript commandJsonScript(graph) + elif commandAlreadyProcessed: discard # already handled else: rawMessage(conf, errGenerated, "invalid command: " & conf.command) diff --git a/compiler/options.nim b/compiler/options.nim index 3e6c7989f..194d635b1 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -223,7 +223,7 @@ type ## fields marked with '*' are subject to ## the incremental compilation mechanisms ## (+) means "part of the dependency" - backend*: TBackend + backend*: TBackend # set via `nim x` or `nim --backend:x` target*: Target # (+) linesCompiled*: int # all lines that have been compiled options*: TOptions # (+) @@ -419,7 +419,7 @@ proc newConfigRef*(): ConfigRef = cIncludes: @[], # directories to search for included files cLibs: @[], # directories to search for lib files cLinkedLibs: @[], # libraries to link - backend: backendC, + backend: backendInvalid, externalToLink: @[], linkOptionsCmd: "", compileOptionsCmd: @[], diff --git a/lib/packages/docutils/rstgen.nim b/lib/packages/docutils/rstgen.nim index edd987a76..816d724ef 100644 --- a/lib/packages/docutils/rstgen.nim +++ b/lib/packages/docutils/rstgen.nim @@ -865,7 +865,7 @@ proc parseCodeBlockField(d: PDoc, n: PRstNode, params: var CodeBlockParams) = of "test": params.testCmd = n.getFieldValue.strip if params.testCmd.len == 0: - params.testCmd = "nim <backend> -r $1" # The nim backend is auto-set in docgen.nim + params.testCmd = "$nim r --backend:$backend $options" # see `interpSnippetCmd` else: params.testCmd = unescape(params.testCmd) of "status", "exitcode": diff --git a/tests/misc/mbackend.nim b/tests/misc/mbackend.nim new file mode 100644 index 000000000..e38eb2d3e --- /dev/null +++ b/tests/misc/mbackend.nim @@ -0,0 +1,31 @@ +#[ +We can't merge this test inside a `when defined(cpp)` because some bug that was +fixed would not trigger in that case. +]# + +import std/compilesettings +import std/unittest + +static: + ## bugfix 1: this used to CT error with: Error: unhandled exception: mimportcpp.nim(6, 18) `defined(cpp)` + doAssert defined(cpp) + doAssert querySetting(backend) == "cpp" + + ## checks that `--backend:c` has no side effect (ie, can be overridden by subsequent commands) + doAssert not defined(c) + doAssert not defined(js) + doAssert not defined(js) + +type + std_exception {.importcpp: "std::exception", header: "<exception>".} = object +proc what(s: std_exception): cstring {.importcpp: "((char *)#.what())".} + +var isThrown = false +try: + ## bugfix 2: this used to CT error with: Error: only a 'ref object' can be raised + raise std_exception() +except std_exception as ex: + doAssert ex.what().len > 0 + isThrown = true + +doAssert isThrown diff --git a/tests/nimdoc/m13129.nim b/tests/nimdoc/m13129.nim index df4b5a3f5..95d072d52 100644 --- a/tests/nimdoc/m13129.nim +++ b/tests/nimdoc/m13129.nim @@ -1,3 +1,5 @@ +# issue #13129 + when defined(cpp): {.push header: "<vector>".} type diff --git a/tests/trunner.nim b/tests/trunner.nim index bd74a8405..e89606bf7 100644 --- a/tests/trunner.nim +++ b/tests/trunner.nim @@ -123,6 +123,16 @@ else: # don't run twice the same test let cmd = fmt"{nim} r --backend:{mode} --hints:off --nimcache:{nimcache} {file}" check execCmdEx(cmd) == ("ok3\n", 0) + block: # further issues with `--backend` + let file = testsDir / "misc/mbackend.nim" + var cmd = fmt"{nim} doc -b:cpp --hints:off --nimcache:{nimcache} {file}" + check execCmdEx(cmd) == ("", 0) + cmd = fmt"{nim} check -b:c -b:cpp --hints:off --nimcache:{nimcache} {file}" + check execCmdEx(cmd) == ("", 0) + # issue https://github.com/timotheecour/Nim/issues/175 + cmd = fmt"{nim} c -b:js -b:cpp --hints:off --nimcache:{nimcache} {file}" + check execCmdEx(cmd) == ("", 0) + block: # some importc tests # issue #14314 let file = testsDir / "misc/mimportc.nim" |