Bug 1744524: part 2) Add `WindowContext::GetUserGestureStart` and remove `WindowConte...
[gecko.git] / build / moz.configure / windows.configure
bloba2af182878d8ad858661f8bd1e22965498172864
1 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
2 # vim: set filetype=python:
3 # This Source Code Form is subject to the terms of the Mozilla Public
4 # License, v. 2.0. If a copy of the MPL was not distributed with this
5 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 option(
8     "--with-windows-version",
9     nargs=1,
10     default="603",
11     help="Windows SDK version to target. Win 8.1 (603) is currently"
12     "the minimum supported version.",
16 @depends("--with-windows-version")
17 @imports(_from="__builtin__", _import="ValueError")
18 def valid_windows_version(value):
19     if not value:
20         die("Cannot build with --without-windows-version")
21     try:
22         version = int(value[0], 16)
23         if version in (0x603,):
24             return version
25     except ValueError:
26         pass
28     die("Invalid value for --with-windows-version (%s)", value[0])
31 option(env="WINDOWSSDKDIR", nargs=1, help="Directory containing the Windows SDK")
34 @depends("WINDOWSSDKDIR", c_compiler, host_c_compiler)
35 def windows_sdk_dir(value, compiler, host_compiler):
36     if value:
37         return value
38     # Ideally, we'd actually check for host/target ABI being MSVC, but
39     # that's waiting for bug 1617793.
40     if compiler.type != "clang-cl" and host_compiler.type != "clang-cl":
41         return ()
43     return set(
44         normalize_path(x[1])
45         for x in get_registry_values(
46             r"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Kits\Installed Roots"
47             r"\KitsRoot*",
48             get_32_and_64_bit=True,
49         )
50     )
53 # The Windows SDK 8.1 and 10 have different layouts. The former has
54 # $SDK/include/$subdir, while the latter has $SDK/include/$version/$subdir.
55 # The vcvars* scripts don't actually care about the version, they just take
56 # the last alphanumerically.
57 # The $SDK/lib directories always have version subdirectories, but while the
58 # versions match the one in $SDK/include for SDK 10, it's "winv6.3" for SDK
59 # 8.1.
62 @imports("os")
63 @imports("re")
64 @imports(_from="__builtin__", _import="Exception")
65 def get_sdk_dirs(sdk, subdir):
66     def get_dirs_containing(sdk, stem, subdir):
67         base = os.path.join(sdk, stem)
68         try:
69             subdirs = [
70                 d for d in os.listdir(base) if os.path.isdir(os.path.join(base, d))
71             ]
72         except Exception:
73             subdirs = []
74         if not subdirs:
75             return ()
76         if subdir in subdirs:
77             return (base,)
78         # At this point, either we have an incomplete or invalid SDK directory,
79         # or we exclusively have version numbers in subdirs.
80         return tuple(
81             os.path.join(base, s)
82             for s in subdirs
83             if os.path.isdir(os.path.join(base, s, subdir))
84         )
86     def categorize(dirs):
87         return {os.path.basename(d): d for d in dirs}
89     include_dirs = categorize(get_dirs_containing(sdk, "include", subdir))
90     lib_dirs = categorize(get_dirs_containing(sdk, "lib", subdir))
92     if "include" in include_dirs:
93         include_dirs["winv6.3"] = include_dirs["include"]
94         del include_dirs["include"]
96     valid_versions = sorted(set(include_dirs) & set(lib_dirs), reverse=True)
97     return [
98         namespace(
99             path=sdk,
100             lib=lib_dirs[vv],
101             include=include_dirs[vv],
102         )
103         for vv in valid_versions
104     ]
107 @imports(_from="mozbuild.shellutil", _import="quote")
108 def valid_windows_sdk_dir_result(value):
109     if value:
110         return "0x%04x in %s" % (value.version, quote(value.path))
113 @depends(
114     c_compiler, host_c_compiler, windows_sdk_dir, valid_windows_version, "WINDOWSSDKDIR"
116 @checking("for Windows SDK", valid_windows_sdk_dir_result)
117 @imports(_from="__builtin__", _import="Exception")
118 @imports(_from="textwrap", _import="dedent")
119 def valid_windows_sdk_dir(
120     compiler, host_compiler, windows_sdk_dir, target_version, windows_sdk_dir_env
122     # Ideally, we'd actually check for host/target ABI being MSVC, but
123     # that's waiting for bug 1617793.
124     if compiler.type != "clang-cl" and host_compiler.type != "clang-cl":
125         return None
126     if windows_sdk_dir_env:
127         windows_sdk_dir_env = windows_sdk_dir_env[0]
128     sdks = {}
129     for d in windows_sdk_dir:
130         sdklist = get_sdk_dirs(d, "um")
131         for sdk in sdklist:
132             check = dedent(
133                 """\
134             #include <winsdkver.h>
135             WINVER_MAXVER
136             """
137             )
138             um_dir = os.path.join(sdk.include, "um")
139             shared_dir = os.path.join(sdk.include, "shared")
140             result = try_preprocess(
141                 compiler.wrapper
142                 + [compiler.compiler]
143                 + compiler.flags
144                 + ["-X", "-I", um_dir, "-I", shared_dir],
145                 "C",
146                 check,
147                 onerror=lambda: "",
148             )
149             if result:
150                 maxver = result.splitlines()[-1]
151                 try:
152                     maxver = int(maxver, 0)
153                 except Exception:
154                     pass
155                 else:
156                     sdks[d] = maxver, sdk
157                     break
159         if d == windows_sdk_dir_env and d not in sdks:
160             raise FatalCheckError(
161                 "Error while checking the version of the SDK in "
162                 "WINDOWSSDKDIR (%s). Please verify it contains a valid and "
163                 "complete SDK installation." % windows_sdk_dir_env
164             )
166     valid_sdks = sorted(sdks, key=lambda x: sdks[x][0], reverse=True)
167     if valid_sdks:
168         biggest_version, sdk = sdks[valid_sdks[0]]
169     if not valid_sdks or biggest_version < target_version:
170         if windows_sdk_dir_env:
171             raise FatalCheckError(
172                 "You are targeting Windows version 0x%04x, but your SDK only "
173                 "supports up to version 0x%04x. Install and use an updated SDK, "
174                 "or target a lower version using --with-windows-version. "
175                 "Alternatively, try running the Windows SDK Configuration Tool "
176                 "and selecting a newer SDK. See "
177                 "https://developer.mozilla.org/En/Windows_SDK_versions for "
178                 "details on fixing this." % (target_version, biggest_version)
179             )
181         raise FatalCheckError(
182             "Cannot find a Windows SDK for version >= 0x%04x." % target_version
183         )
185     return namespace(
186         path=sdk.path,
187         include=sdk.include,
188         lib=sdk.lib,
189         version=biggest_version,
190     )
193 @imports(_from="mozbuild.shellutil", _import="quote")
194 def valid_ucrt_sdk_dir_result(value):
195     if value:
196         return "%s in %s" % (value.version, quote(value.path))
199 @depends(windows_sdk_dir, "WINDOWSSDKDIR", c_compiler, host_c_compiler)
200 @checking("for Universal CRT SDK", valid_ucrt_sdk_dir_result)
201 @imports("os")
202 @imports(_import="mozpack.path", _as="mozpath")
203 def valid_ucrt_sdk_dir(windows_sdk_dir, windows_sdk_dir_env, compiler, host_compiler):
204     # Ideally, we'd actually check for host/target ABI being MSVC, but
205     # that's waiting for bug 1617793.
206     if compiler.type != "clang-cl" and host_compiler.type != "clang-cl":
207         return None
208     if windows_sdk_dir_env:
209         windows_sdk_dir_env = windows_sdk_dir_env[0]
210     sdks = {}
211     for d in windows_sdk_dir:
212         sdklist = get_sdk_dirs(d, "ucrt")
213         for sdk in sdklist:
214             version = os.path.basename(sdk.include)
215             # We're supposed to always find a version in the directory, because
216             # the 8.1 SDK, which doesn't have a version in the directory, doesn't
217             # contain the Universal CRT SDK. When the main SDK is 8.1, there
218             # is, however, supposed to be a reduced install of the SDK 10
219             # with the UCRT.
220             if version != "include":
221                 sdks[d] = Version(version), sdk
222                 break
224         if d == windows_sdk_dir_env and d not in sdks:
225             # When WINDOWSSDKDIR is set in the environment and we can't find the
226             # Universal CRT SDK, chances are this is a start-shell-msvc*.bat
227             # setup, where INCLUDE and LIB already contain the UCRT paths.
228             ucrt_includes = [
229                 p
230                 for p in os.environ.get("INCLUDE", "").split(";")
231                 if os.path.basename(p).lower() == "ucrt"
232             ]
233             ucrt_libs = [
234                 p
235                 for p in os.environ.get("LIB", "").split(";")
236                 if os.path.basename(os.path.dirname(p)).lower() == "ucrt"
237             ]
238             if ucrt_includes and ucrt_libs:
239                 # Pick the first of each, since they are the ones that the
240                 # compiler would look first. Assume they contain the SDK files.
241                 include = os.path.dirname(ucrt_includes[0])
242                 lib = os.path.dirname(os.path.dirname(ucrt_libs[0]))
243                 path = os.path.dirname(os.path.dirname(include))
244                 version = os.path.basename(include)
245                 if version != "include" and mozpath.basedir(lib, [path]):
246                     sdks[d] = (
247                         Version(version),
248                         namespace(
249                             path=path,
250                             include=include,
251                             lib=lib,
252                         ),
253                     )
254                     continue
255             raise FatalCheckError(
256                 "The SDK in WINDOWSSDKDIR (%s) does not contain the Universal "
257                 "CRT." % windows_sdk_dir_env
258             )
260     valid_sdks = sorted(sdks, key=lambda x: sdks[x][0], reverse=True)
261     if not valid_sdks:
262         raise FatalCheckError(
263             "Cannot find the Universal CRT SDK. " "Please install it."
264         )
266     version, sdk = sdks[valid_sdks[0]]
267     minimum_ucrt_version = Version("10.0.17134.0")
268     if version < minimum_ucrt_version:
269         raise FatalCheckError(
270             "Latest Universal CRT SDK version found %s"
271             " and minimum required is %s. This or a later"
272             " version can be installed using the Visual"
273             " Studio installer." % (version, minimum_ucrt_version)
274         )
276     return namespace(
277         path=sdk.path,
278         include=sdk.include,
279         lib=sdk.lib,
280         version=version,
281     )
284 @depends(c_compiler, host_c_compiler, vc_toolchain_search_path)
285 @imports("os")
286 def vc_path(c_compiler, host_c_compiler, vc_toolchain_search_path):
287     if c_compiler.type != "clang-cl" and host_c_compiler.type != "clang-cl":
288         return
290     # In clang-cl builds, we need the headers and libraries from an MSVC installation.
291     vc_program = find_program("cl.exe", paths=vc_toolchain_search_path)
292     if not vc_program:
293         die("Cannot find a Visual C++ install for e.g. ATL headers.")
295     result = os.path.dirname(vc_program)
296     while True:
297         next, p = os.path.split(result)
298         if next == result:
299             die(
300                 "Cannot determine the Visual C++ directory the compiler (%s) "
301                 "is in" % vc_program
302             )
303         result = next
304         if p.lower() == "bin":
305             break
306     return os.path.normpath(result)
309 @depends(vc_path, valid_windows_sdk_dir, valid_ucrt_sdk_dir)
310 @imports("os")
311 def include_path(vc_path, windows_sdk_dir, ucrt_sdk_dir):
312     if not vc_path:
313         return
314     atlmfc_dir = os.path.join(vc_path, "atlmfc", "include")
315     if not os.path.isdir(atlmfc_dir):
316         die(
317             "Cannot find the ATL/MFC headers in the Visual C++ directory (%s). "
318             "Please install them." % vc_path
319         )
321     winrt_dir = os.path.join(windows_sdk_dir.include, "winrt")
322     if not os.path.isdir(winrt_dir):
323         die(
324             "Cannot find the WinRT headers in the Windows SDK directory (%s). "
325             "Please install them." % windows_sdk_dir.path
326         )
328     cppwinrt_dir = os.path.join(windows_sdk_dir.include, "cppwinrt")
329     if not os.path.isdir(cppwinrt_dir):
330         die(
331             "Cannot find the C++/WinRT headers in the Windows SDK directory (%s). "
332             "Please install them." % windows_sdk_dir.path
333         )
335     includes = []
336     include_env = os.environ.get("INCLUDE")
337     if include_env:
338         includes.append(include_env)
339     includes.extend(
340         (
341             os.path.join(vc_path, "include"),
342             atlmfc_dir,
343             os.path.join(windows_sdk_dir.include, "shared"),
344             os.path.join(windows_sdk_dir.include, "um"),
345             winrt_dir,
346             cppwinrt_dir,
347             os.path.join(ucrt_sdk_dir.include, "ucrt"),
348         )
349     )
350     # Set in the environment for old-configure
351     includes = ";".join(includes)
352     os.environ["INCLUDE"] = includes
353     return includes
356 set_config("INCLUDE", include_path)
358 # cppwinrt requires this on clang because of no coroutine support, which is okay
359 set_define("_SILENCE_CLANG_COROUTINE_MESSAGE", "")
362 @template
363 def lib_path_for(host_or_target):
364     @depends(
365         host_or_target,
366         dependable(host_or_target is host),
367         vc_path,
368         valid_windows_sdk_dir,
369         valid_ucrt_sdk_dir,
370     )
371     @imports("os")
372     def lib_path(target, is_host, vc_path, windows_sdk_dir, ucrt_sdk_dir):
373         if not vc_path:
374             return
375         sdk_target = {
376             "x86": "x86",
377             "x86_64": "x64",
378             "arm": "arm",
379             "aarch64": "arm64",
380         }.get(target.cpu)
382         # MSVC2017 switched to use the same target naming as the sdk.
383         atlmfc_dir = os.path.join(vc_path, "atlmfc", "lib", sdk_target)
384         if not os.path.isdir(atlmfc_dir):
385             die(
386                 "Cannot find the ATL/MFC libraries in the Visual C++ directory "
387                 "(%s). Please install them." % vc_path
388             )
390         libs = []
391         lib_env = os.environ.get("LIB")
392         if lib_env and not is_host:
393             libs.extend(lib_env.split(";"))
394         libs.extend(
395             (
396                 os.path.join(vc_path, "lib", sdk_target),
397                 atlmfc_dir,
398                 os.path.join(windows_sdk_dir.lib, "um", sdk_target),
399                 os.path.join(ucrt_sdk_dir.lib, "ucrt", sdk_target),
400             )
401         )
402         return libs
404     return lib_path
407 @depends_if(lib_path_for(target))
408 @imports("os")
409 def lib_path(libs):
410     # Set in the environment for old-configure
411     libs = ";".join(libs)
412     os.environ["LIB"] = libs
413     return libs
416 set_config("LIB", lib_path)
419 lib_path_for_host = lib_path_for(host)
422 @depends_if(lib_path_for_host)
423 @imports(_from="mozbuild.shellutil", _import="quote")
424 def host_linker_libpaths(libs):
425     return ["-LIBPATH:%s" % quote(l) for l in libs]
428 @depends_if(lib_path_for_host)
429 @imports(_from="mozbuild.shellutil", _import="quote")
430 def host_linker_libpaths_bat(libs):
431     # .bat files need a different style of quoting. Batch quoting is actually
432     # not defined, and up to applications to handle, so it's not really clear
433     # what should be escaped and what not, but most paths should work just
434     # fine without escaping. And we don't care about double-quotes possibly
435     # having to be escaped because they're not allowed in file names on
436     # Windows.
437     return ['"-LIBPATH:%s"' % l for l in libs]
440 set_config("HOST_LINKER_LIBPATHS", host_linker_libpaths)
441 set_config("HOST_LINKER_LIBPATHS_BAT", host_linker_libpaths_bat)
444 @depends(valid_windows_sdk_dir, valid_ucrt_sdk_dir, host)
445 @imports(_from="os", _import="environ")
446 def sdk_bin_path(valid_windows_sdk_dir, valid_ucrt_sdk_dir, host):
447     if not valid_windows_sdk_dir:
448         return
450     vc_host = {
451         "x86": "x86",
452         "x86_64": "x64",
453     }.get(host.cpu)
455     # From version 10.0.15063.0 onwards the bin path contains the version number.
456     versioned_bin = (
457         "bin"
458         if valid_ucrt_sdk_dir.version < "10.0.15063.0"
459         else os.path.join("bin", str(valid_ucrt_sdk_dir.version))
460     )
461     result = [
462         environ["PATH"],
463         os.path.join(valid_windows_sdk_dir.path, versioned_bin, vc_host),
464     ]
465     if vc_host == "x64":
466         result.append(os.path.join(valid_windows_sdk_dir.path, versioned_bin, "x86"))
467     return result
470 option(env="LINKER", nargs=1, when=target_is_windows, help="Path to the linker")
472 link = check_prog(
473     "LINKER",
474     ("lld-link",),
475     input="LINKER",
476     when=target_is_windows,
477     paths=clang_search_path,
480 option(env="HOST_LINKER", nargs=1, when=host_is_windows, help="Path to the host linker")
482 host_link = check_prog(
483     "HOST_LINKER",
484     ("lld-link",),
485     input="HOST_LINKER",
486     when=host_is_windows,
487     paths=clang_search_path,
490 add_old_configure_assignment("LINKER", link)