Show friendly error message when stdlib is outdated.

This commit is contained in:
Dominik Picheta 2018-01-27 15:37:19 +00:00
commit 2b9215256b

View file

@ -16,7 +16,7 @@ from compiler/astalgo import strTableGet
import compiler/options as compiler_options import compiler/options as compiler_options
import common, version, options, packageinfo, cli import common, version, options, packageinfo, cli
import os, strutils, strtabs, tables, times, osproc, sets import os, strutils, strtabs, tables, times, osproc, sets, pegs
when not declared(resetAllModulesHard): when not declared(resetAllModulesHard):
import compiler/modulegraphs import compiler/modulegraphs
@ -214,6 +214,33 @@ proc getNimPrefixDir(options: Options): string =
# the code responsible for this. # the code responsible for this.
result = "" result = ""
proc getLibVersion(lib: string): Version =
## This is quite a hacky procedure, but there is no other way to extract
## this out of the ``system`` module. We could evaluate it, but that would
## cause an error if the stdlib is out of date. The purpose of this
## proc is to give a nice error message to the user instead of a confusing
## Nim compile error.
let systemPath = lib / "system.nim"
if not fileExists(systemPath):
raiseNimbleError("system module not found in stdlib path: " & lib)
let systemFile = readFile(systemPath)
let majorPeg = peg"'NimMajor' @ '=' \s* {\d*}"
let minorPeg = peg"'NimMinor' @ '=' \s* {\d*}"
let patchPeg = peg"'NimPatch' @ '=' \s* {\d*}"
var majorMatches: array[1, string]
let major = find(systemFile, majorPeg, majorMatches)
var minorMatches: array[1, string]
let minor = find(systemFile, minorPeg, minorMatches)
var patchMatches: array[1, string]
let patch = find(systemFile, patchPeg, patchMatches)
if major != -1 and minor != -1 and patch != -1:
return newVersion(majorMatches[0] & "." & minorMatches[0] & "." & patchMatches[0])
else:
return system.NimVersion.newVersion()
when declared(ModuleGraph): when declared(ModuleGraph):
var graph: ModuleGraph var graph: ModuleGraph
@ -249,6 +276,22 @@ proc execScript(scriptName: string, flags: Flags, options: Options): PSym =
"more info." "more info."
raiseNimbleError(msg, hint) raiseNimbleError(msg, hint)
# Verify that the stdlib that was found isn't older than the stdlib that Nimble
# was compiled with.
let libVersion = getLibVersion(compiler_options.libpath)
if NimVersion.newVersion() > libVersion:
let msg = ("Nimble cannot use an older stdlib than the one it was compiled " &
"with.\n Stdlib in '$#' has version: $#.\n Nimble needs at least: $#.") %
[compiler_options.libpath, $libVersion, NimVersion]
let hint = "You may be running a newer version of Nimble than you intended " &
"to. Run an older version of Nimble that is compatible with " &
"the stdlib that Nimble is attempting to use or set the environment variable " &
"NIM_LIB_PREFIX to where a different stdlib's `lib` directory is located as " &
"a workaround." &
"See https://github.com/nim-lang/nimble#troubleshooting for " &
"more info."
raiseNimbleError(msg, hint)
let pkgName = scriptName.splitFile.name let pkgName = scriptName.splitFile.name
# Ensure that "nimblepkg/nimscriptapi" is in the PATH. # Ensure that "nimblepkg/nimscriptapi" is in the PATH.