summary refs log tree commit diff stats
path: root/tools/niminst
diff options
context:
space:
mode:
Diffstat (limited to 'tools/niminst')
-rw-r--r--tools/niminst/buildsh.nimf62
-rw-r--r--tools/niminst/debcreation.nim4
-rw-r--r--tools/niminst/deinstall.nimf2
-rw-r--r--tools/niminst/install.nimf89
-rw-r--r--tools/niminst/makefile.nimf33
-rw-r--r--tools/niminst/nim-file.icobin0 -> 3311 bytes
-rw-r--r--tools/niminst/niminst.nim146
-rw-r--r--tools/niminst/setup.icobin0 -> 2551 bytes
-rw-r--r--tools/niminst/uninstall.icobin0 -> 2226 bytes
9 files changed, 199 insertions, 137 deletions
diff --git a/tools/niminst/buildsh.nimf b/tools/niminst/buildsh.nimf
index 5d532a0fd..063a02779 100644
--- a/tools/niminst/buildsh.nimf
+++ b/tools/niminst/buildsh.nimf
@@ -1,6 +1,6 @@
 #? stdtmpl(subsChar='?') | standard
 #proc generateBuildShellScript(c: ConfigData): string =
-#  result = "#! /bin/sh\n# Generated from niminst\n" &
+#  result = "#!/bin/sh\n# Generated from niminst\n" &
 #           "# Template is in tools/niminst/buildsh.nimf\n" &
 #           "# To regenerate run ``niminst csource`` or ``koch csource``\n"
 
@@ -21,10 +21,23 @@ do
       optosname=$2
       shift 2
       ;;
+    --parallel)
+      parallel=$2
+      shift 2
+      ;;
     --extraBuildArgs)
       extraBuildArgs=" $2"
       shift 2
       ;;
+    -h | --help)
+      echo "Options:"
+      echo "  --os <OS>"
+      echo "  --cpu <CPU architecture>"
+      echo "  --osname <name>           Additional OS specification (used for Android)"
+      echo "  --extraBuildArgs <args>   Additional arguments passed to the compiler"
+      echo "  --parallel <number>       Multiprocess build. Requires GNU parallel"
+      exit 0
+      ;;
     --) # End of all options
       shift
       break;
@@ -39,7 +52,15 @@ do
   esac
 done
 
+parallel="${parallel:-0}"
 CC="${CC:-gcc}"
+if [ "$parallel" -gt 1 ]; then
+  if ! command -v sem > /dev/null; then
+    echo "Error: GNU parallel is required to use --parallel"
+    exit 1
+  fi
+  CC="sem -j $parallel --id $$ ${CC}"
+fi
 COMP_FLAGS="${CPPFLAGS:-} ${CFLAGS:-} ?{c.ccompiler.flags}$extraBuildArgs"
 LINK_FLAGS="${LDFLAGS:-} ?{c.linker.flags}"
 PS4=""
@@ -88,6 +109,11 @@ case $uos in
     CC="clang"
     LINK_FLAGS="$LINK_FLAGS -lm"
     ;;
+  *crossos* )
+    myos="crossos"
+    CC="clang"
+    LINK_FLAGS="$LINK_FLAGS -lm"
+    ;;
   *openbsd* )
     myos="openbsd"
     CC="clang"
@@ -96,6 +122,7 @@ case $uos in
   *netbsd* )
     myos="netbsd"
     LINK_FLAGS="$LINK_FLAGS -lm"
+    ucpu=`uname -p`
     ;;
   *darwin* )
     myos="macosx"
@@ -113,6 +140,11 @@ case $uos in
     myos="solaris"
     LINK_FLAGS="$LINK_FLAGS -ldl -lm -lsocket -lnsl"
     ;;
+  *SunOS* )
+    myos="solaris"
+    LINK_FLAGS="$LINK_FLAGS -ldl -lm -lsocket -lnsl"
+    isOpenIndiana="yes"
+    ;;
   *haiku* )
     myos="haiku"
     LINK_FLAGS="$LINK_FLAGS -lroot -lnetwork"
@@ -133,7 +165,12 @@ esac
 
 case $ucpu in
   *i386* | *i486* | *i586* | *i686* | *bepc* | *i86pc* )
-    mycpu="i386" ;;
+    if [ "$isOpenIndiana" = "yes" ] || [ `uname -o` == "illumos" ] ; then
+      mycpu="amd64"
+    else
+      mycpu="i386"
+    fi
+    ;;
   *amd*64* | *x86-64* | *x86_64* )
     mycpu="amd64" ;;
   *sparc*|*sun* )
@@ -156,10 +193,16 @@ case $ucpu in
     mycpu="powerpc64" ;;
   *power*|*ppc* )
     if [ "$myos" = "freebsd" ] ; then
-      COMP_FLAGS="$COMP_FLAGS -m64"
-      LINK_FLAGS="$LINK_FLAGS -m64"
+      if [ "$ucpu" != "powerpc" ] ; then
+        COMP_FLAGS="$COMP_FLAGS -m64"
+        LINK_FLAGS="$LINK_FLAGS -m64"
+      fi
       mycpu=`uname -p`
-	else
+      case $mycpu in
+        powerpc64le)
+        mycpu="powerpc64el"
+      esac
+    else
       mycpu="powerpc"
     fi
     ;;
@@ -183,10 +226,14 @@ case $ucpu in
     mycpu="alpha" ;;
   *aarch64*|*arm64* )
     mycpu="arm64" ;;
-  *arm*|*armv6l*|*armv71* )
+  *arm*|*armv6l*|*armv7l*|*armv8l* )
     mycpu="arm" ;;
   *riscv64|riscv* )
     mycpu="riscv64" ;;
+  *e2k* )
+    mycpu="e2k" ;;
+  *loongarch64* )
+    mycpu="loongarch64" ;;
   *)
     echo 2>&1 "Error: unknown processor: $ucpu"
     exit 1
@@ -218,6 +265,9 @@ case $myos in
     $CC $COMP_FLAGS -Ic_code -c ?{f} -o ?{changeFileExt(f, "o")}
 #        add(linkCmd, " \\\n" & changeFileExt(f, "o"))
 #      end for
+    if [ "$parallel" -gt 0 ]; then
+      sem --wait --id $$
+    fi
     $CC -o ?{"$binDir/" & toLowerAscii(c.name)} ?linkCmd $LINK_FLAGS
     ;;
 #    end for
diff --git a/tools/niminst/debcreation.nim b/tools/niminst/debcreation.nim
index d0f46fa52..219cb44ce 100644
--- a/tools/niminst/debcreation.nim
+++ b/tools/niminst/debcreation.nim
@@ -9,6 +9,10 @@
 
 import osproc, times, os, strutils
 
+
+when defined(nimPreviewSlimSystem):
+  import std/[assertions, syncio]
+
 # http://www.debian.org/doc/manuals/maint-guide/
 
 # Required files for debhelper.
diff --git a/tools/niminst/deinstall.nimf b/tools/niminst/deinstall.nimf
index 8b4477369..0dcfda75e 100644
--- a/tools/niminst/deinstall.nimf
+++ b/tools/niminst/deinstall.nimf
@@ -1,6 +1,6 @@
 #? stdtmpl(subsChar='?') | standard
 #proc generateDeinstallScript(c: ConfigData): string =
-#  result = "#! /bin/sh\n# Generated by niminst\n"
+#  result = "#!/bin/sh\n# Generated by niminst\n"
 #  var proj = c.name.toLowerAscii
 
 if [ $# -eq 1 ] ; then
diff --git a/tools/niminst/install.nimf b/tools/niminst/install.nimf
index a78914ecd..75ff9ce11 100644
--- a/tools/niminst/install.nimf
+++ b/tools/niminst/install.nimf
@@ -1,24 +1,24 @@
 #? stdtmpl(subsChar = '?') | standard
 #proc generateInstallScript(c: ConfigData): string =
-#  result = "#! /bin/sh\n# Generated by niminst\n"
+#  result = "#!/bin/sh\n# Generated by niminst\n"
 #  var proj = c.name.toLowerAscii
 
 set -e
 
 if [ $# -eq 1 ] ; then
-# if c.cat[fcUnixBin].len > 0:
-  if test -f ?{c.cat[fcUnixBin][0].toUnix}
+#if c.cat[fcUnixBin].len > 0:
+  if [ -f "?{c.cat[fcUnixBin][0].toUnix}" ]
   then
     echo "?c.displayName build detected"
   else
     echo "Please build ?c.displayName before installing it"
     exit 1
   fi
-#  end if
+#end if
   case $1 in
     "--help"|"-h"|"help"|"h")
       echo "?c.displayName installation script"
-      echo "Usage: [sudo] sh install.sh DIR"
+      echo "Usage: [sudo] [env DESTDIR=...] sh install.sh DIR"
       echo "Where DIR may be:"
       echo "  /usr/bin"
       echo "  /usr/local/bin"
@@ -29,19 +29,19 @@ if [ $# -eq 1 ] ; then
       exit 1
       ;;
     "/usr/bin")
-      bindir=/usr/bin
-      configdir=/etc/?proj
-      libdir=/usr/lib/?proj
-      docdir=/usr/share/?proj/doc
-      datadir=/usr/share/?proj/data
+      bindir=$1
+      configdir="/etc/?proj"
+      libdir="/usr/lib/?proj"
+      docdir="/usr/share/?proj/doc"
+      datadir="/usr/share/?proj/data"
       nimbleDir="/opt/nimble/pkgs/?c.nimblePkgName-?c.version"
       ;;
     "/usr/local/bin")
-      bindir=/usr/local/bin
-      configdir=/etc/?proj
-      libdir=/usr/local/lib/?proj
-      docdir=/usr/local/share/?proj/doc
-      datadir=/usr/local/share/?proj/data
+      bindir=$1
+      configdir="/etc/?proj"
+      libdir="/usr/local/lib/?proj"
+      docdir="/usr/local/share/?proj/doc"
+      datadir="/usr/local/share/?proj/data"
       nimbleDir="/opt/nimble/pkgs/?c.nimblePkgName-?c.version"
       ;;
     "/opt")
@@ -51,9 +51,6 @@ if [ $# -eq 1 ] ; then
       docdir="/opt/?proj/doc"
       datadir="/opt/?proj/data"
       nimbleDir="/opt/nimble/pkgs/?c.nimblePkgName-?c.version"
-      mkdir -p /opt/?proj
-      mkdir -p $bindir
-      mkdir -p $configdir
       ;;
     *)
       bindir="$1/?proj/bin"
@@ -62,16 +59,22 @@ if [ $# -eq 1 ] ; then
       docdir="$1/?proj/doc"
       datadir="$1/?proj/data"
       nimbleDir="$1/?proj"
-      mkdir -p $1/?proj
-      mkdir -p $bindir
-      mkdir -p $configdir
       ;;
   esac
 
-  mkdir -p $libdir
-  mkdir -p $docdir
-  mkdir -p $configdir
-  mkdir -p $nimbleDir/
+  bindir="${DESTDIR}${bindir}"
+  configdir="${DESTDIR}${configdir}"
+  libdir="${DESTDIR}${libdir}"
+  docdir="${DESTDIR}${docdir}"
+  datadir="${DESTDIR}${datadir}"
+  nimbleDir="${DESTDIR}${nimbleDir}"
+
+  mkdir -p "$bindir"
+  mkdir -p "$configdir"
+  mkdir -p "$libdir"
+  mkdir -p "$docdir"
+  mkdir -p "$datadir"
+  mkdir -p "$nimbleDir"
   echo "copying files..."
 #var createdDirs = newStringTable()
 #for cat in {fcConfig..fcLib, fcNimble}:
@@ -84,46 +87,46 @@ if [ $# -eq 1 ] ; then
 #    end if
 #    if mk.len > 0 and not createdDirs.hasKey(mk):
 #      createdDirs[mk] = "true"
-  mkdir -p ?{mk.toUnix}
+  mkdir -p "?{mk.toUnix}"
 #    end if
 #  end for
 #end for
 
 #for f in items(c.cat[fcUnixBin]):
-  cp ?f.toUnix $bindir/?f.skipRoot.toUnix
-  chmod 755 $bindir/?f.skipRoot.toUnix
+  cp "?f.toUnix" "$bindir/?f.skipRoot.toUnix"
+  chmod 755 "$bindir/?f.skipRoot.toUnix"
 #end for
 #for f in items(c.cat[fcConfig]):
-  cp ?f.toUnix $configdir/?f.skipRoot.toUnix
-  chmod 644 $configdir/?f.skipRoot.toUnix
+  cp "?f.toUnix" "$configdir/?f.skipRoot.toUnix"
+  chmod 644 "$configdir/?f.skipRoot.toUnix"
 #end for
 #for f in items(c.cat[fcData]):
-  if [ -f ?f.toUnix ]; then
-    cp ?f.toUnix $datadir/?f.skipRoot.toUnix
-    chmod 644 $datadir/?f.skipRoot.toUnix
+  if [ -f "?f.toUnix" ]; then
+    cp "?f.toUnix" "$datadir/?f.skipRoot.toUnix"
+    chmod 644 "$datadir/?f.skipRoot.toUnix"
   fi
 #end for
 #for f in items(c.cat[fcDoc]):
-  if [ -f ?f.toUnix ]; then
-    cp ?f.toUnix $docdir/?f.skipRoot.toUnix
-    chmod 644 $docdir/?f.skipRoot.toUnix
+  if [ -f "?f.toUnix" ]; then
+    cp "?f.toUnix" "$docdir/?f.skipRoot.toUnix"
+    chmod 644 "$docdir/?f.skipRoot.toUnix"
   fi
 #end for
 #for f in items(c.cat[fcLib]):
-  cp ?f.toUnix $libdir/?f.skipRoot.toUnix
-  chmod 644 $libdir/?f.skipRoot.toUnix
+  cp "?f.toUnix" "$libdir/?f.skipRoot.toUnix"
+  chmod 644 "$libdir/?f.skipRoot.toUnix"
 #end for
 #for f in items(c.cat[fcNimble]):
-  cp ?f.toUnix $nimbleDir/?f.toUnix
-  chmod 644 $nimbleDir/?f.toUnix
+  cp "?f.toUnix" "$nimbleDir/?f.toUnix"
+  chmod 644 "$nimbleDir/?f.toUnix"
 #end for
-cp ?{c.nimblePkgName}.nimble $nimbleDir/?{c.nimblePkgName}.nimble
-chmod 644 $nimbleDir/?{c.nimblePkgName}.nimble
+cp "?{c.nimblePkgName}.nimble" "$nimbleDir/?{c.nimblePkgName}.nimble"
+chmod 644 "$nimbleDir/?{c.nimblePkgName}.nimble"
 
   echo "installation successful"
 else
   echo "?c.displayName installation script"
-  echo "Usage: [sudo] sh install.sh DIR"
+  echo "Usage: [sudo] [env DESTDIR=...] sh install.sh DIR"
   echo "Where DIR may be:"
   echo "  /usr/bin"
   echo "  /usr/local/bin"
diff --git a/tools/niminst/makefile.nimf b/tools/niminst/makefile.nimf
index ad9d55c03..002bc0592 100644
--- a/tools/niminst/makefile.nimf
+++ b/tools/niminst/makefile.nimf
@@ -16,6 +16,7 @@ endif
 
 target := ?{"$(binDir)/" & toLowerAscii(c.name)}
 
+
 ucpu := $(shell sh -c 'uname -m | tr "[:upper:]" "[:lower:]"')
 ifeq ($(OS),Windows_NT)
   uos := windows
@@ -25,7 +26,8 @@ endif
 
 ifeq ($(uos),linux)
   myos = linux
-  LDFLAGS += -ldl -lm
+  ## add -lrt to avoid "undefined reference to `clock_gettime'" with glibc<2.17
+  LDFLAGS += -ldl -lm -lrt
 endif
 ifeq ($(uos),dragonfly)
   myos = freebsd
@@ -43,6 +45,7 @@ endif
 ifeq ($(uos),netbsd)
   myos = netbsd
   LDFLAGS += -lm
+  ucpu = $(shell sh -c 'uname -p')
 endif
 ifeq ($(uos),darwin)
   myos = macosx
@@ -102,9 +105,18 @@ endif
 ifeq ($(ucpu),x86_64)
   mycpu = amd64
 endif
+ifeq ($(ucpu),parisc64)
+  mycpu = hppa
+endif
+ifeq ($(ucpu),s390x)
+  mycpu = s390x
+endif
 ifeq ($(ucpu),sparc)
   mycpu = sparc
 endif
+ifeq ($(ucpu),sparc64)
+  mycpu = sparc64
+endif
 ifeq ($(ucpu),sun)
   mycpu = sparc
 endif
@@ -124,10 +136,13 @@ ifeq ($(ucpu),powerpc)
     mycpu = $(shell sh -c 'uname -p | tr "[:upper:]" "[:lower:]"')
     CFLAGS += -m64
     LDFLAGS += -m64
+    ifeq ($(mycpu),powerpc64le)
+      mycpu = powerpc64el
+    endif
   endif
 endif
 ifeq ($(ucpu),ppc)
-  mycpu = ppc
+   mycpu = powerpc
 endif
 ifneq (,$(filter $(ucpu), mips mips64))
   mycpu = $(shell /bin/sh -c '"$(CC)" -dumpmachine | sed "s/-.*//"')
@@ -153,14 +168,26 @@ endif
 ifeq ($(ucpu),armv7hl)
   mycpu = arm
 endif
+ifeq ($(ucpu),armv8l)
+  mycpu = arm
+endif
 ifeq ($(ucpu),aarch64)
   mycpu = arm64
 endif
+ifeq ($(ucpu),arm64)
+  mycpu = arm64
+endif
 ifeq ($(ucpu),riscv64)
   mycpu = riscv64
 endif
+ifeq ($(ucpu),e2k)
+  mycpu = e2k
+endif
+ifeq ($(ucpu),loongarch64)
+  mycpu = loongarch64
+endif
 ifndef mycpu
-  $(error unknown processor: $(ucpu))
+  $(error unknown CPU architecture: $(ucpu) See makefile.nimf)
 endif
 
 # for osA in 1..c.oses.len:
diff --git a/tools/niminst/nim-file.ico b/tools/niminst/nim-file.ico
new file mode 100644
index 000000000..0685fedcb
--- /dev/null
+++ b/tools/niminst/nim-file.ico
Binary files differdiff --git a/tools/niminst/niminst.nim b/tools/niminst/niminst.nim
index a5fc388cd..40ee79814 100644
--- a/tools/niminst/niminst.nim
+++ b/tools/niminst/niminst.nim
@@ -7,15 +7,16 @@
 #    distribution, for details about the copyright.
 #
 
-const
-  haveZipLib = false # zip not in stdlib anymore
+import
+  os, strutils, parseopt, parsecfg, strtabs, streams, debcreation
 
-when haveZipLib:
-  import zipfiles
+import ../../dist/checksums/src/checksums/sha1
 
-import
-  os, strutils, parseopt, parsecfg, strtabs, streams, debcreation,
-  std / sha1
+when defined(nimPreviewSlimSystem):
+  import std/syncio
+
+when not defined(nimHasEffectsOf):
+  {.pragma: effectsOf.}
 
 const
   maxOS = 20 # max number of OSes
@@ -36,7 +37,7 @@ type
     actionInno,   # action: create Inno Setup installer
     actionNsis,   # action: create NSIS installer
     actionScripts # action: create install and deinstall scripts
-    actionZip,    # action: create zip file
+    actionZip     # action: create zip file
     actionXz,     # action: create xz file
     actionDeb     # action: prepare deb package
 
@@ -75,7 +76,7 @@ const
     "$configdir", "$datadir", "$docdir", "$libdir"
   ]
 
-proc iniConfigData(c: var ConfigData) =
+func iniConfigData(c: var ConfigData) =
   c.actions = {}
   for i in low(FileCategory)..high(FileCategory): c.cat[i] = @[]
   c.binPaths = @[]
@@ -107,17 +108,17 @@ proc iniConfigData(c: var ConfigData) =
   c.debOpts.shortDesc = ""
   c.debOpts.licenses = @[]
 
-proc firstBinPath(c: ConfigData): string =
+func firstBinPath(c: ConfigData): string =
   if c.binPaths.len > 0: result = c.binPaths[0]
   else: result = ""
 
-proc `\`(a, b: string): string =
+func `\`(a, b: string): string =
   result = if a.len == 0: b else: a & '\\' & b
 
 template toUnix(s: string): string = s.replace('\\', '/')
 template toWin(s: string): string = s.replace('/', '\\')
 
-proc skipRoot(f: string): string =
+func skipRoot(f: string): string =
   # "abc/def/xyz" --> "def/xyz"
   var i = 0
   result = ""
@@ -167,11 +168,11 @@ proc parseCmdLine(c: var ConfigData) =
     next(p)
     var kind = p.kind
     var key = p.key
-    var val = p.val.string
+    var val = p.val
     case kind
     of cmdArgument:
       if c.actions == {}:
-        for a in split(normalize(key.string), {';', ','}):
+        for a in split(normalize(key), {';', ','}):
           case a
           of "csource": incl(c.actions, actionCSource)
           of "scripts": incl(c.actions, actionScripts)
@@ -182,11 +183,11 @@ proc parseCmdLine(c: var ConfigData) =
           of "deb": incl(c.actions, actionDeb)
           else: quit(Usage)
       else:
-        c.infile = addFileExt(key.string, "ini")
-        c.nimArgs = cmdLineRest(p).string
+        c.infile = addFileExt(key, "ini")
+        c.nimArgs = cmdLineRest(p)
         break
     of cmdLongOption, cmdShortOption:
-      case normalize(key.string)
+      case normalize(key)
       of "help", "h":
         stdout.write(Usage)
         quit(0)
@@ -204,7 +205,7 @@ proc parseCmdLine(c: var ConfigData) =
   if c.infile.len == 0: quit(Usage)
   if c.mainfile.len == 0: c.mainfile = changeFileExt(c.infile, "nim")
 
-proc eqT(a, b: string; t: proc (a: char): char{.nimcall.}): bool =
+proc eqT(a, b: string; t: proc (a: char): char {.nimcall.}): bool {.effectsOf: t.} =
   ## equality under a transformation ``t``. candidate for the stdlib?
   var i = 0
   var j = 0
@@ -221,11 +222,11 @@ proc eqT(a, b: string; t: proc (a: char): char{.nimcall.}): bool =
       inc j
   result = i >= a.len and j >= b.len
 
-proc tPath(c: char): char =
+func tPath(c: char): char =
   if c == '\\': '/'
   else: c
 
-proc ignoreFile(f, explicit: string, allowHtml: bool): bool =
+func ignoreFile(f, explicit: string, allowHtml: bool): bool =
   let (_, name, ext) = splitFile(f)
   let html = if not allowHtml: ".html" else: ""
   result = (ext in ["", ".exe", ".idx", ".o", ".obj", ".dylib"] or
@@ -283,13 +284,13 @@ proc yesno(p: var CfgParser, v: string): bool =
     result = false
   else: quit(errorStr(p, "unknown value; use: yes|no"))
 
-proc incl(s: var seq[string], x: string): int =
+func incl(s: var seq[string], x: string): int =
   for i in 0 ..< s.len:
     if cmpIgnoreStyle(s[i], x) == 0: return i
   s.add(x)
   result = s.len-1
 
-proc platforms(c: var ConfigData, v: string) =
+func platforms(c: var ConfigData, v: string) =
   for line in splitLines(v):
     let p = line.find(": ")
     if p <= 1: continue
@@ -462,10 +463,10 @@ proc readCFiles(c: var ConfigData, osA, cpuA: int) =
   else:
     quit("Cannot open: " & f)
 
-proc buildDir(os, cpu: int): string =
-  return "c_code" / ($os & "_" & $cpu)
+func buildDir(os, cpu: int): string =
+  "c_code" / ($os & "_" & $cpu)
 
-proc getOutputDir(c: var ConfigData): string =
+func getOutputDir(c: var ConfigData): string =
   if c.outdir.len > 0: c.outdir else: "build"
 
 proc writeFile(filename, content, newline: string) =
@@ -483,8 +484,6 @@ proc deduplicateFiles(c: var ConfigData) =
   let build = getOutputDir(c)
   for osA in countup(1, c.oses.len):
     for cpuA in countup(1, c.cpus.len):
-      when not defined(nimNoNilSeqs):
-        if c.cfiles[osA][cpuA].isNil: c.cfiles[osA][cpuA] = @[]
       if c.explicitPlatforms and not c.platforms[osA][cpuA]: continue
       for dup in mitems(c.cfiles[osA][cpuA]):
         let key = $secureHashFile(build / dup)
@@ -516,6 +515,17 @@ template gatherFiles(fun, libpath, outDir) =
     # commenting out for now, see discussion in https://github.com/nim-lang/Nim/pull/13413
     # copySrc(libpath / "lib/wrappers/linenoise/linenoise.h")
 
+proc exe(f: string): string =
+  result = addFileExt(f, ExeExt)
+  when defined(windows):
+    result = result.replace('/','\\')
+
+proc findNim(): string =
+  let nim = "nim".exe
+  result = quoteShell("bin" / nim)
+  if not fileExists(result):
+    result = "nim"
+
 proc srcdist(c: var ConfigData) =
   let cCodeDir = getOutputDir(c) / "c_code"
   if not dirExists(cCodeDir): createDir(cCodeDir)
@@ -534,10 +544,10 @@ proc srcdist(c: var ConfigData) =
       var dir = getOutputDir(c) / buildDir(osA, cpuA)
       if dirExists(dir): removeDir(dir)
       createDir(dir)
-      var cmd = ("nim compile -f --symbolfiles:off --compileonly " &
+      var cmd = ("$# compile -f --incremental:off --compileonly " &
                  "--gen_mapping --cc:gcc --skipUserCfg" &
                  " --os:$# --cpu:$# $# $#") %
-                 [osname, cpuname, c.nimArgs, c.mainfile]
+                 [findNim(), osname, cpuname, c.nimArgs, c.mainfile]
       echo(cmd)
       if execShellCmd(cmd) != 0:
         quit("Error: call to nim compiler failed")
@@ -596,42 +606,6 @@ proc setupDist2(c: var ConfigData) =
     else:
       quit("External program failed")
 
-# ------------------ generate ZIP file ---------------------------------------
-when haveZipLib:
-  proc zipDist(c: var ConfigData) =
-    var proj = toLowerAscii(c.name) & "-" & c.version
-    var n = "$#.zip" % proj
-    if c.outdir.len == 0: n = "build" / n
-    else: n = c.outdir / n
-    var z: ZipArchive
-    if open(z, n, fmWrite):
-      addFile(z, proj / buildBatFile, "build" / buildBatFile)
-      addFile(z, proj / buildBatFile32, "build" / buildBatFile32)
-      addFile(z, proj / buildBatFile64, "build" / buildBatFile64)
-      addFile(z, proj / buildShFile, "build" / buildShFile)
-      addFile(z, proj / makeFile, "build" / makeFile)
-      addFile(z, proj / installShFile, installShFile)
-      addFile(z, proj / deinstallShFile, deinstallShFile)
-
-      template addFileAux(src, dst) = addFile(z, dst, src)
-      gatherFiles(addFileAux, c.libpath, proj / "c_code")
-      for osA in 1..c.oses.len:
-        for cpuA in 1..c.cpus.len:
-          var dir = buildDir(osA, cpuA)
-          for k, f in walkDir("build" / dir):
-            if k == pcFile: addFile(z, proj / dir / extractFilename(f), f)
-
-      for cat in items({fcConfig..fcOther, fcUnix, fcNimble}):
-        for f in items(c.cat[cat]): addFile(z, proj / f, f)
-
-      # Copy the .nimble file over
-      let nimbleFile = c.nimblePkgName & ".nimble"
-      processFile(z, proj / nimbleFile, nimbleFile)
-
-      close(z)
-    else:
-      quit("Cannot open for writing: " & n)
-
 proc xzDist(c: var ConfigData; windowsZip=false) =
   let proj = toLowerAscii(c.name) & "-" & c.version
   let tmpDir = if c.outdir.len == 0: "build" else: c.outdir
@@ -647,7 +621,7 @@ proc xzDist(c: var ConfigData; windowsZip=false) =
 
   if not windowsZip and not fileExists("build" / buildBatFile):
     quit("No C sources found in ./build/, please build by running " &
-         "./koch csource -d:release.")
+         "./koch csource -d:danger.")
 
   if not windowsZip:
     processFile(proj / buildBatFile, "build" / buildBatFile)
@@ -753,21 +727,25 @@ proc debDist(c: var ConfigData) =
 
 # ------------------- main ----------------------------------------------------
 
-var c: ConfigData
-iniConfigData(c)
-parseCmdLine(c)
-parseIniFile(c)
-if actionInno in c.actions:
-  setupDist(c)
-if actionNsis in c.actions:
-  setupDist2(c)
-if actionCSource in c.actions:
-  srcdist(c)
-if actionScripts in c.actions:
-  writeInstallScripts(c)
-if actionZip in c.actions:
-  xzDist(c, true)
-if actionXz in c.actions:
-  xzDist(c)
-if actionDeb in c.actions:
-  debDist(c)
+proc main() =
+  var c: ConfigData
+  iniConfigData(c)
+  parseCmdLine(c)
+  parseIniFile(c)
+  if actionInno in c.actions:
+    setupDist(c)
+  if actionNsis in c.actions:
+    setupDist2(c)
+  if actionCSource in c.actions:
+    srcdist(c)
+  if actionScripts in c.actions:
+    writeInstallScripts(c)
+  if actionZip in c.actions:
+    xzDist(c, true)
+  if actionXz in c.actions:
+    xzDist(c)
+  if actionDeb in c.actions:
+    debDist(c)
+
+when isMainModule:
+  main()
diff --git a/tools/niminst/setup.ico b/tools/niminst/setup.ico
new file mode 100644
index 000000000..867163046
--- /dev/null
+++ b/tools/niminst/setup.ico
Binary files differdiff --git a/tools/niminst/uninstall.ico b/tools/niminst/uninstall.ico
new file mode 100644
index 000000000..aff054644
--- /dev/null
+++ b/tools/niminst/uninstall.ico
Binary files differ