diff options
-rw-r--r-- | tools/vccexe/vccexe.nim | 8 | ||||
-rw-r--r-- | tools/vccexe/vccvswhere.nim | 47 |
2 files changed, 53 insertions, 2 deletions
diff --git a/tools/vccexe/vccexe.nim b/tools/vccexe/vccexe.nim index 28d9e4173..feea6c0c0 100644 --- a/tools/vccexe/vccexe.nim +++ b/tools/vccexe/vccexe.nim @@ -1,4 +1,4 @@ -import strutils, strtabs, os, osproc, vcvarsall, vccenv +import strutils, strtabs, os, osproc, vcvarsall, vccenv, vccvswhere type VccVersion* = enum ## VCC compiler backend versions @@ -18,7 +18,11 @@ proc discoverVccVcVarsAllPath*(version: VccVersion = vccUndefined): string = ## ## Returns `nil` if the VCC compiler backend discovery failed. - # TODO: Attempt discovery using vswhere utility. + # Attempt discovery using vswhere utility (VS 2017 and later) if no version specified. + if version == vccUndefined: + result = vccVswhereVcVarsAllPath() + if result.len > 0: + return # Attempt discovery through VccEnv # (Trying Visual Studio Common Tools Environment Variables) diff --git a/tools/vccexe/vccvswhere.nim b/tools/vccexe/vccvswhere.nim new file mode 100644 index 000000000..11ad39ce9 --- /dev/null +++ b/tools/vccexe/vccvswhere.nim @@ -0,0 +1,47 @@ +## VCC compiler discovery using vswhere (https://github.com/Microsoft/vswhere) + +import os, osproc, strformat, strutils + +const + vswhereRelativePath = joinPath("Microsoft Visual Studio", "Installer", "vswhere.exe") + vswhereArgs = "-latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath" + vcvarsRelativePath = joinPath("VC", "Auxiliary", "Build", "vcvarsall.bat") + +proc vccVswhereExtractVcVarsAllPath(vswherePath: string): string = + ## Returns the path to `vcvarsall.bat` if Visual Studio location was obtained by executing `vswhere.exe`. + ## + ## `vcvarsall.bat` is supposed to exist under {vsPath}\VC\Auxiliary\Build directory. + ## + ## Returns "" if no appropriate `vcvarsall.bat` file was found. + + # For more detail on vswhere arguments, refer to https://github.com/microsoft/vswhere/wiki/Find-VC + let vsPath = execProcess(&"\"{vswherePath}\" {vswhereArgs}").strip() + if vsPath.len > 0: + let vcvarsallPath = joinPath(vsPath, vcvarsRelativePath) + if existsFile(vcvarsallPath): + return vcvarsallPath + +proc vccVswhereGeneratePath(envName: string): string = + ## Generate a path to vswhere.exe under "Program Files" or "Program Files (x86)" depending on envName. + ## + ## Returns "" if an environment variable specified by envName was not available. + + let val = getEnv(envName) + if val.len > 0: + result = try: expandFilename(joinPath(val, vswhereRelativePath)) except OSError: "" + +proc vccVswhereVcVarsAllPath*(): string = + ## Returns the path to `vcvarsall.bat` for the latest Visual Studio (2017 and later). + ## + ## Returns "" if no recognizable Visual Studio installation was found. + ## + ## 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. + + for tryEnv in ["ProgramFiles(x86)", "ProgramFiles"]: + let vswherePath = vccVswhereGeneratePath(tryEnv) + if vswherePath.len > 0 and existsFile(vswherePath): + let vcVarsAllPath = vccVswhereExtractVcVarsAllPath(vswherePath) + if vcVarsAllPath.len > 0: + return vcVarsAllPath |