# # # Maintenance program for Nim # (c) Copyright 2015 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. # # See doc/koch.txt for documentation. # when defined(gcc) and defined(windows): when defined(x86): {.link: "icons/koch.res".} else: {.link: "icons/koch_icon.o".} when defined(amd64) and defined(windows) and defined(vcc): {.link: "icons/koch-amd64-windows-vcc.res" .} when defined(i386) and defined(windows) and defined(vcc): {.link: "icons/koch-i386-windows-vcc.res" .} import os, strutils, parseopt, osproc, streams const VersionAsString = system.NimVersion #"0.10.2" when defined(withUpdate): import httpclient when defined(haveZipLib): import zipfiles const HelpText = """ +-----------------------------------------------------------------+ | Maintenance program for Nim | | Version $1| | (c) 2015 Andreas Rumpf | +-----------------------------------------------------------------+ Build time: $2, $3 Usage: koch [options] command [options for command] 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! geninstall generate ./install.sh; Unix only! testinstall test tar.xz package; Unix only! Only for devs! clean cleans Nim project; removes generated files web [options] generates the website and the full documentation website [options] generates only the website csource [options] builds the C sources for installation pdf builds the PDF documentation zip builds the installation ZIP package 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: -d:release produce a release version of the compiler -d:tinyc include the Tiny C backend (not supported on Windows) -d:useLinenoise use the linenoise library for interactive mode (not needed on Windows) -d:nativeStacktrace use native stack traces (only for Mac OS X or Linux) -d:noCaas build Nim without CAAS support -d:avoidTimeMachine only for Mac OS X, excludes nimcache dir from backups Web options: --googleAnalytics:UA-... add the given google analytics code to the docs. To build the official docs, use UA-48159761-1 """ proc exe(f: string): string = return addFileExt(f, ExeExt) proc findNim(): string = var nim = "nim".exe result = "bin" / nim if existsFile(result): return for dir in split(getEnv("PATH"), PathSep): if existsFile(dir / nim): return dir / nim # assume there is a symlink to the exe or something: return nim proc exec(cmd: string, errorcode: int = QuitFailure, additionalPATH = "") = let prevPATH = getEnv("PATH") if additionalPATH.len > 0: var absolute = additionalPATH if not absolute.isAbsolute: absolute = getCurrentDir() / absolute echo("Adding to $PATH: ", absolute) putEnv("PATH", prevPATH & PathSep & absolute) echo(cmd) if execShellCmd(cmd) != 0: quit("FAILURE", errorcode) putEnv("PATH", prevPATH) proc execCleanPath(cmd: string, additionalPath = ""; errorcode: int = QuitFailure) = # simulate a poor man's virtual environment let prevPath = getEnv("PATH") when defined(windows): let CleanPath = r"$1\system32;$1;$1\System32\Wbem" % getEnv"SYSTEMROOT" else: const CleanPath = r"/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin" putEnv("PATH", CleanPath & PathSep & additionalPath) echo(cmd) if execShellCmd(cmd) != 0: quit("FAILURE", errorcode) putEnv("PATH", prevPath) proc testUnixInstall() = let oldCurrentDir = getCurrentDir() try: let destDir = getTempDir() copyFile("build/nim-$1.tar.xz" % VersionAsString, destDir / "nim-$1.tar.xz" % VersionAsString) setCurrentDir(destDir) execCleanPath("tar -xJf nim-$1.tar.xz" % VersionAsString) setCurrentDir("nim-$1" % VersionAsString) execCleanPath("sh build.sh") # first test: try if './bin/nim --version' outputs something sane: let output = execProcess("./bin/nim --version").splitLines if output.len > 0 and output[0].contains(VersionAsString): echo "Version check: success" execCleanPath("./bin/nim c koch.nim") execCleanPath("./koch boot -d:release", destDir / "bin") # check the docs build: execCleanPath("./koch web", destDir / "bin") # check the tests work: execCleanPath("./koch tests", destDir / "bin") else: echo "Version check: failure" finally: setCurrentDir oldCurrentDir proc tryExec(cmd: string): bool = echo(cmd) result = execShellCmd(cmd) == 0 proc safeRemove(filename: string) = if existsFile(filename): removeFile(filename) proc copyExe(source, dest: string) = safeRemove(dest) copyFile(dest=dest, source=source) inclFilePermissions(dest, {fpUserExec}) const compileNimInst = "-d:useLibzipSrc tools/niminst/niminst" proc csource(args: string) = exec("$4 cc $1 -r $3 --var:version=$2 --var:mingw=none csource --main:compiler/nim.nim compiler/installer.ini $1" % [args, VersionAsString, compileNimInst, findNim()]) proc bundleNimble() = if dirExists("dist/nimble/.git"): exec("git --git-dir dist/nimble/.git pull") else: exec("git clone https://github.com/nim-lang/nimble.git dist/nimble") let tags = execProcess("git --git-dir dist/nimble/.git tag -l v*").splitLines let tag = tags[^1] exec("git --git-dir dist/nimble/.git checkout " & tag) # now compile Nimble and copy it to $nim/bin for the installer.ini # to pick it up: exec(findNim() & " c dist/nimble/src/nimble.nim") copyExe("dist/nimble/src/nimble".exe, "bin/nimble".exe) proc zip(args: string) = bundleNimble() exec("$3 cc -r $2 --var:version=$1 --var:mingw=none --main:compiler/nim.nim scripts compiler/installer.ini" % [VersionAsString, compileNimInst, findNim()]) exec("$# --var:version=$# --var:mingw=none --main:compiler/nim.nim zip compiler/installer.ini" % ["tools/niminst/niminst".exe, VersionAsString]) proc xz(args: string) = bundleNimble() exec("$3 cc -r $2 --var:version=$1 --var:mingw=none --main:compiler/nim.nim scripts compiler/installer.ini" % [VersionAsString, compileNimInst, findNim()]) exec("$# --var:version=$# --var:mingw=none --main:compiler/nim.nim xz compiler/installer.ini" % ["tools" / "niminst" / "niminst".exe, VersionAsString]) proc buildTool(toolname, args: string) = exec("$# cc $# $#" % [findNim(), args, toolname]) copyFile(dest="bin"/ splitFile(toolname).name.exe, source=toolname.exe) proc nsis(args: string) = bundleNimble() # make sure we have generated the niminst executables: buildTool("tools/niminst/niminst", args) #buildTool("tools/nimgrep", args) # produce 'nim_debug.exe': #exec "nim c compiler" / "nim.nim" #copyExe("compiler/nim".exe, "bin/nim_debug".exe) exec(("tools" / "niminst" / "niminst --var:version=$# --var:mingw=mingw$#" & " nsis compiler/installer.ini") % [VersionAsString, $(sizeof(pointer)*8)]) 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("$# cc -r tools/nimweb.nim $# web/website.ini --putenv:nimversion=$#" % [findNim(), args, VersionAsString]) proc website(args: string) = exec("$# cc -r tools/nimweb.nim $# --website web/website.ini --putenv:nimversion=$#" % [findNim(), args, VersionAsString]) proc pdf(args="") = exec("$# cc -r tools/nimweb.nim $# --pdf web/website.ini --putenv:nimversion=$#" % [findNim(), args, VersionAsString], additionalPATH=findNim().splitFile.dir) # -------------- boot --------------------------------------------------------- proc findStartNim: string = # we try several things before giving up: # * bin/nim # * $PATH/nim # If these fail, we try to build nim with the "build.(sh|bat)" script. var nim = "nim".exe result = "bin" / nim if existsFile(result): return for dir in split(getEnv("PATH"), PathSep): if existsFile(dir / nim): return dir / nim when defined(Posix): const buildScript = "build.sh" if existsFile(buildScript): if tryExec("./" & buildScript): return "bin" / nim else: const bui
discard """
outputsub: '''
false
Within finally->try
'''
exitCode: 1
"""
# Test break in try statement:
proc main: bool =
while true:
try:
return true
finally:
break
return false
echo main() #OUT false
# bug #5871
try:
raise newException(Exception, "First")
finally:
try:
raise newException(Exception, "Within finally->try")
except:
echo<