summary refs log tree commit diff stats
path: root/koch.nim
diff options
context:
space:
mode:
Diffstat (limited to 'koch.nim')
-rw-r--r--koch.nim243
1 files changed, 110 insertions, 133 deletions
diff --git a/koch.nim b/koch.nim
index 97f6a0c8e..a3f5fb3de 100644
--- a/koch.nim
+++ b/koch.nim
@@ -1,7 +1,7 @@
 #
 #
 #         Maintenance program for Nim
-#        (c) Copyright 2015 Andreas Rumpf
+#        (c) Copyright 2016 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -25,17 +25,12 @@ import
 
 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                              |
+|             (c) 2016 Andreas Rumpf                              |
 +-----------------------------------------------------------------+
 Build time: $2, $3
 
@@ -45,7 +40,7 @@ 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!
+  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
@@ -57,10 +52,10 @@ 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)
+  nimble                   builds the Nimble tool
+  tools                    builds Nim related tools
 Boot options:
   -d:release               produce a release version of the compiler
   -d:tinyc                 include the Tiny C backend (not supported on Windows)
@@ -74,7 +69,10 @@ Web options:
                            build the official docs, use UA-48159761-1
 """
 
-proc exe(f: string): string = return addFileExt(f, ExeExt)
+proc exe(f: string): string =
+  result = addFileExt(f, ExeExt)
+  when defined(windows):
+    result = result.replace('/','\\')
 
 proc findNim(): string =
   var nim = "nim".exe
@@ -85,17 +83,20 @@ proc findNim(): string =
   # 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:
+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)
+    putEnv("PATH", prevPath & PathSep & absolute)
   echo(cmd)
   if execShellCmd(cmd) != 0: quit("FAILURE", errorcode)
-  putEnv("PATH", prevPATH)
+  putEnv("PATH", prevPath)
+
+proc nimexec(cmd: string) =
+  exec findNim() & " " & cmd
 
 proc execCleanPath(cmd: string,
                    additionalPath = ""; errorcode: int = QuitFailure) =
@@ -128,6 +129,8 @@ proc testUnixInstall() =
       execCleanPath("./koch boot -d:release", destDir / "bin")
       # check the docs build:
       execCleanPath("./koch web", destDir / "bin")
+      # check nimble builds:
+      execCleanPath("./bin/nim e install_tools.nims")
       # check the tests work:
       execCleanPath("./koch tests", destDir / "bin")
     else:
@@ -148,13 +151,16 @@ proc copyExe(source, dest: string) =
   inclFilePermissions(dest, {fpUserExec})
 
 const
-  compileNimInst = "-d:useLibzipSrc tools/niminst/niminst"
+  compileNimInst = "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()])
+  nimexec(("cc $1 -r $3 --var:version=$2 --var:mingw=none csource " &
+           "--main:compiler/nim.nim compiler/installer.ini $1") %
+       [args, VersionAsString, compileNimInst])
 
-proc bundleNimble() =
+proc bundleNimbleSrc() =
+  ## bunldeNimbleSrc() bundles a specific Nimble commit with the tarball. We
+  ## always bundle the latest official release.
   if dirExists("dist/nimble/.git"):
     exec("git --git-dir dist/nimble/.git pull")
   else:
@@ -162,31 +168,86 @@ proc bundleNimble() =
   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)
+
+proc bundleNimbleExe() =
+  bundleNimbleSrc()
   # 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")
+  nimexec("c dist/nimble/src/nimble.nim")
   copyExe("dist/nimble/src/nimble".exe, "bin/nimble".exe)
 
+proc buildNimble() =
+  ## buildNimble() builds Nimble for the building via "github". As such, we
+  ## choose the most recent commit of Nimble too.
+  var installDir = "dist/nimble"
+  if dirExists("dist/nimble/.git"):
+    exec("git --git-dir dist/nimble/.git pull")
+  else:
+    # if dist/nimble exist, but is not a git repo, don't mess with it:
+    if dirExists(installDir):
+      var id = 0
+      while dirExists("dist/nimble" & $id):
+        inc id
+      installDir = "dist/nimble" & $id
+    exec("git clone https://github.com/nim-lang/nimble.git " & installDir)
+  nimexec("c " & installDir / "src/nimble.nim")
+  copyExe(installDir / "src/nimble".exe, "bin/nimble".exe)
+
+proc bundleNimsuggest(buildExe: bool) =
+  if dirExists("dist/nimsuggest/.git"):
+    exec("git --git-dir dist/nimsuggest/.git pull")
+  else:
+    exec("git clone https://github.com/nim-lang/nimsuggest.git dist/nimsuggest")
+  if buildExe:
+    nimexec("c --noNimblePath -d:release -p:compiler dist/nimsuggest/nimsuggest.nim")
+    copyExe("dist/nimsuggest/nimsuggest".exe, "bin/nimsuggest".exe)
+    removeFile("dist/nimsuggest/nimsuggest".exe)
+
+proc bundleFinishExe() =
+  nimexec("c tools/finish.nim")
+  copyExe("tools/finish".exe, "finish".exe)
+  removeFile("tools/finish".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()])
+  bundleNimbleSrc()
+  bundleNimsuggest(false)
+  bundleFinishExe()
+  nimexec("cc -r $2 --var:version=$1 --var:mingw=none --main:compiler/nim.nim scripts compiler/installer.ini" %
+       [VersionAsString, compileNimInst])
   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()])
+  bundleNimbleSrc()
+  bundleNimsuggest(false)
+  nimexec("cc -r $2 --var:version=$1 --var:mingw=none --main:compiler/nim.nim scripts compiler/installer.ini" %
+       [VersionAsString, compileNimInst])
   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])
+  nimexec("cc $# $#" % [args, toolname])
   copyFile(dest="bin"/ splitFile(toolname).name.exe, source=toolname.exe)
 
+proc buildTools() =
+  if not dirExists"dist/nimble":
+    echo "[Error] 'koch tools' only works for the tarball."
+  else:
+    let nimbleExe = "bin/nimble".exe
+    nimexec "c --noNimblePath -p:compiler -o:" & nimbleExe &
+        " dist/nimble/src/nimble.nim"
+
+    let nimsugExe = "bin/nimsuggest".exe
+    nimexec "c --noNimblePath -p:compiler -d:release -o:" & nimsugExe &
+        " dist/nimsuggest/nimsuggest.nim"
+
+    let nimgrepExe = "bin/nimgrep".exe
+    nimexec "c -o:" & nimgrepExe & " tools/nimgrep.nim"
+
 proc nsis(args: string) =
-  bundleNimble()
+  bundleNimbleExe()
+  bundleNimsuggest(true)
+  bundleFinishExe()
   # make sure we have generated the niminst executables:
   buildTool("tools/niminst/niminst", args)
   #buildTool("tools/nimgrep", args)
@@ -197,20 +258,21 @@ proc nsis(args: string) =
         " 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])
+  nimexec("cc -r $# --var:version=$# --var:mingw=none --main:compiler/nim.nim scripts compiler/installer.ini $#" %
+       [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])
+  nimexec("js tools/dochack/dochack.nim")
+  nimexec("cc -r tools/nimweb.nim $# web/website.ini --putenv:nimversion=$#" %
+       [args, VersionAsString])
 
 proc website(args: string) =
-  exec("$# cc -r tools/nimweb.nim $# --website web/website.ini --putenv:nimversion=$#" %
-       [findNim(), args, VersionAsString])
+  nimexec("cc -r tools/nimweb.nim $# --website web/website.ini --putenv:nimversion=$#" %
+       [args, VersionAsString])
 
 proc pdf(args="") =
   exec("$# cc -r tools/nimweb.nim $# --pdf web/website.ini --putenv:nimversion=$#" %
@@ -249,11 +311,13 @@ proc boot(args: string) =
   var finalDest = "bin" / "nim".exe
   # default to use the 'c' command:
   let bootOptions = if args.len == 0 or args.startsWith("-"): "c" else: ""
+  let smartNimcache = if "release" in args: "nimcache/release" else: "nimcache/debug"
 
   copyExe(findStartNim(), 0.thVersion)
   for i in 0..2:
     echo "iteration: ", i+1
-    exec i.thVersion & " $# $# compiler" / "nim.nim" % [bootOptions, args]
+    exec i.thVersion & " $# $# --nimcache:$# compiler" / "nim.nim" % [bootOptions, args,
+        smartNimcache]
     if sameFileContent(output, i.thVersion):
       copyExe(output, finalDest)
       echo "executables are equal: SUCCESS!"
@@ -278,7 +342,7 @@ proc cleanAux(dir: string) =
   for kind, path in walkDir(dir):
     case kind
     of pcFile:
-      var (dir, name, ext) = splitFile(path)
+      var (_, name, ext) = splitFile(path)
       if ext == "" or cleanExt.contains(ext):
         if not ignore.contains(name):
           echo "removing: ", path
@@ -298,7 +362,6 @@ proc removePattern(pattern: string) =
     removeFile(f)
 
 proc clean(args: string) =
-  if existsFile("koch.dat"): removeFile("koch.dat")
   removePattern("web/*.html")
   removePattern("doc/*.html")
   cleanAux(getCurrentDir())
@@ -307,108 +370,22 @@ 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 ---------------------------------------------
 
-proc run7z(platform: string, patterns: varargs[string]) =
-  const tmpDir = "nim-" & VersionAsString
-  createDir tmpDir
-  try:
-    for pattern in patterns:
-      for f in walkFiles(pattern):
-        if "nimcache" notin f:
-          copyFile(f, tmpDir / f)
-    exec("7z a -tzip $1-$2.zip $1" % [tmpDir, platform])
-  finally:
-    removeDir tmpDir
-
 proc winRelease() =
-  boot(" -d:release")
-  #buildTool("tools/niminst/niminst", " -d:release")
-  buildTool("tools/nimgrep", " -d:release")
-  buildTool("compiler/nimfix/nimfix", " -d:release")
-  buildTool("compiler/nimsuggest/nimsuggest", " -d:release")
-
-  #run7z("win32", "bin/nim.exe", "bin/c2nim.exe", "bin/nimgrep.exe",
-  #      "bin/nimfix.exe",
-  #      "bin/nimble.exe", "bin/*.dll",
-  #      "config", "dist/*.dll", "examples", "lib",
-  #      "readme.txt", "contributors.txt", "copying.txt")
-
-  # second step: XXX build 64 bit version
+  exec(r"call ci\nsis_build.bat " & VersionAsString)
 
 # -------------- tests --------------------------------------------------------
 
-template `|`(a, b): expr = (if a.len > 0: a else: b)
+template `|`(a, b): string = (if a.len > 0: a else: b)
 
 proc tests(args: string) =
   # we compile the tester with taintMode:on to have a basic
   # taint mode test :-)
-  let nimexe = findNim()
-  exec nimexe & " cc --taintMode:on tests/testament/tester"
+  nimexec "cc --taintMode:on tests/testament/tester"
   # Since tests take a long time (on my machine), and we want to defy Murhpys
   # law - lets make sure the compiler really is freshly compiled!
-  exec nimexe & " c --lib:lib -d:release --opt:speed compiler/nim.nim"
+  nimexec "c --lib:lib -d:release --opt:speed compiler/nim.nim"
   let tester = quoteShell(getCurrentDir() / "tests/testament/tester".exe)
   let success = tryExec tester & " " & (args|"all")
   if not existsEnv("TRAVIS") and not existsEnv("APPVEYOR"):
@@ -438,6 +415,8 @@ of cmdArgument:
   of "boot": boot(op.cmdLineRest)
   of "clean": clean(op.cmdLineRest)
   of "web": web(op.cmdLineRest)
+  of "doc", "docs": web("--onlyDocs " & op.cmdLineRest)
+  of "json2": web("--json2 " & op.cmdLineRest)
   of "website": website(op.cmdLineRest & " --googleAnalytics:UA-48159761-1")
   of "web0":
     # undocumented command for Araq-the-merciful:
@@ -448,15 +427,13 @@ of cmdArgument:
   of "xz": xz(op.cmdLineRest)
   of "nsis": nsis(op.cmdLineRest)
   of "geninstall": geninstall(op.cmdLineRest)
+  of "distrohelper": geninstall()
   of "install": install(op.cmdLineRest)
   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()
+  of "nimble": buildNimble()
+  of "tools": buildTools()
   else: showHelp()
 of cmdEnd: showHelp()