• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2# Copyright (C) 2017 The Android Open Source Project
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#      http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15"""
16Finds and prints MSVC and Windows SDK paths.
17
18It outpus:
19Line 1: the base path of the Windows SDK.
20Line 2: the most recent version of the Windows SDK.
21Line 3: the path of the most recent MSVC.
22
23Example:
24C:\Program Files (x86)\Windows Kits\10
2510.0.19041.0
26C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.28.29333
27"""
28
29import os
30import itertools
31import subprocess
32import sys
33
34
35def ver_to_tuple(ver_str):
36  """Turns '10.1.2' into [10,1,2] so it can be compared using > """
37  parts = [int(x) for x in ver_str.split('.')]
38  return parts
39
40
41def find_max_subdir(base_dir, filter=lambda x: True):
42  """Finds the max subdirectory in base_dir by comparing semantic versions."""
43  max_ver = None
44  for ver in os.listdir(base_dir) if os.path.exists(base_dir) else []:
45    cur = os.path.join(base_dir, ver)
46    if not filter(cur):
47      continue
48    if max_ver is None or ver_to_tuple(ver) > ver_to_tuple(max_ver):
49      max_ver = ver
50  return max_ver
51
52
53def main():
54  out = [
55      '',
56      '',
57      '',
58  ]
59  winsdk_base = 'C:\\Program Files (x86)\\Windows Kits\\10'
60  if os.path.exists(winsdk_base):
61    out[0] = winsdk_base
62    lib_base = winsdk_base + '\\Lib'
63    filt = lambda x: os.path.exists(os.path.join(x, 'ucrt', 'x64', 'ucrt.lib'))
64    out[1] = find_max_subdir(lib_base, filt)
65
66  for try_dir in itertools.product(
67      ['2022', '2021', '2020', '2019'],
68      ['BuildTools', 'Community', 'Professional', 'Enterprise', 'Preview'],
69      ['Program Files', 'Program Files (x86)']):
70    msvc_base = (f'C:\\{try_dir[2]}\\Microsoft Visual Studio\\'
71                f'{try_dir[0]}\\{try_dir[1]}\\VC\\Tools\\MSVC')
72    if os.path.exists(msvc_base):
73      filt = lambda x: os.path.exists(
74          os.path.join(x, 'lib', 'x64', 'libcmt.lib'))
75      max_msvc = find_max_subdir(msvc_base, filt)
76      if max_msvc is not None:
77        out[2] = os.path.join(msvc_base, max_msvc)
78      break
79
80  # Don't error in case of failure, GN scripts are supposed to deal with
81  # failures and allow the user to override the dirs.
82
83  print('\n'.join(out))
84  return 0
85
86
87if __name__ == '__main__':
88  sys.exit(main())
89