Moved vccenv over to vcvarsall

Updated vccexe with new command-line arguments
This commit is contained in:
Fredrik Høisæther Rasch
2017-03-20 16:23:54 +01:00
parent 93e03144fc
commit 9446ae5576
3 changed files with 116 additions and 72 deletions

View File

@@ -1,58 +0,0 @@
import strtabs, os, osproc, streams, strutils
const
comSpecEnvKey = "ComSpec"
vsComnToolsEnvKeys = [
"VS140COMNTOOLS",
"VS130COMNTOOLS",
"VS120COMNTOOLS",
"VS110COMNTOOLS",
"VS100COMNTOOLS",
"VS90COMNTOOLS"
]
vcvarsallRelativePath = joinPath("..", "..", "VC", "vcvarsall")
proc getVsComnToolsPath*(): TaintedString =
for vsComnToolsEnvKey in vsComnToolsEnvKeys:
let vsComnToolsEnvVal = getEnv vsComnToolsEnvKey
if vsComnToolsEnvVal.len > 0:
return vsComnToolsEnvVal
proc getVccEnv*(platform: string, windowsStoreSdk: bool = false,
sdkVersion: string = nil): StringTableRef =
var comSpecCommandString = getEnv comSpecEnvKey
if comSpecCommandString.len == 0:
comSpecCommandString = "cmd"
let vsComnToolsPath = getVsComnToolsPath()
if vsComnToolsPath.len < 1:
return nil
let vcvarsallPath = expandFilename joinPath(vsComnToolsPath, vcvarsallRelativePath)
var vcvarsallArgs: seq[string] = @[]
if platform.len > 0:
vcvarsallArgs.add(platform)
if windowsStoreSdk:
vcvarsallArgs.add("store")
if sdkVersion.len > 0:
vcvarsallArgs.add(sdkVersion)
let vcvarsallArgString = vcvarsallArgs.join(" ")
var vcvarsallCommandString: string
if vcvarsallArgString.len > 0:
vcvarsallCommandString = "\"$1\" $2" % [vcvarsallPath, vcvarsallArgString]
else:
vcvarsallCommandString = vcvarsallPath
let vcvarsallExecCommand = "\"$1\" /C \"$2 && SET\"" %
[comSpecCommandString, vcvarsallCommandString]
when defined(release):
let vccvarsallOptions = {poEvalCommand, poDemon}
else:
let vccvarsallOptions = {poEchoCmd, poEvalCommand, poDemon}
let vcvarsallStdOut = execProcess(vcvarsallExecCommand, options = vccvarsallOptions)
result = newStringTable(modeCaseInsensitive)
for line in vcvarsallStdOut.splitLines:
let idx = line.find('=')
if idx > 0:
result[line[0..(idx - 1)]] = line[(idx + 1)..(line.len - 1)]

View File

@@ -1,4 +1,4 @@
import strutils, strtabs, os, osproc, vccenv
import strutils, strtabs, os, osproc, vcvarsall
when defined(release):
let vccOptions = {poParentStreams}
@@ -6,47 +6,73 @@ else:
let vccOptions = {poEchoCmd, poParentStreams}
const
vcvarsallPrefix = "--vcvarsall"
commandPrefix = "--command"
platformPrefix = "--platform"
winstorePrefix = "--winstore"
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) 2016 Fredrik Høisæther Rasch |
| (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
--winstore Use Windows Store (rather than desktop) development tools
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
Microsoft C/C++ compiler for the specified SDK toolset
secondary command specified by --command or to the
Microsoft (R) C/C++ Optimizing Compiler if no secondary
command was specified
"""
when isMainModule:
var platformArg: string = nil
var vcvarsallArg: string = nil
var commandArg: string = nil
var platformArg: VccArch
var sdkTypeArg: VccPlatformType
var sdkVersionArg: string = nil
var storeArg: bool = false
var clArgs: seq[TaintedString] = @[]
var wrapperArgs = commandLineParams()
for wargv in wrapperArgs:
# Check whether the current argument contains -- prefix
if wargv.startsWith(platformPrefix): # Check for platform
platformArg = wargv.substr(platformSepIdx + 1)
elif wargv == winstorePrefix: # Check for winstore
storeArg = true
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
@@ -54,10 +80,13 @@ when isMainModule:
echo HelpText
clArgs.add(wargv)
var vccEnvStrTab = getVccEnv(platformArg, storeArg, sdkVersionArg)
if vccEnvStrTab != nil:
for vccEnvKey, vccEnvVal in vccEnvStrTab:
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,

View File

@@ -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)]