Added documentation and explanatory comments to vccexe
This commit is contained in:
parent
24f07d9b71
commit
3d21e2ab66
4 changed files with 117 additions and 36 deletions
|
|
@ -1,15 +1,33 @@
|
||||||
|
## VCC compiler backend discovery Utility
|
||||||
|
##
|
||||||
|
## Module to discover the path to the vcvarsall utility of a VCC compiler backend.
|
||||||
|
## The module supports discovery for either the latest recognizable version (default)
|
||||||
|
## or discovery of a specific VCC compiler backend version.
|
||||||
|
##
|
||||||
|
## This module can also produce a standalone command-line executable.
|
||||||
|
## It supports a `--help` command-line argument. Refer to its output for further
|
||||||
|
## documentation on the `vccdiscover` standalone command-line application.
|
||||||
|
|
||||||
import strutils, os, vccenv
|
import strutils, os, vccenv
|
||||||
|
|
||||||
type
|
type
|
||||||
VccVersion* = enum
|
VccVersion* = enum ## VCC compiler backend versions
|
||||||
vccUndefined = (0, ""),
|
vccUndefined = (0, ""), ## VCC version undefined, resolves to the latest recognizable VCC version
|
||||||
vcc90 = vs90, # Visual Studio 2008
|
vcc90 = vs90, ## Visual Studio 2008 (Version 9.0)
|
||||||
vcc100 = vs100, # Visual Studio 2010
|
vcc100 = vs100, ## Visual Studio 2010 (Version 10.0)
|
||||||
vcc110 = vs110, # Visual Studio 2012
|
vcc110 = vs110, ## Visual Studio 2012 (Version 11.0)
|
||||||
vcc120 = vs120, # Visual Studio 2013
|
vcc120 = vs120, ## Visual Studio 2013 (Version 12.0)
|
||||||
vcc140 = vs140 # Visual Studio 2015
|
vcc140 = vs140 ## Visual Studio 2015 (Version 14.0)
|
||||||
|
|
||||||
proc discoverVccVcVarsAllPath*(version: VccVersion = vccUndefined): string =
|
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.
|
# TODO: Attempt discovery using vswhere utility.
|
||||||
|
|
||||||
# Attempt discovery through VccEnv
|
# Attempt discovery through VccEnv
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,40 @@
|
||||||
|
## VCC compiler backend installation discovery using Visual Studio common tools
|
||||||
|
## environment variables.
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
type
|
type
|
||||||
VccEnvVersion* = enum
|
VccEnvVersion* = enum ## The version of the Visual Studio C/C++ Developer Environment to load
|
||||||
vsUndefined = (0, ""),
|
## Valid versions are Versions of Visual Studio that permanently set a COMNTOOLS
|
||||||
vs90 = (90, "VS90COMNTOOLS"), # Visual Studio 2008
|
## environment variable. That includes Visual Studio version up to and including
|
||||||
vs100 = (100, "VS100COMNTOOLS"), # Visual Studio 2010
|
## Visual Studio 2015
|
||||||
vs110 = (110, "VS110COMNTOOLS"), # Visual Studio 2012
|
vsUndefined = (0, ""), ## Version not specified, use latest recogized version on the system
|
||||||
vs120 = (120, "VS120COMNTOOLS"), # Visual Studio 2013
|
vs90 = (90, "VS90COMNTOOLS"), ## Visual Studio 2008
|
||||||
vs140 = (140, "VS140COMNTOOLS") # Visual Studio 2015
|
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
|
const
|
||||||
vcvarsallRelativePath = joinPath("..", "..", "VC", "vcvarsall")
|
vcvarsallRelativePath = joinPath("..", "..", "VC", "vcvarsall") ## Relative path from the COMNTOOLS path to the vcvarsall file.
|
||||||
|
|
||||||
proc vccEnvVcVarsAllPath*(version: VccEnvVersion = vsUndefined): string =
|
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:
|
if version == vsUndefined:
|
||||||
for tryVersion in [vs140, vs120, vs110, vs100, vs90]:
|
for tryVersion in [vs140, vs120, vs110, vs100, vs90]:
|
||||||
let tryPath = vccEnvVcVarsAllPath(tryVersion)
|
let tryPath = vccEnvVcVarsAllPath(tryVersion)
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,8 @@ Options:
|
||||||
--sdkversion:<v> Use a specific Windows SDK version:
|
--sdkversion:<v> Use a specific Windows SDK version:
|
||||||
<v> is either the full Windows 10 SDK version number or
|
<v> is either the full Windows 10 SDK version number or
|
||||||
"8.1" to use the windows 8.1 SDK
|
"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
|
Other command line arguments are passed on to the
|
||||||
secondary command specified by --command or to the
|
secondary command specified by --command or to the
|
||||||
|
|
@ -65,6 +67,11 @@ when isMainModule:
|
||||||
|
|
||||||
var clArgs: seq[TaintedString] = @[]
|
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()
|
var wrapperArgs = commandLineParams()
|
||||||
for wargv in wrapperArgs:
|
for wargv in wrapperArgs:
|
||||||
# Check whether the current argument contains -- prefix
|
# Check whether the current argument contains -- prefix
|
||||||
|
|
@ -87,6 +94,8 @@ when isMainModule:
|
||||||
echo HelpText
|
echo HelpText
|
||||||
clArgs.add(wargv)
|
clArgs.add(wargv)
|
||||||
|
|
||||||
|
# Support for multiple specified versions. Attempt VCC discovery for each version
|
||||||
|
# specified, first successful discovery wins
|
||||||
for vccversionItem in vccversionArg:
|
for vccversionItem in vccversionArg:
|
||||||
var vccversionValue: VccVersion
|
var vccversionValue: VccVersion
|
||||||
try:
|
try:
|
||||||
|
|
@ -96,9 +105,11 @@ when isMainModule:
|
||||||
vcvarsallArg = discoverVccVcVarsAllPath(vccversionValue)
|
vcvarsallArg = discoverVccVcVarsAllPath(vccversionValue)
|
||||||
if vcvarsallArg.len > 0:
|
if vcvarsallArg.len > 0:
|
||||||
break
|
break
|
||||||
|
# VCC version not specified, discover latest (call discover without args)
|
||||||
if vcvarsallArg.len < 1 and vccversionArg.len < 1:
|
if vcvarsallArg.len < 1 and vccversionArg.len < 1:
|
||||||
vcvarsallArg = discoverVccVcVarsAllPath()
|
vcvarsallArg = discoverVccVcVarsAllPath()
|
||||||
|
|
||||||
|
# Call vcvarsall to get the appropiate VCC process environment
|
||||||
var vcvars = vccVarsAll(vcvarsallArg, platformArg, sdkTypeArg, sdkVersionArg, verboseArg)
|
var vcvars = vccVarsAll(vcvarsallArg, platformArg, sdkTypeArg, sdkVersionArg, verboseArg)
|
||||||
if vcvars != nil:
|
if vcvars != nil:
|
||||||
for vccEnvKey, vccEnvVal in vcvars:
|
for vccEnvKey, vccEnvVal in vcvars:
|
||||||
|
|
@ -108,8 +119,11 @@ when isMainModule:
|
||||||
if verboseArg:
|
if verboseArg:
|
||||||
vccOptions.incl poEchoCmd
|
vccOptions.incl poEchoCmd
|
||||||
|
|
||||||
|
# Default to the cl.exe command if no secondary command was specified
|
||||||
if commandArg.len < 1:
|
if commandArg.len < 1:
|
||||||
commandArg = "cl.exe"
|
commandArg = "cl.exe"
|
||||||
|
|
||||||
|
# Run VCC command with the VCC process environment
|
||||||
let vccProcess = startProcess(
|
let vccProcess = startProcess(
|
||||||
commandArg,
|
commandArg,
|
||||||
args = clArgs,
|
args = clArgs,
|
||||||
|
|
|
||||||
|
|
@ -1,33 +1,53 @@
|
||||||
|
## 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
|
import strtabs, strutils, os, osproc
|
||||||
|
|
||||||
const
|
const
|
||||||
comSpecEnvKey = "ComSpec" # Environment Variable that specifies the command-line application path in Windows
|
comSpecEnvKey = "ComSpec" ## Environment Variable that specifies the command-line application path in Windows
|
||||||
# Usually set to cmd.exe
|
## Usually set to cmd.exe
|
||||||
vcvarsallDefaultPath = "vcvarsall.bat"
|
vcvarsallDefaultPath = "vcvarsall.bat"
|
||||||
|
|
||||||
type
|
type
|
||||||
VccArch* = enum
|
VccArch* = enum ## The VCC compile target architectures
|
||||||
vccarchUnspecified = "",
|
vccarchUnspecified = "",
|
||||||
vccarchX86 = "x86",
|
vccarchX86 = "x86", ## VCC for compilation against the x86 architecture.
|
||||||
vccarchAmd64 = "amd64",
|
vccarchAmd64 = "amd64", ## VCC for compilation against the amd64 architecture.
|
||||||
vccarchX86Amd64 = "x86_amd64",
|
vccarchX86Amd64 = "x86_amd64", ## VCC cross-compilation tools using x86 VCC for compilation against the amd64 architecture.
|
||||||
vccarchX86Arm = "x86_arm",
|
vccarchX86Arm = "x86_arm", ## VCC cross-compilation tools using x86 VCC for compilation against the ARM architecture.
|
||||||
vccarchX86Arm64 = "x86_arm64",
|
vccarchX86Arm64 = "x86_arm64", ## VCC cross-compilation tools using x86 VCC for compilation against the ARM (64-bit) architecture.
|
||||||
vccarchAmd64X86 = "amd64_x86",
|
vccarchAmd64X86 = "amd64_x86", ## VCC cross-compilation tools using amd64 VCC for compilation against the x86 architecture.
|
||||||
vccarchAmd64Arm = "amd64_arm",
|
vccarchAmd64Arm = "amd64_arm", ## VCC cross-compilation tools using amd64 VCC for compilation against the ARM architecture.
|
||||||
vccarchAmd64Arm64 = "amd64_arm64",
|
vccarchAmd64Arm64 = "amd64_arm64", ## VCC cross-compilation tools using amd64 VCC for compilation against the ARM (64-bit) architecture.
|
||||||
vccarchX64 = "x64",
|
vccarchX64 = "x64", ## VCC for compilation against the x64 architecture.
|
||||||
vccarchX64X86 = "x64_x86",
|
vccarchX64X86 = "x64_x86", ## VCC cross-compilation tools using x64 VCC for compilation against the x86 architecture.
|
||||||
vccarchX64Arm = "x64_arm",
|
vccarchX64Arm = "x64_arm", ## VCC cross-compilation tools using x64 VCC for compilation against the ARM architecture.
|
||||||
vccarchX64Arm64 = "x64_arm64"
|
vccarchX64Arm64 = "x64_arm64" ## VCC cross-compilation tools using x64 VCC for compilation against the ARM (64-bit) architecture.
|
||||||
|
|
||||||
VccPlatformType* = enum
|
VccPlatformType* = enum ## The VCC platform type of the compile target
|
||||||
vccplatEmpty = "",
|
vccplatEmpty = "", ## Default (i.e. Desktop) Platfor Type
|
||||||
vccplatStore = "store",
|
vccplatStore = "store", ## Windows Store Application
|
||||||
vccplatUWP = "uwp",
|
vccplatUWP = "uwp", ## Universal Windows Platform (UWP) Application
|
||||||
vccplatOneCore = "onecore"
|
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 =
|
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
|
var vccvarsallpath = path
|
||||||
# Assume that default executable is in current directory or in PATH
|
# Assume that default executable is in current directory or in PATH
|
||||||
if path == nil or path.len < 1:
|
if path == nil or path.len < 1:
|
||||||
|
|
@ -58,12 +78,19 @@ proc vccVarsAll*(path: string, arch: VccArch = vccarchUnspecified, platform_type
|
||||||
if comSpecCmd.len < 1:
|
if comSpecCmd.len < 1:
|
||||||
comSpecCmd = "cmd"
|
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]
|
let comSpecExec = "\"$1\" /C \"$2 && SET\"" % [comSpecCmd, vcvarsExec]
|
||||||
var comSpecOpts = {poEvalCommand, poDemon, poStdErrToStdOut}
|
var comSpecOpts = {poEvalCommand, poDemon, poStdErrToStdOut}
|
||||||
if verbose:
|
if verbose:
|
||||||
comSpecOpts.incl poEchoCmd
|
comSpecOpts.incl poEchoCmd
|
||||||
let comSpecOut = execProcess(comSpecExec, options = comSpecOpts)
|
let comSpecOut = execProcess(comSpecExec, options = comSpecOpts)
|
||||||
|
|
||||||
result = newStringTable(modeCaseInsensitive)
|
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:
|
for line in comSpecOut.splitLines:
|
||||||
let idx = line.find('=')
|
let idx = line.find('=')
|
||||||
if idx > 0:
|
if idx > 0:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue