Merge pull request #4655 from bdbaddog/fix_new_ninja_package
[scons.git] / SCons / Tool / MSCommon / MSVC / WinSDK.py
blob7115d505ee6198891c2a27585b7b1085954d39cf
1 # MIT License
3 # Copyright The SCons Foundation
5 # Permission is hereby granted, free of charge, to any person obtaining
6 # a copy of this software and associated documentation files (the
7 # "Software"), to deal in the Software without restriction, including
8 # without limitation the rights to use, copy, modify, merge, publish,
9 # distribute, sublicense, and/or sell copies of the Software, and to
10 # permit persons to whom the Software is furnished to do so, subject to
11 # the following conditions:
13 # The above copyright notice and this permission notice shall be included
14 # in all copies or substantial portions of the Software.
16 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
17 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
18 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 """
25 Windows SDK functions for Microsoft Visual C/C++.
26 """
28 import os
30 from ..common import (
31 debug,
34 from . import Util
35 from . import Config
36 from . import Registry
38 from .Exceptions import (
39 MSVCInternalError,
42 from . import Dispatcher
43 Dispatcher.register_modulename(__name__)
46 _DESKTOP = Config.MSVC_PLATFORM_INTERNAL['Desktop']
47 _UWP = Config.MSVC_PLATFORM_INTERNAL['UWP']
49 def _new_sdk_map():
50 sdk_map = {
51 _DESKTOP.vc_platform: [],
52 _UWP.vc_platform: [],
54 return sdk_map
56 def _sdk_10_layout(version):
58 folder_prefix = version + '.'
60 sdk_map = _new_sdk_map()
62 sdk_roots = Registry.sdk_query_paths(version)
64 sdk_version_platform_seen = set()
65 sdk_roots_seen = set()
67 for sdk_t in sdk_roots:
69 sdk_root = sdk_t[0]
70 if sdk_root in sdk_roots_seen:
71 continue
72 sdk_roots_seen.add(sdk_root)
74 if not os.path.exists(sdk_root):
75 continue
77 sdk_include_path = os.path.join(sdk_root, 'include')
78 if not os.path.exists(sdk_include_path):
79 continue
81 for version_nbr, version_nbr_path in Util.listdir_dirs(sdk_include_path):
83 if not version_nbr.startswith(folder_prefix):
84 continue
86 sdk_inc_path = Util.normalize_path(os.path.join(version_nbr_path, 'um'))
87 if not os.path.exists(sdk_inc_path):
88 continue
90 for vc_platform, sdk_inc_file in [
91 (_DESKTOP.vc_platform, 'winsdkver.h'),
92 (_UWP.vc_platform, 'windows.h'),
95 if not os.path.exists(os.path.join(sdk_inc_path, sdk_inc_file)):
96 continue
98 key = (version_nbr, vc_platform)
99 if key in sdk_version_platform_seen:
100 continue
101 sdk_version_platform_seen.add(key)
103 sdk_map[vc_platform].append(version_nbr)
105 for key, val in sdk_map.items():
106 val.sort(reverse=True)
108 return sdk_map
110 def _sdk_81_layout(version):
112 version_nbr = version
114 sdk_map = _new_sdk_map()
116 sdk_roots = Registry.sdk_query_paths(version)
118 sdk_version_platform_seen = set()
119 sdk_roots_seen = set()
121 for sdk_t in sdk_roots:
123 sdk_root = sdk_t[0]
124 if sdk_root in sdk_roots_seen:
125 continue
126 sdk_roots_seen.add(sdk_root)
128 # msvc does not check for existence of root or other files
130 sdk_inc_path = Util.normalize_path(os.path.join(sdk_root, r'include\um'))
131 if not os.path.exists(sdk_inc_path):
132 continue
134 for vc_platform, sdk_inc_file in [
135 (_DESKTOP.vc_platform, 'winsdkver.h'),
136 (_UWP.vc_platform, 'windows.h'),
139 if not os.path.exists(os.path.join(sdk_inc_path, sdk_inc_file)):
140 continue
142 key = (version_nbr, vc_platform)
143 if key in sdk_version_platform_seen:
144 continue
145 sdk_version_platform_seen.add(key)
147 sdk_map[vc_platform].append(version_nbr)
149 for key, val in sdk_map.items():
150 val.sort(reverse=True)
152 return sdk_map
154 _sdk_map_cache = {}
155 _sdk_cache = {}
157 def _reset_sdk_cache() -> None:
158 global _sdk_map_cache
159 global _sdk_cache
160 debug('')
161 _sdk_map_cache = {}
162 _sdk_cache = {}
164 def _sdk_10(key, reg_version):
165 if key in _sdk_map_cache:
166 sdk_map = _sdk_map_cache[key]
167 else:
168 sdk_map = _sdk_10_layout(reg_version)
169 _sdk_map_cache[key] = sdk_map
170 return sdk_map
172 def _sdk_81(key, reg_version):
173 if key in _sdk_map_cache:
174 sdk_map = _sdk_map_cache[key]
175 else:
176 sdk_map = _sdk_81_layout(reg_version)
177 _sdk_map_cache[key] = sdk_map
178 return sdk_map
180 def _combine_sdk_map_list(sdk_map_list):
181 combined_sdk_map = _new_sdk_map()
182 for sdk_map in sdk_map_list:
183 for key, val in sdk_map.items():
184 combined_sdk_map[key].extend(val)
185 return combined_sdk_map
187 _sdk_dispatch_map = {
188 '10.0': (_sdk_10, '10.0'),
189 '8.1': (_sdk_81, '8.1'),
192 def _verify_sdk_dispatch_map():
193 debug('')
194 for sdk_version in Config.MSVC_SDK_VERSIONS:
195 if sdk_version in _sdk_dispatch_map:
196 continue
197 err_msg = f'sdk version {sdk_version} not in sdk_dispatch_map'
198 raise MSVCInternalError(err_msg)
199 return None
201 def _version_list_sdk_map(version_list):
202 sdk_map_list = []
203 for version in version_list:
204 func, reg_version = _sdk_dispatch_map[version]
205 sdk_map = func(version, reg_version)
206 sdk_map_list.append(sdk_map)
208 combined_sdk_map = _combine_sdk_map_list(sdk_map_list)
209 return combined_sdk_map
211 def _sdk_map(version_list):
212 key = tuple(version_list)
213 if key in _sdk_cache:
214 sdk_map = _sdk_cache[key]
215 else:
216 version_numlist = [float(v) for v in version_list]
217 version_numlist.sort(reverse=True)
218 key = tuple([str(v) for v in version_numlist])
219 sdk_map = _version_list_sdk_map(key)
220 _sdk_cache[key] = sdk_map
221 return sdk_map
223 def get_msvc_platform(is_uwp: bool=False):
224 platform_def = _UWP if is_uwp else _DESKTOP
225 return platform_def
227 def get_sdk_version_list(vs_def, platform_def):
228 version_list = vs_def.vc_sdk_versions if vs_def.vc_sdk_versions is not None else []
229 sdk_map = _sdk_map(version_list)
230 sdk_list = sdk_map.get(platform_def.vc_platform, [])
231 return sdk_list
233 def get_msvc_sdk_version_list(msvc_version, msvc_uwp_app: bool=False):
234 debug('msvc_version=%s, msvc_uwp_app=%s', repr(msvc_version), repr(msvc_uwp_app))
236 sdk_versions = []
238 verstr = Util.get_msvc_version_prefix(msvc_version)
239 if not verstr:
240 debug('msvc_version is not defined')
241 return sdk_versions
243 vs_def = Config.MSVC_VERSION_EXTERNAL.get(verstr, None)
244 if not vs_def:
245 debug('vs_def is not defined')
246 return sdk_versions
248 is_uwp = True if msvc_uwp_app in Config.BOOLEAN_SYMBOLS[True] else False
249 platform_def = get_msvc_platform(is_uwp)
250 sdk_list = get_sdk_version_list(vs_def, platform_def)
252 sdk_versions.extend(sdk_list)
253 debug('sdk_versions=%s', repr(sdk_versions))
255 return sdk_versions
257 def reset() -> None:
258 debug('')
259 _reset_sdk_cache()
261 def verify() -> None:
262 debug('')
263 _verify_sdk_dispatch_map()