diff options
author | Araq <rumpf_a@web.de> | 2016-10-09 01:59:50 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2016-10-09 01:59:50 +0200 |
commit | 6e6b90278c895170e4cdabd5f0507fb17b794453 (patch) | |
tree | 6cef008c635a5fbce5c7fa840a9a686defb620b9 /koch.nim | |
parent | 3dc8e593ff0c762445a5b25e59003b34a109dc04 (diff) | |
download | Nim-6e6b90278c895170e4cdabd5f0507fb17b794453.tar.gz |
koch supports the finish command for smooth installations on Windows
Diffstat (limited to 'koch.nim')
-rw-r--r-- | koch.nim | 231 |
1 files changed, 157 insertions, 74 deletions
diff --git a/koch.nim b/koch.nim index 1e78abbca..57948f839 100644 --- a/koch.nim +++ b/koch.nim @@ -40,7 +40,8 @@ Options: --help, -h shows this help and quits Possible Commands: boot [options] bootstraps with given command line options - install [bindir] installs to given directory; Unix only! + finish setup PATH and check for a valid GCC installation + distrohelper [bindir] helper for distro packagers geninstall generate ./install.sh; Unix only! testinstall test tar.xz package; Unix only! Only for devs! clean cleans Nim project; removes generated files @@ -52,8 +53,6 @@ Possible Commands: xz builds the installation XZ package nsis [options] builds the NSIS Setup installer (for Windows) tests [options] run the testsuite - update updates nim to the latest version from github - (compile koch with -d:withUpdate to enable) temp options creates a temporary compiler for testing winrelease creates a release (for coredevs only) Boot options: @@ -211,10 +210,6 @@ proc geninstall(args="") = exec("$# cc -r $# --var:version=$# --var:mingw=none --main:compiler/nim.nim scripts compiler/installer.ini $#" % [findNim(), compileNimInst, VersionAsString, args]) -proc install(args: string) = - geninstall() - exec("sh ./install.sh $#" % args) - proc web(args: string) = exec("$# js tools/dochack/dochack.nim" % findNim()) exec("$# cc -r tools/nimweb.nim $# web/website.ini --putenv:nimversion=$#" % @@ -321,67 +316,6 @@ proc clean(args: string) = echo "removing dir: ", path removeDir(path) -# -------------- update ------------------------------------------------------- - -when defined(withUpdate): - when defined(windows): - {.warning: "Windows users: Make sure to run 'koch update' in Bash.".} - - proc update(args: string) = - when defined(windows): - echo("Windows users: Make sure to be running this in Bash. ", - "If you aren't, press CTRL+C now.") - - var thisDir = getAppDir() - var git = findExe("git") - echo("Checking for git repo and git executable...") - if existsDir(thisDir & "/.git") and git != "": - echo("Git repo found!") - # use git to download latest source - echo("Checking for updates...") - discard startCmd(git & " fetch origin master") - var procs = startCmd(git & " diff origin/master master") - var errcode = procs.waitForExit() - var output = readLine(procs.outputStream) - echo(output) - if errcode == 0: - if output == "": - # No changes - echo("No update. Exiting...") - return - else: - echo("Fetching updates from repo...") - var pullout = execCmdEx(git & " pull origin master") - if pullout[1] != 0: - quit("An error has occurred.") - else: - if pullout[0].startsWith("Already up-to-date."): - quit("No new changes fetched from the repo. " & - "Local branch must be ahead of it. Exiting...") - else: - quit("An error has occurred.") - - else: - echo("No repo or executable found!") - when defined(haveZipLib): - echo("Falling back.. Downloading source code from repo...") - # use dom96's httpclient to download zip - downloadFile("https://github.com/Araq/Nim/zipball/master", - thisDir / "update.zip") - try: - echo("Extracting source code from archive...") - var zip: TZipArchive - discard open(zip, thisDir & "/update.zip", fmRead) - extractAll(zip, thisDir & "/") - except: - quit("Error reading archive.") - else: - quit("No failback available. Exiting...") - - echo("Starting update...") - boot(args) - echo("Update complete!") - # -------------- builds a release --------------------------------------------- #[ @@ -401,6 +335,159 @@ proc run7z(platform: string, patterns: varargs[string]) = proc winRelease() = exec(r"call ci\nsis_build.bat " & VersionAsString) +# -------------- post unzip steps --------------------------------------------- + +when defined(windows): + import registry + + proc askBool(m: string): bool = + stdout.write m + while true: + let answer = stdin.readLine().normalize + case answer + of "y", "yes": + return true + of "n", "no": + return false + else: + echo "Please type 'y' or 'n'" + + proc askNumber(m: string; a, b: int): int = + stdout.write m + stdout.write " [" & $a & ".." & $b & "] " + while true: + let answer = stdin.readLine() + try: + result = parseInt answer + if result < a or result > b: + raise newException(ValueError, "number out of range") + break + except ValueError: + echo "Please type in a number between ", a, " and ", b + + proc patchConfig(mingw: string) = + const + cfgFile = "config/nim.cfg" + lookFor = """#gcc.path = r"$nim\dist\mingw\bin"""" + replacePattern = """gcc.path = r"$1"""" + try: + let cfg = readFile(cfgFile) + let newCfg = cfg.replace(lookFor, replacePattern % mingw) + if newCfg == cfg: + echo "Could not patch 'config/nim.cfg' [Error]" + echo "Reason: patch substring not found:" + echo lookFor + else: + writeFile(cfgFile, newCfg) + except IOError: + echo "Could not access 'config/nim.cfg' [Error]" + + proc addToPathEnv(e: string) = + let p = getUnicodeValue(r"Environment", "Path", HKEY_CURRENT_USER) + let x = if e.contains(Whitespace): "\"" & e & "\"" else: e + setUnicodeValue(r"Environment", "Path", p & ";" & x, HKEY_CURRENT_USER) + + proc createShortcut(src, dest: string; icon = "") = + var cmd = "bin\\makelink.exe \"" & src & "\" \"\" \"" & dest & + ".lnk\" \"\" 1 \"" & splitFile(src).dir & "\"" + if icon.len != 0: + cmd.add " \"" & icon & "\" 0" + discard execShellCmd(cmd) + + proc createStartMenuEntry() = + let appdata = getEnv("APPDATA") + if appdata.len == 0: return + let dest = appdata & r"\Microsoft\Windows\Start Menu\Programs\Nim-" & + VersionAsString + if dirExists(dest): return + if askBool("Would like to add Nim-" & VersionAsString & + " to your start menu? (y/n) "): + createDir(dest) + createShortcut(getCurrentDir() / "start.bat", dest / "Nim", + getCurrentDir() / r"icons\nim.ico") + if fileExists("doc/overview.html"): + createShortcut(getCurrentDir() / "doc" / "overview.html", + dest / "Overview") + if dirExists(r"dist\aporia-0.4.0"): + createShortcut(getCurrentDir() / r"dist\aporia-0.4.0\bin\aporia.exe", + dest / "Aporia") + + proc checkGccArch(mingw: string): bool = + let gccExe = mingw / r"gcc.exe" + if fileExists(gccExe): + try: + let arch = execProcess(gccExe, ["-dumpmachine"], nil, {poStdErrToStdOut, + poUsePath}) + when hostCPU == "i386": + result = arch.startsWith("i686-") + elif hostCPU == "amd64": + result = arch.startsWith("x86_64-") + else: + {.error: "Unknown CPU for Windows.".} + except OSError, IOError: + result = false + + proc tryDirs(dirs: varargs[string]): string = + let bits = $(sizeof(pointer)*8) + for d in dirs: + if dirExists d: + let x = expandFilename(d / "bin") + if checkGccArch(x): return x + elif dirExists(d & bits): + let x = expandFilename((d & bits) / "bin") + if checkGccArch(x): return x + +proc finish() = + when defined(windows): + let desiredPath = expandFilename(getCurrentDir() / "bin") + let p = getUnicodeValue(r"Environment", "Path", + HKEY_CURRENT_USER) + var alreadyInPath = false + var mingWchoices: seq[string] = @[] + for x in p.split(';'): + let y = expandFilename(if x[0] == '"' and x[^1] == '"': + substr(x, 1, x.len-2) else: x) + if y == desiredPath: alreadyInPath = true + if y.toLowerAscii.contains("mingw"): + if dirExists(y) and checkGccArch(y): + mingWchoices.add y + + if alreadyInPath: + echo "bin/nim.exe is already in your PATH [Skipping]" + else: + if askBool("nim.exe is not in your PATH environment variable.\n" & + " Should it be added permanently? (y/n) "): + addToPathEnv(desiredPath) + if mingWchoices.len == 0: + # No mingw in path, so try a few locations: + let alternative = tryDirs("dist/mingw", "../mingw", r"C:\mingw") + if alternative.len == 0: + echo "No MingW found in PATH and no candidate found " & + " in the standard locations [Error]" + else: + if askBool("Found a MingW directory that is not in your PATH.\n" & + alternative & + "\nShould it be added to your PATH permanently? (y/n) "): + addToPathEnv(alternative) + elif askBool("Do you want to patch Nim's config to use this? (y/n) "): + patchConfig(alternative) + elif mingWchoices.len == 1: + if askBool("MingW installation found at " & mingWchoices[0] & "\n" & + "Do you want to patch Nim's config to use this?\n" & + "(Not required since it's in your PATH!) (y/n) "): + patchConfig(mingWchoices[0]) + else: + echo "Multiple MingW installations found: " + for i in 0..high(mingWchoices): + echo "[", i, "] ", mingWchoices[i] + if askBool("Do you want to patch Nim's config to use one of these? (y/n) "): + let idx = askNumber("Which one do you want to use for Nim? ", + 1, len(mingWchoices)) + patchConfig(mingWchoices[idx-1]) + createStartMenuEntry() + else: + echo("Add ", getCurrentDir(), "/bin to your PATH...") + # -------------- tests -------------------------------------------------------- template `|`(a, b): string = (if a.len > 0: a else: b) @@ -440,6 +527,7 @@ of cmdLongOption, cmdShortOption: showHelp() of cmdArgument: case normalize(op.key) of "boot": boot(op.cmdLineRest) + of "finish": finish() of "clean": clean(op.cmdLineRest) of "web": web(op.cmdLineRest) of "json2": web("--json2 " & op.cmdLineRest) @@ -453,14 +541,9 @@ of cmdArgument: of "xz": xz(op.cmdLineRest) of "nsis": nsis(op.cmdLineRest) of "geninstall": geninstall(op.cmdLineRest) - of "install": install(op.cmdLineRest) + of "distrohelper": geninstall() of "testinstall": testUnixInstall() of "test", "tests": tests(op.cmdLineRest) - of "update": - when defined(withUpdate): - update(op.cmdLineRest) - else: - quit "this Koch has not been compiled with -d:withUpdate" of "temp": temp(op.cmdLineRest) of "winrelease": winRelease() else: showHelp() |