vcvarsall.nim 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. ## VCC Developer Command Prompt Loader
  2. ##
  3. ## In order for the VCC compiler backend to work properly, it requires numerous
  4. ## environment variables to be set properly for the desired architecture and compile target.
  5. ## For that purpose the VCC compiler ships with the vcvarsall utility which is an executable
  6. ## batch script that can be used to properly set up an Command Prompt environment.
  7. import strtabs, strutils, os, osproc
  8. const
  9. comSpecEnvKey = "ComSpec" ## Environment Variable that specifies the command-line application path in Windows
  10. ## Usually set to cmd.exe
  11. vcvarsallDefaultPath = "vcvarsall.bat"
  12. type
  13. VccArch* = enum ## The VCC compile target architectures
  14. vccarchUnspecified = "",
  15. vccarchX86 = "x86", ## VCC for compilation against the x86 architecture.
  16. vccarchAmd64 = "amd64", ## VCC for compilation against the amd64 architecture.
  17. vccarchX86Amd64 = "x86_amd64", ## VCC cross-compilation tools using x86 VCC for compilation against the amd64 architecture.
  18. vccarchX86Arm = "x86_arm", ## VCC cross-compilation tools using x86 VCC for compilation against the ARM architecture.
  19. vccarchX86Arm64 = "x86_arm64", ## VCC cross-compilation tools using x86 VCC for compilation against the ARM (64-bit) architecture.
  20. vccarchAmd64X86 = "amd64_x86", ## VCC cross-compilation tools using amd64 VCC for compilation against the x86 architecture.
  21. vccarchAmd64Arm = "amd64_arm", ## VCC cross-compilation tools using amd64 VCC for compilation against the ARM architecture.
  22. vccarchAmd64Arm64 = "amd64_arm64", ## VCC cross-compilation tools using amd64 VCC for compilation against the ARM (64-bit) architecture.
  23. vccarchX64 = "x64", ## VCC for compilation against the x64 architecture.
  24. vccarchX64X86 = "x64_x86", ## VCC cross-compilation tools using x64 VCC for compilation against the x86 architecture.
  25. vccarchX64Arm = "x64_arm", ## VCC cross-compilation tools using x64 VCC for compilation against the ARM architecture.
  26. vccarchX64Arm64 = "x64_arm64" ## VCC cross-compilation tools using x64 VCC for compilation against the ARM (64-bit) architecture.
  27. VccPlatformType* = enum ## The VCC platform type of the compile target
  28. vccplatEmpty = "", ## Default (i.e. Desktop) Platfor Type
  29. vccplatStore = "store", ## Windows Store Application
  30. vccplatUWP = "uwp", ## Universal Windows Platform (UWP) Application
  31. vccplatOneCore = "onecore" # Undocumented platform type in the Windows SDK, probably XBox One SDK platform type.
  32. proc vccVarsAll*(path: string, arch: VccArch = vccarchUnspecified, platform_type: VccPlatformType = vccplatEmpty, sdk_version: string = "", verbose: bool = false): StringTableRef =
  33. ## 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.
  34. ##
  35. ## path
  36. ## The path to the vcvarsall utility for VCC compiler backend.
  37. ## arch
  38. ## The compile target CPU architecture. Starting with Visual Studio 2017, this value must be specified and must not be set to `vccarchUnspecified`.
  39. ## platform_type
  40. ## The compile target Platform Type. Defaults to the Windows Desktop platform, i.e. a regular Windows executable binary.
  41. ## sdk_version
  42. ## The Windows SDK version to use.
  43. ## verbose
  44. ## Echo the command-line passed on to the system to load the VCC environment. Defaults to `false`.
  45. var vccvarsallpath = path
  46. # Assume that default executable is in current directory or in PATH
  47. if path == "":
  48. vccvarsallpath = vcvarsallDefaultPath
  49. var args: seq[string] = @[]
  50. let archStr: string = $arch
  51. if archStr.len > 0:
  52. args.add(archStr)
  53. let platStr: string = $platform_type
  54. if platStr.len > 0:
  55. args.add(platStr)
  56. if sdk_version.len > 0:
  57. args.add(sdk_version)
  58. let argStr = args.join " "
  59. var vcvarsExec: string
  60. if argStr.len > 0:
  61. vcvarsExec = "\"$1\" $2" % [vccvarsallpath, argStr]
  62. else:
  63. vcvarsExec = "\"$1\"" % vccvarsallpath
  64. var comSpecCmd = getenv comSpecEnvKey
  65. if comSpecCmd.len < 1:
  66. comSpecCmd = "cmd"
  67. # Run the Windows Command Prompt with the /C argument
  68. # Execute vcvarsall with its command-line arguments
  69. # and then execute the SET command to list all environment variables
  70. let comSpecExec = "\"$1\" /C \"$2 && SET\"" % [comSpecCmd, vcvarsExec]
  71. var comSpecOpts = {poEvalCommand, poDemon, poStdErrToStdOut}
  72. if verbose:
  73. comSpecOpts.incl poEchoCmd
  74. let comSpecOut = execProcess(comSpecExec, options = comSpecOpts)
  75. result = newStringTable(modeCaseInsensitive)
  76. # Parse the output of the final SET command to construct a String Table
  77. # with the appropiate environment variables
  78. for line in comSpecOut.splitLines:
  79. let idx = line.find('=')
  80. if idx > 0:
  81. result[line[0..(idx - 1)]] = line[(idx + 1)..(line.len - 1)]
  82. elif verbose:
  83. echo line