diff options
Diffstat (limited to 'compiler/nim.nim')
-rw-r--r-- | compiler/nim.nim | 202 |
1 files changed, 119 insertions, 83 deletions
diff --git a/compiler/nim.nim b/compiler/nim.nim index 90049bdfb..005f11a58 100644 --- a/compiler/nim.nim +++ b/compiler/nim.nim @@ -7,21 +7,29 @@ # distribution, for details about the copyright. # -when defined(gcc) and defined(windows): - when defined(x86): - {.link: "icons/nim.res".} - else: - {.link: "icons/nim_icon.o".} +import std/[os, strutils, parseopt] + +when defined(nimPreviewSlimSystem): + import std/assertions -when defined(amd64) and defined(windows) and defined(vcc): - {.link: "icons/nim-amd64-windows-vcc.res".} -when defined(i386) and defined(windows) and defined(vcc): - {.link: "icons/nim-i386-windows-vcc.res".} +when defined(windows): + when defined(gcc): + when defined(x86): + {.link: "../icons/nim.res".} + else: + {.link: "../icons/nim_icon.o".} + + when defined(amd64) and defined(vcc): + {.link: "../icons/nim-amd64-windows-vcc.res".} + when defined(i386) and defined(vcc): + {.link: "../icons/nim-i386-windows-vcc.res".} import - commands, lexer, condsyms, options, msgs, nversion, nimconf, ropes, - extccomp, strutils, os, osproc, platform, main, parseopt, - nodejs, scriptconfig, idents, modulegraphs, lineinfos + commands, options, msgs, extccomp, main, idents, lineinfos, cmdlinehelper, + pathutils, modulegraphs + +from std/browsers import openDefaultBrowser +from nodejs import findNodeJs when hasTinyCBackend: import tccgen @@ -30,101 +38,129 @@ when defined(profiler) or defined(memProfiler): {.hint: "Profiling support is turned on!".} import nimprof -proc prependCurDir(f: string): string = - when defined(unix): - if os.isAbsolute(f): result = f - else: result = "./" & f - else: - result = f +proc nimbleLockExists(config: ConfigRef): bool = + const nimbleLock = "nimble.lock" + let pd = if not config.projectPath.isEmpty: config.projectPath else: AbsoluteDir(getCurrentDir()) + if optSkipParentConfigFiles notin config.globalOptions: + for dir in parentDirs(pd.string, fromRoot=true, inclusive=false): + if fileExists(dir / nimbleLock): + return true + return fileExists(pd.string / nimbleLock) proc processCmdLine(pass: TCmdLinePass, cmd: string; config: ConfigRef) = var p = parseopt.initOptParser(cmd) var argsCount = 0 + + config.commandLine.setLen 0 + # bugfix: otherwise, config.commandLine ends up duplicated + while true: parseopt.next(p) case p.kind of cmdEnd: break - of cmdLongoption, cmdShortOption: - if p.key == " ": + of cmdLongOption, cmdShortOption: + config.commandLine.add " " + config.commandLine.addCmdPrefix p.kind + config.commandLine.add p.key.quoteShell # quoteShell to be future proof + if p.val.len > 0: + config.commandLine.add ':' + config.commandLine.add p.val.quoteShell + + if p.key == "": # `-` was passed to indicate main project is stdin p.key = "-" if processArgument(pass, p, argsCount, config): break else: processSwitch(pass, p, config) of cmdArgument: + config.commandLine.add " " + config.commandLine.add p.key.quoteShell if processArgument(pass, p, argsCount, config): break if pass == passCmd2: - if optRun notin config.globalOptions and config.arguments.len > 0 and config.command.normalize != "run": + if {optRun, optWasNimscript} * config.globalOptions == {} and + config.arguments.len > 0 and config.cmd notin {cmdTcc, cmdNimscript, cmdCrun}: rawMessage(config, errGenerated, errArgsNeedRunOption) + if config.nimbleLockExists: + # disable nimble path if nimble.lock is present. + # see https://github.com/nim-lang/nimble/issues/1004 + disableNimblePath(config) + +proc getNimRunExe(conf: ConfigRef): string = + # xxx consider defining `conf.getConfigVar("nimrun.exe")` to allow users to + # customize the binary to run the command with, e.g. for custom `nodejs` or `wine`. + if conf.isDefined("mingw"): + if conf.isDefined("i386"): result = "wine" + elif conf.isDefined("amd64"): result = "wine64" + else: result = "" + else: + result = "" + proc handleCmdLine(cache: IdentCache; conf: ConfigRef) = - condsyms.initDefines(conf.symbols) + let self = NimProg( + supportsStdinFile: true, + processCmdLine: processCmdLine + ) + self.initDefinesProg(conf, "nim_compiler") if paramCount() == 0: - writeCommandLineUsage(conf, conf.helpWritten) - else: - # Process command line arguments: - processCmdLine(passCmd1, "", conf) - if conf.projectName == "-": - conf.projectName = "stdinfile" - conf.projectFull = "stdinfile" - conf.projectPath = canonicalizePath(conf, getCurrentDir()) - conf.projectIsStdin = true - elif conf.projectName != "": - try: - conf.projectFull = canonicalizePath(conf, conf.projectName) - except OSError: - conf.projectFull = conf.projectName - let p = splitFile(conf.projectFull) - let dir = if p.dir.len > 0: p.dir else: getCurrentDir() - conf.projectPath = canonicalizePath(conf, dir) - conf.projectName = p.name + writeCommandLineUsage(conf) + return + + self.processCmdLineAndProjectPath(conf) + + var graph = newModuleGraph(cache, conf) + if not self.loadConfigsAndProcessCmdLine(cache, conf, graph): + return + + if conf.cmd == cmdCheck and optWasNimscript notin conf.globalOptions and + conf.backend == backendInvalid: + conf.backend = backendC + + if conf.selectedGC == gcUnselected: + if conf.backend in {backendC, backendCpp, backendObjc} or + (conf.cmd in cmdDocLike and conf.backend != backendJs) or + conf.cmd == cmdGendepend: + initOrcDefines(conf) + + mainCommand(graph) + if conf.hasHint(hintGCStats): echo(GC_getStatistics()) + #echo(GC_getStatistics()) + if conf.errorCounter != 0: return + when hasTinyCBackend: + if conf.cmd == cmdTcc: + tccgen.run(conf, conf.arguments) + if optRun in conf.globalOptions: + let output = conf.absOutFile + case conf.cmd + of cmdBackends, cmdTcc: + let nimRunExe = getNimRunExe(conf) + var cmdPrefix = "" + if nimRunExe.len > 0: cmdPrefix.add nimRunExe.quoteShell + case conf.backend + of backendC, backendCpp, backendObjc: discard + of backendJs: + # D20210217T215950:here this flag is needed for node < v15.0.0, otherwise + # tasyncjs_fail` would fail, refs https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode + if cmdPrefix.len == 0: cmdPrefix = findNodeJs().quoteShell + cmdPrefix.add " --unhandled-rejections=strict" + else: raiseAssert $conf.backend + if cmdPrefix.len > 0: cmdPrefix.add " " + # without the `cmdPrefix.len > 0` check, on windows you'd get a cryptic: + # `The parameter is incorrect` + let cmd = cmdPrefix & output.quoteShell & ' ' & conf.arguments + execExternalProgram(conf, cmd.strip(leading=false,trailing=true)) + of cmdDocLike, cmdRst2html, cmdRst2tex, cmdMd2html, cmdMd2tex: # bugfix(cmdRst2tex was missing) + if conf.arguments.len > 0: + # reserved for future use + rawMessage(conf, errGenerated, "'$1 cannot handle arguments" % [$conf.cmd]) + openDefaultBrowser($output) else: - conf.projectPath = canonicalizePath(conf, getCurrentDir()) - loadConfigs(DefaultConfig, cache, conf) # load all config files - let scriptFile = conf.projectFull.changeFileExt("nims") - if fileExists(scriptFile): - runNimScript(cache, scriptFile, freshDefines=false, conf) - # 'nim foo.nims' means to just run the NimScript file and do nothing more: - if scriptFile == conf.projectFull: return - elif fileExists(conf.projectPath / "config.nims"): - # directory wide NimScript file - runNimScript(cache, conf.projectPath / "config.nims", freshDefines=false, conf) - # now process command line arguments again, because some options in the - # command line can overwite the config file's settings - extccomp.initVars(conf) - processCmdLine(passCmd2, "", conf) - if conf.command == "": - rawMessage(conf, errGenerated, "command missing") - mainCommand(newModuleGraph(cache, conf)) - if optHints in conf.options and hintGCStats in conf.notes: echo(GC_getStatistics()) - #echo(GC_getStatistics()) - if conf.errorCounter == 0: - when hasTinyCBackend: - if conf.cmd == cmdRun: - tccgen.run(conf.arguments) - if optRun in conf.globalOptions: - if conf.cmd == cmdCompileToJS: - var ex: string - if conf.outFile.len > 0: - ex = conf.outFile.prependCurDir.quoteShell - else: - ex = quoteShell( - completeCFilePath(conf, changeFileExt(conf.projectFull, "js").prependCurDir)) - execExternalProgram(conf, findNodeJs() & " " & ex & ' ' & conf.arguments) - else: - var binPath: string - if conf.outFile.len > 0: - # If the user specified an outFile path, use that directly. - binPath = conf.outFile.prependCurDir - else: - # Figure out ourselves a valid binary name. - binPath = changeFileExt(conf.projectFull, ExeExt).prependCurDir - var ex = quoteShell(binPath) - execExternalProgram(conf, ex & ' ' & conf.arguments) + # support as needed + rawMessage(conf, errGenerated, "'$1 cannot handle --run" % [$conf.cmd]) when declared(GC_setMaxPause): GC_setMaxPause 2_000 -when compileOption("gc", "v2") or compileOption("gc", "refc"): +when compileOption("gc", "refc"): # the new correct mark&sweet collector is too slow :-/ GC_disableMarkAndSweep() |