diff options
author | Fredrik Høisæther Rasch <fredrik.rasch@gmail.com> | 2017-03-26 17:08:41 +0200 |
---|---|---|
committer | Fredrik Høisæther Rasch <fredrik.rasch@gmail.com> | 2017-03-26 17:14:02 +0200 |
commit | 3d21e2ab668c1bf2df58829185507bc739440526 (patch) | |
tree | 165c4ff160da388b15edc2e5fa1edd5715a94cd6 /tools/vccexe | |
parent | 24f07d9b71a5302047fa0183318d35fbc74222b4 (diff) | |
download | Nim-3d21e2ab668c1bf2df58829185507bc739440526.tar.gz |
Added documentation and explanatory comments to vccexe
Diffstat (limited to 'tools/vccexe')
-rw-r--r-- | tools/vccexe/vccdiscover.nim | 32 | ||||
-rw-r--r-- | tools/vccexe/vccenv.nim | 40 | ||||
-rw-r--r-- | tools/vccexe/vccexe.nim | 14 | ||||
-rw-r--r-- | tools/vccexe/vcvarsall.nim | 67 |
4 files changed, 117 insertions, 36 deletions
diff --git a/tools/vccexe/vccdiscover.nim b/tools/vccexe/vccdiscover.nim index 88dfd1999..f20bf2441 100644 --- a/tools/vccexe/vccdiscover.nim +++ b/tools/vccexe/vccdiscover.nim @@ -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 type - VccVersion* = enum - vccUndefined = (0, ""), - vcc90 = vs90, # Visual Studio 2008 - vcc100 = vs100, # Visual Studio 2010 - vcc110 = vs110, # Visual Studio 2012 - vcc120 = vs120, # Visual Studio 2013 - vcc140 = vs140 # Visual Studio 2015 + 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 diff --git a/tools/vccexe/vccenv.nim b/tools/vccexe/vccenv.nim index addf77e38..6ddf2e29a 100644 --- a/tools/vccexe/vccenv.nim +++ b/tools/vccexe/vccenv.nim @@ -1,18 +1,40 @@ +## VCC compiler backend installation discovery using Visual Studio common tools +## environment variables. + import os type - VccEnvVersion* = enum - vsUndefined = (0, ""), - 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 + 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") + 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. -proc vccEnvVcVarsAllPath*(version: VccEnvVersion = vsUndefined): string = if version == vsUndefined: for tryVersion in [vs140, vs120, vs110, vs100, vs90]: let tryPath = vccEnvVcVarsAllPath(tryVersion) diff --git a/tools/vccexe/vccexe.nim b/tools/vccexe/vccexe.nim index 4dec0db04..86ad86d97 100644 --- a/tools/vccexe/vccexe.nim +++ b/tools/vccexe/vccexe.nim @@ -47,6 +47,8 @@ Options: --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 @@ -65,6 +67,11 @@ when isMainModule: 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 @@ -87,6 +94,8 @@ when isMainModule: echo HelpText clArgs.add(wargv) + # Support for multiple specified versions. Attempt VCC discovery for each version + # specified, first successful discovery wins for vccversionItem in vccversionArg: var vccversionValue: VccVersion try: @@ -96,9 +105,11 @@ when isMainModule: 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: vcvarsallArg = discoverVccVcVarsAllPath() + # 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: @@ -108,8 +119,11 @@ when isMainModule: if verboseArg: vccOptions.incl poEchoCmd + # Default to the cl.exe command if no secondary command was specified if commandArg.len < 1: commandArg = "cl.exe" + + # Run VCC command with the VCC process environment let vccProcess = startProcess( commandArg, args = clArgs, diff --git a/tools/vccexe/vcvarsall.nim b/tools/vccexe/vcvarsall.nim index dcd7ef868..e7a55069c 100644 --- a/tools/vccexe/vcvarsall.nim +++ b/tools/vccexe/vcvarsall.nim @@ -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 const - comSpecEnvKey = "ComSpec" # Environment Variable that specifies the command-line application path in Windows - # Usually set to cmd.exe + comSpecEnvKey = "ComSpec" ## Environment Variable that specifies the command-line application path in Windows + ## Usually set to cmd.exe vcvarsallDefaultPath = "vcvarsall.bat" type - VccArch* = enum + VccArch* = enum ## The VCC compile target architectures 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" + 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 - vccplatEmpty = "", - vccplatStore = "store", - vccplatUWP = "uwp", - vccplatOneCore = "onecore" + 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: @@ -58,12 +78,19 @@ proc vccVarsAll*(path: string, arch: VccArch = vccarchUnspecified, platform_type 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: |