|  | #!/usr/bin/env python3 | 
|  | # Copyright (C) 2017 The Android Open Source Project | 
|  | # | 
|  | # Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | # you may not use this file except in compliance with the License. | 
|  | # You may obtain a copy of the License at | 
|  | # | 
|  | #      http://www.apache.org/licenses/LICENSE-2.0 | 
|  | # | 
|  | # Unless required by applicable law or agreed to in writing, software | 
|  | # distributed under the License is distributed on an "AS IS" BASIS, | 
|  | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | # See the License for the specific language governing permissions and | 
|  | # limitations under the License. | 
|  | """ | 
|  | Finds and prints MSVC and Windows SDK paths. | 
|  |  | 
|  | It outpus: | 
|  | Line 1: the base path of the Windows SDK. | 
|  | Line 2: the most recent version of the Windows SDK. | 
|  | Line 3: the path of the most recent MSVC. | 
|  |  | 
|  | Example: | 
|  | C:\Program Files (x86)\Windows Kits\10 | 
|  | 10.0.19041.0 | 
|  | C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.28.29333 | 
|  | """ | 
|  |  | 
|  | import os | 
|  | import subprocess | 
|  | import sys | 
|  |  | 
|  |  | 
|  | def ver_to_tuple(ver_str): | 
|  | """Turns '10.1.2' into [10,1,2] so it can be compared using > """ | 
|  | parts = [int(x) for x in ver_str.split('.')] | 
|  | return parts | 
|  |  | 
|  |  | 
|  | def find_max_subdir(base_dir, filter=lambda x: True): | 
|  | """Finds the max subdirectory in base_dir by comparing semantic versions.""" | 
|  | max_ver = None | 
|  | for ver in os.listdir(base_dir) if os.path.exists(base_dir) else []: | 
|  | cur = os.path.join(base_dir, ver) | 
|  | if not filter(cur): | 
|  | continue | 
|  | if max_ver is None or ver_to_tuple(ver) > ver_to_tuple(max_ver): | 
|  | max_ver = ver | 
|  | return max_ver | 
|  |  | 
|  |  | 
|  | def main(): | 
|  | out = [ | 
|  | '', | 
|  | '', | 
|  | '', | 
|  | ] | 
|  | winsdk_base = 'C:\\Program Files (x86)\\Windows Kits\\10' | 
|  | if os.path.exists(winsdk_base): | 
|  | out[0] = winsdk_base | 
|  | lib_base = winsdk_base + '\\Lib' | 
|  | filt = lambda x: os.path.exists(os.path.join(x, 'ucrt', 'x64', 'ucrt.lib')) | 
|  | out[1] = find_max_subdir(lib_base, filt) | 
|  |  | 
|  | for year in ['2022', '2021', '2020', '2019']: | 
|  | for version in [ | 
|  | 'BuildTools', 'Community', 'Professional', 'Enterprise', 'Preview' | 
|  | ]: | 
|  | msvc_base = ('C:\\Program Files (x86)\\Microsoft Visual Studio\\' | 
|  | f'{year}\\{version}\\VC\\Tools\\MSVC') | 
|  | if os.path.exists(msvc_base): | 
|  | filt = lambda x: os.path.exists( | 
|  | os.path.join(x, 'lib', 'x64', 'libcmt.lib')) | 
|  | max_msvc = find_max_subdir(msvc_base, filt) | 
|  | if max_msvc is not None: | 
|  | out[2] = os.path.join(msvc_base, max_msvc) | 
|  | break | 
|  |  | 
|  | # Don't error in case of failure, GN scripts are supposed to deal with | 
|  | # failures and allow the user to override the dirs. | 
|  |  | 
|  | print('\n'.join(out)) | 
|  | return 0 | 
|  |  | 
|  |  | 
|  | if __name__ == '__main__': | 
|  | sys.exit(main()) |