Bug 1885602 - Part 3: Add MenuHeader for the menu redesign r=android-reviewers,007
[gecko.git] / toolkit / moz.configure
blob2b034e666c7bb9f30a3b5a614d0e7a01d8ccf346
1 # -*- Mode: python; 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/.
8 # Set the MOZ_CONFIGURE_OPTIONS variable with all the options that
9 # were passed somehow (environment, command line, mozconfig)
10 @dependable
11 @imports(_from="mozbuild.shellutil", _import="quote")
12 @imports(_from="mozbuild.util", _import="ensure_unicode")
13 @imports(_from="mozbuild.util", _import="system_encoding")
14 @imports("__sandbox__")
15 def all_configure_options():
16     result = []
17     previous = None
18     for option in __sandbox__._options.values():
19         # __sandbox__._options contains items for both option.name and
20         # option.env. But it's also an OrderedDict, meaning both are
21         # consecutive.
22         # Also ignore OLD_CONFIGURE and MOZCONFIG because they're not
23         # interesting.
24         if option == previous or option.env in ("OLD_CONFIGURE", "MOZCONFIG"):
25             continue
26         previous = option
27         value = __sandbox__._value_for(option)
28         # We only want options that were explicitly given on the command
29         # line, the environment, or mozconfig, and that differ from the
30         # defaults.
31         if (
32             value is not None
33             and value.origin not in ("default", "implied")
34             and value != option.default
35         ):
36             result.append(
37                 ensure_unicode(__sandbox__._raw_options[option], system_encoding)
38             )
39         # We however always include options that are sent to old configure
40         # because we don't know their actual defaults. (Keep the conditions
41         # separate for ease of understanding and ease of removal)
42         elif (
43             option.help == "Help missing for old configure options"
44             and option in __sandbox__._raw_options
45         ):
46             result.append(
47                 ensure_unicode(__sandbox__._raw_options[option], system_encoding)
48             )
50     # We shouldn't need this, but currently, quote will return a byte string
51     # if result is empty, and that's not wanted here.
52     if not result:
53         return ""
55     return quote(*result)
58 set_config("MOZ_CONFIGURE_OPTIONS", all_configure_options)
61 @depends(target)
62 def fold_libs(target):
63     return target.os in ("WINNT", "OSX", "iOS", "Android")
66 set_config("MOZ_FOLD_LIBS", fold_libs)
68 # Profiling
69 # ==============================================================
70 # Some of the options here imply an option from js/moz.configure,
71 # so, need to be declared before the include.
73 option(
74     "--enable-jprof",
75     env="MOZ_JPROF",
76     help="Enable jprof profiling tool (needs mozilla/tools/jprof)",
80 @depends("--enable-jprof")
81 def jprof(value):
82     if value:
83         return True
86 set_config("MOZ_JPROF", jprof)
87 set_define("MOZ_JPROF", jprof)
88 imply_option("--enable-profiling", jprof)
90 option("--disable-gecko-profiler", help="Disable the Gecko profiler")
93 @depends("--disable-gecko-profiler", target)
94 def gecko_profiler(enable_gecko_profiler, target):
95     if not enable_gecko_profiler:
96         return False
98     if target.os == "Android":
99         return target.cpu in ("aarch64", "arm", "x86", "x86_64")
100     elif target.kernel == "Linux":
101         return target.cpu in ("aarch64", "arm", "x86", "x86_64", "mips64")
102     elif target.kernel == "FreeBSD":
103         return target.cpu in ("aarch64", "x86_64")
104     return target.kernel in ("Darwin", "WINNT")
107 @depends(gecko_profiler)
108 def gecko_profiler_define(value):
109     if value:
110         return True
113 set_config("MOZ_GECKO_PROFILER", gecko_profiler_define)
114 set_define("MOZ_GECKO_PROFILER", gecko_profiler_define)
117 # Enable perfetto on Android if gecko profiling is enabled and only for
118 # nightly builds. Linux support requires at least linux-headers-3.18 for <linux/vm_sockets.h>
119 set_config(
120     "MOZ_PERFETTO", gecko_profiler_define, when=target_is_android & milestone.is_nightly
122 set_define(
123     "MOZ_PERFETTO", gecko_profiler_define, when=target_is_android & milestone.is_nightly
127 # Whether code to parse ELF binaries should be compiled for the Gecko profiler
128 # (for symbol table dumping).
129 @depends(gecko_profiler, target)
130 def gecko_profiler_parse_elf(value, target):
131     # Currently we only want to build this code on Linux (including Android) and BSD.
132     # For Android, this is in order to dump symbols from Android system, where
133     # on other platforms there exist alternatives that don't require bloating
134     # up our binary size. For Linux more generally, we use this in profile
135     # pre-symbolication support, since MozDescribeCodeAddress doesn't do
136     # anything useful on that platform. (Ideally, we would update
137     # MozDescribeCodeAddress to call into some Rust crates that parse ELF and
138     # DWARF data, but build system issues currently prevent Rust from being
139     # used in mozglue.)
140     if value and (target.kernel == "Linux" or target.kernel == "FreeBSD"):
141         return True
144 set_config("MOZ_GECKO_PROFILER_PARSE_ELF", gecko_profiler_parse_elf)
145 set_define("MOZ_GECKO_PROFILER_PARSE_ELF", gecko_profiler_parse_elf)
147 # enable this by default if the profiler is enabled
148 # Note: also requires jemalloc
149 set_config("MOZ_PROFILER_MEMORY", gecko_profiler_define)
150 set_define("MOZ_PROFILER_MEMORY", gecko_profiler_define)
153 @depends(
154     "--enable-debug",
155     milestone,
156     build_project,
157     # Artifact builds are included because the downloaded artifacts can
158     # have DMD enabled.
159     when=artifact_builds | depends(when="--enable-replace-malloc")(lambda: True),
161 def dmd_default(debug, milestone, build_project):
162     return bool(build_project == "browser" and (debug or milestone.is_nightly))
165 option(
166     "--enable-dmd",
167     env="MOZ_DMD",
168     default=dmd_default,
169     help="{Enable|Disable} Dark Matter Detector (heap profiler). "
170     "Also enables jemalloc, replace-malloc and profiling",
174 @depends("--enable-dmd")
175 def dmd(value):
176     if value:
177         return True
180 set_config("MOZ_DMD", dmd)
181 set_define("MOZ_DMD", dmd)
182 imply_option("--enable-profiling", dmd)
183 imply_option("--enable-jemalloc", dmd, when=compile_environment)
184 imply_option("--enable-replace-malloc", dmd, when=compile_environment)
187 # midir-based Web MIDI support
188 # ==============================================================
189 @depends(target)
190 def midir_linux_support(target):
191     return (
192         target.kernel == "Linux" and target.os != "Android" and target.cpu != "riscv64"
193     )
196 @depends(target, midir_linux_support)
197 def midir_support(target, midir_linux_support):
198     if target.os in ("WINNT", "OSX") or midir_linux_support:
199         return True
202 set_config("MOZ_WEBMIDI_MIDIR_IMPL", midir_support)
205 # Enable various cubeb backends
206 # ==============================================================
207 @depends(target)
208 def audio_backends_default(target):
209     if target.os == "Android":
210         return (
211             "aaudio",
212             "opensl",
213         )
214     elif target.os in ("DragonFly", "FreeBSD", "SunOS"):
215         return ("oss",)
216     elif target.os == "OpenBSD":
217         return ("sndio",)
218     elif target.kernel == "Darwin":
219         return ("audiounit",)
220     elif target.os == "NetBSD":
221         return ("sunaudio",)
222     elif target.os == "SunOS":
223         return ("sunaudio",)
224     elif target.os == "WINNT":
225         return ("wasapi",)
226     else:
227         return ("pulseaudio",)
230 option(
231     "--enable-audio-backends",
232     nargs="+",
233     choices=(
234         "aaudio",
235         "alsa",
236         "audiounit",
237         "jack",
238         "opensl",
239         "oss",
240         "pulseaudio",
241         "sndio",
242         "sunaudio",
243         "wasapi",
244     ),
245     default=audio_backends_default,
246     help="{Enable|Disable} various cubeb backends",
250 @depends("--enable-audio-backends", target)
251 def imply_aaudio(values, target):
252     if any("aaudio" in value for value in values) and target.os != "Android":
253         die("Cannot enable AAudio on %s", target.os)
254     return any("aaudio" in value for value in values) or None
257 @depends("--enable-audio-backends", target)
258 def imply_alsa(values, target):
259     if (
260         any("alsa" in value for value in values)
261         and target.kernel != "Linux"
262         and target.os != "FreeBSD"
263     ):
264         die("Cannot enable ALSA on %s", target.os)
265     return any("alsa" in value for value in values) or None
268 @depends("--enable-audio-backends", target)
269 def imply_audiounit(values, target):
270     if any("audiounit" in value for value in values) and target.kernel != "Darwin":
271         die("Cannot enable AudioUnit on %s", target.os)
272     return any("audiounit" in value for value in values) or None
275 @depends("--enable-audio-backends")
276 def imply_jack(values):
277     return any("jack" in value for value in values) or None
280 @depends("--enable-audio-backends", target)
281 def imply_opensl(values, target):
282     if any("opensl" in value for value in values) and target.os != "Android":
283         die("Cannot enable OpenSL on %s", target.os)
284     return any("opensl" in value for value in values) or None
287 @depends("--enable-audio-backends", target)
288 def imply_oss(values, target):
289     if any("oss" in value for value in values) and (
290         target.os in ("Android", "OSX", "iOS", "WINNT")
291     ):
292         die("Cannot enable OSS on %s", target.os)
293     return any("oss" in value for value in values) or None
296 @depends("--enable-audio-backends", target)
297 def imply_pulseaudio(values, target):
298     if any("pulseaudio" in value for value in values) and (
299         target.os in ("Android", "OSX", "iOS", "WINNT")
300     ):
301         die("Cannot enable PulseAudio on %s", target.os)
302     return any("pulseaudio" in value for value in values) or None
305 @depends("--enable-audio-backends", target)
306 def imply_sndio(values, target):
307     if any("sndio" in value for value in values) and (
308         target.os in ("Android", "OSX", "iOS", "WINNT")
309     ):
310         die("Cannot enable sndio on %s", target.os)
311     return any("sndio" in value for value in values) or None
314 @depends("--enable-audio-backends", target)
315 def imply_sunaudio(values, target):
316     if any("sunaudio" in value for value in values) and (
317         target.os != "NetBSD" and target.os != "SunOS"
318     ):
319         die("Cannot enable sunaudio on %s", target.os)
320     return any("sunaudio" in value for value in values) or None
323 @depends("--enable-audio-backends", target)
324 def imply_wasapi(values, target):
325     if any("wasapi" in value for value in values) and target.os != "WINNT":
326         die("Cannot enable WASAPI on %s", target.os)
327     return any("wasapi" in value for value in values) or None
330 set_config("MOZ_AAUDIO", imply_aaudio, when="--enable-audio-backends")
332 imply_option("--enable-alsa", imply_alsa, reason="--enable-audio-backends")
334 set_config("MOZ_AUDIOUNIT_RUST", imply_audiounit, when="--enable-audio-backends")
336 imply_option("--enable-jack", imply_jack, reason="--enable-audio-backends")
338 set_config("MOZ_OPENSL", imply_opensl, when="--enable-audio-backends")
340 set_config("MOZ_OSS", imply_oss, when="--enable-audio-backends")
342 imply_option("--enable-pulseaudio", imply_pulseaudio, reason="--enable-audio-backends")
344 imply_option("--enable-sndio", imply_sndio, reason="--enable-audio-backends")
346 set_config("MOZ_SUNAUDIO", imply_sunaudio, when="--enable-audio-backends")
348 set_config("MOZ_WASAPI", imply_wasapi, when="--enable-audio-backends")
350 # ALSA cubeb backend
351 # ==============================================================
352 option("--enable-alsa", env="MOZ_ALSA", help="Enable ALSA audio backend.")
355 @depends("--enable-alsa", midir_linux_support)
356 def enable_alsa_or_midir_linux_support(alsa_enabled, midir_linux_support):
357     return alsa_enabled or midir_linux_support
360 pkg_check_modules("MOZ_ALSA", "alsa", when=enable_alsa_or_midir_linux_support)
362 set_config("MOZ_ALSA", True, when="--enable-alsa")
363 set_define("MOZ_ALSA", True, when="--enable-alsa")
365 # JACK cubeb backend
366 # ==============================================================
367 system_lib_option("--enable-jack", env="MOZ_JACK", help="Enable JACK audio backend.")
369 jack = pkg_check_modules("MOZ_JACK", "jack", when="--enable-jack")
371 set_config("MOZ_JACK", depends_if(jack)(lambda _: True))
373 # PulseAudio cubeb backend
374 # ==============================================================
375 option(
376     "--enable-pulseaudio",
377     env="MOZ_PULSEAUDIO",
378     help="{Enable|Disable} PulseAudio audio backend.",
381 pulseaudio = pkg_check_modules("MOZ_PULSEAUDIO", "libpulse", when="--enable-pulseaudio")
383 set_config("MOZ_PULSEAUDIO", depends_if(pulseaudio)(lambda _: True))
384 set_define("MOZ_PULSEAUDIO", depends_if(pulseaudio)(lambda _: True))
386 # sndio cubeb backend
387 # ==============================================================
388 system_lib_option("--enable-sndio", env="MOZ_SNDIO", help="Enable sndio audio backend.")
390 sndio = pkg_check_modules("MOZ_SNDIO", "sndio", when="--enable-sndio")
392 set_config("MOZ_SNDIO", depends_if(sndio)(lambda _: True))
394 # Javascript engine
395 # ==============================================================
396 include("../js/moz.configure")
399 # NodeJS
400 # ==============================================================
401 include("../build/moz.configure/node.configure")
403 # JsonCpp
404 # ==============================================================
405 set_define("JSON_USE_EXCEPTION", 0)
407 # L10N
408 # ==============================================================
409 option("--with-l10n-base", nargs=1, env="L10NBASEDIR", help="Path to l10n repositories")
412 @depends("--with-l10n-base", "MOZ_AUTOMATION", build_environment)
413 @imports(_from="os.path", _import="isdir")
414 @imports(_from="os.path", _import="expanduser")
415 @imports(_from="os", _import="environ")
416 def l10n_base(value, automation, build_env):
417     if value:
418         path = value[0]
419         if not isdir(path):
420             die("Invalid value --with-l10n-base, %s doesn't exist", path)
421     elif automation:
422         path = os.path.join(build_env.topsrcdir, "../l10n-central")
423     else:
424         path = os.path.join(
425             environ.get(
426                 "MOZBUILD_STATE_PATH", expanduser(os.path.join("~", ".mozbuild"))
427             ),
428             "l10n-central",
429         )
430     return os.path.realpath(os.path.abspath(path))
433 set_config("L10NBASEDIR", l10n_base)
436 # Default toolkit
437 # ==============================================================
438 @depends(target)
439 def toolkit_choices(target):
440     if target.os == "WINNT":
441         return ("cairo-windows",)
442     elif target.os == "OSX":
443         return ("cairo-cocoa",)
444     elif target.os == "iOS":
445         return ("cairo-uikit",)
446     elif target.os == "Android":
447         return ("cairo-android",)
448     else:
449         # cairo-gtk3 - X11 backend with optional Wayland backend (auto detected)
450         # cairo-gtk3-wayland - Wayland backend with optional X11 backend (auto detected)
451         # cairo-gtk3-x11-wayland - builds explicitly with X11 & Wayland backends
452         return (
453             "cairo-gtk3",
454             "cairo-gtk3-wayland",
455             "cairo-gtk3-x11-wayland",
456             "cairo-gtk3-wayland-only",
457             "cairo-gtk3-x11-only",
458         )
461 @depends(toolkit_choices)
462 def toolkit_default(choices):
463     return choices[0]
466 option(
467     "--enable-default-toolkit",
468     nargs=1,
469     choices=toolkit_choices,
470     default=toolkit_default,
471     help="Select default toolkit",
475 @depends("--enable-default-toolkit")
476 def full_toolkit(value):
477     if value:
478         return value[0]
481 @depends(full_toolkit)
482 def toolkit(toolkit):
483     if toolkit.startswith("cairo-gtk3"):
484         widget_toolkit = "gtk"
485     else:
486         widget_toolkit = toolkit.replace("cairo-", "")
487     return widget_toolkit
490 set_config("MOZ_WIDGET_TOOLKIT", toolkit)
491 add_old_configure_assignment("MOZ_WIDGET_TOOLKIT", toolkit)
494 @depends(toolkit)
495 def toolkit_define(toolkit):
496     if toolkit != "windows":
497         return "MOZ_WIDGET_%s" % toolkit.upper()
500 set_define(toolkit_define, True)
503 @depends(toolkit)
504 def toolkit_gtk(toolkit):
505     return toolkit == "gtk"
508 @depends(toolkit_gtk, full_toolkit)
509 def toolkit_gtk_x11(toolkit_gtk, full_toolkit):
510     return toolkit_gtk and full_toolkit != "cairo-gtk3-wayland-only"
513 @depends(full_toolkit)
514 def toolkit_gtk_x11_optional(full_toolkit):
515     return full_toolkit == "cairo-gtk3-wayland"
518 @depends(toolkit_gtk, full_toolkit)
519 def toolkit_gtk_wayland(toolkit_gtk, full_toolkit):
520     return toolkit_gtk and full_toolkit != "cairo-gtk3-x11-only"
523 @depends(full_toolkit)
524 def toolkit_gtk_wayland_optional(full_toolkit):
525     return full_toolkit == "cairo-gtk3"
528 # Wayland support
529 # ==============================================================
530 wayland_headers = pkg_check_modules(
531     "MOZ_WAYLAND",
532     "gtk+-wayland-3.0 >= 3.14 xkbcommon >= 0.4.1",
533     allow_missing=toolkit_gtk_wayland_optional,
534     when=toolkit_gtk_wayland,
538 @depends(wayland_headers, toolkit_gtk, artifact_builds, toolkit_gtk_wayland)
539 def wayland_headers(wayland, toolkit_gtk, artifacts, toolkit_gtk_wayland):
540     if not toolkit_gtk_wayland:
541         return False
542     if toolkit_gtk and artifacts:
543         return True
544     return wayland
547 set_config("MOZ_WAYLAND", depends_if(wayland_headers)(lambda _: True))
548 set_define("MOZ_WAYLAND", depends_if(wayland_headers)(lambda _: True))
551 # Hardware-accelerated video decode with VAAPI and V4L2 on Linux
552 # ==============================================================
553 set_config("MOZ_ENABLE_VAAPI", True, when=toolkit_gtk)
554 set_define("MOZ_ENABLE_VAAPI", True, when=toolkit_gtk)
557 @depends(target, toolkit_gtk)
558 def v4l2(target, toolkit_gtk):
559     # V4L2 decode is only used in GTK/Linux and generally only appears on
560     # embedded SOCs.
561     if target.cpu in ("arm", "aarch64", "riscv64") and toolkit_gtk:
562         return True
565 set_config("MOZ_ENABLE_V4L2", True, when=v4l2)
566 set_define("MOZ_ENABLE_V4L2", True, when=v4l2)
568 # GL Provider
569 # ==============================================================
570 option("--with-gl-provider", nargs=1, help="Set GL provider backend type")
573 @depends("--with-gl-provider")
574 def gl_provider(value):
575     if value:
576         return value[0]
579 @depends(gl_provider)
580 def gl_provider_define(provider):
581     if provider:
582         return "GLContextProvider%s" % provider
585 set_define("MOZ_GL_PROVIDER", gl_provider_define)
588 @depends(gl_provider, toolkit_gtk)
589 def gl_default_provider(value, toolkit_gtk):
590     if value:
591         return value
592     elif toolkit_gtk:
593         return "EGL"
596 set_config("MOZ_GL_PROVIDER", gl_provider)
597 set_config("MOZ_GL_DEFAULT_PROVIDER", gl_default_provider)
600 @depends(gl_default_provider)
601 def gl_provider_define(provider):
602     if provider:
603         return "GL_PROVIDER_%s" % provider
606 set_define(gl_provider_define, True)
609 # PDF printing
610 # ==============================================================
611 @depends(toolkit)
612 def pdf_printing(toolkit):
613     if toolkit in ("windows", "gtk", "android"):
614         return True
617 set_config("MOZ_PDF_PRINTING", pdf_printing)
618 set_define("MOZ_PDF_PRINTING", pdf_printing)
621 # Event loop instrumentation
622 # ==============================================================
623 option(env="MOZ_INSTRUMENT_EVENT_LOOP", help="Force-enable event loop instrumentation")
626 @depends("MOZ_INSTRUMENT_EVENT_LOOP", toolkit)
627 def instrument_event_loop(value, toolkit):
628     if value or (
629         toolkit in ("windows", "gtk", "cocoa", "android") and value.origin == "default"
630     ):
631         return True
634 set_config("MOZ_INSTRUMENT_EVENT_LOOP", instrument_event_loop)
635 set_define("MOZ_INSTRUMENT_EVENT_LOOP", instrument_event_loop)
638 # Fontconfig Freetype
639 # ==============================================================
640 option(env="USE_FC_FREETYPE", help="Force-enable the use of fontconfig freetype")
643 @depends("USE_FC_FREETYPE", toolkit)
644 def fc_freetype(value, toolkit):
645     if value or (toolkit == "gtk" and value.origin == "default"):
646         return True
649 set_define("USE_FC_FREETYPE", fc_freetype)
651 # Pango
652 # ==============================================================
653 pkg_check_modules("MOZ_PANGO", "pango >= 1.22.0", when=toolkit_gtk)
655 # Fontconfig
656 # ==============================================================
657 fontconfig_info = pkg_check_modules(
658     "_FONTCONFIG", "fontconfig >= 2.7.0", when=fc_freetype
662 @depends(fc_freetype)
663 def check_for_freetype2(fc_freetype):
664     if fc_freetype:
665         return True
668 # Check for freetype2. Flags are combined with fontconfig flags.
669 freetype2_info = pkg_check_modules(
670     "_FT2", "freetype2 >= 9.10.3", when=check_for_freetype2
674 @depends(fontconfig_info, freetype2_info)
675 def freetype2_combined_info(fontconfig_info, freetype2_info):
676     if not freetype2_info:
677         return
678     if not fontconfig_info:
679         return freetype2_info
680     return namespace(
681         cflags=freetype2_info.cflags + fontconfig_info.cflags,
682         libs=freetype2_info.libs + fontconfig_info.libs,
683     )
686 set_define("MOZ_HAVE_FREETYPE2", depends_if(freetype2_info)(lambda _: True))
689 # Apple platform decoder support
690 # ==============================================================
691 @depends(toolkit)
692 def applemedia(toolkit):
693     if toolkit in ("cocoa", "uikit"):
694         return True
697 set_config("MOZ_APPLEMEDIA", applemedia)
698 set_define("MOZ_APPLEMEDIA", applemedia)
700 # Windows Media Foundation support
701 # ==============================================================
702 option("--disable-wmf", help="Disable support for Windows Media Foundation")
705 @depends("--disable-wmf", target, "--help")
706 def wmf(value, target, _):
707     enabled = bool(value)
708     if value.origin == "default":
709         # Enable Windows Media Foundation support by default.
710         # Note our minimum SDK version is Windows 7 SDK, so we are (currently)
711         # guaranteed to have a recent-enough SDK to build WMF.
712         enabled = target.os == "WINNT"
713     if enabled and target.os != "WINNT":
714         die("Cannot enable Windows Media Foundation support on %s", target.os)
715     if enabled:
716         return True
719 @depends(artifact_builds, c_compiler, when=wmf)
720 def wmfmediaengine(artifact_builds, c_compiler):
721     if c_compiler:
722         return c_compiler.type == "clang-cl"
723     return bool(artifact_builds)
726 set_config("MOZ_WMF", wmf)
727 set_define("MOZ_WMF", wmf)
729 set_config("MOZ_WMF_MEDIA_ENGINE", True, when=wmfmediaengine)
730 set_define("MOZ_WMF_MEDIA_ENGINE", True, when=wmfmediaengine)
732 # FFmpeg H264/AAC Decoding Support
733 # ==============================================================
734 option("--disable-ffmpeg", help="Disable FFmpeg for fragmented H264/AAC decoding")
737 @depends("--disable-ffmpeg", target)
738 def ffmpeg(value, target):
739     enabled = bool(value)
740     if value.origin == "default":
741         enabled = target.os not in ("Android", "WINNT")
742     if enabled:
743         return True
746 set_config("MOZ_FFMPEG", ffmpeg)
747 set_define("MOZ_FFMPEG", ffmpeg)
749 # AV1 Video Codec Support
750 # ==============================================================
751 option("--disable-av1", help="Disable av1 video support")
754 @depends("--enable-av1")
755 def av1(value):
756     if value:
757         return True
760 @depends(target, when=av1 & compile_environment)
761 def dav1d_asm(target):
762     if target.cpu in ("aarch64", "x86", "x86_64"):
763         return True
766 @depends(target, when=av1 & compile_environment)
767 def dav1d_nasm(target):
768     if target.cpu in ("x86", "x86_64"):
769         return namespace(version="2.14", what="AV1")
772 set_config("MOZ_DAV1D_ASM", dav1d_asm)
773 set_define("MOZ_DAV1D_ASM", dav1d_asm)
774 set_config("MOZ_AV1", av1)
775 set_define("MOZ_AV1", av1)
777 # JXL Image Codec Support
778 # ==============================================================
779 option("--disable-jxl", help="Disable jxl image support")
782 @depends("--disable-jxl", milestone.is_nightly)
783 def jxl(value, is_nightly):
784     if is_nightly and value:
785         return True
788 set_config("MOZ_JXL", jxl)
789 set_define("MOZ_JXL", jxl)
791 set_config("MOZ_SAMPLE_TYPE_FLOAT32", True)
792 set_define("MOZ_SAMPLE_TYPE_FLOAT32", True)
794 set_define("MOZ_VORBIS", True)
795 set_config("MOZ_VORBIS", True)
797 option(
798     "--disable-real-time-tracing",
799     help="Disable tracing of real-time audio callbacks",
802 set_config("MOZ_REAL_TIME_TRACING", True, when="--enable-real-time-tracing")
803 set_define("MOZ_REAL_TIME_TRACING", True, when="--enable-real-time-tracing")
805 # OpenMAX IL Decoding Support
806 # ==============================================================
807 option("--enable-openmax", help="Enable OpenMAX IL for video/audio decoding")
810 @depends("--enable-openmax")
811 def openmax(value):
812     enabled = bool(value)
813     if enabled:
814         return True
817 set_config("MOZ_OMX", openmax)
818 set_define("MOZ_OMX", openmax)
821 # EME Support
822 # ==============================================================
823 @depends(target, wmf)
824 def eme_choices(target, wmf):
825     if (
826         target.kernel in ("WINNT", "Linux")
827         and target.os != "Android"
828         and target.cpu in ("x86", "x86_64")
829     ):
830         if wmf:
831             return ("widevine", "wmfcdm")
832         return ("widevine",)
833     if target.kernel == "WINNT" and target.cpu == "aarch64":
834         return ("widevine",)
835     if target.os in ("OSX"):
836         return ("widevine",)
839 # Widevine is enabled by default in desktop browser builds.
840 @depends(build_project, eme_choices)
841 def eme_default(build_project, choices):
842     if build_project == "browser":
843         return choices
846 option(
847     "--enable-eme",
848     nargs="+",
849     choices=eme_choices,
850     default=eme_default,
851     when=eme_choices,
852     help="{Enable|Disable} support for Encrypted Media Extensions",
856 @depends("--enable-eme", when=eme_choices)
857 def eme_modules(value):
858     return value
861 # Fallback to an empty list when eme_choices is empty, setting eme_modules to
862 # None.
863 set_config("MOZ_EME_MODULES", eme_modules | dependable([]))
866 # Media Foundation CDM support
867 # ==============================================================
868 @depends(eme_modules, when=wmfmediaengine)
869 def wmfcdm(modules):
870     if "wmfcdm" in modules:
871         return True
874 set_config("MOZ_WMF_CDM", True, when=wmfcdm)
875 set_define("MOZ_WMF_CDM", True, when=wmfcdm)
878 option(
879     name="--enable-chrome-format",
880     help="Select FORMAT of chrome files during packaging.",
881     nargs=1,
882     choices=("omni", "jar", "flat"),
883     default="omni",
887 @depends("--enable-chrome-format")
888 def packager_format(value):
889     return value[0]
892 set_config("MOZ_PACKAGER_FORMAT", packager_format)
894 # The packager minifies two different types of files: non-JS (mostly property
895 # files for l10n), and JS.  Setting MOZ_PACKAGER_MINIFY only minifies the
896 # former.  Firefox doesn't yet minify JS, due to concerns about debuggability.
898 # Also, the JS minification setup really only works correctly on Android:
899 # we need extra setup to use the newly-built shell for Linux and Windows,
900 # and cross-compilation for macOS requires some extra care.
903 @depends(target_is_android, "--enable-debug", milestone.is_nightly)
904 def enable_minify_default(is_android, debug, is_nightly):
905     if is_android and not debug and not is_nightly:
906         return ("properties", "js")
907     return ("properties",)
910 option(
911     name="--enable-minify",
912     help="Select types of files to minify during packaging.",
913     nargs="*",
914     choices=("properties", "js"),
915     default=enable_minify_default,
919 @depends("--enable-minify")
920 def enable_minify(value):
921     if "js" in value and "properties" not in value:
922         die("--enable-minify=js requires --enable-minify=properties.")
923     return namespace(
924         properties="properties" in value,
925         js="js" in value,
926     )
929 set_config("MOZ_PACKAGER_MINIFY", True, when=enable_minify.properties)
930 set_config("MOZ_PACKAGER_MINIFY_JS", True, when=enable_minify.js)
933 @depends(host, build_project)
934 def jar_maker_format(host, build_project):
935     # Multilocales for mobile/android use the same mergedirs for all locales,
936     # so we can't use symlinks for those builds.
937     if host.os == "WINNT" or build_project == "mobile/android":
938         return "flat"
939     return "symlink"
942 set_config("MOZ_JAR_MAKER_FILE_FORMAT", jar_maker_format)
945 @depends(toolkit)
946 def omnijar_name(toolkit):
947     # Fennec's static resources live in the assets/ folder of the
948     # APK.  Adding a path to the name here works because we only
949     # have one omnijar file in the final package (which is not the
950     # case on desktop).
951     return "assets/omni.ja" if toolkit == "android" else "omni.ja"
954 set_config("OMNIJAR_NAME", omnijar_name)
956 project_flag("MOZ_PLACES", help="Build Places if required", set_as_define=True)
958 project_flag(
959     "MOZ_SERVICES_HEALTHREPORT",
960     help="Build Firefox Health Reporter Service",
961     set_as_define=True,
964 project_flag(
965     "MOZ_NORMANDY",
966     help="Enable Normandy recipe runner",
967     set_as_define=True,
970 project_flag("MOZ_SERVICES_SYNC", help="Build Sync Services if required")
972 project_flag(
973     "MOZ_ANDROID_HISTORY",
974     help="Enable Android History instead of Places",
975     set_as_define=True,
978 project_flag(
979     "MOZ_DEDICATED_PROFILES",
980     help="Enable dedicated profiles per install",
981     set_as_define=True,
984 project_flag(
985     "MOZ_BLOCK_PROFILE_DOWNGRADE",
986     help="Block users from starting profiles last used by a newer build",
987     set_as_define=True,
991 @depends("MOZ_PLACES", "MOZ_ANDROID_HISTORY")
992 def check_places_and_android_history(places, android_history):
993     if places and android_history:
994         die("Cannot use MOZ_ANDROID_HISTORY alongside MOZ_PLACES.")
995     if not places and not android_history:
996         die("One of MOZ_ANDROID_HISTORY or MOZ_PLACES must be set.")
999 option(
1000     env="MOZ_TELEMETRY_REPORTING",
1001     default=mozilla_official,
1002     help="Enable telemetry reporting",
1005 set_define("MOZ_TELEMETRY_REPORTING", True, when="MOZ_TELEMETRY_REPORTING")
1008 @depends("MOZ_TELEMETRY_REPORTING", milestone.is_nightly)
1009 def telemetry_on_by_default(reporting, is_nightly):
1010     return reporting and is_nightly
1013 set_define("MOZ_TELEMETRY_ON_BY_DEFAULT", True, when=telemetry_on_by_default)
1016 # gpsd support
1017 # ==============================================================
1018 system_lib_option("--enable-gpsd", env="MOZ_GPSD", help="Enable gpsd support")
1021 @depends("--enable-gpsd")
1022 def gpsd(value):
1023     return bool(value)
1026 system_gpsd = pkg_check_modules("MOZ_GPSD", "libgps >= 3.11", when=gpsd)
1028 set_config("MOZ_GPSD", depends_if(system_gpsd)(lambda _: True))
1030 # Miscellaneous programs
1031 # ==============================================================
1033 check_prog("TAR", ("gnutar", "gtar", "tar"))
1034 check_prog("UNZIP", ("unzip",))
1036 # Key files
1037 # ==============================================================
1038 include("../build/moz.configure/keyfiles.configure")
1040 simple_keyfile("Mozilla API")
1042 simple_keyfile("Google Location Service API")
1044 simple_keyfile("Google Safebrowsing API")
1046 id_and_secret_keyfile("Bing API")
1048 simple_keyfile("Adjust SDK")
1050 id_and_secret_keyfile("Leanplum SDK")
1052 simple_keyfile("Pocket API")
1055 # WebRender Debugger integration
1056 # ==============================================================
1058 option(
1059     "--enable-webrender-debugger", help="Build the websocket debug server in WebRender"
1062 set_config(
1063     "MOZ_WEBRENDER_DEBUGGER", depends_if("--enable-webrender-debugger")(lambda _: True)
1066 # Additional system headers defined at the application level
1067 # ==============================================================
1069 option(
1070     "--enable-app-system-headers",
1071     env="MOZ_APP_SYSTEM_HEADERS",
1072     help="Use additional system headers defined in $MOZ_BUILD_APP/app-system-headers.mozbuild",
1076 @depends("--enable-app-system-headers")
1077 def app_system_headers(value):
1078     if value:
1079         return True
1082 set_config("MOZ_APP_SYSTEM_HEADERS", app_system_headers)
1083 set_define("MOZ_APP_SYSTEM_HEADERS", app_system_headers)
1086 # Printing
1087 # ==============================================================
1088 @depends(target)
1089 def printing_default(target):
1090     return target.os != "iOS"
1093 option(
1094     "--disable-printing",
1095     default=printing_default,
1096     help="{Enable|Disable} printing support",
1100 @depends("--disable-printing")
1101 def printing(value):
1102     if value:
1103         return True
1106 set_config("NS_PRINTING", printing)
1107 set_define("NS_PRINTING", printing)
1108 set_define("NS_PRINT_PREVIEW", printing)
1111 # Speech-dispatcher support
1112 # ==============================================================
1113 @depends(toolkit)
1114 def no_speechd_on_non_gtk(toolkit):
1115     if toolkit != "gtk":
1116         return False
1119 imply_option(
1120     "--enable-synth-speechd", no_speechd_on_non_gtk, reason="--enable-default-toolkit"
1123 option("--disable-synth-speechd", help="Disable speech-dispatcher support")
1125 set_config("MOZ_SYNTH_SPEECHD", depends_if("--disable-synth-speechd")(lambda _: True))
1127 # Speech API
1128 # ==============================================================
1129 option("--disable-webspeech", help="Disable support for HTML Speech API")
1132 @depends("--disable-webspeech")
1133 def webspeech(value):
1134     if value:
1135         return True
1138 set_config("MOZ_WEBSPEECH", webspeech)
1139 set_define("MOZ_WEBSPEECH", webspeech)
1141 # Speech API test backend
1142 # ==============================================================
1143 option(
1144     "--enable-webspeechtestbackend",
1145     default=webspeech,
1146     help="{Enable|Disable} support for HTML Speech API Test Backend",
1150 @depends_if("--enable-webspeechtestbackend")
1151 def webspeech_test_backend(value):
1152     return True
1155 set_config("MOZ_WEBSPEECH_TEST_BACKEND", webspeech_test_backend)
1156 set_define("MOZ_WEBSPEECH_TEST_BACKEND", webspeech_test_backend)
1159 # Graphics
1160 # ==============================================================
1161 @depends(target, milestone)
1162 def skia_pdf_default(target, milestone):
1163     return milestone.is_nightly and target.os != "WINNT"
1166 option("--enable-skia-pdf", default=skia_pdf_default, help="{Enable|Disable} Skia PDF")
1168 set_config("MOZ_ENABLE_SKIA_PDF", True, when="--enable-skia-pdf")
1169 set_define("MOZ_ENABLE_SKIA_PDF", True, when="--enable-skia-pdf")
1171 set_config(
1172     "SKIA_INCLUDES",
1173     [
1174         "/gfx/skia",
1175         "/gfx/skia/skia",
1176     ],
1179 system_lib_option(
1180     "--with-system-webp", help="Use system libwebp (located with pkgconfig)"
1183 system_webp = pkg_check_modules(
1184     "MOZ_WEBP", "libwebp >= 1.0.2 libwebpdemux >= 1.0.2", when="--with-system-webp"
1187 set_config("MOZ_SYSTEM_WEBP", depends(when=system_webp)(lambda: True))
1190 # Build Freetype in the tree
1191 # ==============================================================
1192 @depends(target, "--enable-skia-pdf")
1193 def tree_freetype(target, skia_pdf):
1194     if target.os == "Android" or (skia_pdf and target.os == "WINNT"):
1195         return True
1198 set_define("MOZ_TREE_FREETYPE", tree_freetype)
1199 set_config("MOZ_TREE_FREETYPE", tree_freetype)
1201 set_define("HAVE_FT_BITMAP_SIZE_Y_PPEM", tree_freetype)
1202 set_define("HAVE_FT_GLYPHSLOT_EMBOLDEN", tree_freetype)
1203 set_define("HAVE_FT_LOAD_SFNT_TABLE", tree_freetype)
1206 @depends(freetype2_combined_info, tree_freetype, build_environment)
1207 def ft2_info(freetype2_combined_info, tree_freetype, build_env):
1208     if tree_freetype:
1209         return namespace(
1210             cflags=("-I%s/modules/freetype2/include" % build_env.topsrcdir,), libs=()
1211         )
1212     if freetype2_combined_info:
1213         return freetype2_combined_info
1216 set_config("FT2_LIBS", ft2_info.libs)
1219 @depends(target, tree_freetype, freetype2_info)
1220 def enable_cairo_ft(target, tree_freetype, freetype2_info):
1221     # Avoid defining MOZ_ENABLE_CAIRO_FT on Windows platforms because
1222     # "cairo-ft-font.c" includes <dlfcn.h>, which only exists on posix platforms
1223     return freetype2_info or (tree_freetype and target.os != "WINNT")
1226 set_config("MOZ_ENABLE_CAIRO_FT", True, when=enable_cairo_ft)
1227 set_config("CAIRO_FT_CFLAGS", ft2_info.cflags, when=enable_cairo_ft)
1230 # WebDriver (HTTP / BiDi)
1231 # ==============================================================
1233 # WebDriver is a remote control interface that enables introspection and
1234 # control of user agents. It provides a platform- and language-neutral wire
1235 # protocol as a way for out-of-process programs to remotely instruct the
1236 # behavior of web browsers.
1238 # The Gecko implementation is backed by Marionette and Remote Agent.
1239 # Both protocols are not really toolkit features, as much as Gecko engine
1240 # features. But they are enabled based on the toolkit, so here it lives.
1242 # Marionette remote protocol
1243 # -----------------------------------------------------------
1245 # Marionette is the Gecko remote protocol used for various remote control,
1246 # automation, and testing purposes throughout Gecko-based applications like
1247 # Firefox, Thunderbird, and any mobile browser built upon GeckoView.
1249 # It also backs ../testing/geckodriver, which is Mozilla's WebDriver
1250 # implementation.
1252 # The source of Marionette lives in ../remote/marionette.
1254 # For more information, see:
1255 # https://firefox-source-docs.mozilla.org/testing/marionette/index.html
1257 # Remote Agent (WebDriver BiDi / partial CDP)
1258 # -----------------------------------------------------------
1260 # The primary purpose is the implementation of the WebDriver BiDi specification.
1261 # But it also complements the existing Firefox Developer Tools Remote Debugging
1262 # Protocol (RDP) by implementing a subset of the Chrome DevTools Protocol (CDP).
1264 # The source of Remote Agent lives in ../remote.
1266 # For more information, see:
1267 # https://firefox-source-docs.mozilla.org/remote/index.html
1270 option(
1271     "--disable-webdriver",
1272     help="Disable support for WebDriver remote protocols",
1276 @depends("--disable-webdriver")
1277 def webdriver(enabled):
1278     if enabled:
1279         return True
1282 set_config("ENABLE_WEBDRIVER", webdriver)
1283 set_define("ENABLE_WEBDRIVER", webdriver)
1286 # geckodriver WebDriver implementation
1287 # ==============================================================
1289 # Turn off geckodriver for build configs we don't handle yet,
1290 # but allow --enable-geckodriver to override when compile environment is available.
1291 # --disable-tests implies disabling geckodriver.
1292 # Disable building in CI
1295 @depends(
1296     "--enable-tests", target, cross_compiling, hazard_analysis, asan, "MOZ_AUTOMATION"
1298 def geckodriver_default(enable_tests, target, cross_compile, hazard, asan, automation):
1299     if not enable_tests:
1300         return False
1301     if hazard or target.os == "Android" or (asan and cross_compile):
1302         return False
1303     if automation:
1304         return False
1305     return True
1308 option(
1309     "--enable-geckodriver",
1310     default=geckodriver_default,
1311     when="--enable-compile-environment",
1312     help="{Build|Do not build} geckodriver",
1316 @depends("--enable-geckodriver", when="--enable-compile-environment")
1317 def geckodriver(enabled):
1318     if enabled:
1319         return True
1322 set_config("MOZ_GECKODRIVER", geckodriver)
1325 # WebRTC
1326 # ========================================================
1327 @depends(target)
1328 def webrtc_default(target):
1329     # Turn off webrtc for OS's we don't handle yet, but allow
1330     # --enable-webrtc to override.
1331     os_match = target.kernel in (
1332         "Linux",
1333         "WINNT",
1334         "DragonFly",
1335         "FreeBSD",
1336         "kFreeBSD",
1337         "NetBSD",
1338         "OpenBSD",
1339     )
1341     if not os_match:
1342         os_match = target.os in ("OSX",)
1344     cpu_match = target.cpu in (
1345         "x86_64",
1346         "arm",
1347         "aarch64",
1348         "x86",
1349         "ia64",
1350         "mips32",
1351         "mips64",
1352         "ppc",
1353         "ppc64",
1354         "riscv64",
1355     )
1357     return os_match and cpu_match and target.endianness == "little"
1360 option(
1361     "--disable-webrtc",
1362     default=webrtc_default,
1363     help="{Enable|Disable} support for WebRTC",
1367 @depends("--disable-webrtc")
1368 def webrtc(enabled):
1369     if enabled:
1370         return True
1373 set_config("MOZ_WEBRTC", webrtc)
1374 set_define("MOZ_WEBRTC", webrtc)
1375 set_config("MOZ_SCTP", webrtc)
1376 set_define("MOZ_SCTP", webrtc)
1377 set_config("MOZ_SRTP", webrtc)
1378 set_define("MOZ_SRTP", webrtc)
1379 set_config("MOZ_WEBRTC_SIGNALING", webrtc)
1380 set_define("MOZ_WEBRTC_SIGNALING", webrtc)
1381 set_config("MOZ_PEERCONNECTION", webrtc)
1382 set_define("MOZ_PEERCONNECTION", webrtc)
1383 # MOZ_WEBRTC_ASSERT_ALWAYS turns on a number of safety asserts in
1384 # opt/production builds (via MOZ_CRASH())
1385 set_config("MOZ_WEBRTC_ASSERT_ALWAYS", webrtc)
1386 set_define("MOZ_WEBRTC_ASSERT_ALWAYS", webrtc)
1388 # RAW media
1389 # ==============================================================
1392 @depends(target, webrtc)
1393 def raw_media_default(target, webrtc):
1394     if target.os == "Android":
1395         return True
1396     if webrtc:
1397         return True
1400 option(
1401     "--enable-raw",
1402     default=raw_media_default,
1403     help="{Enable|Disable} support for RAW media",
1406 set_config("MOZ_RAW", depends_if("--enable-raw")(lambda _: True))
1407 set_define("MOZ_RAW", depends_if("--enable-raw")(lambda _: True))
1410 # X11
1411 # ==============================================================
1412 @depends(webrtc, when=toolkit_gtk)
1413 def x11_libs(webrtc):
1414     libs = [
1415         "x11",
1416         "xcb",
1417         "xcb-shm",
1418         "x11-xcb",
1419         "xext",
1420         "xrandr >= 1.4.0",
1421     ]
1422     if webrtc:
1423         # third_party/libwebrtc/webrtc/webrtc_gn/moz.build adds those
1424         # manually, ensure they're available.
1425         libs += [
1426             "xcomposite",
1427             "xcursor",
1428             "xdamage",
1429             "xfixes",
1430             "xi",
1431         ]
1432     return libs
1435 x11_headers = pkg_check_modules(
1436     "MOZ_X11",
1437     x11_libs,
1438     allow_missing=toolkit_gtk_x11_optional,
1439     when=toolkit_gtk_x11,
1443 set_config("MOZ_X11", True, when=x11_headers)
1444 set_define("MOZ_X11", True, when=x11_headers)
1446 pkg_check_modules(
1447     "MOZ_X11_SM",
1448     ["ice", "sm"],
1449     cflags_only=True,
1450     allow_missing=toolkit_gtk_x11_optional,
1451     when=toolkit_gtk_x11,
1455 # ASan Reporter Addon
1456 # ==============================================================
1457 option(
1458     "--enable-address-sanitizer-reporter",
1459     help="Enable Address Sanitizer Reporter Extension",
1463 @depends("--enable-address-sanitizer-reporter")
1464 def enable_asan_reporter(value):
1465     if value:
1466         return True
1469 set_config("MOZ_ASAN_REPORTER", enable_asan_reporter)
1470 set_define("MOZ_ASAN_REPORTER", enable_asan_reporter)
1472 # Checks for library functions
1473 # ==============================================================
1474 with only_when(compile_environment & depends(target.os)(lambda os: os != "WINNT")):
1475     set_define("HAVE_STAT64", check_symbol("stat64"))
1476     set_define("HAVE_LSTAT64", check_symbol("lstat64"))
1477     set_define("HAVE_TRUNCATE64", check_symbol("truncate64"))
1478     set_define("HAVE_STATVFS64", check_symbol("statvfs64"))
1479     set_define("HAVE_STATVFS", check_symbol("statvfs"))
1480     set_define("HAVE_STATFS64", check_symbol("statfs64"))
1481     set_define("HAVE_STATFS", check_symbol("statfs"))
1482     set_define("HAVE_LUTIMES", check_symbol("lutimes"))
1483     set_define("HAVE_POSIX_FADVISE", check_symbol("posix_fadvise"))
1484     set_define("HAVE_POSIX_FALLOCATE", check_symbol("posix_fallocate"))
1485     set_define("HAVE_EVENTFD", check_symbol("eventfd"))
1487     have_arc4random = check_symbol("arc4random")
1488     set_define("HAVE_ARC4RANDOM", have_arc4random)
1489     set_define("HAVE_ARC4RANDOM_BUF", check_symbol("arc4random_buf"))
1490     set_define("HAVE_MALLINFO", check_symbol("mallinfo"))
1492 # Checks for headers
1493 # ==============================================================
1494 with only_when(compile_environment & depends(target.os)(lambda os: os != "WINNT")):
1495     set_define("HAVE_SYSIOCCOM_H", check_header("sys/ioccom.h"))
1497 # Elfhack
1498 # ==============================================================
1499 with only_when("--enable-compile-environment"):
1501     @depends(host, target)
1502     def has_elfhack(host, target):
1503         return (
1504             target.kernel == "Linux"
1505             and host.kernel == "Linux"
1506             and target.cpu in ("arm", "aarch64", "x86", "x86_64")
1507         )
1509     option(
1510         "--disable-elf-hack",
1511         nargs="?",
1512         choices=("legacy", "relr"),
1513         help="{Enable|Disable} elf hacks",
1514         when=has_elfhack,
1515     )
1517     @depends("--enable-elf-hack", when=has_elfhack)
1518     def may_enable_legacy_elfhack(enable):
1519         if enable and enable != ("relr",):
1520             return enable
1522     @depends("--enable-elf-hack", when=has_elfhack)
1523     def may_enable_relrhack(enable):
1524         if enable and enable != ("legacy",):
1525             return enable
1527     @depends(
1528         have_arc4random,
1529         android_version,
1530         when=target_has_linux_kernel,
1531     )
1532     def may_use_pack_relative_relocs(have_arc4random, android_version):
1533         # Packed relative relocations are only supported on Android since
1534         # version 11 (API 30), and in glibc since version 2.36.
1535         # glibc 2.36 also added the arc4random function, which is our proxy
1536         # to detect this (or newer) version being used.
1537         # When targetting those newer versions, we allow ourselves to use
1538         # packed relative relocations rather than elfhack.
1539         if android_version:
1540             return android_version >= 30
1541         return have_arc4random
1543     @depends(
1544         c_compiler,
1545         extra_toolchain_flags,
1546         linker_ldflags,
1547         readelf,
1548         when=may_use_pack_relative_relocs | may_enable_relrhack,
1549     )
1550     @checking("for -z pack-relative-relocs option to ld", bool)
1551     @imports(_from="__builtin__", _import="FileNotFoundError")
1552     @imports("os")
1553     @imports(_from="tempfile", _import="mkstemp")
1554     @imports("textwrap")
1555     def has_pack_relative_relocs(
1556         c_compiler,
1557         extra_toolchain_flags,
1558         linker_ldflags,
1559         readelf,
1560     ):
1561         try:
1562             fd, path = mkstemp(prefix="conftest.")
1563             os.close(fd)
1565             pack_rel_relocs = ["-Wl,-z,pack-relative-relocs"]
1566             if (
1567                 try_invoke_compiler(
1568                     # No configure_cache because it would not create the
1569                     # expected output file.
1570                     None,
1571                     [c_compiler.compiler] + c_compiler.flags,
1572                     c_compiler.language,
1573                     # The resulting binary is expected to have relative
1574                     # relocations, the `ptr` variable attempts to ensure
1575                     # there is at least one. This requires the executable
1576                     # being built as position independent.
1577                     "int main() { return 0; }\nint (*ptr)() = main;",
1578                     pack_rel_relocs
1579                     + ["-pie", "-o", path]
1580                     + (extra_toolchain_flags or [])
1581                     + linker_ldflags,
1582                     wrapper=c_compiler.wrapper,
1583                     onerror=lambda: None,
1584                 )
1585                 is not None
1586             ):
1587                 # BFD ld ignores options it doesn't understand. So check
1588                 # that we did get packed relative relocations (DT_RELR).
1589                 env = os.environ.copy()
1590                 env["LANG"] = "C"
1591                 dyn = check_cmd_output(readelf, "-d", path, env=env).splitlines()
1592                 tags = [
1593                     int(l.split()[0], 16) for l in dyn if l.strip().startswith("0x")
1594                 ]
1595                 # Older versions of readelf don't know about DT_RELR but will
1596                 # still display the tag number.
1597                 if 0x23 in tags:
1598                     needed = [l for l in dyn if l.split()[1:2] == ["(NEEDED)"]]
1599                     is_glibc = any(l.endswith("[libc.so.6]") for l in needed)
1600                     # The mold linker doesn't add a GLIBC_ABI_DT_RELR version
1601                     # dependency, which ld.so doesn't like.
1602                     # https://github.com/rui314/mold/issues/653#issuecomment-1670274638
1603                     if is_glibc:
1604                         versions = check_cmd_output(readelf, "-V", path, env=env)
1605                         if "GLIBC_ABI_DT_RELR" in versions.split():
1606                             return pack_rel_relocs
1607                     else:
1608                         return pack_rel_relocs
1609         finally:
1610             try:
1611                 os.remove(path)
1612             except FileNotFoundError:
1613                 pass
1615     @depends(
1616         has_pack_relative_relocs,
1617         may_enable_legacy_elfhack,
1618         may_enable_relrhack,
1619         may_use_pack_relative_relocs,
1620         when=has_pack_relative_relocs,
1621     )
1622     def pack_relative_relocs_flags(
1623         flags,
1624         may_enable_legacy_elfhack,
1625         may_enable_relrhack,
1626         may_use_pack_relative_relocs,
1627     ):
1628         # When relrhack is enabled, we don't pass the flag to the linker because
1629         # relrhack will take care of it.
1630         if may_enable_relrhack and may_enable_relrhack.origin != "default":
1631             return None
1632         # if elfhack is explicitly enabled instead of relrhack, we prioritize it
1633         # over packed relative relocs.
1634         if may_enable_legacy_elfhack and may_enable_legacy_elfhack.origin != "default":
1635             return None
1636         if may_use_pack_relative_relocs:
1637             return flags
1639     add_old_configure_assignment("PACK_REL_RELOC_FLAGS", pack_relative_relocs_flags)
1641     @depends(
1642         select_linker,
1643         pack_relative_relocs_flags,
1644         has_pack_relative_relocs,
1645         may_enable_legacy_elfhack,
1646         may_enable_relrhack,
1647         when=has_elfhack,
1648     )
1649     def which_elf_hack(
1650         linker,
1651         pack_relative_relocs_flags,
1652         has_pack_relative_relocs,
1653         may_enable_legacy_elfhack,
1654         may_enable_relrhack,
1655     ):
1656         if pack_relative_relocs_flags:
1657             return
1658         if may_enable_relrhack:
1659             if has_pack_relative_relocs:
1660                 return "relr"
1661             elif (
1662                 may_enable_relrhack.origin != "default"
1663                 and not may_enable_legacy_elfhack
1664             ):
1665                 die(
1666                     "Cannot enable relrhack without linker support for -z pack-relative-relocs"
1667                 )
1668         if may_enable_legacy_elfhack:
1669             if linker and linker.KIND in ("lld", "mold"):
1670                 if may_enable_legacy_elfhack.origin != "default":
1671                     die(
1672                         f"Cannot enable elfhack with {linker.KIND}."
1673                         " Use --enable-linker=bfd, --enable-linker=gold, or --disable-elf-hack"
1674                     )
1675             else:
1676                 return "legacy"
1678     set_config(
1679         "USE_ELF_HACK", True, when=depends(which_elf_hack)(lambda x: x == "legacy")
1680     )
1682     use_relrhack = depends(which_elf_hack)(lambda x: x == "relr")
1683     set_config("RELRHACK", True, when=use_relrhack)
1685     @depends(c_compiler, linker_ldflags, when=use_relrhack)
1686     def relrhack_real_linker(c_compiler, linker_ldflags):
1687         ld = "ld"
1688         for flag in linker_ldflags:
1689             if flag.startswith("-fuse-ld="):
1690                 ld = "ld." + flag[len("-fuse-ld=") :]
1691         ld = check_cmd_output(
1692             c_compiler.compiler, f"--print-prog-name={ld}", *c_compiler.flags
1693         )
1694         return ld.rstrip()
1696     @depends(relrhack_real_linker, when=use_relrhack)
1697     def relrhack_linker(ld):
1698         return os.path.basename(ld)
1700     set_config("RELRHACK_LINKER", relrhack_linker)
1702     std_filesystem = host_cxx_compiler.try_run(
1703         header="#include <filesystem>",
1704         body='auto foo = std::filesystem::absolute("");',
1705         flags=host_linker_ldflags,
1706         when=use_relrhack,
1707         onerror=lambda: None,
1708     )
1710     stdcxxfs = host_cxx_compiler.try_run(
1711         header="#include <filesystem>",
1712         body='auto foo = std::filesystem::absolute("");',
1713         flags=depends(host_linker_ldflags)(
1714             lambda flags: (flags or []) + ["-lstdc++fs"]
1715         ),
1716         check_msg="whether std::filesystem requires -lstdc++fs",
1717         when=use_relrhack & depends(std_filesystem)(lambda x: not x),
1718         onerror=lambda: None,
1719     )
1721     set_config("RELRHACK_LIBS", ["stdc++fs"], when=stdcxxfs)
1723     @depends(build_environment, relrhack_real_linker, when=use_relrhack)
1724     def relrhack_ldflags(build_env, ld):
1725         flags = [
1726             "-B",
1727             os.path.join(build_env.topobjdir, "build", "unix", "elfhack"),
1728         ]
1729         if os.path.basename(ld) != ld:
1730             flags.append(f"-Wl,--real-linker,{ld}")
1731         return flags
1733     set_config("RELRHACK_LDFLAGS", relrhack_ldflags)
1736 @depends(build_environment)
1737 def idl_roots(build_env):
1738     return namespace(
1739         ipdl_root=os.path.join(build_env.topobjdir, "ipc", "ipdl"),
1740         webidl_root=os.path.join(build_env.topobjdir, "dom", "bindings"),
1741         xpcom_root=os.path.join(build_env.topobjdir, "xpcom", "components"),
1742     )
1745 set_config("WEBIDL_ROOT", idl_roots.webidl_root)
1746 set_config("IPDL_ROOT", idl_roots.ipdl_root)
1747 set_config("XPCOM_ROOT", idl_roots.xpcom_root)
1749 # Proxy bypass protection
1750 # ==============================================================
1752 option(
1753     "--enable-proxy-bypass-protection",
1754     help="Prevent suspected or confirmed proxy bypasses",
1758 @depends_if("--enable-proxy-bypass-protection")
1759 def proxy_bypass_protection(_):
1760     return True
1763 set_config("MOZ_PROXY_BYPASS_PROTECTION", proxy_bypass_protection)
1764 set_define("MOZ_PROXY_BYPASS_PROTECTION", proxy_bypass_protection)
1766 # Proxy direct failover
1767 # ==============================================================
1769 option(
1770     "--disable-proxy-direct-failover",
1771     help="Disable direct failover for system requests",
1775 @depends_if("--disable-proxy-direct-failover")
1776 def proxy_direct_failover(value):
1777     if value:
1778         return True
1781 set_config("MOZ_PROXY_DIRECT_FAILOVER", proxy_direct_failover)
1782 set_define("MOZ_PROXY_DIRECT_FAILOVER", proxy_direct_failover)
1784 # MIDL
1785 # ==============================================================
1788 @depends(c_compiler, toolchain_prefix)
1789 def midl_names(c_compiler, toolchain_prefix):
1790     if c_compiler and c_compiler.type in ["gcc", "clang"]:
1791         # mingw
1792         widl = ("widl",)
1793         if toolchain_prefix:
1794             prefixed = tuple("%s%s" % (p, "widl") for p in toolchain_prefix)
1795             widl = prefixed + widl
1796         return widl
1798     return ("midl.exe",)
1801 @depends(target, "--enable-compile-environment")
1802 def check_for_midl(target, compile_environment):
1803     if target.os != "WINNT":
1804         return
1806     if compile_environment:
1807         return True
1810 midl = check_prog(
1811     "MIDL",
1812     midl_names,
1813     when=check_for_midl,
1814     allow_missing=True,
1815     paths=sdk_bin_path,
1816     # MIDL being used from a python wrapper script, we can live with it
1817     # having spaces.
1818     allow_spaces=True,
1821 option(env="MIDL_FLAGS", nargs=1, help="Extra flags to pass to MIDL")
1824 @depends(
1825     "MIDL_FLAGS",
1826     target,
1827     midl,
1828     when=depends(midl, target)(lambda m, t: m and t.kernel == "WINNT"),
1830 def midl_flags(flags, target, midl):
1831     if flags:
1832         flags = flags[0].split()
1833     else:
1834         flags = []
1836     if not midl.endswith("widl"):
1837         env = {
1838             "x86": "win32",
1839             "x86_64": "x64",
1840             "aarch64": "arm64",
1841         }[target.cpu]
1842         return flags + ["-nologo", "-no_cpp", "-env", env]
1844     # widl
1845     return (
1846         flags
1847         + {
1848             "x86": ["--win32", "-m32"],
1849             "x86_64": ["--win64", "-m64"],
1850         }[target.cpu]
1851     )
1854 set_config("MIDL_FLAGS", midl_flags)
1856 # Accessibility
1857 # ==============================================================
1859 option("--disable-accessibility", help="Disable accessibility support")
1862 @depends("--enable-accessibility", check_for_midl, midl, c_compiler)
1863 def accessibility(value, check_for_midl, midl, c_compiler):
1864     enabled = bool(value)
1866     if not enabled:
1867         return
1869     if check_for_midl and not midl:
1870         if c_compiler and c_compiler.type in ("gcc", "clang"):
1871             die(
1872                 "You have accessibility enabled, but widl could not be found. "
1873                 "Add --disable-accessibility to your mozconfig or install widl. "
1874                 "See https://developer.mozilla.org/en-US/docs/Cross_Compile_Mozilla_for_Mingw32 for details."
1875             )
1876         else:
1877             die(
1878                 "MIDL could not be found. "
1879                 "Building accessibility without MIDL is not supported."
1880             )
1882     return enabled
1885 set_config("ACCESSIBILITY", accessibility)
1886 set_define("ACCESSIBILITY", accessibility)
1889 @depends(moz_debug, developer_options)
1890 def a11y_log(debug, developer_options):
1891     return debug or developer_options
1894 set_config("A11Y_LOG", True, when=a11y_log)
1895 set_define("A11Y_LOG", True, when=a11y_log)
1898 # Addon signing
1899 # ==============================================================
1900 @depends(milestone)
1901 def require_signing(milestone):
1902     return milestone.is_release_or_beta and not milestone.is_esr
1905 option(
1906     env="MOZ_REQUIRE_SIGNING",
1907     default=require_signing,
1908     help="Enforce that add-ons are signed by the trusted root",
1911 set_config("MOZ_REQUIRE_SIGNING", True, when="MOZ_REQUIRE_SIGNING")
1912 set_define("MOZ_REQUIRE_SIGNING", True, when="MOZ_REQUIRE_SIGNING")
1914 option(
1915     "--with-unsigned-addon-scopes",
1916     nargs="+",
1917     choices=("app", "system"),
1918     help="Addon scopes where signature is not required",
1922 @depends("--with-unsigned-addon-scopes")
1923 def unsigned_addon_scopes(scopes):
1924     return namespace(
1925         app="app" in scopes or None,
1926         system="system" in scopes or None,
1927     )
1930 set_config("MOZ_UNSIGNED_APP_SCOPE", unsigned_addon_scopes.app)
1931 set_config("MOZ_UNSIGNED_SYSTEM_SCOPE", unsigned_addon_scopes.system)
1934 # Addon sideloading
1935 # ==============================================================
1936 option(
1937     "--allow-addon-sideload",
1938     default=milestone.is_esr,
1939     help="Addon sideloading is allowed",
1943 set_config("MOZ_ALLOW_ADDON_SIDELOAD", True, when="--allow-addon-sideload")
1945 # WebExtensions API WebIDL bindings
1946 # ==============================================================
1949 @depends(milestone)
1950 def extensions_webidl_bindings_default(milestone):
1951     # Only enable the webidl bindings for the WebExtensions APIs
1952     # in Nightly.
1953     return milestone.is_nightly
1956 option(
1957     "--enable-extensions-webidl-bindings",
1958     default=extensions_webidl_bindings_default,
1959     help="{Enable|Disable} building experimental WebExtensions WebIDL bindings",
1963 @depends("--enable-extensions-webidl-bindings")
1964 def extensions_webidl_enabled(value):
1965     return bool(value)
1968 set_config("MOZ_WEBEXT_WEBIDL_ENABLED", extensions_webidl_enabled)
1970 # Launcher process (Windows only)
1971 # ==============================================================
1974 @depends(target)
1975 def launcher_process_default(target):
1976     return target.os == "WINNT"
1979 option(
1980     "--enable-launcher-process",
1981     default=launcher_process_default,
1982     help="{Enable|Disable} launcher process by default",
1986 @depends("--enable-launcher-process", target)
1987 def launcher(value, target):
1988     enabled = bool(value)
1989     if enabled and target.os != "WINNT":
1990         die("Cannot enable launcher process on %s", target.os)
1991     if enabled:
1992         return True
1995 set_config("MOZ_LAUNCHER_PROCESS", launcher)
1996 set_define("MOZ_LAUNCHER_PROCESS", launcher)
1998 # llvm-dlltool (Windows only)
1999 # ==============================================================
2002 @depends(build_project, target, "--enable-compile-environment")
2003 def check_for_llvm_dlltool(build_project, target, compile_environment):
2004     if build_project != "browser":
2005         return
2007     if target.os != "WINNT":
2008         return
2010     return compile_environment
2013 llvm_dlltool = check_prog(
2014     "LLVM_DLLTOOL",
2015     ("llvm-dlltool",),
2016     what="llvm-dlltool",
2017     when=check_for_llvm_dlltool,
2018     paths=clang_search_path,
2022 @depends(target, when=llvm_dlltool)
2023 def llvm_dlltool_flags(target):
2024     arch = {
2025         "x86": "i386",
2026         "x86_64": "i386:x86-64",
2027         "aarch64": "arm64",
2028     }[target.cpu]
2030     return ["-m", arch]
2033 set_config("LLVM_DLLTOOL_FLAGS", llvm_dlltool_flags)
2035 # BITS download (Windows only)
2036 # ==============================================================
2038 option(
2039     "--enable-bits-download",
2040     when=target_is_windows,
2041     default=target_is_windows,
2042     help="{Enable|Disable} building BITS download support",
2045 set_define(
2046     "MOZ_BITS_DOWNLOAD",
2047     depends_if("--enable-bits-download", when=target_is_windows)(lambda _: True),
2049 set_config(
2050     "MOZ_BITS_DOWNLOAD",
2051     depends_if("--enable-bits-download", when=target_is_windows)(lambda _: True),
2054 # Bundled fonts on desktop platform
2055 # ==============================================================
2058 @depends(target)
2059 def bundled_fonts_default(target):
2060     return target.os == "WINNT" or target.kernel == "Linux"
2063 @depends(build_project)
2064 def allow_bundled_fonts(project):
2065     return project == "browser" or project == "comm/mail"
2068 option(
2069     "--enable-bundled-fonts",
2070     default=bundled_fonts_default,
2071     when=allow_bundled_fonts,
2072     help="{Enable|Disable} support for bundled fonts on desktop platforms",
2075 set_define(
2076     "MOZ_BUNDLED_FONTS",
2077     depends_if("--enable-bundled-fonts", when=allow_bundled_fonts)(lambda _: True),
2080 # Reflow counting
2081 # ==============================================================
2084 @depends(moz_debug)
2085 def reflow_perf(debug):
2086     if debug:
2087         return True
2090 option(
2091     "--enable-reflow-perf",
2092     default=reflow_perf,
2093     help="{Enable|Disable} reflow performance tracing",
2096 # The difference in conditions here comes from the initial implementation
2097 # in old-configure, which was unexplained there as well.
2098 set_define("MOZ_REFLOW_PERF", depends_if("--enable-reflow-perf")(lambda _: True))
2099 set_define("MOZ_REFLOW_PERF_DSP", reflow_perf)
2101 # Layout debugger
2102 # ==============================================================
2105 @depends(moz_debug)
2106 def layout_debugger(debug):
2107     if debug:
2108         return True
2111 option(
2112     "--enable-layout-debugger",
2113     default=layout_debugger,
2114     help="{Enable|Disable} layout debugger",
2117 set_config("MOZ_LAYOUT_DEBUGGER", True, when="--enable-layout-debugger")
2118 set_define("MOZ_LAYOUT_DEBUGGER", True, when="--enable-layout-debugger")
2121 # Shader Compiler for Windows (and MinGW Cross Compile)
2122 # ==============================================================
2124 with only_when(compile_environment):
2125     fxc = check_prog(
2126         "FXC",
2127         ("fxc.exe", "fxc2.exe"),
2128         when=depends(target)(lambda t: t.kernel == "WINNT"),
2129         paths=sdk_bin_path,
2130         # FXC being used from a python wrapper script, we can live with it
2131         # having spaces.
2132         allow_spaces=True,
2133     )
2136 # VPX
2137 # ===
2139 with only_when(compile_environment):
2140     system_lib_option(
2141         "--with-system-libvpx", help="Use system libvpx (located with pkgconfig)"
2142     )
2144     with only_when("--with-system-libvpx"):
2145         vpx = pkg_check_modules("MOZ_LIBVPX", "vpx >= 1.10.0")
2147         check_header(
2148             "vpx/vpx_decoder.h",
2149             flags=vpx.cflags,
2150             onerror=lambda: die(
2151                 "Couldn't find vpx/vpx_decoder.h, which is required to build "
2152                 "with system libvpx. Use --without-system-libvpx to build "
2153                 "with in-tree libvpx."
2154             ),
2155         )
2157         check_symbol(
2158             "vpx_codec_dec_init_ver",
2159             flags=vpx.libs,
2160             onerror=lambda: die(
2161                 "--with-system-libvpx requested but symbol vpx_codec_dec_init_ver "
2162                 "not found"
2163             ),
2164         )
2166         set_config("MOZ_SYSTEM_LIBVPX", True)
2168     @depends("--with-system-libvpx", target)
2169     def in_tree_vpx(system_libvpx, target):
2170         if system_libvpx:
2171             return
2173         arm_asm = (target.cpu == "arm") or None
2174         return namespace(arm_asm=arm_asm)
2176     @depends(target, when=in_tree_vpx)
2177     def vpx_nasm(target):
2178         if target.cpu in ("x86", "x86_64"):
2179             if target.kernel == "WINNT":
2180                 # Version 2.03 is needed for automatic safeseh support.
2181                 return namespace(version="2.03", what="VPX")
2182             return namespace(what="VPX")
2184     @depends(in_tree_vpx, vpx_nasm, target, neon_flags)
2185     def vpx_as_flags(vpx, vpx_nasm, target, neon_flags):
2186         if vpx and vpx.arm_asm:
2187             # These flags are a lie; they're just used to enable the requisite
2188             # opcodes; actual arch detection is done at runtime.
2189             return neon_flags
2190         elif vpx and vpx_nasm and target.os != "WINNT" and target.cpu != "x86_64":
2191             return ("-DPIC",)
2193     set_config("VPX_USE_NASM", True, when=vpx_nasm)
2194     set_config("VPX_ASFLAGS", vpx_as_flags)
2197 # JPEG
2198 # ====
2200 with only_when(compile_environment):
2201     system_lib_option(
2202         "--with-system-jpeg",
2203         nargs="?",
2204         help="Use system libjpeg (installed at given prefix)",
2205     )
2207     @depends_if("--with-system-jpeg")
2208     def jpeg_flags(value):
2209         if len(value):
2210             return namespace(
2211                 cflags=("-I%s/include" % value[0],),
2212                 ldflags=("-L%s/lib" % value[0], "-ljpeg"),
2213             )
2214         return namespace(
2215             ldflags=("-ljpeg",),
2216         )
2218     with only_when("--with-system-jpeg"):
2219         check_symbol(
2220             "jpeg_destroy_compress",
2221             flags=jpeg_flags.ldflags,
2222             onerror=lambda: die(
2223                 "--with-system-jpeg requested but symbol "
2224                 "jpeg_destroy_compress not found."
2225             ),
2226         )
2228         c_compiler.try_compile(
2229             includes=[
2230                 "stdio.h",
2231                 "sys/types.h",
2232                 "jpeglib.h",
2233             ],
2234             body="""
2235                 #if JPEG_LIB_VERSION < 62
2236                 #error Insufficient JPEG library version
2237                 #endif
2238             """,
2239             flags=jpeg_flags.cflags,
2240             check_msg="for sufficient jpeg library version",
2241             onerror=lambda: die(
2242                 "Insufficient JPEG library version for "
2243                 "--with-system-jpeg (62 required)"
2244             ),
2245         )
2247         c_compiler.try_compile(
2248             includes=[
2249                 "stdio.h",
2250                 "sys/types.h",
2251                 "jpeglib.h",
2252             ],
2253             body="""
2254                 #ifndef JCS_EXTENSIONS
2255                 #error libjpeg-turbo JCS_EXTENSIONS required
2256                 #endif
2257             """,
2258             flags=jpeg_flags.cflags,
2259             check_msg="for sufficient libjpeg-turbo JCS_EXTENSIONS",
2260             onerror=lambda: die(
2261                 "libjpeg-turbo JCS_EXTENSIONS required for " "--with-system-jpeg"
2262             ),
2263         )
2265         set_config("MOZ_JPEG_CFLAGS", jpeg_flags.cflags)
2266         set_config("MOZ_JPEG_LIBS", jpeg_flags.ldflags)
2268     @depends("--with-system-jpeg", target, neon_flags)
2269     def in_tree_jpeg_arm(system_jpeg, target, neon_flags):
2270         if system_jpeg:
2271             return
2273         if target.cpu == "arm":
2274             return neon_flags
2275         elif target.cpu == "aarch64":
2276             return ("-march=armv8-a",)
2278     @depends("--with-system-jpeg", target)
2279     def in_tree_jpeg_mips64(system_jpeg, target):
2280         if system_jpeg:
2281             return
2283         if target.cpu == "mips64":
2284             return ("-Wa,-mloongson-mmi", "-mloongson-ext")
2286     # Compiler check from https://github.com/libjpeg-turbo/libjpeg-turbo/blob/57ba02a408a9a55ccff25aae8b164632a3a4f177/simd/CMakeLists.txt#L419
2287     jpeg_mips64_mmi = c_compiler.try_compile(
2288         body='int c = 0, a = 0, b = 0; asm("paddb %0, %1, %2" : "=f" (c) : "f" (a), "f" (b));',
2289         check_msg="for loongson mmi support",
2290         flags=in_tree_jpeg_mips64,
2291         when=in_tree_jpeg_mips64,
2292     )
2294     @depends(
2295         "--with-system-jpeg",
2296         target,
2297         in_tree_jpeg_arm,
2298         in_tree_jpeg_mips64,
2299         jpeg_mips64_mmi,
2300     )
2301     def in_tree_jpeg(
2302         system_jpeg, target, in_tree_jpeg_arm, in_tree_jpeg_mips64, jpeg_mips64_mmi
2303     ):
2304         if system_jpeg:
2305             return
2307         if target.cpu in ("arm", "aarch64"):
2308             return in_tree_jpeg_arm
2309         elif target.kernel == "Darwin":
2310             if target.cpu == "x86":
2311                 return ("-DPIC", "-DMACHO")
2312             elif target.cpu == "x86_64":
2313                 return ("-D__x86_64__", "-DPIC", "-DMACHO")
2314         elif target.kernel == "WINNT":
2315             if target.cpu == "x86":
2316                 return ("-DPIC", "-DWIN32")
2317             elif target.cpu == "x86_64":
2318                 return ("-D__x86_64__", "-DPIC", "-DWIN64", "-DMSVC")
2319         elif target.cpu == "mips32":
2320             return ("-mdspr2",)
2321         elif target.cpu == "mips64" and jpeg_mips64_mmi:
2322             return in_tree_jpeg_mips64
2323         elif target.cpu == "x86":
2324             return ("-DPIC", "-DELF")
2325         elif target.cpu == "x86_64":
2326             return ("-D__x86_64__", "-DPIC", "-DELF")
2328     @depends(target, when=depends("--with-system-jpeg")(lambda x: not x))
2329     def jpeg_nasm(target):
2330         if target.cpu in ("x86", "x86_64"):
2331             # libjpeg-turbo 2.0.6 requires nasm 2.10.
2332             return namespace(version="2.10", what="JPEG")
2334     # Compiler checks from https://github.com/libjpeg-turbo/libjpeg-turbo/blob/57ba02a408a9a55ccff25aae8b164632a3a4f177/simd/CMakeLists.txt#L258
2335     jpeg_arm_neon_vld1_s16_x3 = c_compiler.try_compile(
2336         includes=["arm_neon.h"],
2337         body="int16_t input[12] = {}; int16x4x3_t output = vld1_s16_x3(input);",
2338         check_msg="for vld1_s16_x3 in arm_neon.h",
2339         flags=in_tree_jpeg_arm,
2340         when=in_tree_jpeg_arm,
2341     )
2343     jpeg_arm_neon_vld1_u16_x2 = c_compiler.try_compile(
2344         includes=["arm_neon.h"],
2345         body="uint16_t input[8] = {}; uint16x4x2_t output = vld1_u16_x2(input);",
2346         check_msg="for vld1_u16_x2 in arm_neon.h",
2347         flags=in_tree_jpeg_arm,
2348         when=in_tree_jpeg_arm,
2349     )
2351     jpeg_arm_neon_vld1q_u8_x4 = c_compiler.try_compile(
2352         includes=["arm_neon.h"],
2353         body="uint8_t input[64] = {}; uint8x16x4_t output = vld1q_u8_x4(input);",
2354         check_msg="for vld1q_u8_x4 in arm_neon.h",
2355         flags=in_tree_jpeg_arm,
2356         when=in_tree_jpeg_arm,
2357     )
2359     set_config("LIBJPEG_TURBO_USE_NASM", True, when=jpeg_nasm)
2360     set_config("LIBJPEG_TURBO_SIMD_FLAGS", in_tree_jpeg)
2361     set_config("LIBJPEG_TURBO_HAVE_VLD1_S16_X3", jpeg_arm_neon_vld1_s16_x3)
2362     set_config("LIBJPEG_TURBO_HAVE_VLD1_U16_X2", jpeg_arm_neon_vld1_u16_x2)
2363     set_config("LIBJPEG_TURBO_HAVE_VLD1Q_U8_X4", jpeg_arm_neon_vld1q_u8_x4)
2364     set_config(
2365         "LIBJPEG_TURBO_NEON_INTRINSICS",
2366         jpeg_arm_neon_vld1_s16_x3
2367         & jpeg_arm_neon_vld1_u16_x2
2368         & jpeg_arm_neon_vld1q_u8_x4,
2369     )
2372 # PNG
2373 # ===
2374 with only_when(compile_environment):
2375     system_lib_option(
2376         "--with-system-png",
2377         nargs="?",
2378         help="Use system libpng",
2379     )
2381     @depends("--with-system-png")
2382     def deprecated_system_png_path(value):
2383         if len(value) == 1:
2384             die(
2385                 "--with-system-png=PATH is not supported anymore. Please use "
2386                 "--with-system-png and set any necessary pkg-config environment variable."
2387             )
2389     png = pkg_check_modules("MOZ_PNG", "libpng >= 1.6.35", when="--with-system-png")
2391     check_symbol(
2392         "png_get_acTL",
2393         flags=png.libs,
2394         onerror=lambda: die(
2395             "--with-system-png won't work because the system's libpng doesn't have APNG support"
2396         ),
2397         when="--with-system-png",
2398     )
2400     set_config("MOZ_SYSTEM_PNG", True, when="--with-system-png")
2403 # FFmpeg's ffvpx configuration
2404 # ==============================================================
2407 @depends(target)
2408 def ffvpx(target):
2409     use_nasm = True
2410     audio_only = False
2411     flags = []
2413     # This enables audio and video codecs paths on Windows  x86 and x86_64,
2414     # macOS (all arch), and Linux x86_64. On other arch / OS combinations,
2415     # only audio codecs are enabled.
2416     if target.kernel == "WINNT":
2417         if target.cpu == "x86":
2418             # 32-bit windows need to prefix symbols with an underscore.
2419             flags = ["-DPIC", "-DWIN32", "-DPREFIX", "-Pconfig_win32.asm"]
2420         elif target.cpu == "x86_64":
2421             flags = [
2422                 "-D__x86_64__",
2423                 "-DPIC",
2424                 "-DWIN64",
2425                 "-DMSVC",
2426                 "-Pconfig_win64.asm",
2427             ]
2428         elif target.cpu == "aarch64":
2429             flags = ["-DPIC", "-DWIN64"]
2430             use_nasm = False
2431     elif target.kernel == "Darwin":
2432         # 32/64-bit macosx assemblers need to prefix symbols with an
2433         # underscore.
2434         flags = ["-DPIC", "-DMACHO", "-DPREFIX"]
2435         if target.cpu == "x86_64":
2436             flags += [
2437                 "-D__x86_64__",
2438                 "-Pconfig_darwin64.asm",
2439             ]
2440         elif target.cpu == "aarch64":
2441             use_nasm = False
2442     elif target.cpu == "x86_64":
2443         flags = ["-D__x86_64__", "-DPIC", "-DELF", "-Pconfig_unix64.asm"]
2444     else:
2445         audio_only = True
2447     if audio_only:
2448         use_nasm = False
2450     return namespace(
2451         use_nasm=use_nasm,
2452         audio_only=audio_only,
2453         flags=flags,
2454     )
2457 @depends(when=ffvpx.use_nasm)
2458 def ffvpx_nasm():
2459     # nasm 2.10 for AVX-2 support.
2460     return namespace(version="2.10", what="FFVPX")
2463 # ffvpx_nasm can't indirectly depend on vpx_as_flags, because it depends
2464 # on a compiler test, so we have to do a little bit of dance here.
2465 @depends(ffvpx, vpx_as_flags, target)
2466 def ffvpx(ffvpx, vpx_as_flags, target):
2467     if ffvpx and vpx_as_flags and target.cpu in ("arm", "aarch64"):
2468         ffvpx.flags.extend(vpx_as_flags)
2469     return ffvpx
2472 set_config("MOZ_FFVPX_AUDIOONLY", True, when=ffvpx.audio_only)
2473 set_define("MOZ_FFVPX_AUDIOONLY", True, when=ffvpx.audio_only)
2474 set_config("FFVPX_ASFLAGS", ffvpx.flags)
2475 set_config("FFVPX_USE_NASM", True, when=ffvpx.use_nasm)
2478 # nasm detection
2479 # ==============================================================
2480 @depends(dav1d_nasm, vpx_nasm, jpeg_nasm, ffvpx_nasm, when=compile_environment)
2481 def need_nasm(*requirements):
2482     requires = {
2483         x.what: x.version if hasattr(x, "version") else True for x in requirements if x
2484     }
2485     if requires:
2486         items = sorted(requires.keys())
2487         if len(items) > 1:
2488             what = " and ".join((", ".join(items[:-1]), items[-1]))
2489         else:
2490             what = items[0]
2491         versioned = {k: v for (k, v) in requires.items() if v is not True}
2492         return namespace(what=what, versioned=versioned)
2495 nasm = check_prog(
2496     "NASM",
2497     ["nasm"],
2498     allow_missing=True,
2499     bootstrap="nasm",
2500     when=need_nasm,
2504 @depends(nasm, need_nasm.what)
2505 def check_nasm(nasm, what):
2506     if not nasm and what:
2507         die("Nasm is required to build with %s, but it was not found." % what)
2508     return nasm
2511 @depends_if(check_nasm)
2512 @checking("nasm version")
2513 def nasm_version(nasm):
2514     version = (
2515         check_cmd_output(nasm, "-v", onerror=lambda: die("Failed to get nasm version."))
2516         .splitlines()[0]
2517         .split()[2]
2518     )
2519     return Version(version)
2522 @depends(nasm_version, need_nasm.versioned, when=need_nasm.versioned)
2523 def check_nasm_version(nasm_version, versioned):
2524     by_version = sorted(versioned.items(), key=lambda x: x[1])
2525     what, version = by_version[-1]
2526     if nasm_version < version:
2527         die(
2528             "Nasm version %s or greater is required to build with %s." % (version, what)
2529         )
2530     return nasm_version
2533 @depends(target, when=check_nasm_version)
2534 def nasm_asflags(target):
2535     asflags = {
2536         ("Darwin", "x86"): ["-f", "macho32"],
2537         ("Darwin", "x86_64"): ["-f", "macho64"],
2538         ("WINNT", "x86"): ["-f", "win32"],
2539         ("WINNT", "x86_64"): ["-f", "win64"],
2540     }.get((target.kernel, target.cpu), None)
2541     if asflags is None:
2542         # We're assuming every x86 platform we support that's
2543         # not Windows or Mac is ELF.
2544         if target.cpu == "x86":
2545             asflags = ["-f", "elf32"]
2546         elif target.cpu == "x86_64":
2547             asflags = ["-f", "elf64"]
2548     return asflags
2551 set_config("NASM_ASFLAGS", nasm_asflags)
2554 # ANGLE OpenGL->D3D translator for WebGL
2555 # ==============================================================
2557 with only_when(compile_environment & target_is_windows):
2558     set_config("MOZ_ANGLE_RENDERER", True)
2560 # Remoting protocol support
2561 # ==============================================================
2564 @depends(toolkit)
2565 def has_remote(toolkit):
2566     if toolkit in ("gtk", "windows", "cocoa"):
2567         return True
2570 set_config("MOZ_HAS_REMOTE", has_remote)
2571 set_define("MOZ_HAS_REMOTE", has_remote)
2573 # RLBox Library Sandboxing wasm support
2574 # ==============================================================
2577 def wasm_sandboxing_libraries():
2578     return (
2579         "graphite",
2580         "ogg",
2581         "hunspell",
2582         "expat",
2583         "woff2",
2584         "soundtouch",
2585     )
2588 @depends(dependable(wasm_sandboxing_libraries), build_project)
2589 def default_wasm_sandboxing_libraries(libraries, build_project):
2590     if build_project != "tools/rusttests":
2591         non_default_libs = {}
2593         return tuple(l for l in libraries if l not in non_default_libs)
2596 option(
2597     "--with-wasm-sandboxed-libraries",
2598     env="WASM_SANDBOXED_LIBRARIES",
2599     help="{Enable wasm sandboxing for the selected libraries|Disable wasm sandboxing}",
2600     nargs="+",
2601     choices=dependable(wasm_sandboxing_libraries),
2602     default=default_wasm_sandboxing_libraries,
2606 @depends("--with-wasm-sandboxed-libraries")
2607 def requires_wasm_sandboxing(libraries):
2608     if libraries:
2609         return True
2612 set_config("MOZ_USING_WASM_SANDBOXING", requires_wasm_sandboxing)
2613 set_define("MOZ_USING_WASM_SANDBOXING", requires_wasm_sandboxing)
2615 with only_when(requires_wasm_sandboxing & compile_environment):
2616     option(
2617         "--with-wasi-sysroot",
2618         env="WASI_SYSROOT",
2619         nargs=1,
2620         help="Path to wasi sysroot for wasm sandboxing",
2621     )
2623     @depends("--with-wasi-sysroot", requires_wasm_sandboxing)
2624     def bootstrap_wasi_sysroot(wasi_sysroot, requires_wasm_sandboxing):
2625         return requires_wasm_sandboxing and not wasi_sysroot
2627     @depends(
2628         "--with-wasi-sysroot",
2629         bootstrap_path("sysroot-wasm32-wasi", when=bootstrap_wasi_sysroot),
2630     )
2631     @imports("os")
2632     def wasi_sysroot(wasi_sysroot, bootstrapped_sysroot):
2633         if not wasi_sysroot:
2634             return bootstrapped_sysroot
2636         wasi_sysroot = wasi_sysroot[0]
2637         if not os.path.isdir(wasi_sysroot):
2638             die("Argument to --with-wasi-sysroot must be a directory")
2639         if not os.path.isabs(wasi_sysroot):
2640             die("Argument to --with-wasi-sysroot must be an absolute path")
2642         return wasi_sysroot
2644     @depends(wasi_sysroot)
2645     def wasi_sysroot_flags(wasi_sysroot):
2646         if wasi_sysroot:
2647             log.info("Using wasi sysroot in %s", wasi_sysroot)
2648             return ["--sysroot=%s" % wasi_sysroot]
2649         return []
2651     set_config("WASI_SYSROOT", wasi_sysroot)
2653     def wasm_compiler_with_flags(compiler, sysroot_flags):
2654         if compiler:
2655             return (
2656                 compiler.wrapper + [compiler.compiler] + compiler.flags + sysroot_flags
2657             )
2659     @template
2660     def wasm_compiler_error(msg):
2661         @depends("--with-wasm-sandboxed-libraries")
2662         def wasm_compiler_error(sandboxed_libs):
2663             suggest_disable = ""
2664             if sandboxed_libs.origin == "default":
2665                 suggest_disable = " Or build with --without-wasm-sandboxed-libraries."
2666             return lambda: die(msg + suggest_disable)
2668         return wasm_compiler_error
2670     @template
2671     def check_wasm_compiler(compiler, language):
2672         compiler.try_compile(
2673             includes=["cstring" if language == "C++" else "string.h"],
2674             flags=wasi_sysroot_flags,
2675             check_msg="the wasm %s compiler can find wasi headers" % language,
2676             onerror=wasm_compiler_error(
2677                 "Cannot find wasi headers or problem with the wasm compiler. "
2678                 "Please fix the problem."
2679             ),
2680         )
2682         compiler.try_run(
2683             flags=wasi_sysroot_flags,
2684             check_msg="the wasm %s linker can find wasi libraries" % language,
2685             onerror=wasm_compiler_error(
2686                 "Cannot find wasi libraries or problem with the wasm linker. "
2687                 "Please fix the problem."
2688             ),
2689         )
2691     wasm_cc = compiler("C", wasm, other_compiler=c_compiler)
2692     check_wasm_compiler(wasm_cc, "C")
2694     @depends(wasm_cc, wasi_sysroot_flags)
2695     def wasm_cc_with_flags(wasm_cc, wasi_sysroot_flags):
2696         return wasm_compiler_with_flags(wasm_cc, wasi_sysroot_flags)
2698     set_config("WASM_CC", wasm_cc_with_flags)
2700     wasm_cxx = compiler(
2701         "C++",
2702         wasm,
2703         c_compiler=wasm_cc,
2704         other_compiler=cxx_compiler,
2705         other_c_compiler=c_compiler,
2706     )
2707     check_wasm_compiler(wasm_cxx, "C++")
2709     @depends(wasm_cxx, wasi_sysroot_flags)
2710     def wasm_cxx_with_flags(wasm_cxx, wasi_sysroot_flags):
2711         return wasm_compiler_with_flags(wasm_cxx, wasi_sysroot_flags)
2713     set_config("WASM_CXX", wasm_cxx_with_flags)
2715     wasm_compile_flags = dependable(["-fno-exceptions", "-fno-strict-aliasing"])
2716     option(env="WASM_CFLAGS", nargs=1, help="Options to pass to WASM_CC")
2718     @depends("WASM_CFLAGS", wasm_compile_flags)
2719     def wasm_cflags(value, wasm_compile_flags):
2720         if value:
2721             return wasm_compile_flags + value
2722         else:
2723             return wasm_compile_flags
2725     set_config("WASM_CFLAGS", wasm_cflags)
2727     option(env="WASM_CXXFLAGS", nargs=1, help="Options to pass to WASM_CXX")
2729     @depends("WASM_CXXFLAGS", wasm_compile_flags)
2730     def wasm_cxxflags(value, wasm_compile_flags):
2731         if value:
2732             return wasm_compile_flags + value
2733         else:
2734             return wasm_compile_flags
2736     set_config("WASM_CXXFLAGS", wasm_cxxflags)
2739 @depends("--with-wasm-sandboxed-libraries")
2740 def wasm_sandboxing(libraries):
2741     if not libraries:
2742         return
2744     return namespace(**{name: True for name in libraries})
2747 @template
2748 def wasm_sandboxing_config_defines():
2749     for lib in wasm_sandboxing_libraries():
2750         set_config(
2751             "MOZ_WASM_SANDBOXING_%s" % lib.upper(), getattr(wasm_sandboxing, lib)
2752         )
2753         set_define(
2754             "MOZ_WASM_SANDBOXING_%s" % lib.upper(), getattr(wasm_sandboxing, lib)
2755         )
2758 wasm_sandboxing_config_defines()
2761 with only_when(compile_environment & wasm_sandboxing.hunspell):
2762     clock_in_wasi_sysroot = wasm_cc.try_run(
2763         header="#include <time.h>",
2764         body="clock();",
2765         check_msg="for clock() in wasi sysroot",
2766         flags=depends(wasi_sysroot_flags)(
2767             lambda sysroot_flags: ["-Werror"] + sysroot_flags
2768         ),
2769     )
2771     wasi_emulated_clock = wasm_cc.try_run(
2772         header="#include <time.h>",
2773         body="clock();",
2774         check_msg="for emulated clock() in wasi sysroot",
2775         flags=depends(wasi_sysroot_flags)(
2776             lambda sysroot_flags: [
2777                 "-Werror",
2778                 "-D_WASI_EMULATED_PROCESS_CLOCKS",
2779                 "-lwasi-emulated-process-clocks",
2780             ]
2781             + sysroot_flags
2782         ),
2783         when=depends(clock_in_wasi_sysroot)(lambda x: not x),
2784         onerror=lambda: die("Can't find clock() in wasi sysroot."),
2785     )
2787     set_config("MOZ_WASI_EMULATED_CLOCK", True, when=wasi_emulated_clock)
2790 # Auxiliary files persistence on application close
2791 # ==============================================================
2793 option(
2794     "--enable-disk-remnant-avoidance",
2795     help="Prevent persistence of auxiliary files on application close",
2799 set_config(
2800     "MOZ_AVOID_DISK_REMNANT_ON_CLOSE",
2801     True,
2802     when="--enable-disk-remnant-avoidance",
2806 # Glean SDK Integration Crate
2807 # ==============================================================
2810 @depends(target)
2811 def glean_android(target):
2812     return target.os == "Android"
2815 set_config("MOZ_GLEAN_ANDROID", True, when=glean_android)
2816 set_define("MOZ_GLEAN_ANDROID", True, when=glean_android)
2819 # dump_syms
2820 # ==============================================================
2822 check_prog(
2823     "DUMP_SYMS",
2824     ["dump_syms"],
2825     allow_missing=True,
2826     bootstrap="dump_syms",
2827     when=compile_environment,
2831 @depends(valid_windows_sdk_dir, host)
2832 @imports(_from="os", _import="environ")
2833 def pdbstr_paths(valid_windows_sdk_dir, host):
2834     if not valid_windows_sdk_dir:
2835         return
2837     vc_host = {
2838         "x86": "x86",
2839         "x86_64": "x64",
2840     }.get(host.cpu)
2842     return [
2843         environ["PATH"],
2844         os.path.join(valid_windows_sdk_dir.path, "Debuggers", vc_host, "srcsrv"),
2845     ]
2848 @depends("MOZ_AUTOMATION", c_compiler)
2849 def allow_missing_wintools(automation, c_compiler):
2850     if not automation:
2851         return True
2852     if c_compiler and c_compiler.type != "clang-cl":
2853         return True
2856 check_prog(
2857     "PDBSTR",
2858     ["pdbstr.exe"],
2859     allow_missing=allow_missing_wintools,
2860     when=compile_environment & target_is_windows,
2861     paths=pdbstr_paths,
2862     allow_spaces=True,
2866 check_prog(
2867     "WINCHECKSEC",
2868     ["winchecksec.exe", "winchecksec"],
2869     bootstrap="winchecksec",
2870     allow_missing=allow_missing_wintools,
2871     when=compile_environment & target_is_windows,
2875 # Fork server
2876 @depends(target, build_project)
2877 def forkserver_default(target, build_project):
2878     return build_project == "browser" and (
2879         (target.os == "GNU" and target.kernel == "Linux")
2880         or target.os == "FreeBSD"
2881         or target.os == "OpenBSD"
2882     )
2885 option(
2886     "--enable-forkserver",
2887     default=forkserver_default,
2888     env="MOZ_ENABLE_FORKSERVER",
2889     help="{Enable|Disable} fork server",
2893 @depends("--enable-forkserver", target)
2894 def forkserver_flag(value, target):
2895     if (
2896         target.os == "Android"
2897         or (target.os == "GNU" and target.kernel == "Linux")
2898         or target.os == "FreeBSD"
2899         or target.os == "OpenBSD"
2900     ):
2901         return bool(value)
2902     pass
2905 set_config("MOZ_ENABLE_FORKSERVER", forkserver_flag)
2906 set_define("MOZ_ENABLE_FORKSERVER", forkserver_flag, forkserver_flag)
2908 # Crash Reporter
2909 # ==============================================================
2911 with only_when(compile_environment & target_has_linux_kernel):
2912     # Check if we need to use the breakpad_getcontext fallback.
2913     getcontext = check_symbol("getcontext")
2914     set_config("HAVE_GETCONTEXT", getcontext)
2915     set_define("HAVE_GETCONTEXT", getcontext)
2917 # NSS
2918 # ==============================================================
2919 include("../build/moz.configure/nss.configure")
2922 # Enable or disable running in background task mode: headless for
2923 # periodic, short-lived, maintenance tasks.
2924 # ==============================================================================
2925 option(
2926     "--disable-backgroundtasks",
2927     help="Disable running in background task mode",
2929 set_config("MOZ_BACKGROUNDTASKS", True, when="--enable-backgroundtasks")
2930 set_define("MOZ_BACKGROUNDTASKS", True, when="--enable-backgroundtasks")
2933 # Update-related programs: updater, maintenance service, update agent,
2934 # default browser agent.
2935 # ==============================================================
2936 include("../build/moz.configure/update-programs.configure")
2939 # Mobile optimizations
2940 # ==============================================================
2941 option(
2942     "--enable-mobile-optimize",
2943     default=target_is_android,
2944     help="{Enable|Disable} mobile optimizations",
2947 set_define("MOZ_GFX_OPTIMIZE_MOBILE", True, when="--enable-mobile-optimize")
2948 # We ignore "paint will resample" on mobile for performance.
2949 # We may want to revisit this later.
2950 set_define("MOZ_IGNORE_PAINT_WILL_RESAMPLE", True, when="--enable-mobile-optimize")
2952 # Pref extensions
2953 # ==============================================================
2954 option("--disable-pref-extensions", help="Disable pref extensions such as autoconfig")
2955 set_config("MOZ_PREF_EXTENSIONS", True, when="--enable-pref-extensions")
2957 # Offer a way to disable the startup cache
2958 # ==============================================================
2959 option("--disable-startupcache", help="Disable startup cache")
2962 @depends("--enable-startupcache")
2963 def enable_startupcache(value):
2964     if value:
2965         return True
2968 set_define(
2969     "MOZ_DISABLE_STARTUPCACHE", True, when=depends(enable_startupcache)(lambda x: not x)
2973 # Branding
2974 # ==============================================================
2975 option(
2976     env="MOZ_APP_REMOTINGNAME",
2977     nargs=1,
2978     help="Used for the internal program name, which affects profile name "
2979     "and remoting. If not set, defaults to MOZ_APP_NAME if the update channel "
2980     "is release, and MOZ_APP_NAME-MOZ_UPDATE_CHANNEL otherwise.",
2984 @depends("MOZ_APP_REMOTINGNAME", moz_app_name, update_channel)
2985 def moz_app_remotingname(value, moz_app_name, update_channel):
2986     if value:
2987         return value[0]
2988     if update_channel == "release":
2989         return moz_app_name
2990     return moz_app_name + "-" + update_channel
2993 set_config("MOZ_APP_REMOTINGNAME", moz_app_remotingname)
2995 option(
2996     env="ANDROID_PACKAGE_NAME",
2997     nargs=1,
2998     help="Name of the Android package (default org.mozilla.$MOZ_APP_NAME)",
3002 @depends("ANDROID_PACKAGE_NAME", moz_app_name)
3003 def android_package_name(value, moz_app_name):
3004     if value:
3005         return value[0]
3006     if moz_app_name == "fennec":
3007         return "org.mozilla.fennec_aurora"
3008     return "org.mozilla.%s" % moz_app_name
3011 set_config("ANDROID_PACKAGE_NAME", android_package_name)
3014 # Miscellaneous options
3015 # ==============================================================
3016 option(env="MOZ_WINCONSOLE", nargs="?", help="Whether we can create a console window.")
3017 set_define("MOZ_WINCONSOLE", True, when=depends("MOZ_WINCONSOLE")(lambda x: x))
3020 # Alternative Crashreporter setting
3021 option(
3022     "--with-crashreporter-url",
3023     env="MOZ_CRASHREPORTER_URL",
3024     default="https://crash-reports.mozilla.com/",
3025     nargs=1,
3026     help="Set an alternative crashreporter url",
3029 set_config(
3030     "MOZ_CRASHREPORTER_URL",
3031     depends("--with-crashreporter-url")(lambda x: x[0].rstrip("/")),
3035 # Crash reporter options
3036 # ==============================================================
3037 @depends(target)
3038 def oxidized_breakpad(target):
3039     if target.kernel == "Linux":
3040         return target.cpu in ("aarch64", "arm", "x86", "x86_64")
3041     return False
3044 set_config("MOZ_OXIDIZED_BREAKPAD", True, when=oxidized_breakpad)
3045 set_define("MOZ_OXIDIZED_BREAKPAD", True, when=oxidized_breakpad)
3047 # Environment variable to mock the crashreporter for testing
3048 option(env="MOZ_CRASHREPORTER_MOCK", help="Mock the crashreporter to test native GUIs")
3049 set_config("MOZ_CRASHREPORTER_MOCK", True, when="MOZ_CRASHREPORTER_MOCK")
3052 # Wine
3053 # ==============================================================
3054 @depends(target, host)
3055 def want_wine(target, host):
3056     return target.kernel == "WINNT" and host.kernel != "WINNT"
3059 wine = check_prog(
3060     "WINE",
3061     ["wine64", "wine"],
3062     when=want_wine,
3063     bootstrap="wine/bin",
3066 # DOM Streams
3067 # ==============================================================
3068 # Set this to true so the JS engine knows we're doing a browser build.
3069 set_config("MOZ_DOM_STREAMS", True)
3070 set_define("MOZ_DOM_STREAMS", True)
3072 # libevent
3073 # ==============================================================
3074 with only_when(compile_environment):
3075     system_lib_option(
3076         "--with-system-libevent",
3077         nargs="?",
3078         help="Use system libevent",
3079     )
3081     @depends("--with-system-libevent")
3082     def deprecated_system_libevent_path(value):
3083         if len(value) == 1:
3084             die(
3085                 "--with-system-libevent=PATH is not supported anymore. Please use "
3086                 "--with-system-libevent and set any necessary pkg-config environment variable."
3087             )
3089     pkg_check_modules("MOZ_LIBEVENT", "libevent", when="--with-system-libevent")
3091     set_config("MOZ_SYSTEM_LIBEVENT", True, when="--with-system-libevent")
3094 # Crash reporting
3095 # ==============================================================
3096 @depends(target, developer_options, artifact_builds)
3097 def crashreporter_default(target, developer_options, artifacts):
3098     if target.os in ("WINNT", "OSX"):
3099         return True
3100     if target.kernel == "Linux" and target.cpu in ("x86", "x86_64", "arm", "aarch64"):
3101         # The crash reporter prevents crash stacktraces to be logged in the
3102         # logs on Android, so we leave it out by default in developer builds.
3103         return target.os != "Android" or not developer_options or artifacts
3106 option(
3107     "--enable-crashreporter",
3108     default=crashreporter_default,
3109     help="{Enable|Disable} crash reporting",
3113 set_config("MOZ_CRASHREPORTER", True, when="--enable-crashreporter")
3114 set_define("MOZ_CRASHREPORTER", True, when="--enable-crashreporter")
3116 with only_when(compile_environment):
3117     with only_when("--enable-crashreporter"):
3118         pkg_check_modules(
3119             "MOZ_GTHREAD",
3120             "gthread-2.0",
3121             when=depends(target)(lambda t: t.os == "GNU" and t.kernel == "Linux"),
3122         )
3124         set_config(
3125             "MOZ_CRASHREPORTER_INJECTOR",
3126             True,
3127             when=depends(target)(lambda t: t.os == "WINNT" and t.bitness == 32),
3128         )
3129         set_define(
3130             "MOZ_CRASHREPORTER_INJECTOR",
3131             True,
3132             when=depends(target)(lambda t: t.os == "WINNT" and t.bitness == 32),
3133         )
3136 # If we have any service that uploads data (and requires data submission
3137 # policy alert), set MOZ_DATA_REPORTING.
3138 # ==============================================================
3139 @depends(
3140     "MOZ_TELEMETRY_REPORTING",
3141     "MOZ_SERVICES_HEALTHREPORT",
3142     "--enable-crashreporter",
3143     "MOZ_NORMANDY",
3145 def data_reporting(telemetry, healthreport, crashreporter, normandy):
3146     return telemetry or healthreport or crashreporter or normandy
3149 set_config("MOZ_DATA_REPORTING", True, when=data_reporting)
3150 set_define("MOZ_DATA_REPORTING", True, when=data_reporting)
3153 # Gtk+
3154 # ==============================================================
3155 with only_when(toolkit_gtk):
3156     pkg_check_modules(
3157         "MOZ_GTK3",
3158         "gtk+-3.0 >= 3.14.0 gtk+-unix-print-3.0 glib-2.0 gobject-2.0 gio-unix-2.0",
3159     )
3161     set_define("GDK_VERSION_MIN_REQUIRED", "GDK_VERSION_3_14")
3162     set_define("GDK_VERSION_MAX_ALLOWED", "GDK_VERSION_3_14")
3164     pkg_check_modules("GLIB", "glib-2.0 >= 2.42 gobject-2.0")
3166     set_define("GLIB_VERSION_MIN_REQUIRED", "GLIB_VERSION_2_42")
3167     set_define("GLIB_VERSION_MAX_ALLOWED", "GLIB_VERSION_2_42")
3169     set_define("MOZ_ACCESSIBILITY_ATK", True, when=accessibility)
3171 # DBus
3172 # ==============================================================
3173 with only_when(toolkit_gtk):
3174     option("--disable-dbus", help="Disable dbus support")
3176     with only_when("--enable-dbus"):
3177         pkg_check_modules("MOZ_DBUS", "dbus-1 >= 0.60")
3179         set_config("MOZ_ENABLE_DBUS", True)
3180         set_define("MOZ_ENABLE_DBUS", True)
3183 # Necko's wifi scanner
3184 # ==============================================================
3185 @depends(target)
3186 def necko_wifi_when(target):
3187     return target.os in ("WINNT", "OSX", "DragonFly", "FreeBSD") or (
3188         target.kernel == "Linux" and target.os == "GNU"
3189     )
3192 option("--disable-necko-wifi", help="Disable necko wifi scanner", when=necko_wifi_when)
3194 set_config("NECKO_WIFI", True, when="--enable-necko-wifi")
3195 set_define("NECKO_WIFI", True, when="--enable-necko-wifi")
3198 @depends(
3199     depends("--enable-necko-wifi", when=necko_wifi_when)(lambda x: x),
3200     depends("--enable-dbus", when=toolkit_gtk)(lambda x: x),
3201     when=depends(target)(lambda t: t.os == "GNU" and t.kernel == "Linux"),
3203 def necko_wifi_dbus(necko_wifi, dbus):
3204     if necko_wifi and not dbus:
3205         die(
3206             "Necko WiFi scanning needs DBus on your platform, remove --disable-dbus"
3207             " or use --disable-necko-wifi"
3208         )
3209     return necko_wifi and dbus
3212 set_config("NECKO_WIFI_DBUS", True, when=necko_wifi_dbus)
3213 set_define("NECKO_WIFI_DBUS", True, when=necko_wifi_dbus)
3216 # Frontend JS debug mode
3217 # ==============================================================
3218 option("--enable-debug-js-modules", help="Enable debug mode for frontend JS libraries")
3220 set_config("DEBUG_JS_MODULES", True, when="--enable-debug-js-modules")
3223 # moz_dump_painting
3224 # ==============================================================
3225 option("--enable-dump-painting", help="Enable paint debugging")
3227 set_define(
3228     "MOZ_DUMP_PAINTING",
3229     True,
3230     when=depends("--enable-dump-painting", "--enable-debug")(
3231         lambda painting, debug: painting or debug
3232     ),
3234 set_define("MOZ_LAYERS_HAVE_LOG", True, when="--enable-dump-painting")
3237 # libproxy support
3238 # ==============================================================
3239 with only_when(toolkit_gtk):
3240     system_lib_option("--enable-libproxy", help="Enable libproxy support")
3242     with only_when("--enable-libproxy"):
3243         pkg_check_modules("MOZ_LIBPROXY", "libproxy-1.0")
3245         set_config("MOZ_ENABLE_LIBPROXY", True)
3246         set_define("MOZ_ENABLE_LIBPROXY", True)
3249 # Enable runtime logging
3250 # ==============================================================
3251 set_define("MOZ_LOGGING", True)
3252 set_define("FORCE_PR_LOG", True)
3254 # This will enable logging of addref, release, ctor, dtor.
3255 # ==============================================================
3256 option(
3257     "--enable-logrefcnt",
3258     default=moz_debug,
3259     help="{Enable|Disable} logging of refcounts",
3262 set_define("NS_BUILD_REFCNT_LOGGING", True, when="--enable-logrefcnt")
3265 # NegotiateAuth
3266 # ==============================================================
3267 option("--disable-negotiateauth", help="Disable GSS-API negotiation")
3269 set_config("MOZ_AUTH_EXTENSION", True, when="--enable-negotiateauth")
3270 set_define("MOZ_AUTH_EXTENSION", True, when="--enable-negotiateauth")
3273 # Parental control
3274 # ==============================================================
3275 option("--disable-parental-controls", help="Do not build parental controls")
3277 set_config(
3278     "MOZ_DISABLE_PARENTAL_CONTROLS",
3279     True,
3280     when=depends("--enable-parental-controls")(lambda x: not x),
3282 set_define(
3283     "MOZ_DISABLE_PARENTAL_CONTROLS",
3284     True,
3285     when=depends("--enable-parental-controls")(lambda x: not x),
3289 # Sandboxing support
3290 # ==============================================================
3291 @depends(target, tsan, asan)
3292 def sandbox_default(target, tsan, asan):
3293     # Only enable the sandbox by default on Linux, OpenBSD, macOS, and Windows
3294     if target.kernel == "Linux" and target.os == "GNU":
3295         # Bug 1182565: TSan conflicts with sandboxing on Linux.
3296         # Bug 1287971: LSan also conflicts with sandboxing on Linux.
3297         if tsan or asan:
3298             return False
3299         # Linux sandbox is only available on x86{,_64} and arm{,64}.
3300         return target.cpu in ("x86", "x86_64", "arm", "aarch64")
3301     return target.kernel in ("WINNT", "Darwin", "OpenBSD")
3304 option(
3305     "--enable-sandbox",
3306     default=sandbox_default,
3307     help="{Enable|Disable} sandboxing support",
3310 set_config("MOZ_SANDBOX", True, when="--enable-sandbox")
3311 set_define("MOZ_SANDBOX", True, when="--enable-sandbox")
3313 with only_when(depends(target.kernel)(lambda k: k not in ("Darwin", "WINNT"))):
3314     set_define("MOZ_CONTENT_TEMP_DIR", True, when="--enable-sandbox")
3316 # Searching of system directories for extensions.
3317 # ==============================================================
3318 # Note: this switch is meant to be used for test builds whose behavior should
3319 # not depend on what happens to be installed on the local machine.
3320 option(
3321     "--disable-system-extension-dirs",
3322     help="Disable searching system- and account-global directories for extensions"
3323     " of any kind; use only profile-specific extension directories",
3326 set_define("ENABLE_SYSTEM_EXTENSION_DIRS", True, when="--enable-system-extension-dirs")
3329 # Pixman
3330 # ==============================================================
3331 with only_when(compile_environment):
3332     system_lib_option(
3333         "--enable-system-pixman", help="Use system pixman (located with pkgconfig)"
3334     )
3336     @depends("--enable-system-pixman")
3337     def in_tree_pixman(pixman):
3338         return not pixman
3340     set_config("MOZ_TREE_PIXMAN", True, when=in_tree_pixman)
3341     set_define("MOZ_TREE_PIXMAN", True, when=in_tree_pixman)
3343     pkg_check_modules("MOZ_PIXMAN", "pixman-1 >= 0.36.0", when="--enable-system-pixman")
3344     # Set MOZ_PIXMAN_CFLAGS to an explicit empty value when --enable-system-pixman is *not* used,
3345     # for layout/style/extra-bindgen-flags
3346     set_config("MOZ_PIXMAN_CFLAGS", [], when=in_tree_pixman)
3349 # Universalchardet
3350 # ==============================================================
3351 with only_when(compile_environment):
3352     option("--disable-universalchardet", help="Disable universal encoding detection")
3354     set_config("MOZ_UNIVERSALCHARDET", True, when="--enable-universalchardet")
3357 # Disable zipwriter
3358 # ==============================================================
3359 with only_when(compile_environment):
3360     option("--disable-zipwriter", help="Disable zipwriter component")
3362     set_config("MOZ_ZIPWRITER", True, when="--enable-zipwriter")
3365 # Location of the mozilla user directory
3366 # ==============================================================
3367 with only_when(compile_environment):
3369     @depends(target)
3370     def default_user_appdir(target):
3371         if target.kernel in ("WINNT", "Darwin"):
3372             return "Mozilla"
3373         return ".mozilla"
3375     option(
3376         "--with-user-appdir",
3377         nargs=1,
3378         default=default_user_appdir,
3379         help="Set user-specific appdir",
3380     )
3382     @depends("--with-user-appdir")
3383     def user_appdir(appdir):
3384         if not appdir:
3385             die("--without-user-appdir is not a valid option.")
3386         if "/" in appdir[0]:
3387             die("--with-user-appdir must be a single relative path.")
3388         return '"{}"'.format(appdir[0])
3390     set_define("MOZ_USER_DIR", user_appdir)
3393 # Check for sin_len and sin6_len - used by SCTP; only appears in Mac/*BSD generally
3394 # ==============================================================
3395 with only_when(compile_environment):
3396     have_sin_len = c_compiler.try_compile(
3397         includes=["netinet/in.h"],
3398         body="struct sockaddr_in x; void *foo = (void*) &x.sin_len;",
3399         check_msg="for sin_len in struct sockaddr_in",
3400     )
3401     have_sin6_len = c_compiler.try_compile(
3402         includes=["netinet/in.h"],
3403         body="struct sockaddr_in6 x; void *foo = (void*) &x.sin6_len;",
3404         check_msg="for sin_len6 in struct sockaddr_in6",
3405     )
3406     set_define("HAVE_SIN_LEN", have_sin_len)
3407     set_define("HAVE_SIN6_LEN", have_sin6_len)
3408     # HAVE_CONN_LEN must be the same as HAVE_SIN_LEN and HAVE_SIN6_LEN
3409     set_define("HAVE_SCONN_LEN", have_sin_len & have_sin6_len)
3410     set_define(
3411         "HAVE_SA_LEN",
3412         c_compiler.try_compile(
3413             includes=["netinet/in.h"],
3414             body="struct sockaddr x; void *foo = (void*) &x.sa_len;",
3415             check_msg="for sa_len in struct sockaddr",
3416         ),
3417     )
3420 # Check for pthread_cond_timedwait_monotonic_np
3421 # ==============================================================
3422 with only_when(compile_environment):
3423     set_define(
3424         "HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC",
3425         c_compiler.try_compile(
3426             includes=["pthread.h"],
3427             body="pthread_cond_timedwait_monotonic_np(0, 0, 0);",
3428             # -Werror to catch any "implicit declaration" warning that means the function
3429             # is not supported.
3430             flags=["-Werror=implicit-function-declaration"],
3431             check_msg="for pthread_cond_timedwait_monotonic_np",
3432         ),
3433     )
3436 # Custom dynamic linker for Android
3437 # ==============================================================
3438 with only_when(target_has_linux_kernel & compile_environment):
3439     option(
3440         env="MOZ_LINKER",
3441         default=depends(target.os, when="--enable-jemalloc")(
3442             lambda os: os == "Android"
3443         ),
3444         help="{Enable|Disable} custom dynamic linker",
3445     )
3447     set_config("MOZ_LINKER", True, when="MOZ_LINKER")
3448     set_define("MOZ_LINKER", True, when="MOZ_LINKER")
3449     add_old_configure_assignment("MOZ_LINKER", True, when="MOZ_LINKER")
3451     moz_linker = depends(when="MOZ_LINKER")(lambda: True)
3454 # 32-bits ethtool_cmd.speed
3455 # ==============================================================
3456 with only_when(target_has_linux_kernel & compile_environment):
3457     set_config(
3458         "MOZ_WEBRTC_HAVE_ETHTOOL_SPEED_HI",
3459         c_compiler.try_compile(
3460             includes=["linux/ethtool.h"],
3461             body="struct ethtool_cmd cmd; cmd.speed_hi = 0;",
3462             check_msg="for 32-bits ethtool_cmd.speed",
3463         ),
3464     )
3466 # Gamepad support
3467 # ==============================================================
3468 check_header(
3469     "linux/joystick.h",
3470     onerror=lambda: die(
3471         "Can't find header linux/joystick.h, needed for gamepad support."
3472         " Please install Linux kernel headers."
3473     ),
3474     when=target_has_linux_kernel & compile_environment,
3478 # Smart card support
3479 # ==============================================================
3480 @depends(build_project)
3481 def disable_smart_cards(build_project):
3482     return build_project == "mobile/android"
3485 set_config("MOZ_NO_SMART_CARDS", True, when=disable_smart_cards)
3486 set_define("MOZ_NO_SMART_CARDS", True, when=disable_smart_cards)
3488 # Enable UniFFI fixtures
3489 # ==============================================================
3490 # These are used to test the uniffi-bindgen-gecko-js code generation.  They
3491 # should not be enabled in release builds.
3493 option(
3494     "--enable-uniffi-fixtures",
3495     help="Enable UniFFI Fixtures/Examples",
3498 set_config("MOZ_UNIFFI_FIXTURES", True, when="--enable-uniffi-fixtures")
3500 # System policies
3501 # ==============================================================
3503 option(
3504     "--disable-system-policies",
3505     help="Disable reading policies from Windows registry, macOS's file system attributes, and /etc/firefox",
3508 set_config("MOZ_SYSTEM_POLICIES", True, when="--enable-system-policies")
3510 # Allow disabling the creation a legacy profile
3511 # ==============================================================
3513 option(
3514     "--disable-legacy-profile-creation",
3515     help="Disable the creation a legacy profile, to be used by old versions "
3516     "of Firefox, when no profiles exist.",
3519 set_config("MOZ_CREATE_LEGACY_PROFILE", True, when="--enable-legacy-profile-creation")
3522 # STL wrapping
3523 # ==============================================================
3524 set_config("WRAP_STL_INCLUDES", True)
3525 set_config(
3526     "STL_FLAGS",
3527     depends(build_environment.dist)(lambda dist: [f"-I{dist}/stl_wrappers"]),
3531 # Perl detection
3532 # ==============================================================
3533 @depends(target)
3534 def need_perl(target):
3535     # Ideally, we'd also depend on gnu_as here, but that adds complications.
3536     return target.cpu == "arm"
3539 perl = check_prog("PERL", ("perl5", "perl"), when=need_perl)
3542 @template
3543 def perl_version_check(min_version):
3544     @depends(perl)
3545     @checking("for minimum required perl version >= %s" % min_version)
3546     def get_perl_version(perl):
3547         return Version(
3548             check_cmd_output(
3549                 perl,
3550                 "-e",
3551                 "print $]",
3552                 onerror=lambda: die("Failed to get perl version."),
3553             )
3554         )
3556     @depends(get_perl_version)
3557     def check_perl_version(version):
3558         if version < min_version:
3559             die("Perl %s or higher is required.", min_version)
3561     @depends(perl)
3562     @checking("for full perl installation")
3563     @imports("subprocess")
3564     def has_full_perl_installation(perl):
3565         ret = subprocess.call([perl, "-e", "use Config; exit(!-d $Config{archlib})"])
3566         return ret == 0
3568     @depends(has_full_perl_installation)
3569     def require_full_perl_installation(has_full_perl_installation):
3570         if not has_full_perl_installation:
3571             die(
3572                 "Cannot find Config.pm or $Config{archlib}. "
3573                 "A full perl installation is required."
3574             )
3577 with only_when(need_perl):
3578     perl_version_check("5.006")
3581 # windows-rs as bootstrappable toolchain
3582 # ==============================================================
3583 # The in-tree windows crate's purpose is to avoid vendoring the
3584 # original windows crate, which is too large.
3585 # The ideal solution would be for cargo to allow exceptions to
3586 # vendoring, but it doesn't.
3587 # The adopted solution is to somehow use the crate contents from
3588 # a directory given via the mozbuild config, or bootstrapped.
3590 # Unfortunately, doing `include!(mozbuild::windows_rs_path!("src/lib.rs"))`
3591 # in the crate's lib.rs doesn't work because of
3592 # https://github.com/rust-lang/rust/issues/66920.
3594 # Previous versions of the windows crate had submodules declared
3595 # directly in lib.rs. Annotating each of them with
3596 # `#[path = concat!(mozbuild::windows_rs_path!("path/to/mod.rs"))]`
3597 # unfortunately also didn't work, because of
3598 # https://github.com/rust-lang/rust/issues/48250.
3600 # Thankfully, newer versions of the windows crate now only have an
3601 # `include!` at the end of lib.rs, so we can get away with simply
3602 # replacing it with an `include!` that uses `mozbuild::windows_rs_path!`.
3604 # We ensure that the in-tree contents match what we expect based on
3605 # the original crate.
3606 # The expectations are as such:
3607 # - Cargo.toml is identical to the original one with the addition of the
3608 #   following two lines at the end (after an empty line):
3609 #     [dependencies.mozbuild]
3610 #     version = "0.1"
3611 # - src/lib.rs is mostly identical to the original one, with two notable
3612 #   differences:
3613 #   - the addition of `#![allow(warnings)]` on the first line, because if
3614 #     the crate had been vendored normally, it would not be affected by
3615 #     `-D warnings`, and `#![allow(warnings)]` mimicks that.
3616 #   - the replacement of any
3617 #     `include!("path/file.rs")`
3618 #     with
3619 #     `include!(mozbuild::windows_rs_path!("src/path/file.rs"))`
3620 with only_when(target_is_windows & compile_environment):
3621     option(
3622         env="MOZ_WINDOWS_RS_DIR",
3623         nargs=1,
3624         help="Path to the source of the 'windows' Rust crate",
3625     )
3627     @depends(
3628         "MOZ_WINDOWS_RS_DIR",
3629         bootstrap_path(
3630             "windows-rs",
3631             when=depends("MOZ_WINDOWS_RS_DIR")(lambda x: not x),
3632         ),
3633         build_environment.topsrcdir,
3634     )
3635     @checking("for the windows rust crate source")
3636     @imports(_from="__builtin__", _import="open")
3637     @imports("re")
3638     @imports("toml")
3639     def windows_rs_dir(dir, bootstrapped, topsrcdir):
3640         if bootstrapped:
3641             dir = bootstrapped
3642         elif dir:
3643             dir = dir[0]
3645         raw_cargo_toml = open(
3646             os.path.join(topsrcdir, "build/rust/windows/Cargo.toml")
3647         ).read()
3648         cargo_toml = toml.loads(raw_cargo_toml)
3649         expected_version = cargo_toml["package"]["version"]
3651         if not dir:
3652             raise FatalCheckError(
3653                 "Cannot find the windows rust crate source.\n"
3654                 f"Try downloading it with `cargo download -x windows={expected_version}`\n"
3655                 "(you may need to `cargo install cargo-download` first)\n"
3656                 f"and set `MOZ_WINDOWS_RS_DIR` to location of the `windows-{expected_version}`"
3657                 " directory"
3658             )
3660         raw_cargo_toml_orig = open(os.path.join(dir, "Cargo.toml")).read()
3661         cargo_toml = toml.loads(raw_cargo_toml_orig)
3662         version = cargo_toml["package"]["version"]
3663         if version != expected_version:
3664             raise FatalCheckError(
3665                 f"The windows rust crate source in {dir} contains version "
3666                 f"{version}, but expected {expected_version}."
3667             )
3668         # Now that we've done the basic sanity check, let's go deeper.
3669         DEPENDENCIES = '\n[dependencies.mozbuild]\nversion = "0.1"\n'
3670         if not raw_cargo_toml.endswith(DEPENDENCIES):
3671             configure_error("In-tree windows crate is missing dependency on mozbuild")
3672         if raw_cargo_toml[: -len(DEPENDENCIES)] != raw_cargo_toml_orig:
3673             configure_error("In-tree windows crate Cargo.toml doesn't match original")
3675         lib_rs = open(os.path.join(topsrcdir, "build/rust/windows/src/lib.rs")).read()
3676         lib_rs_orig = open(os.path.join(dir, "src/lib.rs")).read()
3677         lib_rs_expected = "#![allow(warnings)]\n" + re.sub(
3678             r'include!\("([^"]*)"\)',
3679             r'include!(mozbuild::windows_rs_path!("src/\1"))',
3680             lib_rs_orig,
3681         )
3682         if lib_rs != lib_rs_expected:
3683             configure_error("In-tree windows crate lib.rs doesn't match original")
3685         return dir
3687     set_config("MOZ_WINDOWS_RS_DIR", windows_rs_dir)