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