1 # This Source Code Form is subject to the terms of the Mozilla Public
2 # License, v. 2.0. If a copy of the MPL was not distributed with this
3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 from pathlib
import Path
12 from mozbuild
.buildversion
import mozilla_build_version
13 from packaging
.version
import Version
15 from mozboot
.base
import BaseBootstrapper
18 def is_aarch64_host():
19 from ctypes
import wintypes
21 kernel32
= ctypes
.windll
.kernel32
22 IMAGE_FILE_MACHINE_UNKNOWN
= 0
23 IMAGE_FILE_MACHINE_ARM64
= 0xAA64
26 iswow64process2
= kernel32
.IsWow64Process2
28 # If we can't access the symbol, we know we're not on aarch64.
31 currentProcess
= kernel32
.GetCurrentProcess()
32 processMachine
= wintypes
.USHORT(IMAGE_FILE_MACHINE_UNKNOWN
)
33 nativeMachine
= wintypes
.USHORT(IMAGE_FILE_MACHINE_UNKNOWN
)
35 gotValue
= iswow64process2(
36 currentProcess
, ctypes
.byref(processMachine
), ctypes
.byref(nativeMachine
)
38 # If this call fails, we have no idea.
42 return nativeMachine
.value
== IMAGE_FILE_MACHINE_ARM64
45 def get_is_windefender_disabled():
49 with winreg
.OpenKeyEx(
50 winreg
.HKEY_LOCAL_MACHINE
, r
"SOFTWARE\Microsoft\Windows Defender"
52 is_antivirus_disabled
, _
= winreg
.QueryValueEx(
53 windefender_key
, "DisableAntiSpyware"
55 # is_antivirus_disabled is either 0 (False) or 1 (True)
56 return bool(is_antivirus_disabled
)
57 except FileNotFoundError
:
61 def get_windefender_exclusion_paths():
66 with winreg
.OpenKeyEx(
67 winreg
.HKEY_LOCAL_MACHINE
,
68 r
"SOFTWARE\Microsoft\Windows Defender\Exclusions\Paths",
70 _
, values_count
, __
= winreg
.QueryInfoKey(exclusions_key
)
71 for i
in range(0, values_count
):
72 path
, _
, __
= winreg
.EnumValue(exclusions_key
, i
)
73 paths
.append(Path(path
))
74 except FileNotFoundError
:
80 def is_windefender_affecting_srcdir(src_dir
: Path
):
81 if get_is_windefender_disabled():
84 # When there's a match, but path cases aren't the same between srcdir and exclusion_path,
85 # commonpath will use the casing of the first path provided.
86 # To avoid surprises here, we normcase(...) so we don't get unexpected breakage if we change
88 src_dir
= src_dir
.resolve()
91 exclusion_paths
= get_windefender_exclusion_paths()
94 # A version of Windows 10 released in 2021 raises an "Access is denied"
95 # error (ERROR_ACCESS_DENIED == 5) to un-elevated processes when they
96 # query Windows Defender's exclusions. Skip the exclusion path checking.
100 for exclusion_path
in exclusion_paths
:
101 exclusion_path
= exclusion_path
.resolve()
103 if Path(os
.path
.commonpath((exclusion_path
, src_dir
))) == exclusion_path
:
104 # exclusion_path is an ancestor of srcdir
107 # ValueError: Paths don't have the same drive - can't be ours
112 class MozillaBuildBootstrapper(BaseBootstrapper
):
113 """Bootstrapper for MozillaBuild to install rustup."""
115 def __init__(self
, no_interactive
=False, no_system_changes
=False):
116 BaseBootstrapper
.__init
__(
117 self
, no_interactive
=no_interactive
, no_system_changes
=no_system_changes
120 def validate_environment(self
):
121 if is_windefender_affecting_srcdir(self
.srcdir
):
123 "Warning: the Firefox checkout directory is currently not in the "
124 "Windows Defender exclusion list. This can cause the build process "
125 "to be dramatically slowed or broken. To resolve this, follow the "
127 "https://firefox-source-docs.mozilla.org/setup/windows_build.html"
128 "#antivirus-performance",
132 def install_system_packages(self
):
135 def upgrade_mercurial(self
, current
):
136 # Mercurial upstream sometimes doesn't upload wheels, and building
137 # from source requires MS Visual C++ 9.0. So we force pip to install
138 # the last version that comes with wheels.
139 if mozilla_build_version() >= Version("4.0"):
141 Path(os
.environ
["MOZILLABUILD"]) / "python3" / "Scripts" / "pip.exe"
145 Path(os
.environ
["MOZILLABUILD"]) / "python" / "Scripts" / "pip.exe"
158 def install_browser_packages(self
, mozconfig_builder
):
161 def install_browser_artifact_mode_packages(self
, mozconfig_builder
):
165 os_arch
= platform
.machine()
166 if os_arch
== "AMD64":
167 # On Windows, x86_64 is reported as AMD64 but we use x86_64
168 # everywhere else, so let's normalized it here.
172 def install_mobile_android_packages(self
, mozconfig_builder
, artifact_mode
=False):
173 from mozboot
import android
175 os_arch
= self
._os
_arch
()
176 android
.ensure_android(
179 artifact_mode
=artifact_mode
,
180 no_interactive
=self
.no_interactive
,
182 android
.ensure_android(
185 system_images_only
=True,
186 artifact_mode
=artifact_mode
,
187 no_interactive
=self
.no_interactive
,
188 avd_manifest_path
=android
.AVD_MANIFEST_X86_64
,
190 android
.ensure_android(
193 system_images_only
=True,
194 artifact_mode
=artifact_mode
,
195 no_interactive
=self
.no_interactive
,
196 avd_manifest_path
=android
.AVD_MANIFEST_ARM
,
199 def ensure_mobile_android_packages(self
):
200 from mozboot
import android
202 android
.ensure_java("windows", self
._os
_arch
())
203 self
.install_toolchain_artifact(android
.WINDOWS_X86_64_ANDROID_AVD
)
204 self
.install_toolchain_artifact(android
.WINDOWS_ARM_ANDROID_AVD
)
206 def install_mobile_android_artifact_mode_packages(self
, mozconfig_builder
):
207 self
.install_mobile_android_packages(mozconfig_builder
, artifact_mode
=True)
209 def generate_mobile_android_mozconfig(self
, artifact_mode
=False):
210 from mozboot
import android
212 return android
.generate_mozconfig("windows", artifact_mode
=artifact_mode
)
214 def generate_mobile_android_artifact_mode_mozconfig(self
):
215 return self
.generate_mobile_android_mozconfig(artifact_mode
=True)
217 def ensure_sccache_packages(self
):
218 from mozboot
import sccache
220 self
.install_toolchain_artifact(sccache
.RUSTC_DIST_TOOLCHAIN
, no_unpack
=True)
221 self
.install_toolchain_artifact(sccache
.CLANG_DIST_TOOLCHAIN
, no_unpack
=True)
223 def _update_package_manager(self
):
226 def run(self
, command
):
227 subprocess
.check_call(command
, stdin
=sys
.stdin
)