profile_toolchain.py 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. from __future__ import unicode_literals
  2. import contextlib
  3. import sys
  4. import os
  5. import optparse
  6. import json
  7. import re
  8. import subprocess
  9. sys.path.append("%s/../../build" % os.path.dirname(os.path.realpath(__file__)))
  10. import find_depot_tools
  11. from vs_toolchain import \
  12. SetEnvironmentAndGetRuntimeDllDirs, \
  13. SetEnvironmentAndGetSDKDir, \
  14. NormalizePath
  15. sys.path.append("%s/win_toolchain" % find_depot_tools.add_depot_tools_to_path())
  16. from get_toolchain_if_necessary import CalculateHash
  17. @contextlib.contextmanager
  18. def cwd(directory):
  19. curdir = os.getcwd()
  20. try:
  21. os.chdir(directory)
  22. yield
  23. finally:
  24. os.chdir(curdir)
  25. def calculate_hash(root):
  26. with cwd(root):
  27. return CalculateHash('.', None)
  28. def windows_installed_software():
  29. powershell_command = [
  30. "Get-CimInstance",
  31. "-Namespace",
  32. "root\cimv2",
  33. "-Class",
  34. "Win32_product",
  35. "|",
  36. "Select",
  37. "vendor,",
  38. "description,",
  39. "@{l='install_location';e='InstallLocation'},",
  40. "@{l='install_date';e='InstallDate'},",
  41. "@{l='install_date_2';e='InstallDate2'},",
  42. "caption,",
  43. "version,",
  44. "name,",
  45. "@{l='sku_number';e='SKUNumber'}",
  46. "|",
  47. "ConvertTo-Json",
  48. ]
  49. proc = subprocess.Popen(
  50. ["powershell.exe", "-Command", "-"],
  51. stdin=subprocess.PIPE,
  52. stdout=subprocess.PIPE,
  53. )
  54. stdout, _ = proc.communicate(" ".join(powershell_command).encode("utf-8"))
  55. if proc.returncode != 0:
  56. raise RuntimeError("Failed to get list of installed software")
  57. # On AppVeyor there's other output related to PSReadline,
  58. # so grab only the JSON output and ignore everything else
  59. json_match = re.match(
  60. r".*(\[.*{.*}.*\]).*", stdout.decode("utf-8"), re.DOTALL
  61. )
  62. if not json_match:
  63. raise RuntimeError(
  64. "Couldn't find JSON output for list of installed software"
  65. )
  66. # Filter out missing keys
  67. return list(
  68. map(
  69. lambda info: {k: info[k] for k in info if info[k]},
  70. json.loads(json_match.group(1)),
  71. )
  72. )
  73. def windows_profile():
  74. runtime_dll_dirs = SetEnvironmentAndGetRuntimeDllDirs()
  75. win_sdk_dir = SetEnvironmentAndGetSDKDir()
  76. path = NormalizePath(os.environ['GYP_MSVS_OVERRIDE_PATH'])
  77. # since current windows executable are symbols path dependant,
  78. # profile the current directory too
  79. return {
  80. 'pwd': os.getcwd(),
  81. 'installed_software': windows_installed_software(),
  82. 'sdks': [
  83. {'name': 'vs', 'path': path, 'hash': calculate_hash(path)},
  84. {
  85. 'name': 'wsdk',
  86. 'path': win_sdk_dir,
  87. 'hash': calculate_hash(win_sdk_dir),
  88. },
  89. ],
  90. 'runtime_lib_dirs': runtime_dll_dirs,
  91. }
  92. def main(options):
  93. if sys.platform == 'win32':
  94. with open(options.output_json, 'w') as f:
  95. json.dump(windows_profile(), f)
  96. else:
  97. raise OSError("Unsupported OS")
  98. if __name__ == '__main__':
  99. parser = optparse.OptionParser()
  100. parser.add_option('--output-json', metavar='FILE', default='profile.json',
  101. help='write information about toolchain to FILE')
  102. opts, args = parser.parse_args()
  103. sys.exit(main(opts))