tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

windows.configure (22192B)


      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/.
      6 
      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",
     13 )
     14 
     15 
     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
     27 
     28     die("Invalid value for --with-windows-version (%s)", value[0])
     29 
     30 
     31 option(env="WINDOWSSDKDIR", nargs=1, help="Directory containing the Windows SDK")
     32 
     33 
     34 @depends(
     35     "WINDOWSSDKDIR", "WINSYSROOT", winsysroot, target_windows_abi, host_windows_abi
     36 )
     37 def windows_sdk_dir(
     38     value, winsysroot_env, winsysroot, target_windows_abi, host_windows_abi
     39 ):
     40     if value:
     41         if winsysroot_env:
     42             die("WINDOWSSDKDIR and WINSYSROOT cannot be set together.")
     43         if winsysroot:
     44             die("WINDOWSSDKDIR cannot be set when using the bootstrapped WINSYSROOT")
     45         return value
     46     if target_windows_abi != "msvc" and host_windows_abi != "msvc":
     47         return ()
     48 
     49     if winsysroot:
     50         return [os.path.join(winsysroot, "Windows Kits", "10")]
     51 
     52     return set(
     53         normalize_path(x[1])
     54         for x in get_registry_values(
     55             r"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Kits\Installed Roots"
     56             r"\KitsRoot*",
     57             get_32_and_64_bit=True,
     58         )
     59     )
     60 
     61 
     62 @imports("glob")
     63 def get_sdk_dirs(sdk, subdir):
     64     def get_dirs_containing(sdk, stem, subdir):
     65         return [
     66             os.path.dirname(p) for p in glob.glob(os.path.join(sdk, stem, "*", subdir))
     67         ]
     68 
     69     def categorize(dirs):
     70         return {os.path.basename(d): d for d in dirs}
     71 
     72     include_dirs = categorize(get_dirs_containing(sdk, "Include", subdir))
     73     lib_dirs = categorize(get_dirs_containing(sdk, "Lib", subdir))
     74 
     75     valid_versions = sorted(set(include_dirs) & set(lib_dirs), reverse=True)
     76     return [
     77         namespace(
     78             path=sdk,
     79             lib=lib_dirs[vv],
     80             include=include_dirs[vv],
     81         )
     82         for vv in valid_versions
     83     ]
     84 
     85 
     86 @imports(_from="mozshellutil", _import="quote")
     87 def valid_windows_sdk_dir_result(value):
     88     if value:
     89         return "0x%04x in %s" % (value.version, quote(value.path))
     90 
     91 
     92 @depends(
     93     target_windows_abi,
     94     host_windows_abi,
     95     windows_sdk_dir,
     96     valid_windows_version,
     97     "WINDOWSSDKDIR",
     98 )
     99 @checking("for Windows SDK", valid_windows_sdk_dir_result)
    100 @imports(_from="__builtin__", _import="Exception")
    101 @imports(_from="__builtin__", _import="open")
    102 def valid_windows_sdk_dir(
    103     target_windows_abi,
    104     host_windows_abi,
    105     windows_sdk_dir,
    106     target_version,
    107     windows_sdk_dir_env,
    108 ):
    109     if target_windows_abi != "msvc" and host_windows_abi != "msvc":
    110         return None
    111     if windows_sdk_dir_env:
    112         windows_sdk_dir_env = windows_sdk_dir_env[0]
    113     sdks = {}
    114     for d in windows_sdk_dir:
    115         sdklist = get_sdk_dirs(d, "um")
    116         for sdk in sdklist:
    117             maxver = None
    118             winsdkver = os.path.join(sdk.include, "um", "winsdkver.h")
    119             with open(winsdkver) as fh:
    120                 for line in fh.readlines():
    121                     if line.startswith("#define"):
    122                         line = line.split(None, 2)
    123                         assert line.pop(0) == "#define"
    124                         if line.pop(0) == "WINVER_MAXVER":
    125                             maxver = line.pop(0)
    126                             break
    127 
    128             if maxver:
    129                 try:
    130                     maxver = int(maxver, 0)
    131                 except Exception:
    132                     pass
    133                 else:
    134                     sdks[d] = maxver, sdk
    135                     break
    136 
    137         if d == windows_sdk_dir_env and d not in sdks:
    138             raise FatalCheckError(
    139                 "Error while checking the version of the SDK in "
    140                 "WINDOWSSDKDIR (%s). Please verify it contains a valid and "
    141                 "complete SDK installation." % windows_sdk_dir_env
    142             )
    143 
    144     valid_sdks = sorted(sdks, key=lambda x: sdks[x][0], reverse=True)
    145     if valid_sdks:
    146         biggest_version, sdk = sdks[valid_sdks[0]]
    147     if not valid_sdks or biggest_version < target_version:
    148         if windows_sdk_dir_env:
    149             raise FatalCheckError(
    150                 "You are targeting Windows version 0x%04x, but your SDK only "
    151                 "supports up to version 0x%04x. Install and use an updated SDK, "
    152                 "or target a lower version using --with-windows-version. "
    153                 "Alternatively, try running the Windows SDK Configuration Tool "
    154                 "and selecting a newer SDK. See "
    155                 "https://developer.mozilla.org/En/Windows_SDK_versions for "
    156                 "details on fixing this." % (target_version, biggest_version)
    157             )
    158 
    159         raise FatalCheckError(
    160             "Cannot find a Windows SDK for version >= 0x%04x." % target_version
    161         )
    162 
    163     return namespace(
    164         path=sdk.path,
    165         include=sdk.include,
    166         lib=sdk.lib,
    167         version=biggest_version,
    168     )
    169 
    170 
    171 @imports(_from="mozshellutil", _import="quote")
    172 def valid_ucrt_sdk_dir_result(value):
    173     if value:
    174         return "%s in %s" % (value.version, quote(value.path))
    175 
    176 
    177 @depends(windows_sdk_dir, "WINDOWSSDKDIR", target_windows_abi, host_windows_abi)
    178 @checking("for Universal CRT SDK", valid_ucrt_sdk_dir_result)
    179 @imports("os")
    180 @imports(_import="mozpack.path", _as="mozpath")
    181 def valid_ucrt_sdk_dir(
    182     windows_sdk_dir, windows_sdk_dir_env, target_windows_abi, host_windows_abi
    183 ):
    184     if target_windows_abi != "msvc" and host_windows_abi != "msvc":
    185         return None
    186     if windows_sdk_dir_env:
    187         windows_sdk_dir_env = windows_sdk_dir_env[0]
    188     sdks = {}
    189     for d in windows_sdk_dir:
    190         sdklist = get_sdk_dirs(d, "ucrt")
    191         for sdk in sdklist:
    192             version = os.path.basename(sdk.include)
    193             # We're supposed to always find a version in the directory, because
    194             # the 8.1 SDK, which doesn't have a version in the directory, doesn't
    195             # contain the Universal CRT SDK. When the main SDK is 8.1, there
    196             # is, however, supposed to be a reduced install of the SDK 10
    197             # with the UCRT.
    198             if version != "include":
    199                 sdks[d] = Version(version), sdk
    200                 break
    201 
    202         if d == windows_sdk_dir_env and d not in sdks:
    203             # When WINDOWSSDKDIR is set in the environment and we can't find the
    204             # Universal CRT SDK, chances are this is a start-shell-msvc*.bat
    205             # setup, where INCLUDE and LIB already contain the UCRT paths.
    206             ucrt_includes = [
    207                 p
    208                 for p in os.environ.get("INCLUDE", "").split(";")
    209                 if os.path.basename(p).lower() == "ucrt"
    210             ]
    211             ucrt_libs = [
    212                 p
    213                 for p in os.environ.get("LIB", "").split(";")
    214                 if os.path.basename(os.path.dirname(p)).lower() == "ucrt"
    215             ]
    216             if ucrt_includes and ucrt_libs:
    217                 # Pick the first of each, since they are the ones that the
    218                 # compiler would look first. Assume they contain the SDK files.
    219                 include = os.path.dirname(ucrt_includes[0])
    220                 lib = os.path.dirname(os.path.dirname(ucrt_libs[0]))
    221                 path = os.path.dirname(os.path.dirname(include))
    222                 version = os.path.basename(include)
    223                 if version != "include" and mozpath.basedir(lib, [path]):
    224                     sdks[d] = (
    225                         Version(version),
    226                         namespace(
    227                             path=path,
    228                             include=include,
    229                             lib=lib,
    230                         ),
    231                     )
    232                     continue
    233             raise FatalCheckError(
    234                 "The SDK in WINDOWSSDKDIR (%s) does not contain the Universal "
    235                 "CRT." % windows_sdk_dir_env
    236             )
    237 
    238     valid_sdks = sorted(sdks, key=lambda x: sdks[x][0], reverse=True)
    239     if not valid_sdks:
    240         raise FatalCheckError(
    241             "Cannot find the Universal CRT SDK. " "Please install it."
    242         )
    243 
    244     version, sdk = sdks[valid_sdks[0]]
    245     minimum_ucrt_version = Version("10.0.17134.0")
    246     if version < minimum_ucrt_version:
    247         raise FatalCheckError(
    248             "Latest Universal CRT SDK version found %s"
    249             " and minimum required is %s. This or a later"
    250             " version can be installed using the Visual"
    251             " Studio installer." % (version, minimum_ucrt_version)
    252         )
    253 
    254     return namespace(
    255         path=sdk.path,
    256         include=sdk.include,
    257         lib=sdk.lib,
    258         version=version,
    259     )
    260 
    261 
    262 @depends(target_windows_abi, host_windows_abi, vc_toolchain_search_path)
    263 @imports("os")
    264 def vc_path(target_windows_abi, host_windows_abi, vc_toolchain_search_path):
    265     if target_windows_abi != "msvc" and host_windows_abi != "msvc":
    266         return
    267 
    268     # In clang-cl builds, we need the headers and libraries from an MSVC installation.
    269     vc_program = find_program("cl.exe", paths=vc_toolchain_search_path)
    270     if not vc_program:
    271         die("Cannot find a Visual C++ install for e.g. ATL headers.")
    272 
    273     result = os.path.dirname(vc_program)
    274     while True:
    275         next, p = os.path.split(result)
    276         if next == result:
    277             die(
    278                 "Cannot determine the Visual C++ directory the compiler (%s) "
    279                 "is in" % vc_program
    280             )
    281         result = next
    282         if p.lower() == "bin":
    283             break
    284     return os.path.normpath(result)
    285 
    286 
    287 @depends(vc_path, valid_windows_sdk_dir, valid_ucrt_sdk_dir)
    288 @imports("os")
    289 def include_path(vc_path, windows_sdk_dir, ucrt_sdk_dir):
    290     if not vc_path:
    291         return
    292     atlmfc_dir = os.path.join(vc_path, "atlmfc", "include")
    293     if not os.path.isdir(atlmfc_dir):
    294         die(
    295             "Cannot find the ATL/MFC headers in the Visual C++ directory (%s). "
    296             "Please install them." % vc_path
    297         )
    298 
    299     winrt_dir = os.path.join(windows_sdk_dir.include, "winrt")
    300     if not os.path.isdir(winrt_dir):
    301         die(
    302             "Cannot find the WinRT headers in the Windows SDK directory (%s). "
    303             "Please install them." % windows_sdk_dir.path
    304         )
    305 
    306     cppwinrt_dir = os.path.join(windows_sdk_dir.include, "cppwinrt")
    307     if not os.path.isdir(cppwinrt_dir):
    308         die(
    309             "Cannot find the C++/WinRT headers in the Windows SDK directory (%s). "
    310             "Please install them." % windows_sdk_dir.path
    311         )
    312 
    313     includes = []
    314     include_env = os.environ.get("INCLUDE")
    315     if include_env:
    316         includes.append(include_env)
    317     includes.extend(
    318         (
    319             os.path.join(vc_path, "include"),
    320             atlmfc_dir,
    321             os.path.join(windows_sdk_dir.include, "shared"),
    322             os.path.join(windows_sdk_dir.include, "um"),
    323             winrt_dir,
    324             cppwinrt_dir,
    325             os.path.join(ucrt_sdk_dir.include, "ucrt"),
    326         )
    327     )
    328     # Set in the environment for old-configure
    329     includes = ";".join(includes)
    330     os.environ["INCLUDE"] = includes
    331     return includes
    332 
    333 
    334 set_config("INCLUDE", include_path)
    335 
    336 # cppwinrt requires this on clang because of no coroutine support, which is okay
    337 set_define("_SILENCE_CLANG_COROUTINE_MESSAGE", "")
    338 
    339 
    340 @template
    341 def lib_path_for(host_or_target):
    342     @depends(
    343         host_or_target,
    344         dependable(host_or_target is host),
    345         vc_path,
    346         valid_windows_sdk_dir,
    347         valid_ucrt_sdk_dir,
    348         c_compiler,
    349     )
    350     @imports("os")
    351     def lib_path(target, is_host, vc_path, windows_sdk_dir, ucrt_sdk_dir, compiler):
    352         if not vc_path or target.os != "WINNT":
    353             return
    354         sdk_target = {
    355             "x86": "x86",
    356             "x86_64": "x64",
    357             "arm": "arm",
    358             "aarch64": "arm64",
    359         }.get(target.cpu)
    360 
    361         # MSVC2017 switched to use the same target naming as the sdk.
    362         atlmfc_dir = os.path.join(vc_path, "atlmfc", "lib", sdk_target)
    363         if not os.path.isdir(atlmfc_dir):
    364             die(
    365                 "Cannot find the ATL/MFC libraries in the Visual C++ directory "
    366                 "(%s). Please install them." % vc_path
    367             )
    368 
    369         libs = []
    370         lib_env = os.environ.get("LIB")
    371         if lib_env and not is_host:
    372             libs.extend(lib_env.split(";"))
    373         libs.extend(
    374             (
    375                 os.path.join(vc_path, "lib", sdk_target),
    376                 atlmfc_dir,
    377                 os.path.join(windows_sdk_dir.lib, "um", sdk_target),
    378                 os.path.join(ucrt_sdk_dir.lib, "ucrt", sdk_target),
    379             )
    380         )
    381         if compiler.type == "clang-cl":
    382             runtime_dir = check_cmd_output(
    383                 compiler.compiler,
    384                 "/clang:--print-runtime-dir",
    385                 *compiler.flags,
    386                 onerror=lambda: None,
    387             ).strip()
    388             if runtime_dir and os.path.exists(runtime_dir):
    389                 # Put the clang runtime directory first, in case there is
    390                 # a different version in some of the other directories (notably,
    391                 # some versions of MSVC come with clang runtimes)
    392                 libs.insert(0, runtime_dir)
    393         return libs
    394 
    395     return lib_path
    396 
    397 
    398 @depends_if(lib_path_for(target), when=target_is_windows)
    399 @imports("os")
    400 def lib_path(libs):
    401     # Set in the environment for old-configure
    402     libs = ";".join(libs)
    403     os.environ["LIB"] = libs
    404     return libs
    405 
    406 
    407 set_config("LIB", lib_path)
    408 
    409 
    410 lib_path_for_host = lib_path_for(host)
    411 
    412 
    413 @depends_if(lib_path_for_host, when=host_is_windows)
    414 @imports(_from="mozshellutil", _import="quote")
    415 def host_linker_libpaths(libs):
    416     return ["-LIBPATH:%s" % quote(l) for l in libs]
    417 
    418 
    419 @depends_if(lib_path_for_host, when=host_is_windows)
    420 @imports(_from="mozshellutil", _import="quote")
    421 def host_linker_libpaths_bat(libs):
    422     # .bat files need a different style of quoting. Batch quoting is actually
    423     # not defined, and up to applications to handle, so it's not really clear
    424     # what should be escaped and what not, but most paths should work just
    425     # fine without escaping. And we don't care about double-quotes possibly
    426     # having to be escaped because they're not allowed in file names on
    427     # Windows.
    428     return ['"-LIBPATH:%s"' % l for l in libs]
    429 
    430 
    431 set_config("HOST_LINKER_LIBPATHS", host_linker_libpaths)
    432 set_config("HOST_LINKER_LIBPATHS_BAT", host_linker_libpaths_bat)
    433 
    434 
    435 @depends(valid_windows_sdk_dir, valid_ucrt_sdk_dir, host)
    436 @imports(_from="os", _import="environ")
    437 def sdk_bin_path(valid_windows_sdk_dir, valid_ucrt_sdk_dir, host):
    438     if not valid_windows_sdk_dir:
    439         return
    440 
    441     vc_host = {
    442         "x86": "x86",
    443         "x86_64": "x64",
    444         "aarch64": "arm64",
    445     }.get(host.cpu)
    446 
    447     # From version 10.0.15063.0 onwards the bin path contains the version number.
    448     versioned_bin = (
    449         "bin"
    450         if valid_ucrt_sdk_dir.version < "10.0.15063.0"
    451         else os.path.join("bin", str(valid_ucrt_sdk_dir.version))
    452     )
    453     result = [
    454         environ["PATH"],
    455         os.path.join(valid_windows_sdk_dir.path, versioned_bin, vc_host),
    456     ]
    457     if vc_host == "x64":
    458         result.append(os.path.join(valid_windows_sdk_dir.path, versioned_bin, "x86"))
    459     return result
    460 
    461 
    462 option(env="LINKER", nargs=1, when=target_is_windows, help="Path to the linker")
    463 
    464 link = check_prog(
    465     "LINKER",
    466     ("lld-link",),
    467     input="LINKER",
    468     when=target_is_windows,
    469     paths=clang_search_path,
    470 )
    471 
    472 option(env="HOST_LINKER", nargs=1, when=host_is_windows, help="Path to the host linker")
    473 
    474 host_link = check_prog(
    475     "HOST_LINKER",
    476     ("lld-link",),
    477     input="HOST_LINKER",
    478     when=host_is_windows,
    479     paths=clang_search_path,
    480 )
    481 
    482 
    483 option(
    484     "--with-redist",
    485     env="WIN32_REDIST_DIR",
    486     nargs="?",
    487     help="{Package|Don't package} redistributable MSVCRT",
    488 )
    489 
    490 
    491 @depends("--with-redist", moz_automation, c_compiler, vc_path, target)
    492 @imports("os")
    493 def win32_redist_dir(redist, automation, c_compiler, vc_path, target):
    494     if len(redist):
    495         if os.path.isdir(redist[0]):
    496             return redist[0]
    497         configure_error(f"Invalid Win32 Redist directory: {redist[0]}")
    498     if redist or (
    499         automation and redist.origin == "default" and c_compiler.type == "clang-cl"
    500     ):
    501         if not vc_path:
    502             configure_error("Cannot ship redistributable MSVCRT without MSVC")
    503         # It would be too simple if the Redist dir had the same version number as
    504         # the MSVC one.
    505         base_redist_path = os.path.join(
    506             os.path.dirname(os.path.dirname(os.path.dirname(vc_path))), "Redist", "MSVC"
    507         )
    508         redist_target = {
    509             "x86": "x86",
    510             "x86_64": "x64",
    511             "aarch64": "arm64",
    512         }.get(target.cpu)
    513         if redist_target and os.path.isdir(base_redist_path):
    514             versions = [Version(v) for v in os.listdir(base_redist_path)]
    515             redist_path = os.path.join(
    516                 base_redist_path,
    517                 str(max(v for v in versions if v.major)),
    518                 redist_target,
    519             )
    520             if os.path.isdir(redist_path):
    521                 crt_path = max(p for p in os.listdir(redist_path) if p.endswith("CRT"))
    522                 if crt_path:
    523                     return os.path.join(redist_path, crt_path)
    524         configure_error("Could not find redistributable MSVCRT files")
    525 
    526 
    527 set_config("WIN32_REDIST_DIR", win32_redist_dir)
    528 
    529 
    530 @template
    531 def check_w32API_version():
    532     # minimum version of toolkit libs used by mozilla
    533     W32API_VERSION = Version("3.14")
    534     # Check w32api version
    535     try_compile(
    536         includes=["w32api.h"],
    537         check_msg=f"for w32api version >= {W32API_VERSION}",
    538         body=f"""
    539         #if (__W32API_MAJOR_VERSION < {W32API_VERSION.major}) || \
    540             (__W32API_MAJOR_VERSION == {W32API_VERSION.major} && \
    541              __W32API_MINOR_VERSION < {W32API_VERSION.minor})
    542             #error "test failed."
    543         #endif
    544         """,
    545         onerror=lambda: die(f"w32api version {W32API_VERSION} or higher required."),
    546         when=target_is_windows & building_with_gnu_compatible_cc,
    547     )
    548 
    549 
    550 @depends(target)
    551 def cpu_arch_macro_definition(target):
    552     if target.cpu == "x86":
    553         return "_X86_"
    554     elif target.cpu == "x86_64":
    555         return "_AMD64_"
    556     elif target.cpu == "aarch64":
    557         return "_ARM64_"
    558     else:
    559         return "_CPU_ARCH_NOT_DEFINED"
    560 
    561 
    562 set_define(cpu_arch_macro_definition, True)
    563 
    564 
    565 check_w32API_version()
    566 
    567 
    568 # -Zc:sizedDealloc- disables C++14 global sized deallocation (see bug 1160146)
    569 add_flag(
    570     "-Zc:sizedDealloc-", compiler=cxx_compiler, when=~building_with_gnu_compatible_cc
    571 )
    572 
    573 
    574 set_define("_USE_MATH_DEFINES", True)  # Otherwise Windows' math.h doesn't #define M_PI.
    575 
    576 WINVER = dependable("0A00")
    577 set_define("WINVER", depends(WINVER)(lambda WINVER: f"0x{WINVER}"))
    578 set_define("_WIN32_WINNT", depends(WINVER)(lambda WINVER: f"0x{WINVER}"))
    579 set_define("_WIN32_IE", "0x0A00")
    580 
    581 with only_when(depends(c_compiler)(lambda c: c.type == "clang-cl")):
    582     set_config("MSVC_C_RUNTIME_DLL", "vcruntime140.dll")
    583     set_config(
    584         "MSVC_C_RUNTIME_1_DLL",
    585         "vcruntime140_1.dll",
    586         when=depends(target)(lambda target: target.cpu != "x86"),
    587     )
    588     set_config("MSVC_CXX_RUNTIME_DLL", "msvcp140.dll")
    589     set_config("MSVC_CXX_RUNTIME_ATOMIC_WAIT_DLL", "msvcp140_atomic_wait.dll")
    590 
    591     # Disable warnings about using MSVC-specific secure CRT functions.
    592     set_define("_CRT_SECURE_NO_WARNINGS", True)
    593     set_define("_CRT_NONSTDC_NO_WARNINGS", True)
    594 
    595     # Work around issues with newer STL and older runtimes, see bug 1994496.
    596     set_define("_DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR", True)
    597 
    598     set_define("HAVE_SEH_EXCEPTIONS", True)
    599     set_define("HAVE_IO_H", True)
    600 
    601     def win32_subsystem_version():
    602         return "10.0"
    603 
    604     set_config(
    605         "WIN32_CONSOLE_EXE_LDFLAGS",
    606         ["-SUBSYSTEM:CONSOLE,{}".format(win32_subsystem_version())],
    607     )
    608     set_config(
    609         "WIN32_GUI_EXE_LDFLAGS",
    610         ["-SUBSYSTEM:WINDOWS,{}".format(win32_subsystem_version())],
    611     )
    612 
    613     add_flag("-Gy")
    614     add_flag("-Zc:inline")
    615 
    616     # VS2013+ supports -Gw for better linker optimizations.
    617     # http://blogs.msdn.com/b/vcblog/archive/2013/09/11/introducing-gw-compiler-switch.aspx
    618     # Disabled on ASan because it causes false-positive ODR violations.
    619     add_flag("-Gw", when=~asan)
    620 
    621     # String tail merging doesn't play nice with ASan's ODR checker.
    622     add_linker_flag("-opt:nolldtailmerge", when=asan)
    623 
    624     # Silence VS2017 15.5+ TR1 deprecation warnings hit by older gtest versions
    625     add_flag("-D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING", compiler=cxx_compiler)
    626 
    627     with only_when(depends(target.cpu)(lambda cpu: cpu == "x86")):
    628         add_linker_flag("-LARGEADDRESSAWARE")
    629         add_linker_flag("-SAFESEH")
    630 
    631 
    632 set_define("WIN32_LEAN_AND_MEAN", True)
    633 
    634 with only_when(depends(c_compiler)(lambda c: c.type == "clang-cl")):
    635     # See http://support.microsoft.com/kb/143208 to use STL
    636     set_define("NOMINMAX", True)
    637 
    638 
    639 with only_when(target_is_windows & depends(c_compiler)(lambda c: c.type != "clang-cl")):
    640     # strsafe.h on mingw uses macros for function deprecation that pollutes namespace
    641     # causing problems with local implementations with the same name.
    642     set_define("STRSAFE_NO_DEPRECATE", True)
    643 
    644     set_config("WIN32_CONSOLE_EXE_LDFLAGS", ["-mconsole"])
    645     set_config("WIN32_GUI_EXE_LDFLAGS", ["-mwindows"])
    646 
    647     # Silence problematic clang warnings
    648     add_flag("-Wno-incompatible-ms-struct", compiler=cxx_compiler)
    649     add_linker_flag("-Wl,--no-insert-timestamp")
    650 
    651     with only_when(depends(target.cpu)(lambda cpu: cpu == "x86")):
    652         add_flag("-mstackrealign")
    653         add_linker_flag("-Wl,--large-address-aware")