summary refs log tree commit diff stats
path: root/tools/vccexe
diff options
context:
space:
mode:
authorFredrik Høisæther Rasch <fredrik.h.rasch@uit.no>2017-03-20 16:36:16 +0100
committerFredrik Høisæther Rasch <fredrik.h.rasch@uit.no>2017-03-21 12:17:09 +0100
commit45f61ad0466d317bb77b151ed633389fd0eeac22 (patch)
treecb61b9039ebb2353f2d0f1344e48cfab070de8e0 /tools/vccexe
parent9446ae5576e43285a28c4b1705a139d317867328 (diff)
downloadNim-45f61ad0466d317bb77b151ed633389fd0eeac22.tar.gz
Moved vccexe to a more logical place (vccexe)
Diffstat (limited to 'tools/vccexe')
-rw-r--r--tools/vccexe/vccexe.nim95
-rw-r--r--tools/vccexe/vcvarsall.nim73
2 files changed, 168 insertions, 0 deletions
diff --git a/tools/vccexe/vccexe.nim b/tools/vccexe/vccexe.nim
new file mode 100644
index 000000000..4ecbfe50e
--- /dev/null
+++ b/tools/vccexe/vccexe.nim
@@ -0,0 +1,95 @@
+import strutils, strtabs, os, osproc, vcvarsall
+
+when defined(release):
+  let vccOptions = {poParentStreams}
+else:
+  let vccOptions = {poEchoCmd, poParentStreams}
+
+const 
+  vcvarsallPrefix = "--vcvarsall"
+  commandPrefix = "--command"
+  platformPrefix = "--platform"
+  sdktypePrefix = "--sdktype"
+  sdkversionPrefix = "--sdkversion"
+
+  vcvarsallSepIdx = vcvarsallPrefix.len
+  commandSepIdx = commandPrefix.len
+  platformSepIdx = platformPrefix.len
+  sdktypeSepIdx = sdktypePrefix.len
+  sdkversionSepIdx = sdkversionPrefix.len
+  
+  HelpText = """
++-----------------------------------------------------------------+
+|         Microsoft C/C++ compiler wrapper for Nim                |
+|            (c) 2017 Fredrik Hoeisaether Rasch                   |
++-----------------------------------------------------------------+
+
+Usage:
+  vccexe [options] [compileroptions]
+Options:
+  --vcvarsall:<path>  Path to the Developer Command Prompt utility vcvarsall.bat that selects
+                      the appropiate devlopment settings.
+                      Usual path for Visual Studio 2015 and below:
+                        %VSInstallDir%\VC\vcvarsall
+                      Usual path for Visual Studio 2017 and above:
+                        %VSInstallDir%\VC\Auxiliary\Build\vcvarsall
+  --command:<exec>    Specify the command to run once the development environment is loaded.
+                      <exec> can be any command-line argument. Any arguments not recognized by vccexe
+                      are passed on as arguments to this command.
+                      cl.exe is invoked by default if this argument is omitted.
+  --platform:<arch>   Specify the Compiler Platform Tools architecture
+                      <arch>: x86 | amd64 | arm | x86_amd64 | x86_arm | amd64_x86 | amd64_arm
+                      Values with two architectures (like x86_amd64) specify the architecture
+                      of the cross-platform compiler (e.g. x86) and the target it compiles to (e.g. amd64).
+  --sdktype:<type>    Specify the SDK flavor to use. Defaults to the Desktop SDK.
+                      <type>: {empty} | store | uwp | onecore
+  --sdkversion:<v>    Use a specific Windows SDK version:
+                      <v> is either the full Windows 10 SDK version number or 
+                      "8.1" to use the windows 8.1 SDK
+
+Other command line arguments are passed on to the
+secondary command specified by --command or to the
+Microsoft (R) C/C++ Optimizing Compiler if no secondary
+command was specified
+"""
+
+when isMainModule:
+  var vcvarsallArg: string = nil
+  var commandArg: string = nil
+  var platformArg: VccArch
+  var sdkTypeArg: VccPlatformType
+  var sdkVersionArg: string = nil
+
+  var clArgs: seq[TaintedString] = @[]
+
+  var wrapperArgs = commandLineParams()
+  for wargv in wrapperArgs:
+    # Check whether the current argument contains -- prefix
+    if wargv.startsWith(vcvarsallPrefix): # Check for vcvarsall
+      vcvarsallArg = wargv.substr(vcvarsallSepIdx + 1)
+    elif wargv.startsWith(commandPrefix): # Check for command
+      commandArg = wargv.substr(commandSepIdx + 1)
+    elif wargv.startsWith(platformPrefix): # Check for platform
+      platformArg = parseEnum[VccArch](wargv.substr(platformSepIdx + 1))
+    elif wargv.startsWith(sdktypePrefix): # Check for sdktype
+      sdkTypeArg = parseEnum[VccPlatformType](wargv.substr(sdktypeSepIdx + 1))
+    elif wargv.startsWith(sdkversionPrefix): # Check for sdkversion
+      sdkVersionArg = wargv.substr(sdkversionSepIdx + 1)
+    else: # Regular cl.exe argument -> store for final cl.exe invocation
+      if (wargv.len == 2) and (wargv[1] == '?'):
+        echo HelpText
+      clArgs.add(wargv)
+
+  var vcvars = vccVarsAll(vcvarsallArg, platformArg, sdkTypeArg, sdkVersionArg)
+  if vcvars != nil:
+    for vccEnvKey, vccEnvVal in vcvars:
+      putEnv(vccEnvKey, vccEnvVal)
+
+  if commandArg.len < 1:
+    commandArg = "cl.exe"
+  let vccProcess = startProcess(
+      "cl.exe",
+      args = clArgs,
+      options = vccOptions
+    )
+  quit vccProcess.waitForExit()
diff --git a/tools/vccexe/vcvarsall.nim b/tools/vccexe/vcvarsall.nim
new file mode 100644
index 000000000..db97177b0
--- /dev/null
+++ b/tools/vccexe/vcvarsall.nim
@@ -0,0 +1,73 @@
+import strtabs, strutils, os, osproc
+
+const
+  comSpecEnvKey = "ComSpec" # Environment Variable that specifies the command-line application path in Windows
+                            # Usually set to cmd.exe
+  vcvarsallDefaultPath = "vcvarsall.bat"
+
+type
+  VccArch* = enum
+    vccarchUnspecified = "",
+    vccarchX86 = "x86",
+    vccarchAmd64 = "amd64",
+    vccarchX86Amd64 = "x86_amd64",
+    vccarchX86Arm = "x86_arm",
+    vccarchX86Arm64 = "x86_arm64",
+    vccarchAmd64X86 = "amd64_x86",
+    vccarchAmd64Arm = "amd64_arm",
+    vccarchAmd64Arm64 = "amd64_arm64",
+    vccarchX64 = "x64",
+    vccarchX64X86 = "x64_x86",
+    vccarchX64Arm = "x64_arm",
+    vccarchX64Arm64 = "x64_arm64"
+
+  VccPlatformType* = enum
+    vccplatEmpty = "",
+    vccplatStore = "store",
+    vccplatUWP = "uwp",
+    vccplatOneCore = "onecore"
+
+proc vccVarsAll*(path: string, arch: VccArch = vccarchUnspecified, platform_type: VccPlatformType = vccplatEmpty, sdk_version: string = nil): StringTableRef =
+  var vccvarsallpath = path
+  # Assume that default executable is in current directory or in PATH
+  if path == nil or path.len < 1:
+    vccvarsallpath = vcvarsallDefaultPath
+  
+  var args: seq[string] = @[]
+  
+  let archStr: string = $arch
+  if archStr.len > 0:
+    args.add(archStr)
+  
+  let platStr: string = $platform_type
+  if platStr.len > 0:
+    args.add(platStr)
+
+  if sdk_version.len > 0:
+    args.add(sdk_version)
+
+  let argStr = args.join " "
+  
+  var vcvarsExec: string
+  if argStr.len > 0:
+    vcvarsExec = "\"$1\" $2" % [vccvarsallpath, argStr]
+  else:
+    vcvarsExec = "\"$1\"" % vccvarsallpath
+
+  var comSpecCmd = getenv comSpecEnvKey
+  if comSpecCmd.len < 1:
+    comSpecCmd = "cmd"
+  
+  let comSpecExec = "\"$1\" /C \"$2 && SET\"" % [comSpecCmd, vcvarsExec]
+  when defined(release):
+    let comSpecOpts = {poEvalCommand, poDemon, poStdErrToStdOut}
+  else:
+    let comSpecOpts = {poEchoCmd, poEvalCommand, poDemon, poStdErrToStdOut}
+  let comSpecOut = execProcess(comSpecExec, options = comSpecOpts)
+  result = newStringTable(modeCaseInsensitive)
+  for line in comSpecOut.splitLines:
+    when not defined(release) or defined(debug):
+      echo line
+    let idx = line.find('=')
+    if idx > 0:
+      result[line[0..(idx - 1)]] = line[(idx + 1)..(line.len - 1)]