| #!/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 itertools |
| 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 try_dir in itertools.product( |
| ['2022', '2021', '2020', '2019'], |
| ['BuildTools', 'Community', 'Professional', 'Enterprise', 'Preview'], |
| ['Program Files', 'Program Files (x86)']): |
| msvc_base = (f'C:\\{try_dir[2]}\\Microsoft Visual Studio\\' |
| f'{try_dir[0]}\\{try_dir[1]}\\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()) |