Merge branch 'couven92-devel' into devel
This commit is contained in:
commit
cc97453808
9 changed files with 367 additions and 147 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -19,6 +19,8 @@ dnimcache/
|
||||||
*.zip
|
*.zip
|
||||||
*.iss
|
*.iss
|
||||||
*.log
|
*.log
|
||||||
|
*.ilk
|
||||||
|
*.pdb
|
||||||
|
|
||||||
mapping.txt
|
mapping.txt
|
||||||
tags
|
tags
|
||||||
|
|
|
||||||
|
|
@ -134,7 +134,7 @@ compiler vcc:
|
||||||
result = (
|
result = (
|
||||||
name: "vcc",
|
name: "vcc",
|
||||||
objExt: "obj",
|
objExt: "obj",
|
||||||
optSpeed: " /Ogityb2 /G7 /arch:SSE2 ",
|
optSpeed: " /Ogityb2 /G7 ",
|
||||||
optSize: " /O1 /G7 ",
|
optSize: " /O1 /G7 ",
|
||||||
compilerExe: "cl",
|
compilerExe: "cl",
|
||||||
cppCompiler: "cl",
|
cppCompiler: "cl",
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ hint[LineTooLong]=off
|
||||||
arm.linux.gcc.exe = "arm-linux-gnueabihf-gcc"
|
arm.linux.gcc.exe = "arm-linux-gnueabihf-gcc"
|
||||||
arm.linux.gcc.linkerexe = "arm-linux-gnueabihf-gcc"
|
arm.linux.gcc.linkerexe = "arm-linux-gnueabihf-gcc"
|
||||||
|
|
||||||
# For OpenWRT, you will also need to adjust PATH to point to your toolchain.
|
# For OpenWRT, you will also need to adjust PATH to point to your toolchain.
|
||||||
mips.linux.gcc.exe = "mips-openwrt-linux-gcc"
|
mips.linux.gcc.exe = "mips-openwrt-linux-gcc"
|
||||||
mips.linux.gcc.linkerexe = "mips-openwrt-linux-gcc"
|
mips.linux.gcc.linkerexe = "mips-openwrt-linux-gcc"
|
||||||
|
|
||||||
|
|
@ -225,9 +225,13 @@ clang.options.speed = "-O3"
|
||||||
clang.options.size = "-Os"
|
clang.options.size = "-Os"
|
||||||
|
|
||||||
# Configuration for the Visual C/C++ compiler:
|
# Configuration for the Visual C/C++ compiler:
|
||||||
vcc.exe = "vccexe.exe"
|
# VCCEXE is a tool that invokes the Visual Studio Developer Command Prompt
|
||||||
|
# before calling the compiler.
|
||||||
|
# Please make sure either Visual Studio or C++ Build SKU is installed when using the vcc compiler backend.
|
||||||
|
|
||||||
|
vcc.exe = "vccexe.exe"
|
||||||
vcc.cpp.exe = "vccexe.exe"
|
vcc.cpp.exe = "vccexe.exe"
|
||||||
vcc.linkerexe = "vccexe.exe"
|
vcc.linkerexe = "vccexe.exe"
|
||||||
vcc.cpp.linkerexe = "vccexe.exe"
|
vcc.cpp.linkerexe = "vccexe.exe"
|
||||||
|
|
||||||
# set the options for specific platforms:
|
# set the options for specific platforms:
|
||||||
|
|
@ -238,30 +242,35 @@ vcc.options.always = "/nologo"
|
||||||
vcc.options.always %= "${vcc.options.always} /Z7" # Get VCC to output full debug symbols in the obj file
|
vcc.options.always %= "${vcc.options.always} /Z7" # Get VCC to output full debug symbols in the obj file
|
||||||
@end
|
@end
|
||||||
vcc.cpp.options.always %= "${vcc.options.always} /EHsc"
|
vcc.cpp.options.always %= "${vcc.options.always} /EHsc"
|
||||||
vcc.options.linker = "/nologo /DEBUG /Zi /F33554432" # set the stack size to 32 MiB
|
vcc.options.linker = "/nologo /DEBUG /Zi /F33554432" # set the stack size to 32 MiB
|
||||||
vcc.cpp.options.linker %= "${vcc.options.linker}"
|
vcc.cpp.options.linker %= "${vcc.options.linker}"
|
||||||
@if i386:
|
@if i386:
|
||||||
vcc.options.always %= "--platform:x86 ${vcc.options.always}"
|
vcc.options.always = "--platform:x86 /nologo"
|
||||||
vcc.cpp.options.always %= "--platform:x86 ${vcc.cpp.options.always}"
|
vcc.cpp.options.always = "--platform:x86 /nologo /EHsc"
|
||||||
vcc.options.linker %= "--platform:x86 ${vcc.options.linker}"
|
vcc.options.linker = "--platform:x86 /nologo /DEBUG /Zi /F33554432" # set the stack size to 32 MiB
|
||||||
vcc.cpp.options.linker %= "--platform:x86 ${vcc.cpp.options.linker}"
|
vcc.cpp.options.linker = "--platform:x86 /nologo /DEBUG /Zi /F33554432" # set the stack size to 32 MiB
|
||||||
@elif amd64:
|
@elif amd64:
|
||||||
vcc.options.always %= "--platform:amd64 ${vcc.options.always}"
|
vcc.options.always = "--platform:amd64 /nologo"
|
||||||
vcc.cpp.options.always %= "--platform:amd64 ${vcc.cpp.options.always}"
|
vcc.cpp.options.always = "--platform:amd64 /nologo /EHsc"
|
||||||
vcc.options.linker %= "--platform:amd64 ${vcc.options.linker}"
|
vcc.options.linker = "--platform:amd64 /nologo /DEBUG /Zi /F33554432" # set the stack size to 32 MiB
|
||||||
vcc.cpp.options.linker %= "--platform:amd64 ${vcc.cpp.options.linker}"
|
vcc.cpp.options.linker = "--platform:amd64 /nologo /DEBUG /Zi /F33554432" # set the stack size to 32 MiB
|
||||||
@elif arm:
|
@elif arm:
|
||||||
vcc.options.always %= "--platform:arm ${vcc.options.always}"
|
vcc.options.always = "--platform:arm /nologo"
|
||||||
vcc.cpp.options.always %= "--platform:arm ${vcc.cpp.options.always}"
|
vcc.cpp.options.always = "--platform:arm /nologo /EHsc"
|
||||||
vcc.options.linker %= "--platform:arm ${vcc.options.linker}"
|
vcc.options.linker = "--platform:arm /nologo /DEBUG /Zi /F33554432" # set the stack size to 32 MiB
|
||||||
vcc.cpp.options.linker %= "--platform:arm ${vcc.cpp.options.linker}"
|
vcc.cpp.options.linker = "--platform:arm /nologo /DEBUG /Zi /F33554432" # set the stack size to 32 MiB
|
||||||
|
@else:
|
||||||
|
vcc.options.always = "/nologo"
|
||||||
|
vcc.cpp.options.always = "/nologo /EHsc"
|
||||||
|
vcc.options.linker = "/nologo /DEBUG /Zi /F33554432" # set the stack size to 32 MiB
|
||||||
|
vcc.cpp.options.linker = "/nologo /DEBUG /Zi /F33554432" # set the stack size to 32 MiB
|
||||||
@end
|
@end
|
||||||
|
|
||||||
vcc.options.debug = "/Od"
|
vcc.options.debug = "/Zi /FS /Od"
|
||||||
vcc.cpp.options.debug = "/Od"
|
vcc.cpp.options.debug = "/Zi /FS /Od"
|
||||||
vcc.options.speed = "/O2"
|
vcc.options.speed = "/O2"
|
||||||
vcc.cpp.options.speed = "/O2"
|
vcc.cpp.options.speed = "/O2"
|
||||||
vcc.options.size = "/O1"
|
vcc.options.size = "/O1"
|
||||||
vcc.cpp.options.size = "/O1"
|
vcc.cpp.options.size = "/O1"
|
||||||
|
|
||||||
# Configuration for the Tiny C Compiler:
|
# Configuration for the Tiny C Compiler:
|
||||||
|
|
|
||||||
2
koch.nim
2
koch.nim
|
|
@ -154,7 +154,7 @@ proc bundleNimsuggest() =
|
||||||
nimCompile("nimsuggest/nimsuggest.nim", options = "-d:release")
|
nimCompile("nimsuggest/nimsuggest.nim", options = "-d:release")
|
||||||
|
|
||||||
proc buildVccTool() =
|
proc buildVccTool() =
|
||||||
nimCompile("tools/vccenv/vccexe.nim")
|
nimCompile("tools/vccexe/vccexe.nim")
|
||||||
|
|
||||||
proc bundleWinTools() =
|
proc bundleWinTools() =
|
||||||
# TODO: consider building under `bin` instead of `.`
|
# TODO: consider building under `bin` instead of `.`
|
||||||
|
|
|
||||||
|
|
@ -1,59 +0,0 @@
|
||||||
import strtabs, os, osproc, streams, strutils
|
|
||||||
|
|
||||||
const
|
|
||||||
comSpecEnvKey = "ComSpec"
|
|
||||||
vsComnToolsEnvKeys = [
|
|
||||||
"VS150COMNTOOLS",
|
|
||||||
"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 = ""): 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)]
|
|
||||||
|
|
@ -1,66 +0,0 @@
|
||||||
import strutils, strtabs, os, osproc, vccenv
|
|
||||||
|
|
||||||
when defined(release):
|
|
||||||
let vccOptions = {poParentStreams}
|
|
||||||
else:
|
|
||||||
let vccOptions = {poEchoCmd, poParentStreams}
|
|
||||||
|
|
||||||
const
|
|
||||||
platformPrefix = "--platform"
|
|
||||||
winstorePrefix = "--winstore"
|
|
||||||
sdkversionPrefix = "--sdkversion"
|
|
||||||
|
|
||||||
platformSepIdx = platformPrefix.len
|
|
||||||
sdkversionSepIdx = sdkversionPrefix.len
|
|
||||||
|
|
||||||
HelpText = """
|
|
||||||
+-----------------------------------------------------------------+
|
|
||||||
| Microsoft C/C++ compiler wrapper for Nim |
|
|
||||||
| (c) 2016 Fredrik Høisæther Rasch |
|
|
||||||
+-----------------------------------------------------------------+
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
vccexe [options] [compileroptions]
|
|
||||||
Options:
|
|
||||||
--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
|
|
||||||
--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
|
|
||||||
"""
|
|
||||||
|
|
||||||
when isMainModule:
|
|
||||||
var platformArg: string = ""
|
|
||||||
var sdkVersionArg: string = ""
|
|
||||||
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
|
|
||||||
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 vccEnvStrTab = getVccEnv(platformArg, storeArg, sdkVersionArg)
|
|
||||||
if vccEnvStrTab != nil:
|
|
||||||
for vccEnvKey, vccEnvVal in vccEnvStrTab:
|
|
||||||
putEnv(vccEnvKey, vccEnvVal)
|
|
||||||
let vccProcess = startProcess(
|
|
||||||
"cl.exe",
|
|
||||||
args = clArgs,
|
|
||||||
options = vccOptions
|
|
||||||
)
|
|
||||||
quit vccProcess.waitForExit()
|
|
||||||
47
tools/vccexe/vccenv.nim
Normal file
47
tools/vccexe/vccenv.nim
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
## VCC compiler backend installation discovery using Visual Studio common tools
|
||||||
|
## environment variables.
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
type
|
||||||
|
VccEnvVersion* = enum ## The version of the Visual Studio C/C++ Developer Environment to load
|
||||||
|
## Valid versions are Versions of Visual Studio that permanently set a COMNTOOLS
|
||||||
|
## environment variable. That includes Visual Studio version up to and including
|
||||||
|
## Visual Studio 2015
|
||||||
|
vsUndefined = (0, ""), ## Version not specified, use latest recogized version on the system
|
||||||
|
vs90 = (90, "VS90COMNTOOLS"), ## Visual Studio 2008
|
||||||
|
vs100 = (100, "VS100COMNTOOLS"), ## Visual Studio 2010
|
||||||
|
vs110 = (110, "VS110COMNTOOLS"), ## Visual Studio 2012
|
||||||
|
vs120 = (120, "VS120COMNTOOLS"), ## Visual Studio 2013
|
||||||
|
vs140 = (140, "VS140COMNTOOLS") ## Visual Studio 2015
|
||||||
|
|
||||||
|
const
|
||||||
|
vcvarsallRelativePath = joinPath("..", "..", "VC", "vcvarsall") ## Relative path from the COMNTOOLS path to the vcvarsall file.
|
||||||
|
|
||||||
|
proc vccEnvVcVarsAllPath*(version: VccEnvVersion = vsUndefined): string =
|
||||||
|
## Returns the path to the VCC Developer Command Prompt executable for the specified VCC version.
|
||||||
|
##
|
||||||
|
## Returns `nil` if the specified VCC compiler backend installation was not found.
|
||||||
|
##
|
||||||
|
## If the `version` parameter is omitted or set to `vsUndefined`, `vccEnvVcVarsAllPath` searches
|
||||||
|
## for the latest recognizable version of the VCC tools it can find.
|
||||||
|
##
|
||||||
|
## `vccEnvVcVarsAllPath` uses the COMNTOOLS environment variables to find the Developer Command Prompt
|
||||||
|
## executable path. The COMNTOOLS environment variable are permanently set when Visual Studio is installed.
|
||||||
|
## Each version of Visual Studio has its own COMNTOOLS environment variable. E.g.: Visual Studio 2015 sets
|
||||||
|
## The VS140COMNTOOLS environment variable.
|
||||||
|
##
|
||||||
|
## Note: Beginning with Visual Studio 2017, the installers no longer set environment variables to allow for
|
||||||
|
## multiple side-by-side installations of Visual Studio. Therefore, `vccEnvVcVarsAllPath` cannot be used
|
||||||
|
## to detect the VCC Developer Command Prompt executable path for Visual Studio 2017 and later.
|
||||||
|
|
||||||
|
if version == vsUndefined:
|
||||||
|
for tryVersion in [vs140, vs120, vs110, vs100, vs90]:
|
||||||
|
let tryPath = vccEnvVcVarsAllPath(tryVersion)
|
||||||
|
if tryPath.len > 0:
|
||||||
|
result = tryPath
|
||||||
|
else: # Specific version requested
|
||||||
|
let key = $version
|
||||||
|
let val = getEnv key
|
||||||
|
if val.len > 0:
|
||||||
|
result = expandFilename(val & vcvarsallRelativePath)
|
||||||
188
tools/vccexe/vccexe.nim
Normal file
188
tools/vccexe/vccexe.nim
Normal file
|
|
@ -0,0 +1,188 @@
|
||||||
|
import strutils, strtabs, os, osproc, vcvarsall, vccenv
|
||||||
|
|
||||||
|
type
|
||||||
|
VccVersion* = enum ## VCC compiler backend versions
|
||||||
|
vccUndefined = (0, ""), ## VCC version undefined, resolves to the latest recognizable VCC version
|
||||||
|
vcc90 = vs90, ## Visual Studio 2008 (Version 9.0)
|
||||||
|
vcc100 = vs100, ## Visual Studio 2010 (Version 10.0)
|
||||||
|
vcc110 = vs110, ## Visual Studio 2012 (Version 11.0)
|
||||||
|
vcc120 = vs120, ## Visual Studio 2013 (Version 12.0)
|
||||||
|
vcc140 = vs140 ## Visual Studio 2015 (Version 14.0)
|
||||||
|
|
||||||
|
proc discoverVccVcVarsAllPath*(version: VccVersion = vccUndefined): string =
|
||||||
|
## Returns the path to the vcvarsall utility of the specified VCC compiler backend.
|
||||||
|
##
|
||||||
|
## version
|
||||||
|
## The specific version of the VCC compiler backend to discover.
|
||||||
|
## Defaults to the latest recognized VCC compiler backend that is found on the system.
|
||||||
|
##
|
||||||
|
## Returns `nil` if the VCC compiler backend discovery failed.
|
||||||
|
|
||||||
|
# TODO: Attempt discovery using vswhere utility.
|
||||||
|
|
||||||
|
# Attempt discovery through VccEnv
|
||||||
|
# (Trying Visual Studio Common Tools Environment Variables)
|
||||||
|
result = vccEnvVcVarsAllPath(cast[VccEnvVersion](version))
|
||||||
|
if result.len > 0:
|
||||||
|
return
|
||||||
|
|
||||||
|
# All attempts to dicover vcc failed
|
||||||
|
|
||||||
|
const
|
||||||
|
vccversionPrefix = "--vccversion"
|
||||||
|
printPathPrefix = "--printPath"
|
||||||
|
vcvarsallPrefix = "--vcvarsall"
|
||||||
|
commandPrefix = "--command"
|
||||||
|
noCommandPrefix = "--noCommand"
|
||||||
|
platformPrefix = "--platform"
|
||||||
|
sdktypePrefix = "--sdktype"
|
||||||
|
sdkversionPrefix = "--sdkversion"
|
||||||
|
verbosePrefix = "--verbose"
|
||||||
|
|
||||||
|
vccversionSepIdx = vccversionPrefix.len
|
||||||
|
vcvarsallSepIdx = vcvarsallPrefix.len
|
||||||
|
commandSepIdx = commandPrefix.len
|
||||||
|
platformSepIdx = platformPrefix.len
|
||||||
|
sdktypeSepIdx = sdktypePrefix.len
|
||||||
|
sdkversionSepIdx = sdkversionPrefix.len
|
||||||
|
|
||||||
|
helpText = """
|
||||||
|
+-----------------------------------------------------------------+
|
||||||
|
| Microsoft C/C++ compiler wrapper for Nim |
|
||||||
|
| & |
|
||||||
|
| Microsoft C/C++ Compiler Discovery Utility |
|
||||||
|
| (c) 2017 Fredrik Hoeisaether Rasch |
|
||||||
|
+-----------------------------------------------------------------+
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
vccexe [options] [compileroptions]
|
||||||
|
Options:
|
||||||
|
--vccversion:<v> Optionally specify the VCC version to discover
|
||||||
|
<v>: 0, 90, 100, 110, 120, 140
|
||||||
|
If <v> is omitted, attempts to discover the latest
|
||||||
|
installed version. <v>: 0, 90, 100, 110, 120, 140
|
||||||
|
A value of 0 will discover the latest installed SDK
|
||||||
|
Multiple values can be specified, separated by ,
|
||||||
|
--printPath Print the discovered path of the vcvarsall utility
|
||||||
|
of the VCC version specified with the --vccversion argument.
|
||||||
|
For each specified version the utility prints a line with the
|
||||||
|
following format: <version>: <path>
|
||||||
|
--noCommand Flag to supress VCC secondary command execution
|
||||||
|
Useful in conjuction with --vccversion and --printPath to
|
||||||
|
only perfom VCC discovery, but without executing VCC tools
|
||||||
|
--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
|
||||||
|
--verbose Echoes the command line for loading the Developer Command Prompt
|
||||||
|
and the command line passed on to the secondary command.
|
||||||
|
|
||||||
|
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 vccversionArg: seq[string] = @[]
|
||||||
|
var printPathArg: bool = false
|
||||||
|
var vcvarsallArg: string = nil
|
||||||
|
var commandArg: string = nil
|
||||||
|
var noCommandArg: bool = false
|
||||||
|
var platformArg: VccArch
|
||||||
|
var sdkTypeArg: VccPlatformType
|
||||||
|
var sdkVersionArg: string = nil
|
||||||
|
var verboseArg: bool = false
|
||||||
|
|
||||||
|
var clArgs: seq[TaintedString] = @[]
|
||||||
|
|
||||||
|
# Cannot use usual command-line argument parser here
|
||||||
|
# Since vccexe command-line arguments are intermingled
|
||||||
|
# with the secondary command-line arguments which have
|
||||||
|
# a syntax that is not supported by the default nim
|
||||||
|
# argument parser.
|
||||||
|
var wrapperArgs = commandLineParams()
|
||||||
|
for wargv in wrapperArgs:
|
||||||
|
# Check whether the current argument contains -- prefix
|
||||||
|
if wargv.startsWith(vccversionPrefix): # Check for vccversion
|
||||||
|
vccversionArg.add(wargv.substr(vccversionSepIdx + 1))
|
||||||
|
elif wargv.cmpIgnoreCase(printPathPrefix) == 0: # Check for printPath
|
||||||
|
printPathArg = true
|
||||||
|
elif 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.cmpIgnoreCase(noCommandPrefix) == 0: # Check for noCommand
|
||||||
|
noCommandArg = true
|
||||||
|
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)
|
||||||
|
elif wargv.startsWith(verbosePrefix):
|
||||||
|
verboseArg = true
|
||||||
|
else: # Regular cl.exe argument -> store for final cl.exe invocation
|
||||||
|
if (wargv.len == 2) and (wargv[1] == '?'):
|
||||||
|
echo helpText
|
||||||
|
clArgs.add(wargv)
|
||||||
|
|
||||||
|
# Support for multiple specified versions. Attempt VCC discovery for each version
|
||||||
|
# specified, first successful discovery wins
|
||||||
|
var vccversionValue: VccVersion = vccUndefined
|
||||||
|
for vccversionItem in vccversionArg:
|
||||||
|
try:
|
||||||
|
vccversionValue = cast[VccVersion](parseInt(vccversionItem))
|
||||||
|
except ValueError:
|
||||||
|
continue
|
||||||
|
vcvarsallArg = discoverVccVcVarsAllPath(vccversionValue)
|
||||||
|
if vcvarsallArg.len > 0:
|
||||||
|
break
|
||||||
|
# VCC version not specified, discover latest (call discover without args)
|
||||||
|
if vcvarsallArg.len < 1 and vccversionArg.len < 1:
|
||||||
|
vccversionValue = vccUndefined
|
||||||
|
vcvarsallArg = discoverVccVcVarsAllPath()
|
||||||
|
|
||||||
|
if printPathArg:
|
||||||
|
var head = $vccversionValue
|
||||||
|
if head.len < 1:
|
||||||
|
head = "latest"
|
||||||
|
echo "$1: $2" % [head, vcvarsallArg]
|
||||||
|
|
||||||
|
# Call vcvarsall to get the appropiate VCC process environment
|
||||||
|
var vcvars = vccVarsAll(vcvarsallArg, platformArg, sdkTypeArg, sdkVersionArg, verboseArg)
|
||||||
|
if vcvars != nil:
|
||||||
|
for vccEnvKey, vccEnvVal in vcvars:
|
||||||
|
putEnv(vccEnvKey, vccEnvVal)
|
||||||
|
|
||||||
|
var vccOptions = {poParentStreams}
|
||||||
|
if verboseArg:
|
||||||
|
vccOptions.incl poEchoCmd
|
||||||
|
|
||||||
|
# Default to the cl.exe command if no secondary command was specified
|
||||||
|
if commandArg.len < 1:
|
||||||
|
commandArg = "cl.exe"
|
||||||
|
|
||||||
|
if not noCommandArg:
|
||||||
|
# Run VCC command with the VCC process environment
|
||||||
|
let vccProcess = startProcess(
|
||||||
|
commandArg,
|
||||||
|
args = clArgs,
|
||||||
|
options = vccOptions
|
||||||
|
)
|
||||||
|
quit vccProcess.waitForExit()
|
||||||
99
tools/vccexe/vcvarsall.nim
Normal file
99
tools/vccexe/vcvarsall.nim
Normal file
|
|
@ -0,0 +1,99 @@
|
||||||
|
## VCC Developer Command Prompt Loader
|
||||||
|
##
|
||||||
|
## In order for the VCC compiler backend to work properly, it requires numerous
|
||||||
|
## environment variables to be set properly for the desired architecture and compile target.
|
||||||
|
## For that purpose the VCC compiler ships with the vcvarsall utility which is an executable
|
||||||
|
## batch script that can be used to properly set up an Command Prompt environment.
|
||||||
|
|
||||||
|
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 ## The VCC compile target architectures
|
||||||
|
vccarchUnspecified = "",
|
||||||
|
vccarchX86 = "x86", ## VCC for compilation against the x86 architecture.
|
||||||
|
vccarchAmd64 = "amd64", ## VCC for compilation against the amd64 architecture.
|
||||||
|
vccarchX86Amd64 = "x86_amd64", ## VCC cross-compilation tools using x86 VCC for compilation against the amd64 architecture.
|
||||||
|
vccarchX86Arm = "x86_arm", ## VCC cross-compilation tools using x86 VCC for compilation against the ARM architecture.
|
||||||
|
vccarchX86Arm64 = "x86_arm64", ## VCC cross-compilation tools using x86 VCC for compilation against the ARM (64-bit) architecture.
|
||||||
|
vccarchAmd64X86 = "amd64_x86", ## VCC cross-compilation tools using amd64 VCC for compilation against the x86 architecture.
|
||||||
|
vccarchAmd64Arm = "amd64_arm", ## VCC cross-compilation tools using amd64 VCC for compilation against the ARM architecture.
|
||||||
|
vccarchAmd64Arm64 = "amd64_arm64", ## VCC cross-compilation tools using amd64 VCC for compilation against the ARM (64-bit) architecture.
|
||||||
|
vccarchX64 = "x64", ## VCC for compilation against the x64 architecture.
|
||||||
|
vccarchX64X86 = "x64_x86", ## VCC cross-compilation tools using x64 VCC for compilation against the x86 architecture.
|
||||||
|
vccarchX64Arm = "x64_arm", ## VCC cross-compilation tools using x64 VCC for compilation against the ARM architecture.
|
||||||
|
vccarchX64Arm64 = "x64_arm64" ## VCC cross-compilation tools using x64 VCC for compilation against the ARM (64-bit) architecture.
|
||||||
|
|
||||||
|
VccPlatformType* = enum ## The VCC platform type of the compile target
|
||||||
|
vccplatEmpty = "", ## Default (i.e. Desktop) Platfor Type
|
||||||
|
vccplatStore = "store", ## Windows Store Application
|
||||||
|
vccplatUWP = "uwp", ## Universal Windows Platform (UWP) Application
|
||||||
|
vccplatOneCore = "onecore" # Undocumented platform type in the Windows SDK, probably XBox One SDK platform type.
|
||||||
|
|
||||||
|
proc vccVarsAll*(path: string, arch: VccArch = vccarchUnspecified, platform_type: VccPlatformType = vccplatEmpty, sdk_version: string = nil, verbose: bool = false): StringTableRef =
|
||||||
|
## Returns a string table containing the proper process environment to successfully execute VCC compile commands for the specified SDK version, CPU architecture and platform type.
|
||||||
|
##
|
||||||
|
## path
|
||||||
|
## The path to the vcvarsall utility for VCC compiler backend.
|
||||||
|
## arch
|
||||||
|
## The compile target CPU architecture. Starting with Visual Studio 2017, this value must be specified and must not be set to `vccarchUnspecified`.
|
||||||
|
## platform_type
|
||||||
|
## The compile target Platform Type. Defaults to the Windows Desktop platform, i.e. a regular Windows executable binary.
|
||||||
|
## sdk_version
|
||||||
|
## The Windows SDK version to use.
|
||||||
|
## verbose
|
||||||
|
## Echo the command-line passed on to the system to load the VCC environment. Defaults to `false`.
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
# Run the Windows Command Prompt with the /C argument
|
||||||
|
# Execute vcvarsall with its command-line arguments
|
||||||
|
# and then execute the SET command to list all environment variables
|
||||||
|
let comSpecExec = "\"$1\" /C \"$2 && SET\"" % [comSpecCmd, vcvarsExec]
|
||||||
|
var comSpecOpts = {poEvalCommand, poDemon, poStdErrToStdOut}
|
||||||
|
if verbose:
|
||||||
|
comSpecOpts.incl poEchoCmd
|
||||||
|
let comSpecOut = execProcess(comSpecExec, options = comSpecOpts)
|
||||||
|
|
||||||
|
result = newStringTable(modeCaseInsensitive)
|
||||||
|
|
||||||
|
# Parse the output of the final SET command to construct a String Table
|
||||||
|
# with the appropiate environment variables
|
||||||
|
for line in comSpecOut.splitLines:
|
||||||
|
let idx = line.find('=')
|
||||||
|
if idx > 0:
|
||||||
|
result[line[0..(idx - 1)]] = line[(idx + 1)..(line.len - 1)]
|
||||||
|
elif verbose:
|
||||||
|
echo line
|
||||||
Loading…
Add table
Add a link
Reference in a new issue