Bug 1880704 - Crop more PDF rendering and wait differently for rendering r=mboldan
[gecko.git] / toolkit / moz.configure
blobb616109b1fd8721a1aa77f619bad4aed420187b1
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", "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)
91 @depends(target)
92 def gecko_profiler(target):
93     if target.os == "Android":
94         return target.cpu in ("aarch64", "arm", "x86", "x86_64")
95     elif target.kernel == "Linux":
96         return target.cpu in ("aarch64", "arm", "x86", "x86_64", "mips64")
97     elif target.kernel == "FreeBSD":
98         return target.cpu in ("aarch64", "x86_64")
99     return target.os in ("OSX", "WINNT")
102 @depends(gecko_profiler)
103 def gecko_profiler_define(value):
104     if value:
105         return True
108 set_config("MOZ_GECKO_PROFILER", gecko_profiler_define)
109 set_define("MOZ_GECKO_PROFILER", gecko_profiler_define)
112 # Whether code to parse ELF binaries should be compiled for the Gecko profiler
113 # (for symbol table dumping).
114 @depends(gecko_profiler, target)
115 def gecko_profiler_parse_elf(value, target):
116     # Currently we only want to build this code on Linux (including Android) and BSD.
117     # For Android, this is in order to dump symbols from Android system, where
118     # on other platforms there exist alternatives that don't require bloating
119     # up our binary size. For Linux more generally, we use this in profile
120     # pre-symbolication support, since MozDescribeCodeAddress doesn't do
121     # anything useful on that platform. (Ideally, we would update
122     # MozDescribeCodeAddress to call into some Rust crates that parse ELF and
123     # DWARF data, but build system issues currently prevent Rust from being
124     # used in mozglue.)
125     if value and (target.kernel == "Linux" or target.kernel == "FreeBSD"):
126         return True
129 set_config("MOZ_GECKO_PROFILER_PARSE_ELF", gecko_profiler_parse_elf)
130 set_define("MOZ_GECKO_PROFILER_PARSE_ELF", gecko_profiler_parse_elf)
132 # enable this by default if the profiler is enabled
133 # Note: also requires jemalloc
134 set_config("MOZ_PROFILER_MEMORY", gecko_profiler_define)
135 set_define("MOZ_PROFILER_MEMORY", gecko_profiler_define)
138 @depends(
139     "--enable-debug",
140     milestone,
141     build_project,
142     # Artifact builds are included because the downloaded artifacts can
143     # have DMD enabled.
144     when=artifact_builds | depends(when="--enable-replace-malloc")(lambda: True),
146 def dmd_default(debug, milestone, build_project):
147     return bool(build_project == "browser" and (debug or milestone.is_nightly))
150 option(
151     "--enable-dmd",
152     env="MOZ_DMD",
153     default=dmd_default,
154     help="{Enable|Disable} Dark Matter Detector (heap profiler). "
155     "Also enables jemalloc, replace-malloc and profiling",
159 @depends("--enable-dmd")
160 def dmd(value):
161     if value:
162         return True
165 set_config("MOZ_DMD", dmd)
166 set_define("MOZ_DMD", dmd)
167 imply_option("--enable-profiling", dmd)
168 imply_option("--enable-jemalloc", dmd, when=compile_environment)
169 imply_option("--enable-replace-malloc", dmd, when=compile_environment)
172 # midir-based Web MIDI support
173 # ==============================================================
174 @depends(target)
175 def midir_linux_support(target):
176     return (
177         target.kernel == "Linux" and target.os != "Android" and target.cpu != "riscv64"
178     )
181 @depends(target, midir_linux_support)
182 def midir_support(target, midir_linux_support):
183     if target.os in ("WINNT", "OSX") or midir_linux_support:
184         return True
187 set_config("MOZ_WEBMIDI_MIDIR_IMPL", midir_support)
190 # Enable various cubeb backends
191 # ==============================================================
192 @depends(target)
193 def audio_backends_default(target):
194     if target.os == "Android":
195         return (
196             "aaudio",
197             "opensl",
198         )
199     elif target.os in ("DragonFly", "FreeBSD", "SunOS"):
200         return ("oss",)
201     elif target.os == "OpenBSD":
202         return ("sndio",)
203     elif target.os == "OSX":
204         return ("audiounit",)
205     elif target.os == "NetBSD":
206         return ("sunaudio",)
207     elif target.os == "SunOS":
208         return ("sunaudio",)
209     elif target.os == "WINNT":
210         return ("wasapi",)
211     else:
212         return ("pulseaudio",)
215 option(
216     "--enable-audio-backends",
217     nargs="+",
218     choices=(
219         "aaudio",
220         "alsa",
221         "audiounit",
222         "jack",
223         "opensl",
224         "oss",
225         "pulseaudio",
226         "sndio",
227         "sunaudio",
228         "wasapi",
229     ),
230     default=audio_backends_default,
231     help="{Enable|Disable} various cubeb backends",
235 @depends("--enable-audio-backends", target)
236 def imply_aaudio(values, target):
237     if any("aaudio" in value for value in values) and target.os != "Android":
238         die("Cannot enable AAudio on %s", target.os)
239     return any("aaudio" in value for value in values) or None
242 @depends("--enable-audio-backends", target)
243 def imply_alsa(values, target):
244     if (
245         any("alsa" in value for value in values)
246         and target.kernel != "Linux"
247         and target.os != "FreeBSD"
248     ):
249         die("Cannot enable ALSA on %s", target.os)
250     return any("alsa" in value for value in values) or None
253 @depends("--enable-audio-backends", target)
254 def imply_audiounit(values, target):
255     if (
256         any("audiounit" in value for value in values)
257         and target.os != "OSX"
258         and target.kernel != "Darwin"
259     ):
260         die("Cannot enable AudioUnit on %s", target.os)
261     return any("audiounit" in value for value in values) or None
264 @depends("--enable-audio-backends")
265 def imply_jack(values):
266     return any("jack" in value for value in values) or None
269 @depends("--enable-audio-backends", target)
270 def imply_opensl(values, target):
271     if any("opensl" in value for value in values) and target.os != "Android":
272         die("Cannot enable OpenSL on %s", target.os)
273     return any("opensl" in value for value in values) or None
276 @depends("--enable-audio-backends", target)
277 def imply_oss(values, target):
278     if any("oss" in value for value in values) and (
279         target.os == "Android" or target.os == "OSX" or target.os == "WINNT"
280     ):
281         die("Cannot enable OSS on %s", target.os)
282     return any("oss" in value for value in values) or None
285 @depends("--enable-audio-backends", target)
286 def imply_pulseaudio(values, target):
287     if any("pulseaudio" in value for value in values) and (
288         target.os == "Android" or target.os == "OSX" or target.os == "WINNT"
289     ):
290         die("Cannot enable PulseAudio on %s", target.os)
291     return any("pulseaudio" in value for value in values) or None
294 @depends("--enable-audio-backends", target)
295 def imply_sndio(values, target):
296     if any("sndio" in value for value in values) and (
297         target.os == "Android" or target.os == "OSX" or target.os == "WINNT"
298     ):
299         die("Cannot enable sndio on %s", target.os)
300     return any("sndio" in value for value in values) or None
303 @depends("--enable-audio-backends", target)
304 def imply_sunaudio(values, target):
305     if any("sunaudio" in value for value in values) and (
306         target.os != "NetBSD" and target.os != "SunOS"
307     ):
308         die("Cannot enable sunaudio on %s", target.os)
309     return any("sunaudio" in value for value in values) or None
312 @depends("--enable-audio-backends", target)
313 def imply_wasapi(values, target):
314     if any("wasapi" in value for value in values) and target.os != "WINNT":
315         die("Cannot enable WASAPI on %s", target.os)
316     return any("wasapi" in value for value in values) or None
319 set_config("MOZ_AAUDIO", imply_aaudio, when="--enable-audio-backends")
321 imply_option("--enable-alsa", imply_alsa, reason="--enable-audio-backends")
323 set_config("MOZ_AUDIOUNIT_RUST", imply_audiounit, when="--enable-audio-backends")
325 imply_option("--enable-jack", imply_jack, reason="--enable-audio-backends")
327 set_config("MOZ_OPENSL", imply_opensl, when="--enable-audio-backends")
329 set_config("MOZ_OSS", imply_oss, when="--enable-audio-backends")
331 imply_option("--enable-pulseaudio", imply_pulseaudio, reason="--enable-audio-backends")
333 imply_option("--enable-sndio", imply_sndio, reason="--enable-audio-backends")
335 set_config("MOZ_SUNAUDIO", imply_sunaudio, when="--enable-audio-backends")
337 set_config("MOZ_WASAPI", imply_wasapi, when="--enable-audio-backends")
339 # ALSA cubeb backend
340 # ==============================================================
341 option("--enable-alsa", env="MOZ_ALSA", help="Enable ALSA audio backend.")
344 @depends("--enable-alsa", midir_linux_support)
345 def enable_alsa_or_midir_linux_support(alsa_enabled, midir_linux_support):
346     return alsa_enabled or midir_linux_support
349 pkg_check_modules("MOZ_ALSA", "alsa", when=enable_alsa_or_midir_linux_support)
351 set_config("MOZ_ALSA", True, when="--enable-alsa")
352 set_define("MOZ_ALSA", True, when="--enable-alsa")
354 # JACK cubeb backend
355 # ==============================================================
356 system_lib_option("--enable-jack", env="MOZ_JACK", help="Enable JACK audio backend.")
358 jack = pkg_check_modules("MOZ_JACK", "jack", when="--enable-jack")
360 set_config("MOZ_JACK", depends_if(jack)(lambda _: True))
362 # PulseAudio cubeb backend
363 # ==============================================================
364 option(
365     "--enable-pulseaudio",
366     env="MOZ_PULSEAUDIO",
367     help="{Enable|Disable} PulseAudio audio backend.",
370 pulseaudio = pkg_check_modules("MOZ_PULSEAUDIO", "libpulse", when="--enable-pulseaudio")
372 set_config("MOZ_PULSEAUDIO", depends_if(pulseaudio)(lambda _: True))
373 set_define("MOZ_PULSEAUDIO", depends_if(pulseaudio)(lambda _: True))
375 # sndio cubeb backend
376 # ==============================================================
377 system_lib_option("--enable-sndio", env="MOZ_SNDIO", help="Enable sndio audio backend.")
379 sndio = pkg_check_modules("MOZ_SNDIO", "sndio", when="--enable-sndio")
381 set_config("MOZ_SNDIO", depends_if(sndio)(lambda _: True))
383 # Javascript engine
384 # ==============================================================
385 include("../js/moz.configure")
388 # NodeJS
389 # ==============================================================
390 include("../build/moz.configure/node.configure")
392 # JsonCpp
393 # ==============================================================
394 set_define("JSON_USE_EXCEPTION", 0)
396 # L10N
397 # ==============================================================
398 option("--with-l10n-base", nargs=1, env="L10NBASEDIR", help="Path to l10n repositories")
401 @depends("--with-l10n-base", "MOZ_AUTOMATION", build_environment)
402 @imports(_from="os.path", _import="isdir")
403 @imports(_from="os.path", _import="expanduser")
404 @imports(_from="os", _import="environ")
405 def l10n_base(value, automation, build_env):
406     if value:
407         path = value[0]
408         if not isdir(path):
409             die("Invalid value --with-l10n-base, %s doesn't exist", path)
410     elif automation:
411         path = os.path.join(build_env.topsrcdir, "../l10n-central")
412     else:
413         path = os.path.join(
414             environ.get(
415                 "MOZBUILD_STATE_PATH", expanduser(os.path.join("~", ".mozbuild"))
416             ),
417             "l10n-central",
418         )
419     return os.path.realpath(os.path.abspath(path))
422 set_config("L10NBASEDIR", l10n_base)
425 # Default toolkit
426 # ==============================================================
427 @depends(target)
428 def toolkit_choices(target):
429     if target.os == "WINNT":
430         return ("cairo-windows",)
431     elif target.os == "OSX":
432         return ("cairo-cocoa",)
433     elif target.os == "Android":
434         return ("cairo-android",)
435     else:
436         # cairo-gtk3 - X11 backend with optional Wayland backend (auto detected)
437         # cairo-gtk3-wayland - Wayland backend with optional X11 backend (auto detected)
438         # cairo-gtk3-x11-wayland - builds explicitly with X11 & Wayland backends
439         return (
440             "cairo-gtk3",
441             "cairo-gtk3-wayland",
442             "cairo-gtk3-x11-wayland",
443             "cairo-gtk3-wayland-only",
444             "cairo-gtk3-x11-only",
445         )
448 @depends(toolkit_choices)
449 def toolkit_default(choices):
450     return choices[0]
453 option(
454     "--enable-default-toolkit",
455     nargs=1,
456     choices=toolkit_choices,
457     default=toolkit_default,
458     help="Select default toolkit",
462 @depends("--enable-default-toolkit")
463 def full_toolkit(value):
464     if value:
465         return value[0]
468 @depends(full_toolkit)
469 def toolkit(toolkit):
470     if toolkit.startswith("cairo-gtk3"):
471         widget_toolkit = "gtk"
472     else:
473         widget_toolkit = toolkit.replace("cairo-", "")
474     return widget_toolkit
477 set_config("MOZ_WIDGET_TOOLKIT", toolkit)
478 add_old_configure_assignment("MOZ_WIDGET_TOOLKIT", toolkit)
481 @depends(toolkit)
482 def toolkit_define(toolkit):
483     if toolkit != "windows":
484         return "MOZ_WIDGET_%s" % toolkit.upper()
487 set_define(toolkit_define, True)
490 @depends(toolkit)
491 def toolkit_gtk(toolkit):
492     return toolkit == "gtk"
495 @depends(toolkit_gtk, full_toolkit)
496 def toolkit_gtk_x11(toolkit_gtk, full_toolkit):
497     return toolkit_gtk and full_toolkit != "cairo-gtk3-wayland-only"
500 @depends(full_toolkit)
501 def toolkit_gtk_x11_optional(full_toolkit):
502     return full_toolkit == "cairo-gtk3-wayland"
505 @depends(toolkit_gtk, full_toolkit)
506 def toolkit_gtk_wayland(toolkit_gtk, full_toolkit):
507     return toolkit_gtk and full_toolkit != "cairo-gtk3-x11-only"
510 @depends(full_toolkit)
511 def toolkit_gtk_wayland_optional(full_toolkit):
512     return full_toolkit == "cairo-gtk3"
515 # Wayland support
516 # ==============================================================
517 wayland_headers = pkg_check_modules(
518     "MOZ_WAYLAND",
519     "gtk+-wayland-3.0 >= 3.14 xkbcommon >= 0.4.1",
520     allow_missing=toolkit_gtk_wayland_optional,
521     when=toolkit_gtk_wayland,
525 @depends(wayland_headers, toolkit_gtk, artifact_builds, toolkit_gtk_wayland)
526 def wayland_headers(wayland, toolkit_gtk, artifacts, toolkit_gtk_wayland):
527     if not toolkit_gtk_wayland:
528         return False
529     if toolkit_gtk and artifacts:
530         return True
531     return wayland
534 set_config("MOZ_WAYLAND", depends_if(wayland_headers)(lambda _: True))
535 set_define("MOZ_WAYLAND", depends_if(wayland_headers)(lambda _: True))
538 # Hardware-accelerated video decode with VAAPI and V4L2 on Linux
539 # ==============================================================
540 set_config("MOZ_ENABLE_VAAPI", True, when=toolkit_gtk)
541 set_define("MOZ_ENABLE_VAAPI", True, when=toolkit_gtk)
544 @depends(target, toolkit_gtk)
545 def v4l2(target, toolkit_gtk):
546     # V4L2 decode is only used in GTK/Linux and generally only appears on
547     # embedded SOCs.
548     if target.cpu in ("arm", "aarch64", "riscv64") and toolkit_gtk:
549         return True
552 set_config("MOZ_ENABLE_V4L2", True, when=v4l2)
553 set_define("MOZ_ENABLE_V4L2", True, when=v4l2)
555 # GL Provider
556 # ==============================================================
557 option("--with-gl-provider", nargs=1, help="Set GL provider backend type")
560 @depends("--with-gl-provider")
561 def gl_provider(value):
562     if value:
563         return value[0]
566 @depends(gl_provider)
567 def gl_provider_define(provider):
568     if provider:
569         return "GLContextProvider%s" % provider
572 set_define("MOZ_GL_PROVIDER", gl_provider_define)
575 @depends(gl_provider, toolkit_gtk)
576 def gl_default_provider(value, toolkit_gtk):
577     if value:
578         return value
579     elif toolkit_gtk:
580         return "EGL"
583 set_config("MOZ_GL_PROVIDER", gl_provider)
584 set_config("MOZ_GL_DEFAULT_PROVIDER", gl_default_provider)
587 @depends(gl_default_provider)
588 def gl_provider_define(provider):
589     if provider:
590         return "GL_PROVIDER_%s" % provider
593 set_define(gl_provider_define, True)
596 # PDF printing
597 # ==============================================================
598 @depends(toolkit)
599 def pdf_printing(toolkit):
600     if toolkit in ("windows", "gtk", "android"):
601         return True
604 set_config("MOZ_PDF_PRINTING", pdf_printing)
605 set_define("MOZ_PDF_PRINTING", pdf_printing)
608 # Event loop instrumentation
609 # ==============================================================
610 option(env="MOZ_INSTRUMENT_EVENT_LOOP", help="Force-enable event loop instrumentation")
613 @depends("MOZ_INSTRUMENT_EVENT_LOOP", toolkit)
614 def instrument_event_loop(value, toolkit):
615     if value or (
616         toolkit in ("windows", "gtk", "cocoa", "android") and value.origin == "default"
617     ):
618         return True
621 set_config("MOZ_INSTRUMENT_EVENT_LOOP", instrument_event_loop)
622 set_define("MOZ_INSTRUMENT_EVENT_LOOP", instrument_event_loop)
625 # Fontconfig Freetype
626 # ==============================================================
627 option(env="USE_FC_FREETYPE", help="Force-enable the use of fontconfig freetype")
630 @depends("USE_FC_FREETYPE", toolkit)
631 def fc_freetype(value, toolkit):
632     if value or (toolkit == "gtk" and value.origin == "default"):
633         return True
636 set_define("USE_FC_FREETYPE", fc_freetype)
638 # Pango
639 # ==============================================================
640 pkg_check_modules("MOZ_PANGO", "pango >= 1.22.0", when=toolkit_gtk)
642 # Fontconfig
643 # ==============================================================
644 fontconfig_info = pkg_check_modules(
645     "_FONTCONFIG", "fontconfig >= 2.7.0", when=fc_freetype
649 @depends(fc_freetype)
650 def check_for_freetype2(fc_freetype):
651     if fc_freetype:
652         return True
655 # Check for freetype2. Flags are combined with fontconfig flags.
656 freetype2_info = pkg_check_modules(
657     "_FT2", "freetype2 >= 9.10.3", when=check_for_freetype2
661 @depends(fontconfig_info, freetype2_info)
662 def freetype2_combined_info(fontconfig_info, freetype2_info):
663     if not freetype2_info:
664         return
665     if not fontconfig_info:
666         return freetype2_info
667     return namespace(
668         cflags=freetype2_info.cflags + fontconfig_info.cflags,
669         libs=freetype2_info.libs + fontconfig_info.libs,
670     )
673 set_define("MOZ_HAVE_FREETYPE2", depends_if(freetype2_info)(lambda _: True))
676 # Apple platform decoder support
677 # ==============================================================
678 @depends(toolkit)
679 def applemedia(toolkit):
680     if toolkit in ("cocoa", "uikit"):
681         return True
684 set_config("MOZ_APPLEMEDIA", applemedia)
685 set_define("MOZ_APPLEMEDIA", applemedia)
687 # Windows Media Foundation support
688 # ==============================================================
689 option("--disable-wmf", help="Disable support for Windows Media Foundation")
692 @depends("--disable-wmf", target, "--help")
693 def wmf(value, target, _):
694     enabled = bool(value)
695     if value.origin == "default":
696         # Enable Windows Media Foundation support by default.
697         # Note our minimum SDK version is Windows 7 SDK, so we are (currently)
698         # guaranteed to have a recent-enough SDK to build WMF.
699         enabled = target.os == "WINNT"
700     if enabled and target.os != "WINNT":
701         die("Cannot enable Windows Media Foundation support on %s", target.os)
702     if enabled:
703         return True
706 @depends(artifact_builds, c_compiler, when=wmf)
707 def wmfmediaengine(artifact_builds, c_compiler):
708     if c_compiler:
709         return c_compiler.type == "clang-cl"
710     return bool(artifact_builds)
713 set_config("MOZ_WMF", wmf)
714 set_define("MOZ_WMF", wmf)
716 set_config("MOZ_WMF_MEDIA_ENGINE", True, when=wmfmediaengine)
717 set_define("MOZ_WMF_MEDIA_ENGINE", True, when=wmfmediaengine)
719 # FFmpeg H264/AAC Decoding Support
720 # ==============================================================
721 option("--disable-ffmpeg", help="Disable FFmpeg for fragmented H264/AAC decoding")
724 @depends("--disable-ffmpeg", target)
725 def ffmpeg(value, target):
726     enabled = bool(value)
727     if value.origin == "default":
728         enabled = target.os not in ("Android", "WINNT")
729     if enabled:
730         return True
733 set_config("MOZ_FFMPEG", ffmpeg)
734 set_define("MOZ_FFMPEG", ffmpeg)
736 # AV1 Video Codec Support
737 # ==============================================================
738 option("--disable-av1", help="Disable av1 video support")
741 @depends("--enable-av1")
742 def av1(value):
743     if value:
744         return True
747 @depends(target, when=av1 & compile_environment)
748 def dav1d_asm(target):
749     if target.cpu in ("aarch64", "x86", "x86_64"):
750         return True
753 @depends(target, when=av1 & compile_environment)
754 def dav1d_nasm(target):
755     if target.cpu in ("x86", "x86_64"):
756         return namespace(version="2.14", what="AV1")
759 set_config("MOZ_DAV1D_ASM", dav1d_asm)
760 set_define("MOZ_DAV1D_ASM", dav1d_asm)
761 set_config("MOZ_AV1", av1)
762 set_define("MOZ_AV1", av1)
764 # JXL Image Codec Support
765 # ==============================================================
766 option("--disable-jxl", help="Disable jxl image support")
769 @depends("--disable-jxl", milestone.is_nightly)
770 def jxl(value, is_nightly):
771     if is_nightly and value:
772         return True
775 set_config("MOZ_JXL", jxl)
776 set_define("MOZ_JXL", jxl)
778 set_config("MOZ_SAMPLE_TYPE_FLOAT32", True)
779 set_define("MOZ_SAMPLE_TYPE_FLOAT32", True)
781 set_define("MOZ_VORBIS", True)
782 set_config("MOZ_VORBIS", True)
784 option(
785     "--disable-real-time-tracing",
786     help="Disable tracing of real-time audio callbacks",
789 set_config("MOZ_REAL_TIME_TRACING", True, when="--enable-real-time-tracing")
790 set_define("MOZ_REAL_TIME_TRACING", True, when="--enable-real-time-tracing")
792 # OpenMAX IL Decoding Support
793 # ==============================================================
794 option("--enable-openmax", help="Enable OpenMAX IL for video/audio decoding")
797 @depends("--enable-openmax")
798 def openmax(value):
799     enabled = bool(value)
800     if enabled:
801         return True
804 set_config("MOZ_OMX", openmax)
805 set_define("MOZ_OMX", openmax)
808 # EME Support
809 # ==============================================================
810 @depends(target, wmf)
811 def eme_choices(target, wmf):
812     if (
813         target.kernel in ("WINNT", "Linux")
814         and target.os != "Android"
815         and target.cpu in ("x86", "x86_64")
816     ):
817         if wmf:
818             return ("widevine", "wmfcdm")
819         return ("widevine",)
820     if target.kernel == "WINNT" and target.cpu == "aarch64":
821         return ("widevine",)
822     if target.os in ("OSX"):
823         return ("widevine",)
826 # Widevine is enabled by default in desktop browser builds.
827 @depends(build_project, eme_choices)
828 def eme_default(build_project, choices):
829     if build_project == "browser":
830         return choices
833 option(
834     "--enable-eme",
835     nargs="+",
836     choices=eme_choices,
837     default=eme_default,
838     when=eme_choices,
839     help="{Enable|Disable} support for Encrypted Media Extensions",
843 @depends("--enable-eme", when=eme_choices)
844 def eme_modules(value):
845     return value
848 # Fallback to an empty list when eme_choices is empty, setting eme_modules to
849 # None.
850 set_config("MOZ_EME_MODULES", eme_modules | dependable([]))
853 # Media Foundation CDM support
854 # ==============================================================
855 @depends(eme_modules, when=wmfmediaengine)
856 def wmfcdm(modules):
857     if "wmfcdm" in modules:
858         return True
861 set_config("MOZ_WMF_CDM", True, when=wmfcdm)
862 set_define("MOZ_WMF_CDM", True, when=wmfcdm)
865 option(
866     name="--enable-chrome-format",
867     help="Select FORMAT of chrome files during packaging.",
868     nargs=1,
869     choices=("omni", "jar", "flat"),
870     default="omni",
874 @depends("--enable-chrome-format")
875 def packager_format(value):
876     return value[0]
879 set_config("MOZ_PACKAGER_FORMAT", packager_format)
881 # The packager minifies two different types of files: non-JS (mostly property
882 # files for l10n), and JS.  Setting MOZ_PACKAGER_MINIFY only minifies the
883 # former.  Firefox doesn't yet minify JS, due to concerns about debuggability.
885 # Also, the JS minification setup really only works correctly on Android:
886 # we need extra setup to use the newly-built shell for Linux and Windows,
887 # and cross-compilation for macOS requires some extra care.
890 @depends(target_is_android, "--enable-debug", milestone.is_nightly)
891 def enable_minify_default(is_android, debug, is_nightly):
892     if is_android and not debug and not is_nightly:
893         return ("properties", "js")
894     return ("properties",)
897 option(
898     name="--enable-minify",
899     help="Select types of files to minify during packaging.",
900     nargs="*",
901     choices=("properties", "js"),
902     default=enable_minify_default,
906 @depends("--enable-minify")
907 def enable_minify(value):
908     if "js" in value and "properties" not in value:
909         die("--enable-minify=js requires --enable-minify=properties.")
910     return namespace(
911         properties="properties" in value,
912         js="js" in value,
913     )
916 set_config("MOZ_PACKAGER_MINIFY", True, when=enable_minify.properties)
917 set_config("MOZ_PACKAGER_MINIFY_JS", True, when=enable_minify.js)
920 @depends(host, build_project)
921 def jar_maker_format(host, build_project):
922     # Multilocales for mobile/android use the same mergedirs for all locales,
923     # so we can't use symlinks for those builds.
924     if host.os == "WINNT" or build_project == "mobile/android":
925         return "flat"
926     return "symlink"
929 set_config("MOZ_JAR_MAKER_FILE_FORMAT", jar_maker_format)
932 @depends(toolkit)
933 def omnijar_name(toolkit):
934     # Fennec's static resources live in the assets/ folder of the
935     # APK.  Adding a path to the name here works because we only
936     # have one omnijar file in the final package (which is not the
937     # case on desktop).
938     return "assets/omni.ja" if toolkit == "android" else "omni.ja"
941 set_config("OMNIJAR_NAME", omnijar_name)
943 project_flag("MOZ_PLACES", help="Build Places if required", set_as_define=True)
945 project_flag(
946     "MOZ_SERVICES_HEALTHREPORT",
947     help="Build Firefox Health Reporter Service",
948     set_as_define=True,
951 project_flag(
952     "MOZ_NORMANDY",
953     help="Enable Normandy recipe runner",
954     set_as_define=True,
957 project_flag("MOZ_SERVICES_SYNC", help="Build Sync Services if required")
959 project_flag(
960     "MOZ_ANDROID_HISTORY",
961     help="Enable Android History instead of Places",
962     set_as_define=True,
965 project_flag(
966     "MOZ_DEDICATED_PROFILES",
967     help="Enable dedicated profiles per install",
968     set_as_define=True,
971 project_flag(
972     "MOZ_BLOCK_PROFILE_DOWNGRADE",
973     help="Block users from starting profiles last used by a newer build",
974     set_as_define=True,
978 @depends("MOZ_PLACES", "MOZ_ANDROID_HISTORY")
979 def check_places_and_android_history(places, android_history):
980     if places and android_history:
981         die("Cannot use MOZ_ANDROID_HISTORY alongside MOZ_PLACES.")
984 option(
985     env="MOZ_TELEMETRY_REPORTING",
986     default=mozilla_official,
987     help="Enable telemetry reporting",
990 set_define("MOZ_TELEMETRY_REPORTING", True, when="MOZ_TELEMETRY_REPORTING")
993 @depends("MOZ_TELEMETRY_REPORTING", milestone.is_nightly)
994 def telemetry_on_by_default(reporting, is_nightly):
995     return reporting and is_nightly
998 set_define("MOZ_TELEMETRY_ON_BY_DEFAULT", True, when=telemetry_on_by_default)
1001 # gpsd support
1002 # ==============================================================
1003 system_lib_option("--enable-gpsd", env="MOZ_GPSD", help="Enable gpsd support")
1006 @depends("--enable-gpsd")
1007 def gpsd(value):
1008     return bool(value)
1011 system_gpsd = pkg_check_modules("MOZ_GPSD", "libgps >= 3.11", when=gpsd)
1013 set_config("MOZ_GPSD", depends_if(system_gpsd)(lambda _: True))
1015 # Miscellaneous programs
1016 # ==============================================================
1018 check_prog("TAR", ("gnutar", "gtar", "tar"))
1019 check_prog("UNZIP", ("unzip",))
1021 # Key files
1022 # ==============================================================
1023 include("../build/moz.configure/keyfiles.configure")
1025 simple_keyfile("Mozilla API")
1027 simple_keyfile("Google Location Service API")
1029 simple_keyfile("Google Safebrowsing API")
1031 id_and_secret_keyfile("Bing API")
1033 simple_keyfile("Adjust SDK")
1035 id_and_secret_keyfile("Leanplum SDK")
1037 simple_keyfile("Pocket API")
1040 # WebRender Debugger integration
1041 # ==============================================================
1043 option(
1044     "--enable-webrender-debugger", help="Build the websocket debug server in WebRender"
1047 set_config(
1048     "MOZ_WEBRENDER_DEBUGGER", depends_if("--enable-webrender-debugger")(lambda _: True)
1051 # Additional system headers defined at the application level
1052 # ==============================================================
1054 option(
1055     "--enable-app-system-headers",
1056     env="MOZ_APP_SYSTEM_HEADERS",
1057     help="Use additional system headers defined in $MOZ_BUILD_APP/app-system-headers.mozbuild",
1061 @depends("--enable-app-system-headers")
1062 def app_system_headers(value):
1063     if value:
1064         return True
1067 set_config("MOZ_APP_SYSTEM_HEADERS", app_system_headers)
1068 set_define("MOZ_APP_SYSTEM_HEADERS", app_system_headers)
1070 # Printing
1071 # ==============================================================
1072 option("--disable-printing", help="Disable printing support")
1075 @depends("--disable-printing")
1076 def printing(value):
1077     if value:
1078         return True
1081 set_config("NS_PRINTING", printing)
1082 set_define("NS_PRINTING", printing)
1083 set_define("NS_PRINT_PREVIEW", printing)
1086 # Speech-dispatcher support
1087 # ==============================================================
1088 @depends(toolkit)
1089 def no_speechd_on_non_gtk(toolkit):
1090     if toolkit != "gtk":
1091         return False
1094 imply_option(
1095     "--enable-synth-speechd", no_speechd_on_non_gtk, reason="--enable-default-toolkit"
1098 option("--disable-synth-speechd", help="Disable speech-dispatcher support")
1100 set_config("MOZ_SYNTH_SPEECHD", depends_if("--disable-synth-speechd")(lambda _: True))
1102 # Speech API
1103 # ==============================================================
1104 option("--disable-webspeech", help="Disable support for HTML Speech API")
1107 @depends("--disable-webspeech")
1108 def webspeech(value):
1109     if value:
1110         return True
1113 set_config("MOZ_WEBSPEECH", webspeech)
1114 set_define("MOZ_WEBSPEECH", webspeech)
1116 # Speech API test backend
1117 # ==============================================================
1118 option(
1119     "--enable-webspeechtestbackend",
1120     default=webspeech,
1121     help="{Enable|Disable} support for HTML Speech API Test Backend",
1125 @depends_if("--enable-webspeechtestbackend")
1126 def webspeech_test_backend(value):
1127     return True
1130 set_config("MOZ_WEBSPEECH_TEST_BACKEND", webspeech_test_backend)
1131 set_define("MOZ_WEBSPEECH_TEST_BACKEND", webspeech_test_backend)
1134 # Graphics
1135 # ==============================================================
1136 @depends(target, milestone)
1137 def skia_pdf_default(target, milestone):
1138     return milestone.is_nightly and target.os != "WINNT"
1141 option("--enable-skia-pdf", default=skia_pdf_default, help="{Enable|Disable} Skia PDF")
1143 set_config("MOZ_ENABLE_SKIA_PDF", True, when="--enable-skia-pdf")
1144 set_define("MOZ_ENABLE_SKIA_PDF", True, when="--enable-skia-pdf")
1146 set_config(
1147     "SKIA_INCLUDES",
1148     [
1149         "/gfx/skia",
1150         "/gfx/skia/skia",
1151     ],
1154 system_lib_option(
1155     "--with-system-webp", help="Use system libwebp (located with pkgconfig)"
1158 system_webp = pkg_check_modules(
1159     "MOZ_WEBP", "libwebp >= 1.0.2 libwebpdemux >= 1.0.2", when="--with-system-webp"
1162 set_config("MOZ_SYSTEM_WEBP", depends(when=system_webp)(lambda: True))
1165 # Build Freetype in the tree
1166 # ==============================================================
1167 @depends(target, "--enable-skia-pdf")
1168 def tree_freetype(target, skia_pdf):
1169     if target.os == "Android" or (skia_pdf and target.os == "WINNT"):
1170         return True
1173 set_define("MOZ_TREE_FREETYPE", tree_freetype)
1174 set_config("MOZ_TREE_FREETYPE", tree_freetype)
1176 set_define("HAVE_FT_BITMAP_SIZE_Y_PPEM", tree_freetype)
1177 set_define("HAVE_FT_GLYPHSLOT_EMBOLDEN", tree_freetype)
1178 set_define("HAVE_FT_LOAD_SFNT_TABLE", tree_freetype)
1181 @depends(freetype2_combined_info, tree_freetype, build_environment)
1182 def ft2_info(freetype2_combined_info, tree_freetype, build_env):
1183     if tree_freetype:
1184         return namespace(
1185             cflags=("-I%s/modules/freetype2/include" % build_env.topsrcdir,), libs=()
1186         )
1187     if freetype2_combined_info:
1188         return freetype2_combined_info
1191 set_config("FT2_LIBS", ft2_info.libs)
1194 @depends(target, tree_freetype, freetype2_info)
1195 def enable_cairo_ft(target, tree_freetype, freetype2_info):
1196     # Avoid defining MOZ_ENABLE_CAIRO_FT on Windows platforms because
1197     # "cairo-ft-font.c" includes <dlfcn.h>, which only exists on posix platforms
1198     return freetype2_info or (tree_freetype and target.os != "WINNT")
1201 set_config("MOZ_ENABLE_CAIRO_FT", True, when=enable_cairo_ft)
1202 set_config("CAIRO_FT_CFLAGS", ft2_info.cflags, when=enable_cairo_ft)
1205 # WebDriver (HTTP / BiDi)
1206 # ==============================================================
1208 # WebDriver is a remote control interface that enables introspection and
1209 # control of user agents. It provides a platform- and language-neutral wire
1210 # protocol as a way for out-of-process programs to remotely instruct the
1211 # behavior of web browsers.
1213 # The Gecko implementation is backed by Marionette and Remote Agent.
1214 # Both protocols are not really toolkit features, as much as Gecko engine
1215 # features. But they are enabled based on the toolkit, so here it lives.
1217 # Marionette remote protocol
1218 # -----------------------------------------------------------
1220 # Marionette is the Gecko remote protocol used for various remote control,
1221 # automation, and testing purposes throughout Gecko-based applications like
1222 # Firefox, Thunderbird, and any mobile browser built upon GeckoView.
1224 # It also backs ../testing/geckodriver, which is Mozilla's WebDriver
1225 # implementation.
1227 # The source of Marionette lives in ../remote/marionette.
1229 # For more information, see:
1230 # https://firefox-source-docs.mozilla.org/testing/marionette/index.html
1232 # Remote Agent (WebDriver BiDi / partial CDP)
1233 # -----------------------------------------------------------
1235 # The primary purpose is the implementation of the WebDriver BiDi specification.
1236 # But it also complements the existing Firefox Developer Tools Remote Debugging
1237 # Protocol (RDP) by implementing a subset of the Chrome DevTools Protocol (CDP).
1239 # The source of Remote Agent lives in ../remote.
1241 # For more information, see:
1242 # https://firefox-source-docs.mozilla.org/remote/index.html
1245 option(
1246     "--disable-webdriver",
1247     help="Disable support for WebDriver remote protocols",
1251 @depends("--disable-webdriver")
1252 def webdriver(enabled):
1253     if enabled:
1254         return True
1257 set_config("ENABLE_WEBDRIVER", webdriver)
1258 set_define("ENABLE_WEBDRIVER", webdriver)
1261 # geckodriver WebDriver implementation
1262 # ==============================================================
1264 # Turn off geckodriver for build configs we don't handle yet,
1265 # but allow --enable-geckodriver to override when compile environment is available.
1266 # --disable-tests implies disabling geckodriver.
1267 # Disable building in CI
1270 @depends(
1271     "--enable-tests", target, cross_compiling, hazard_analysis, asan, "MOZ_AUTOMATION"
1273 def geckodriver_default(enable_tests, target, cross_compile, hazard, asan, automation):
1274     if not enable_tests:
1275         return False
1276     if hazard or target.os == "Android" or (asan and cross_compile):
1277         return False
1278     if automation:
1279         return False
1280     return True
1283 option(
1284     "--enable-geckodriver",
1285     default=geckodriver_default,
1286     when="--enable-compile-environment",
1287     help="{Build|Do not build} geckodriver",
1291 @depends("--enable-geckodriver", when="--enable-compile-environment")
1292 def geckodriver(enabled):
1293     if enabled:
1294         return True
1297 set_config("MOZ_GECKODRIVER", geckodriver)
1300 # WebRTC
1301 # ========================================================
1302 @depends(target)
1303 def webrtc_default(target):
1304     # Turn off webrtc for OS's we don't handle yet, but allow
1305     # --enable-webrtc to override.
1306     os_match = target.kernel in (
1307         "Linux",
1308         "WINNT",
1309         "DragonFly",
1310         "FreeBSD",
1311         "kFreeBSD",
1312         "NetBSD",
1313         "OpenBSD",
1314     )
1316     if not os_match:
1317         os_match = target.os in ("OSX",)
1319     cpu_match = target.cpu in (
1320         "x86_64",
1321         "arm",
1322         "aarch64",
1323         "x86",
1324         "ia64",
1325         "mips32",
1326         "mips64",
1327         "ppc",
1328         "ppc64",
1329         "riscv64",
1330     )
1332     return os_match and cpu_match and target.endianness == "little"
1335 option(
1336     "--disable-webrtc",
1337     default=webrtc_default,
1338     help="{Enable|Disable} support for WebRTC",
1342 @depends("--disable-webrtc")
1343 def webrtc(enabled):
1344     if enabled:
1345         return True
1348 set_config("MOZ_WEBRTC", webrtc)
1349 set_define("MOZ_WEBRTC", webrtc)
1350 set_config("MOZ_SCTP", webrtc)
1351 set_define("MOZ_SCTP", webrtc)
1352 set_config("MOZ_SRTP", webrtc)
1353 set_define("MOZ_SRTP", webrtc)
1354 set_config("MOZ_WEBRTC_SIGNALING", webrtc)
1355 set_define("MOZ_WEBRTC_SIGNALING", webrtc)
1356 set_config("MOZ_PEERCONNECTION", webrtc)
1357 set_define("MOZ_PEERCONNECTION", webrtc)
1358 # MOZ_WEBRTC_ASSERT_ALWAYS turns on a number of safety asserts in
1359 # opt/production builds (via MOZ_CRASH())
1360 set_config("MOZ_WEBRTC_ASSERT_ALWAYS", webrtc)
1361 set_define("MOZ_WEBRTC_ASSERT_ALWAYS", webrtc)
1363 # RAW media
1364 # ==============================================================
1367 @depends(target, webrtc)
1368 def raw_media_default(target, webrtc):
1369     if target.os == "Android":
1370         return True
1371     if webrtc:
1372         return True
1375 option(
1376     "--enable-raw",
1377     default=raw_media_default,
1378     help="{Enable|Disable} support for RAW media",
1381 set_config("MOZ_RAW", depends_if("--enable-raw")(lambda _: True))
1382 set_define("MOZ_RAW", depends_if("--enable-raw")(lambda _: True))
1385 # X11
1386 # ==============================================================
1387 @depends(webrtc, when=toolkit_gtk)
1388 def x11_libs(webrtc):
1389     libs = [
1390         "x11",
1391         "xcb",
1392         "xcb-shm",
1393         "x11-xcb",
1394         "xext",
1395         "xrandr >= 1.4.0",
1396     ]
1397     if webrtc:
1398         # third_party/libwebrtc/webrtc/webrtc_gn/moz.build adds those
1399         # manually, ensure they're available.
1400         libs += [
1401             "xcomposite",
1402             "xcursor",
1403             "xdamage",
1404             "xfixes",
1405             "xi",
1406         ]
1407     return libs
1410 x11_headers = pkg_check_modules(
1411     "MOZ_X11",
1412     x11_libs,
1413     allow_missing=toolkit_gtk_x11_optional,
1414     when=toolkit_gtk_x11,
1418 set_config("MOZ_X11", True, when=x11_headers)
1419 set_define("MOZ_X11", True, when=x11_headers)
1421 pkg_check_modules(
1422     "MOZ_X11_SM",
1423     ["ice", "sm"],
1424     cflags_only=True,
1425     allow_missing=toolkit_gtk_x11_optional,
1426     when=toolkit_gtk_x11,
1430 # ASan Reporter Addon
1431 # ==============================================================
1432 option(
1433     "--enable-address-sanitizer-reporter",
1434     help="Enable Address Sanitizer Reporter Extension",
1438 @depends("--enable-address-sanitizer-reporter")
1439 def enable_asan_reporter(value):
1440     if value:
1441         return True
1444 set_config("MOZ_ASAN_REPORTER", enable_asan_reporter)
1445 set_define("MOZ_ASAN_REPORTER", enable_asan_reporter)
1447 # Checks for library functions
1448 # ==============================================================
1449 with only_when(compile_environment & depends(target.os)(lambda os: os != "WINNT")):
1450     set_define("HAVE_STAT64", check_symbol("stat64"))
1451     set_define("HAVE_LSTAT64", check_symbol("lstat64"))
1452     set_define("HAVE_TRUNCATE64", check_symbol("truncate64"))
1453     set_define("HAVE_STATVFS64", check_symbol("statvfs64"))
1454     set_define("HAVE_STATVFS", check_symbol("statvfs"))
1455     set_define("HAVE_STATFS64", check_symbol("statfs64"))
1456     set_define("HAVE_STATFS", check_symbol("statfs"))
1457     set_define("HAVE_LUTIMES", check_symbol("lutimes"))
1458     set_define("HAVE_POSIX_FADVISE", check_symbol("posix_fadvise"))
1459     set_define("HAVE_POSIX_FALLOCATE", check_symbol("posix_fallocate"))
1460     set_define("HAVE_EVENTFD", check_symbol("eventfd"))
1462     have_arc4random = check_symbol("arc4random")
1463     set_define("HAVE_ARC4RANDOM", have_arc4random)
1464     set_define("HAVE_ARC4RANDOM_BUF", check_symbol("arc4random_buf"))
1465     set_define("HAVE_MALLINFO", check_symbol("mallinfo"))
1467 # Checks for headers
1468 # ==============================================================
1469 with only_when(compile_environment & depends(target.os)(lambda os: os != "WINNT")):
1470     set_define("HAVE_SYSIOCCOM_H", check_header("sys/ioccom.h"))
1472 # Elfhack
1473 # ==============================================================
1474 with only_when("--enable-compile-environment"):
1476     @depends(host, target)
1477     def has_elfhack(host, target):
1478         return (
1479             target.kernel == "Linux"
1480             and host.kernel == "Linux"
1481             and target.cpu in ("arm", "aarch64", "x86", "x86_64")
1482         )
1484     option(
1485         "--disable-elf-hack",
1486         nargs="?",
1487         choices=("legacy", "relr"),
1488         help="{Enable|Disable} elf hacks",
1489         when=has_elfhack,
1490     )
1492     @depends("--enable-elf-hack", when=has_elfhack)
1493     def may_enable_legacy_elfhack(enable):
1494         if enable and enable != ("relr",):
1495             return enable
1497     @depends("--enable-elf-hack", when=has_elfhack)
1498     def may_enable_relrhack(enable):
1499         if enable and enable != ("legacy",):
1500             return enable
1502     @depends(
1503         have_arc4random,
1504         android_version,
1505         when=target_has_linux_kernel,
1506     )
1507     def may_use_pack_relative_relocs(have_arc4random, android_version):
1508         # Packed relative relocations are only supported on Android since
1509         # version 11 (API 30), and in glibc since version 2.36.
1510         # glibc 2.36 also added the arc4random function, which is our proxy
1511         # to detect this (or newer) version being used.
1512         # When targetting those newer versions, we allow ourselves to use
1513         # packed relative relocations rather than elfhack.
1514         if android_version:
1515             return android_version >= 30
1516         return have_arc4random
1518     @depends(
1519         c_compiler,
1520         extra_toolchain_flags,
1521         linker_ldflags,
1522         readelf,
1523         when=may_use_pack_relative_relocs | may_enable_relrhack,
1524     )
1525     @checking("for -z pack-relative-relocs option to ld", bool)
1526     @imports(_from="__builtin__", _import="FileNotFoundError")
1527     @imports("os")
1528     @imports(_from="tempfile", _import="mkstemp")
1529     @imports("textwrap")
1530     def has_pack_relative_relocs(
1531         c_compiler,
1532         extra_toolchain_flags,
1533         linker_ldflags,
1534         readelf,
1535     ):
1536         try:
1537             fd, path = mkstemp(prefix="conftest.")
1538             os.close(fd)
1540             pack_rel_relocs = ["-Wl,-z,pack-relative-relocs"]
1541             if (
1542                 try_invoke_compiler(
1543                     # No configure_cache because it would not create the
1544                     # expected output file.
1545                     None,
1546                     [c_compiler.compiler] + c_compiler.flags,
1547                     c_compiler.language,
1548                     # The resulting binary is expected to have relative
1549                     # relocations, the `ptr` variable attempts to ensure
1550                     # there is at least one. This requires the executable
1551                     # being built as position independent.
1552                     "int main() { return 0; }\nint (*ptr)() = main;",
1553                     pack_rel_relocs
1554                     + ["-pie", "-o", path]
1555                     + (extra_toolchain_flags or [])
1556                     + linker_ldflags,
1557                     wrapper=c_compiler.wrapper,
1558                     onerror=lambda: None,
1559                 )
1560                 is not None
1561             ):
1562                 # BFD ld ignores options it doesn't understand. So check
1563                 # that we did get packed relative relocations (DT_RELR).
1564                 env = os.environ.copy()
1565                 env["LANG"] = "C"
1566                 dyn = check_cmd_output(readelf, "-d", path, env=env).splitlines()
1567                 tags = [
1568                     int(l.split()[0], 16) for l in dyn if l.strip().startswith("0x")
1569                 ]
1570                 # Older versions of readelf don't know about DT_RELR but will
1571                 # still display the tag number.
1572                 if 0x23 in tags:
1573                     needed = [l for l in dyn if l.split()[1:2] == ["(NEEDED)"]]
1574                     is_glibc = any(l.endswith("[libc.so.6]") for l in needed)
1575                     # The mold linker doesn't add a GLIBC_ABI_DT_RELR version
1576                     # dependency, which ld.so doesn't like.
1577                     # https://github.com/rui314/mold/issues/653#issuecomment-1670274638
1578                     if is_glibc:
1579                         versions = check_cmd_output(readelf, "-V", path, env=env)
1580                         if "GLIBC_ABI_DT_RELR" in versions.split():
1581                             return pack_rel_relocs
1582                     else:
1583                         return pack_rel_relocs
1584         finally:
1585             try:
1586                 os.remove(path)
1587             except FileNotFoundError:
1588                 pass
1590     @depends(
1591         has_pack_relative_relocs,
1592         may_enable_legacy_elfhack,
1593         may_enable_relrhack,
1594         may_use_pack_relative_relocs,
1595         when=has_pack_relative_relocs,
1596     )
1597     def pack_relative_relocs_flags(
1598         flags,
1599         may_enable_legacy_elfhack,
1600         may_enable_relrhack,
1601         may_use_pack_relative_relocs,
1602     ):
1603         # When relrhack is enabled, we don't pass the flag to the linker because
1604         # relrhack will take care of it.
1605         if may_enable_relrhack and may_enable_relrhack.origin != "default":
1606             return None
1607         # if elfhack is explicitly enabled instead of relrhack, we prioritize it
1608         # over packed relative relocs.
1609         if may_enable_legacy_elfhack and may_enable_legacy_elfhack.origin != "default":
1610             return None
1611         if may_use_pack_relative_relocs:
1612             return flags
1614     add_old_configure_assignment("PACK_REL_RELOC_FLAGS", pack_relative_relocs_flags)
1616     @depends(
1617         select_linker,
1618         pack_relative_relocs_flags,
1619         has_pack_relative_relocs,
1620         may_enable_legacy_elfhack,
1621         may_enable_relrhack,
1622         when=has_elfhack,
1623     )
1624     def which_elf_hack(
1625         linker,
1626         pack_relative_relocs_flags,
1627         has_pack_relative_relocs,
1628         may_enable_legacy_elfhack,
1629         may_enable_relrhack,
1630     ):
1631         if pack_relative_relocs_flags:
1632             return
1633         if may_enable_relrhack:
1634             if has_pack_relative_relocs:
1635                 return "relr"
1636             elif (
1637                 may_enable_relrhack.origin != "default"
1638                 and not may_enable_legacy_elfhack
1639             ):
1640                 die(
1641                     "Cannot enable relrhack without linker support for -z pack-relative-relocs"
1642                 )
1643         if may_enable_legacy_elfhack:
1644             if linker and linker.KIND in ("lld", "mold"):
1645                 if may_enable_legacy_elfhack.origin != "default":
1646                     die(
1647                         f"Cannot enable elfhack with {linker.KIND}."
1648                         " Use --enable-linker=bfd, --enable-linker=gold, or --disable-elf-hack"
1649                     )
1650             else:
1651                 return "legacy"
1653     set_config(
1654         "USE_ELF_HACK", True, when=depends(which_elf_hack)(lambda x: x == "legacy")
1655     )
1657     use_relrhack = depends(which_elf_hack)(lambda x: x == "relr")
1658     set_config("RELRHACK", True, when=use_relrhack)
1660     @depends(c_compiler, linker_ldflags, when=use_relrhack)
1661     def relrhack_real_linker(c_compiler, linker_ldflags):
1662         ld = "ld"
1663         for flag in linker_ldflags:
1664             if flag.startswith("-fuse-ld="):
1665                 ld = "ld." + flag[len("-fuse-ld=") :]
1666         ld = check_cmd_output(
1667             c_compiler.compiler, f"--print-prog-name={ld}", *c_compiler.flags
1668         )
1669         return ld.rstrip()
1671     @depends(relrhack_real_linker, when=use_relrhack)
1672     def relrhack_linker(ld):
1673         return os.path.basename(ld)
1675     set_config("RELRHACK_LINKER", relrhack_linker)
1677     std_filesystem = host_cxx_compiler.try_run(
1678         header="#include <filesystem>",
1679         body='auto foo = std::filesystem::absolute("");',
1680         flags=host_linker_ldflags,
1681         when=use_relrhack,
1682         onerror=lambda: None,
1683     )
1685     stdcxxfs = host_cxx_compiler.try_run(
1686         header="#include <filesystem>",
1687         body='auto foo = std::filesystem::absolute("");',
1688         flags=depends(host_linker_ldflags)(
1689             lambda flags: (flags or []) + ["-lstdc++fs"]
1690         ),
1691         check_msg="whether std::filesystem requires -lstdc++fs",
1692         when=use_relrhack & depends(std_filesystem)(lambda x: not x),
1693         onerror=lambda: None,
1694     )
1696     set_config("RELRHACK_LIBS", ["stdc++fs"], when=stdcxxfs)
1698     @depends(build_environment, relrhack_real_linker, when=use_relrhack)
1699     def relrhack_ldflags(build_env, ld):
1700         flags = [
1701             "-B",
1702             os.path.join(build_env.topobjdir, "build", "unix", "elfhack"),
1703         ]
1704         if os.path.basename(ld) != ld:
1705             flags.append(f"-Wl,--real-linker,{ld}")
1706         return flags
1708     set_config("RELRHACK_LDFLAGS", relrhack_ldflags)
1711 @depends(build_environment)
1712 def idl_roots(build_env):
1713     return namespace(
1714         ipdl_root=os.path.join(build_env.topobjdir, "ipc", "ipdl"),
1715         webidl_root=os.path.join(build_env.topobjdir, "dom", "bindings"),
1716         xpcom_root=os.path.join(build_env.topobjdir, "xpcom", "components"),
1717     )
1720 set_config("WEBIDL_ROOT", idl_roots.webidl_root)
1721 set_config("IPDL_ROOT", idl_roots.ipdl_root)
1722 set_config("XPCOM_ROOT", idl_roots.xpcom_root)
1724 # Proxy bypass protection
1725 # ==============================================================
1727 option(
1728     "--enable-proxy-bypass-protection",
1729     help="Prevent suspected or confirmed proxy bypasses",
1733 @depends_if("--enable-proxy-bypass-protection")
1734 def proxy_bypass_protection(_):
1735     return True
1738 set_config("MOZ_PROXY_BYPASS_PROTECTION", proxy_bypass_protection)
1739 set_define("MOZ_PROXY_BYPASS_PROTECTION", proxy_bypass_protection)
1741 # Proxy direct failover
1742 # ==============================================================
1744 option(
1745     "--disable-proxy-direct-failover",
1746     help="Disable direct failover for system requests",
1750 @depends_if("--disable-proxy-direct-failover")
1751 def proxy_direct_failover(value):
1752     if value:
1753         return True
1756 set_config("MOZ_PROXY_DIRECT_FAILOVER", proxy_direct_failover)
1757 set_define("MOZ_PROXY_DIRECT_FAILOVER", proxy_direct_failover)
1759 # MIDL
1760 # ==============================================================
1763 @depends(c_compiler, toolchain_prefix)
1764 def midl_names(c_compiler, toolchain_prefix):
1765     if c_compiler and c_compiler.type in ["gcc", "clang"]:
1766         # mingw
1767         widl = ("widl",)
1768         if toolchain_prefix:
1769             prefixed = tuple("%s%s" % (p, "widl") for p in toolchain_prefix)
1770             widl = prefixed + widl
1771         return widl
1773     return ("midl.exe",)
1776 @depends(target, "--enable-compile-environment")
1777 def check_for_midl(target, compile_environment):
1778     if target.os != "WINNT":
1779         return
1781     if compile_environment:
1782         return True
1785 midl = check_prog(
1786     "MIDL",
1787     midl_names,
1788     when=check_for_midl,
1789     allow_missing=True,
1790     paths=sdk_bin_path,
1791     # MIDL being used from a python wrapper script, we can live with it
1792     # having spaces.
1793     allow_spaces=True,
1796 option(env="MIDL_FLAGS", nargs=1, help="Extra flags to pass to MIDL")
1799 @depends(
1800     "MIDL_FLAGS",
1801     target,
1802     midl,
1803     when=depends(midl, target)(lambda m, t: m and t.kernel == "WINNT"),
1805 def midl_flags(flags, target, midl):
1806     if flags:
1807         flags = flags[0].split()
1808     else:
1809         flags = []
1811     if not midl.endswith("widl"):
1812         env = {
1813             "x86": "win32",
1814             "x86_64": "x64",
1815             "aarch64": "arm64",
1816         }[target.cpu]
1817         return flags + ["-nologo", "-no_cpp", "-env", env]
1819     # widl
1820     return (
1821         flags
1822         + {
1823             "x86": ["--win32", "-m32"],
1824             "x86_64": ["--win64", "-m64"],
1825         }[target.cpu]
1826     )
1829 set_config("MIDL_FLAGS", midl_flags)
1831 # Accessibility
1832 # ==============================================================
1834 option("--disable-accessibility", help="Disable accessibility support")
1837 @depends("--enable-accessibility", check_for_midl, midl, c_compiler)
1838 def accessibility(value, check_for_midl, midl, c_compiler):
1839     enabled = bool(value)
1841     if not enabled:
1842         return
1844     if check_for_midl and not midl:
1845         if c_compiler and c_compiler.type in ("gcc", "clang"):
1846             die(
1847                 "You have accessibility enabled, but widl could not be found. "
1848                 "Add --disable-accessibility to your mozconfig or install widl. "
1849                 "See https://developer.mozilla.org/en-US/docs/Cross_Compile_Mozilla_for_Mingw32 for details."
1850             )
1851         else:
1852             die(
1853                 "MIDL could not be found. "
1854                 "Building accessibility without MIDL is not supported."
1855             )
1857     return enabled
1860 set_config("ACCESSIBILITY", accessibility)
1861 set_define("ACCESSIBILITY", accessibility)
1864 @depends(moz_debug, developer_options)
1865 def a11y_log(debug, developer_options):
1866     return debug or developer_options
1869 set_config("A11Y_LOG", True, when=a11y_log)
1870 set_define("A11Y_LOG", True, when=a11y_log)
1873 # Addon signing
1874 # ==============================================================
1875 @depends(milestone)
1876 def require_signing(milestone):
1877     return milestone.is_release_or_beta and not milestone.is_esr
1880 option(
1881     env="MOZ_REQUIRE_SIGNING",
1882     default=require_signing,
1883     help="Enforce that add-ons are signed by the trusted root",
1886 set_config("MOZ_REQUIRE_SIGNING", True, when="MOZ_REQUIRE_SIGNING")
1887 set_define("MOZ_REQUIRE_SIGNING", True, when="MOZ_REQUIRE_SIGNING")
1889 option(
1890     "--with-unsigned-addon-scopes",
1891     nargs="+",
1892     choices=("app", "system"),
1893     help="Addon scopes where signature is not required",
1897 @depends("--with-unsigned-addon-scopes")
1898 def unsigned_addon_scopes(scopes):
1899     return namespace(
1900         app="app" in scopes or None,
1901         system="system" in scopes or None,
1902     )
1905 set_config("MOZ_UNSIGNED_APP_SCOPE", unsigned_addon_scopes.app)
1906 set_config("MOZ_UNSIGNED_SYSTEM_SCOPE", unsigned_addon_scopes.system)
1909 # Addon sideloading
1910 # ==============================================================
1911 option(
1912     "--allow-addon-sideload",
1913     default=milestone.is_esr,
1914     help="Addon sideloading is allowed",
1918 set_config("MOZ_ALLOW_ADDON_SIDELOAD", True, when="--allow-addon-sideload")
1920 # WebExtensions API WebIDL bindings
1921 # ==============================================================
1924 @depends(milestone)
1925 def extensions_webidl_bindings_default(milestone):
1926     # Only enable the webidl bindings for the WebExtensions APIs
1927     # in Nightly.
1928     return milestone.is_nightly
1931 option(
1932     "--enable-extensions-webidl-bindings",
1933     default=extensions_webidl_bindings_default,
1934     help="{Enable|Disable} building experimental WebExtensions WebIDL bindings",
1938 @depends("--enable-extensions-webidl-bindings")
1939 def extensions_webidl_enabled(value):
1940     return bool(value)
1943 set_config("MOZ_WEBEXT_WEBIDL_ENABLED", extensions_webidl_enabled)
1945 # Launcher process (Windows only)
1946 # ==============================================================
1949 @depends(target)
1950 def launcher_process_default(target):
1951     return target.os == "WINNT"
1954 option(
1955     "--enable-launcher-process",
1956     default=launcher_process_default,
1957     help="{Enable|Disable} launcher process by default",
1961 @depends("--enable-launcher-process", target)
1962 def launcher(value, target):
1963     enabled = bool(value)
1964     if enabled and target.os != "WINNT":
1965         die("Cannot enable launcher process on %s", target.os)
1966     if enabled:
1967         return True
1970 set_config("MOZ_LAUNCHER_PROCESS", launcher)
1971 set_define("MOZ_LAUNCHER_PROCESS", launcher)
1973 # llvm-dlltool (Windows only)
1974 # ==============================================================
1977 @depends(build_project, target, "--enable-compile-environment")
1978 def check_for_llvm_dlltool(build_project, target, compile_environment):
1979     if build_project != "browser":
1980         return
1982     if target.os != "WINNT":
1983         return
1985     return compile_environment
1988 llvm_dlltool = check_prog(
1989     "LLVM_DLLTOOL",
1990     ("llvm-dlltool",),
1991     what="llvm-dlltool",
1992     when=check_for_llvm_dlltool,
1993     paths=clang_search_path,
1997 @depends(target, when=llvm_dlltool)
1998 def llvm_dlltool_flags(target):
1999     arch = {
2000         "x86": "i386",
2001         "x86_64": "i386:x86-64",
2002         "aarch64": "arm64",
2003     }[target.cpu]
2005     return ["-m", arch]
2008 set_config("LLVM_DLLTOOL_FLAGS", llvm_dlltool_flags)
2010 # BITS download (Windows only)
2011 # ==============================================================
2013 option(
2014     "--enable-bits-download",
2015     when=target_is_windows,
2016     default=target_is_windows,
2017     help="{Enable|Disable} building BITS download support",
2020 set_define(
2021     "MOZ_BITS_DOWNLOAD",
2022     depends_if("--enable-bits-download", when=target_is_windows)(lambda _: True),
2024 set_config(
2025     "MOZ_BITS_DOWNLOAD",
2026     depends_if("--enable-bits-download", when=target_is_windows)(lambda _: True),
2029 # Bundled fonts on desktop platform
2030 # ==============================================================
2033 @depends(target)
2034 def bundled_fonts_default(target):
2035     return target.os == "WINNT" or target.kernel == "Linux"
2038 @depends(build_project)
2039 def allow_bundled_fonts(project):
2040     return project == "browser" or project == "comm/mail"
2043 option(
2044     "--enable-bundled-fonts",
2045     default=bundled_fonts_default,
2046     when=allow_bundled_fonts,
2047     help="{Enable|Disable} support for bundled fonts on desktop platforms",
2050 set_define(
2051     "MOZ_BUNDLED_FONTS",
2052     depends_if("--enable-bundled-fonts", when=allow_bundled_fonts)(lambda _: True),
2055 # Reflow counting
2056 # ==============================================================
2059 @depends(moz_debug)
2060 def reflow_perf(debug):
2061     if debug:
2062         return True
2065 option(
2066     "--enable-reflow-perf",
2067     default=reflow_perf,
2068     help="{Enable|Disable} reflow performance tracing",
2071 # The difference in conditions here comes from the initial implementation
2072 # in old-configure, which was unexplained there as well.
2073 set_define("MOZ_REFLOW_PERF", depends_if("--enable-reflow-perf")(lambda _: True))
2074 set_define("MOZ_REFLOW_PERF_DSP", reflow_perf)
2076 # Layout debugger
2077 # ==============================================================
2080 @depends(moz_debug)
2081 def layout_debugger(debug):
2082     if debug:
2083         return True
2086 option(
2087     "--enable-layout-debugger",
2088     default=layout_debugger,
2089     help="{Enable|Disable} layout debugger",
2092 set_config("MOZ_LAYOUT_DEBUGGER", True, when="--enable-layout-debugger")
2093 set_define("MOZ_LAYOUT_DEBUGGER", True, when="--enable-layout-debugger")
2096 # Shader Compiler for Windows (and MinGW Cross Compile)
2097 # ==============================================================
2099 with only_when(compile_environment):
2100     fxc = check_prog(
2101         "FXC",
2102         ("fxc.exe", "fxc2.exe"),
2103         when=depends(target)(lambda t: t.kernel == "WINNT"),
2104         paths=sdk_bin_path,
2105         # FXC being used from a python wrapper script, we can live with it
2106         # having spaces.
2107         allow_spaces=True,
2108     )
2111 # VPX
2112 # ===
2114 with only_when(compile_environment):
2115     system_lib_option(
2116         "--with-system-libvpx", help="Use system libvpx (located with pkgconfig)"
2117     )
2119     with only_when("--with-system-libvpx"):
2120         vpx = pkg_check_modules("MOZ_LIBVPX", "vpx >= 1.10.0")
2122         check_header(
2123             "vpx/vpx_decoder.h",
2124             flags=vpx.cflags,
2125             onerror=lambda: die(
2126                 "Couldn't find vpx/vpx_decoder.h, which is required to build "
2127                 "with system libvpx. Use --without-system-libvpx to build "
2128                 "with in-tree libvpx."
2129             ),
2130         )
2132         check_symbol(
2133             "vpx_codec_dec_init_ver",
2134             flags=vpx.libs,
2135             onerror=lambda: die(
2136                 "--with-system-libvpx requested but symbol vpx_codec_dec_init_ver "
2137                 "not found"
2138             ),
2139         )
2141         set_config("MOZ_SYSTEM_LIBVPX", True)
2143     @depends("--with-system-libvpx", target)
2144     def in_tree_vpx(system_libvpx, target):
2145         if system_libvpx:
2146             return
2148         arm_asm = (target.cpu == "arm") or None
2149         return namespace(arm_asm=arm_asm)
2151     @depends(target, when=in_tree_vpx)
2152     def vpx_nasm(target):
2153         if target.cpu in ("x86", "x86_64"):
2154             if target.kernel == "WINNT":
2155                 # Version 2.03 is needed for automatic safeseh support.
2156                 return namespace(version="2.03", what="VPX")
2157             return namespace(what="VPX")
2159     @depends(in_tree_vpx, vpx_nasm, target, neon_flags)
2160     def vpx_as_flags(vpx, vpx_nasm, target, neon_flags):
2161         if vpx and vpx.arm_asm:
2162             # These flags are a lie; they're just used to enable the requisite
2163             # opcodes; actual arch detection is done at runtime.
2164             return neon_flags
2165         elif vpx and vpx_nasm and target.os != "WINNT" and target.cpu != "x86_64":
2166             return ("-DPIC",)
2168     set_config("VPX_USE_NASM", True, when=vpx_nasm)
2169     set_config("VPX_ASFLAGS", vpx_as_flags)
2172 # JPEG
2173 # ====
2175 with only_when(compile_environment):
2176     system_lib_option(
2177         "--with-system-jpeg",
2178         nargs="?",
2179         help="Use system libjpeg (installed at given prefix)",
2180     )
2182     @depends_if("--with-system-jpeg")
2183     def jpeg_flags(value):
2184         if len(value):
2185             return namespace(
2186                 cflags=("-I%s/include" % value[0],),
2187                 ldflags=("-L%s/lib" % value[0], "-ljpeg"),
2188             )
2189         return namespace(
2190             ldflags=("-ljpeg",),
2191         )
2193     with only_when("--with-system-jpeg"):
2194         check_symbol(
2195             "jpeg_destroy_compress",
2196             flags=jpeg_flags.ldflags,
2197             onerror=lambda: die(
2198                 "--with-system-jpeg requested but symbol "
2199                 "jpeg_destroy_compress not found."
2200             ),
2201         )
2203         c_compiler.try_compile(
2204             includes=[
2205                 "stdio.h",
2206                 "sys/types.h",
2207                 "jpeglib.h",
2208             ],
2209             body="""
2210                 #if JPEG_LIB_VERSION < 62
2211                 #error Insufficient JPEG library version
2212                 #endif
2213             """,
2214             flags=jpeg_flags.cflags,
2215             check_msg="for sufficient jpeg library version",
2216             onerror=lambda: die(
2217                 "Insufficient JPEG library version for "
2218                 "--with-system-jpeg (62 required)"
2219             ),
2220         )
2222         c_compiler.try_compile(
2223             includes=[
2224                 "stdio.h",
2225                 "sys/types.h",
2226                 "jpeglib.h",
2227             ],
2228             body="""
2229                 #ifndef JCS_EXTENSIONS
2230                 #error libjpeg-turbo JCS_EXTENSIONS required
2231                 #endif
2232             """,
2233             flags=jpeg_flags.cflags,
2234             check_msg="for sufficient libjpeg-turbo JCS_EXTENSIONS",
2235             onerror=lambda: die(
2236                 "libjpeg-turbo JCS_EXTENSIONS required for " "--with-system-jpeg"
2237             ),
2238         )
2240         set_config("MOZ_JPEG_CFLAGS", jpeg_flags.cflags)
2241         set_config("MOZ_JPEG_LIBS", jpeg_flags.ldflags)
2243     @depends("--with-system-jpeg", target, neon_flags)
2244     def in_tree_jpeg_arm(system_jpeg, target, neon_flags):
2245         if system_jpeg:
2246             return
2248         if target.cpu == "arm":
2249             return neon_flags
2250         elif target.cpu == "aarch64":
2251             return ("-march=armv8-a",)
2253     @depends("--with-system-jpeg", target)
2254     def in_tree_jpeg_mips64(system_jpeg, target):
2255         if system_jpeg:
2256             return
2258         if target.cpu == "mips64":
2259             return ("-Wa,-mloongson-mmi", "-mloongson-ext")
2261     # Compiler check from https://github.com/libjpeg-turbo/libjpeg-turbo/blob/57ba02a408a9a55ccff25aae8b164632a3a4f177/simd/CMakeLists.txt#L419
2262     jpeg_mips64_mmi = c_compiler.try_compile(
2263         body='int c = 0, a = 0, b = 0; asm("paddb %0, %1, %2" : "=f" (c) : "f" (a), "f" (b));',
2264         check_msg="for loongson mmi support",
2265         flags=in_tree_jpeg_mips64,
2266         when=in_tree_jpeg_mips64,
2267     )
2269     @depends(
2270         "--with-system-jpeg",
2271         target,
2272         in_tree_jpeg_arm,
2273         in_tree_jpeg_mips64,
2274         jpeg_mips64_mmi,
2275     )
2276     def in_tree_jpeg(
2277         system_jpeg, target, in_tree_jpeg_arm, in_tree_jpeg_mips64, jpeg_mips64_mmi
2278     ):
2279         if system_jpeg:
2280             return
2282         if target.cpu in ("arm", "aarch64"):
2283             return in_tree_jpeg_arm
2284         elif target.kernel == "Darwin":
2285             if target.cpu == "x86":
2286                 return ("-DPIC", "-DMACHO")
2287             elif target.cpu == "x86_64":
2288                 return ("-D__x86_64__", "-DPIC", "-DMACHO")
2289         elif target.kernel == "WINNT":
2290             if target.cpu == "x86":
2291                 return ("-DPIC", "-DWIN32")
2292             elif target.cpu == "x86_64":
2293                 return ("-D__x86_64__", "-DPIC", "-DWIN64", "-DMSVC")
2294         elif target.cpu == "mips32":
2295             return ("-mdspr2",)
2296         elif target.cpu == "mips64" and jpeg_mips64_mmi:
2297             return in_tree_jpeg_mips64
2298         elif target.cpu == "x86":
2299             return ("-DPIC", "-DELF")
2300         elif target.cpu == "x86_64":
2301             return ("-D__x86_64__", "-DPIC", "-DELF")
2303     @depends(target, when=depends("--with-system-jpeg")(lambda x: not x))
2304     def jpeg_nasm(target):
2305         if target.cpu in ("x86", "x86_64"):
2306             # libjpeg-turbo 2.0.6 requires nasm 2.10.
2307             return namespace(version="2.10", what="JPEG")
2309     # Compiler checks from https://github.com/libjpeg-turbo/libjpeg-turbo/blob/57ba02a408a9a55ccff25aae8b164632a3a4f177/simd/CMakeLists.txt#L258
2310     jpeg_arm_neon_vld1_s16_x3 = c_compiler.try_compile(
2311         includes=["arm_neon.h"],
2312         body="int16_t input[12] = {}; int16x4x3_t output = vld1_s16_x3(input);",
2313         check_msg="for vld1_s16_x3 in arm_neon.h",
2314         flags=in_tree_jpeg_arm,
2315         when=in_tree_jpeg_arm,
2316     )
2318     jpeg_arm_neon_vld1_u16_x2 = c_compiler.try_compile(
2319         includes=["arm_neon.h"],
2320         body="uint16_t input[8] = {}; uint16x4x2_t output = vld1_u16_x2(input);",
2321         check_msg="for vld1_u16_x2 in arm_neon.h",
2322         flags=in_tree_jpeg_arm,
2323         when=in_tree_jpeg_arm,
2324     )
2326     jpeg_arm_neon_vld1q_u8_x4 = c_compiler.try_compile(
2327         includes=["arm_neon.h"],
2328         body="uint8_t input[64] = {}; uint8x16x4_t output = vld1q_u8_x4(input);",
2329         check_msg="for vld1q_u8_x4 in arm_neon.h",
2330         flags=in_tree_jpeg_arm,
2331         when=in_tree_jpeg_arm,
2332     )
2334     set_config("LIBJPEG_TURBO_USE_NASM", True, when=jpeg_nasm)
2335     set_config("LIBJPEG_TURBO_SIMD_FLAGS", in_tree_jpeg)
2336     set_config("LIBJPEG_TURBO_HAVE_VLD1_S16_X3", jpeg_arm_neon_vld1_s16_x3)
2337     set_config("LIBJPEG_TURBO_HAVE_VLD1_U16_X2", jpeg_arm_neon_vld1_u16_x2)
2338     set_config("LIBJPEG_TURBO_HAVE_VLD1Q_U8_X4", jpeg_arm_neon_vld1q_u8_x4)
2339     set_config(
2340         "LIBJPEG_TURBO_NEON_INTRINSICS",
2341         jpeg_arm_neon_vld1_s16_x3
2342         & jpeg_arm_neon_vld1_u16_x2
2343         & jpeg_arm_neon_vld1q_u8_x4,
2344     )
2347 # PNG
2348 # ===
2349 with only_when(compile_environment):
2350     system_lib_option(
2351         "--with-system-png",
2352         nargs="?",
2353         help="Use system libpng",
2354     )
2356     @depends("--with-system-png")
2357     def deprecated_system_png_path(value):
2358         if len(value) == 1:
2359             die(
2360                 "--with-system-png=PATH is not supported anymore. Please use "
2361                 "--with-system-png and set any necessary pkg-config environment variable."
2362             )
2364     png = pkg_check_modules("MOZ_PNG", "libpng >= 1.6.35", when="--with-system-png")
2366     check_symbol(
2367         "png_get_acTL",
2368         flags=png.libs,
2369         onerror=lambda: die(
2370             "--with-system-png won't work because the system's libpng doesn't have APNG support"
2371         ),
2372         when="--with-system-png",
2373     )
2375     set_config("MOZ_SYSTEM_PNG", True, when="--with-system-png")
2378 # FFmpeg's ffvpx configuration
2379 # ==============================================================
2380 with only_when(compile_environment):
2382     @depends(target)
2383     def libav_fft(target):
2384         if target.os == "Android" and target.cpu != "arm":
2385             return True
2386         return target.kernel in ("WINNT", "Darwin") or target.cpu == "x86_64"
2388     set_config("MOZ_LIBAV_FFT", depends(when=libav_fft)(lambda: True))
2389     set_define("MOZ_LIBAV_FFT", depends(when=libav_fft)(lambda: True))
2392 # Artifact builds need MOZ_FFVPX defined as if compilation happened.
2393 with only_when(compile_environment | artifact_builds):
2395     @depends(target)
2396     def ffvpx(target):
2397         enable = use_nasm = True
2398         flac_only = False
2399         flags = []
2401         if target.kernel == "WINNT":
2402             if target.cpu == "x86":
2403                 # 32-bit windows need to prefix symbols with an underscore.
2404                 flags = ["-DPIC", "-DWIN32", "-DPREFIX", "-Pconfig_win32.asm"]
2405             elif target.cpu == "x86_64":
2406                 flags = [
2407                     "-D__x86_64__",
2408                     "-DPIC",
2409                     "-DWIN64",
2410                     "-DMSVC",
2411                     "-Pconfig_win64.asm",
2412                 ]
2413             elif target.cpu == "aarch64":
2414                 flags = ["-DPIC", "-DWIN64"]
2415                 use_nasm = False
2416         elif target.kernel == "Darwin":
2417             # 32/64-bit macosx assemblers need to prefix symbols with an
2418             # underscore.
2419             flags = ["-DPIC", "-DMACHO", "-DPREFIX"]
2420             if target.cpu == "x86_64":
2421                 flags += [
2422                     "-D__x86_64__",
2423                     "-Pconfig_darwin64.asm",
2424                 ]
2425             elif target.cpu == "aarch64":
2426                 use_nasm = False
2427         elif target.cpu == "x86_64":
2428             flags = ["-D__x86_64__", "-DPIC", "-DELF", "-Pconfig_unix64.asm"]
2429         elif target.cpu in ("x86", "arm", "aarch64"):
2430             flac_only = True
2431         else:
2432             enable = False
2434         if flac_only or not enable:
2435             use_nasm = False
2437         return namespace(
2438             enable=enable,
2439             use_nasm=use_nasm,
2440             flac_only=flac_only,
2441             flags=flags,
2442         )
2444     @depends(when=ffvpx.use_nasm)
2445     def ffvpx_nasm():
2446         # nasm 2.10 for AVX-2 support.
2447         return namespace(version="2.10", what="FFVPX")
2449     # ffvpx_nasm can't indirectly depend on vpx_as_flags, because it depends
2450     # on a compiler test, so we have to do a little bit of dance here.
2451     @depends(ffvpx, vpx_as_flags, target)
2452     def ffvpx(ffvpx, vpx_as_flags, target):
2453         if ffvpx and vpx_as_flags and target.cpu in ("arm", "aarch64"):
2454             ffvpx.flags.extend(vpx_as_flags)
2455         return ffvpx
2457     set_config("MOZ_FFVPX", True, when=ffvpx.enable)
2458     set_define("MOZ_FFVPX", True, when=ffvpx.enable)
2459     set_config("MOZ_FFVPX_AUDIOONLY", True, when=ffvpx.flac_only)
2460     set_define("MOZ_FFVPX_AUDIOONLY", True, when=ffvpx.flac_only)
2461     set_config("FFVPX_ASFLAGS", ffvpx.flags)
2462     set_config("FFVPX_USE_NASM", True, when=ffvpx.use_nasm)
2465 # nasm detection
2466 # ==============================================================
2467 @depends(dav1d_nasm, vpx_nasm, jpeg_nasm, ffvpx_nasm, when=compile_environment)
2468 def need_nasm(*requirements):
2469     requires = {
2470         x.what: x.version if hasattr(x, "version") else True for x in requirements if x
2471     }
2472     if requires:
2473         items = sorted(requires.keys())
2474         if len(items) > 1:
2475             what = " and ".join((", ".join(items[:-1]), items[-1]))
2476         else:
2477             what = items[0]
2478         versioned = {k: v for (k, v) in requires.items() if v is not True}
2479         return namespace(what=what, versioned=versioned)
2482 nasm = check_prog(
2483     "NASM",
2484     ["nasm"],
2485     allow_missing=True,
2486     bootstrap="nasm",
2487     when=need_nasm,
2491 @depends(nasm, need_nasm.what)
2492 def check_nasm(nasm, what):
2493     if not nasm and what:
2494         die("Nasm is required to build with %s, but it was not found." % what)
2495     return nasm
2498 @depends_if(check_nasm)
2499 @checking("nasm version")
2500 def nasm_version(nasm):
2501     version = (
2502         check_cmd_output(nasm, "-v", onerror=lambda: die("Failed to get nasm version."))
2503         .splitlines()[0]
2504         .split()[2]
2505     )
2506     return Version(version)
2509 @depends(nasm_version, need_nasm.versioned, when=need_nasm.versioned)
2510 def check_nasm_version(nasm_version, versioned):
2511     by_version = sorted(versioned.items(), key=lambda x: x[1])
2512     what, version = by_version[-1]
2513     if nasm_version < version:
2514         die(
2515             "Nasm version %s or greater is required to build with %s." % (version, what)
2516         )
2517     return nasm_version
2520 @depends(target, when=check_nasm_version)
2521 def nasm_asflags(target):
2522     asflags = {
2523         ("OSX", "x86"): ["-f", "macho32"],
2524         ("OSX", "x86_64"): ["-f", "macho64"],
2525         ("WINNT", "x86"): ["-f", "win32"],
2526         ("WINNT", "x86_64"): ["-f", "win64"],
2527     }.get((target.os, target.cpu), None)
2528     if asflags is None:
2529         # We're assuming every x86 platform we support that's
2530         # not Windows or Mac is ELF.
2531         if target.cpu == "x86":
2532             asflags = ["-f", "elf32"]
2533         elif target.cpu == "x86_64":
2534             asflags = ["-f", "elf64"]
2535     return asflags
2538 set_config("NASM_ASFLAGS", nasm_asflags)
2541 # ANGLE OpenGL->D3D translator for WebGL
2542 # ==============================================================
2544 with only_when(compile_environment & target_is_windows):
2545     set_config("MOZ_ANGLE_RENDERER", True)
2547 # Remoting protocol support
2548 # ==============================================================
2551 @depends(toolkit)
2552 def has_remote(toolkit):
2553     if toolkit in ("gtk", "windows", "cocoa"):
2554         return True
2557 set_config("MOZ_HAS_REMOTE", has_remote)
2558 set_define("MOZ_HAS_REMOTE", has_remote)
2560 # RLBox Library Sandboxing wasm support
2561 # ==============================================================
2564 def wasm_sandboxing_libraries():
2565     return (
2566         "graphite",
2567         "ogg",
2568         "hunspell",
2569         "expat",
2570         "woff2",
2571         "soundtouch",
2572     )
2575 @depends(dependable(wasm_sandboxing_libraries), build_project)
2576 def default_wasm_sandboxing_libraries(libraries, build_project):
2577     if build_project != "tools/rusttests":
2578         non_default_libs = {}
2580         return tuple(l for l in libraries if l not in non_default_libs)
2583 option(
2584     "--with-wasm-sandboxed-libraries",
2585     env="WASM_SANDBOXED_LIBRARIES",
2586     help="{Enable wasm sandboxing for the selected libraries|Disable wasm sandboxing}",
2587     nargs="+",
2588     choices=dependable(wasm_sandboxing_libraries),
2589     default=default_wasm_sandboxing_libraries,
2593 @depends("--with-wasm-sandboxed-libraries")
2594 def requires_wasm_sandboxing(libraries):
2595     if libraries:
2596         return True
2599 set_config("MOZ_USING_WASM_SANDBOXING", requires_wasm_sandboxing)
2600 set_define("MOZ_USING_WASM_SANDBOXING", requires_wasm_sandboxing)
2602 with only_when(requires_wasm_sandboxing & compile_environment):
2603     option(
2604         "--with-wasi-sysroot",
2605         env="WASI_SYSROOT",
2606         nargs=1,
2607         help="Path to wasi sysroot for wasm sandboxing",
2608     )
2610     @depends("--with-wasi-sysroot", requires_wasm_sandboxing)
2611     def bootstrap_wasi_sysroot(wasi_sysroot, requires_wasm_sandboxing):
2612         return requires_wasm_sandboxing and not wasi_sysroot
2614     @depends(
2615         "--with-wasi-sysroot",
2616         bootstrap_path("sysroot-wasm32-wasi", when=bootstrap_wasi_sysroot),
2617     )
2618     @imports("os")
2619     def wasi_sysroot(wasi_sysroot, bootstrapped_sysroot):
2620         if not wasi_sysroot:
2621             return bootstrapped_sysroot
2623         wasi_sysroot = wasi_sysroot[0]
2624         if not os.path.isdir(wasi_sysroot):
2625             die("Argument to --with-wasi-sysroot must be a directory")
2626         if not os.path.isabs(wasi_sysroot):
2627             die("Argument to --with-wasi-sysroot must be an absolute path")
2629         return wasi_sysroot
2631     @depends(wasi_sysroot)
2632     def wasi_sysroot_flags(wasi_sysroot):
2633         if wasi_sysroot:
2634             log.info("Using wasi sysroot in %s", wasi_sysroot)
2635             return ["--sysroot=%s" % wasi_sysroot]
2636         return []
2638     set_config("WASI_SYSROOT", wasi_sysroot)
2640     def wasm_compiler_with_flags(compiler, sysroot_flags):
2641         if compiler:
2642             return (
2643                 compiler.wrapper + [compiler.compiler] + compiler.flags + sysroot_flags
2644             )
2646     @template
2647     def wasm_compiler_error(msg):
2648         @depends("--with-wasm-sandboxed-libraries")
2649         def wasm_compiler_error(sandboxed_libs):
2650             suggest_disable = ""
2651             if sandboxed_libs.origin == "default":
2652                 suggest_disable = " Or build with --without-wasm-sandboxed-libraries."
2653             return lambda: die(msg + suggest_disable)
2655         return wasm_compiler_error
2657     @template
2658     def check_wasm_compiler(compiler, language):
2659         compiler.try_compile(
2660             includes=["cstring" if language == "C++" else "string.h"],
2661             flags=wasi_sysroot_flags,
2662             check_msg="the wasm %s compiler can find wasi headers" % language,
2663             onerror=wasm_compiler_error(
2664                 "Cannot find wasi headers or problem with the wasm compiler. "
2665                 "Please fix the problem."
2666             ),
2667         )
2669         compiler.try_run(
2670             flags=wasi_sysroot_flags,
2671             check_msg="the wasm %s linker can find wasi libraries" % language,
2672             onerror=wasm_compiler_error(
2673                 "Cannot find wasi libraries or problem with the wasm linker. "
2674                 "Please fix the problem."
2675             ),
2676         )
2678     wasm_cc = compiler("C", wasm, other_compiler=c_compiler)
2679     check_wasm_compiler(wasm_cc, "C")
2681     @depends(wasm_cc, wasi_sysroot_flags)
2682     def wasm_cc_with_flags(wasm_cc, wasi_sysroot_flags):
2683         return wasm_compiler_with_flags(wasm_cc, wasi_sysroot_flags)
2685     set_config("WASM_CC", wasm_cc_with_flags)
2687     wasm_cxx = compiler(
2688         "C++",
2689         wasm,
2690         c_compiler=wasm_cc,
2691         other_compiler=cxx_compiler,
2692         other_c_compiler=c_compiler,
2693     )
2694     check_wasm_compiler(wasm_cxx, "C++")
2696     @depends(wasm_cxx, wasi_sysroot_flags)
2697     def wasm_cxx_with_flags(wasm_cxx, wasi_sysroot_flags):
2698         return wasm_compiler_with_flags(wasm_cxx, wasi_sysroot_flags)
2700     set_config("WASM_CXX", wasm_cxx_with_flags)
2702     wasm_compile_flags = dependable(["-fno-exceptions", "-fno-strict-aliasing"])
2703     option(env="WASM_CFLAGS", nargs=1, help="Options to pass to WASM_CC")
2705     @depends("WASM_CFLAGS", wasm_compile_flags)
2706     def wasm_cflags(value, wasm_compile_flags):
2707         if value:
2708             return wasm_compile_flags + value
2709         else:
2710             return wasm_compile_flags
2712     set_config("WASM_CFLAGS", wasm_cflags)
2714     option(env="WASM_CXXFLAGS", nargs=1, help="Options to pass to WASM_CXX")
2716     @depends("WASM_CXXFLAGS", wasm_compile_flags)
2717     def wasm_cxxflags(value, wasm_compile_flags):
2718         if value:
2719             return wasm_compile_flags + value
2720         else:
2721             return wasm_compile_flags
2723     set_config("WASM_CXXFLAGS", wasm_cxxflags)
2726 @depends("--with-wasm-sandboxed-libraries")
2727 def wasm_sandboxing(libraries):
2728     if not libraries:
2729         return
2731     return namespace(**{name: True for name in libraries})
2734 @template
2735 def wasm_sandboxing_config_defines():
2736     for lib in wasm_sandboxing_libraries():
2737         set_config(
2738             "MOZ_WASM_SANDBOXING_%s" % lib.upper(), getattr(wasm_sandboxing, lib)
2739         )
2740         set_define(
2741             "MOZ_WASM_SANDBOXING_%s" % lib.upper(), getattr(wasm_sandboxing, lib)
2742         )
2745 wasm_sandboxing_config_defines()
2748 with only_when(compile_environment & wasm_sandboxing.hunspell):
2749     clock_in_wasi_sysroot = wasm_cc.try_run(
2750         header="#include <time.h>",
2751         body="clock();",
2752         check_msg="for clock() in wasi sysroot",
2753         flags=depends(wasi_sysroot_flags)(
2754             lambda sysroot_flags: ["-Werror"] + sysroot_flags
2755         ),
2756     )
2758     wasi_emulated_clock = wasm_cc.try_run(
2759         header="#include <time.h>",
2760         body="clock();",
2761         check_msg="for emulated clock() in wasi sysroot",
2762         flags=depends(wasi_sysroot_flags)(
2763             lambda sysroot_flags: [
2764                 "-Werror",
2765                 "-D_WASI_EMULATED_PROCESS_CLOCKS",
2766                 "-lwasi-emulated-process-clocks",
2767             ]
2768             + sysroot_flags
2769         ),
2770         when=depends(clock_in_wasi_sysroot)(lambda x: not x),
2771         onerror=lambda: die("Can't find clock() in wasi sysroot."),
2772     )
2774     set_config("MOZ_WASI_EMULATED_CLOCK", True, when=wasi_emulated_clock)
2777 # new Notification Store implementation
2778 # ==============================================================
2781 @depends(milestone)
2782 def new_notification_store(milestone):
2783     if milestone.is_nightly:
2784         return True
2787 set_config("MOZ_NEW_NOTIFICATION_STORE", True, when=new_notification_store)
2788 set_define("MOZ_NEW_NOTIFICATION_STORE", True, when=new_notification_store)
2791 # Auxiliary files persistence on application close
2792 # ==============================================================
2794 option(
2795     "--enable-disk-remnant-avoidance",
2796     help="Prevent persistence of auxiliary files on application close",
2800 set_config(
2801     "MOZ_AVOID_DISK_REMNANT_ON_CLOSE",
2802     True,
2803     when="--enable-disk-remnant-avoidance",
2807 # Glean SDK Integration Crate
2808 # ==============================================================
2811 @depends(target)
2812 def glean_android(target):
2813     return target.os == "Android"
2816 set_config("MOZ_GLEAN_ANDROID", True, when=glean_android)
2817 set_define("MOZ_GLEAN_ANDROID", True, when=glean_android)
2820 # dump_syms
2821 # ==============================================================
2823 check_prog(
2824     "DUMP_SYMS",
2825     ["dump_syms"],
2826     allow_missing=True,
2827     bootstrap="dump_syms",
2828     when=compile_environment,
2832 @depends(valid_windows_sdk_dir, host)
2833 @imports(_from="os", _import="environ")
2834 def pdbstr_paths(valid_windows_sdk_dir, host):
2835     if not valid_windows_sdk_dir:
2836         return
2838     vc_host = {
2839         "x86": "x86",
2840         "x86_64": "x64",
2841     }.get(host.cpu)
2843     return [
2844         environ["PATH"],
2845         os.path.join(valid_windows_sdk_dir.path, "Debuggers", vc_host, "srcsrv"),
2846     ]
2849 check_prog(
2850     "PDBSTR",
2851     ["pdbstr.exe"],
2852     allow_missing=True,
2853     when=compile_environment & target_is_windows,
2854     paths=pdbstr_paths,
2855     allow_spaces=True,
2859 @depends("MOZ_AUTOMATION", c_compiler)
2860 def allow_missing_winchecksec(automation, c_compiler):
2861     if not automation:
2862         return True
2863     if c_compiler and c_compiler.type != "clang-cl":
2864         return True
2867 check_prog(
2868     "WINCHECKSEC",
2869     ["winchecksec.exe", "winchecksec"],
2870     bootstrap="winchecksec",
2871     allow_missing=allow_missing_winchecksec,
2872     when=compile_environment & target_is_windows,
2876 # Fork server
2877 @depends(target, build_project)
2878 def forkserver_default(target, build_project):
2879     return build_project == "browser" and (
2880         (target.os == "GNU" and target.kernel == "Linux")
2881         or target.os == "FreeBSD"
2882         or target.os == "OpenBSD"
2883     )
2886 option(
2887     "--enable-forkserver",
2888     default=forkserver_default,
2889     env="MOZ_ENABLE_FORKSERVER",
2890     help="{Enable|Disable} fork server",
2894 @depends("--enable-forkserver", target)
2895 def forkserver_flag(value, target):
2896     if (
2897         target.os == "Android"
2898         or (target.os == "GNU" and target.kernel == "Linux")
2899         or target.os == "FreeBSD"
2900         or target.os == "OpenBSD"
2901     ):
2902         return bool(value)
2903     pass
2906 set_config("MOZ_ENABLE_FORKSERVER", forkserver_flag)
2907 set_define("MOZ_ENABLE_FORKSERVER", forkserver_flag, forkserver_flag)
2909 # Crash Reporter
2910 # ==============================================================
2912 with only_when(compile_environment & target_has_linux_kernel):
2913     # Check if we need to use the breakpad_getcontext fallback.
2914     getcontext = check_symbol("getcontext")
2915     set_config("HAVE_GETCONTEXT", getcontext)
2916     set_define("HAVE_GETCONTEXT", getcontext)
2918 # NSS
2919 # ==============================================================
2920 include("../build/moz.configure/nss.configure")
2923 # Enable or disable running in background task mode: headless for
2924 # periodic, short-lived, maintenance tasks.
2925 # ==============================================================================
2926 option(
2927     "--disable-backgroundtasks",
2928     help="Disable running in background task mode",
2930 set_config("MOZ_BACKGROUNDTASKS", True, when="--enable-backgroundtasks")
2931 set_define("MOZ_BACKGROUNDTASKS", True, when="--enable-backgroundtasks")
2934 # Update-related programs: updater, maintenance service, update agent,
2935 # default browser agent.
2936 # ==============================================================
2937 include("../build/moz.configure/update-programs.configure")
2940 # Mobile optimizations
2941 # ==============================================================
2942 option(
2943     "--enable-mobile-optimize",
2944     default=target_is_android,
2945     help="{Enable|Disable} mobile optimizations",
2948 set_define("MOZ_GFX_OPTIMIZE_MOBILE", True, when="--enable-mobile-optimize")
2949 # We ignore "paint will resample" on mobile for performance.
2950 # We may want to revisit this later.
2951 set_define("MOZ_IGNORE_PAINT_WILL_RESAMPLE", True, when="--enable-mobile-optimize")
2953 # Pref extensions
2954 # ==============================================================
2955 option("--disable-pref-extensions", help="Disable pref extensions such as autoconfig")
2956 set_config("MOZ_PREF_EXTENSIONS", True, when="--enable-pref-extensions")
2958 # Offer a way to disable the startup cache
2959 # ==============================================================
2960 option("--disable-startupcache", help="Disable startup cache")
2963 @depends("--enable-startupcache")
2964 def enable_startupcache(value):
2965     if value:
2966         return True
2969 set_define(
2970     "MOZ_DISABLE_STARTUPCACHE", True, when=depends(enable_startupcache)(lambda x: not x)
2974 # Branding
2975 # ==============================================================
2976 option(
2977     env="MOZ_APP_REMOTINGNAME",
2978     nargs=1,
2979     help="Used for the internal program name, which affects profile name "
2980     "and remoting. If not set, defaults to MOZ_APP_NAME if the update channel "
2981     "is release, and MOZ_APP_NAME-MOZ_UPDATE_CHANNEL otherwise.",
2985 @depends("MOZ_APP_REMOTINGNAME", moz_app_name, update_channel)
2986 def moz_app_remotingname(value, moz_app_name, update_channel):
2987     if value:
2988         return value[0]
2989     if update_channel == "release":
2990         return moz_app_name
2991     return moz_app_name + "-" + update_channel
2994 set_config("MOZ_APP_REMOTINGNAME", moz_app_remotingname)
2996 option(
2997     env="ANDROID_PACKAGE_NAME",
2998     nargs=1,
2999     help="Name of the Android package (default org.mozilla.$MOZ_APP_NAME)",
3003 @depends("ANDROID_PACKAGE_NAME", moz_app_name)
3004 def android_package_name(value, moz_app_name):
3005     if value:
3006         return value[0]
3007     if moz_app_name == "fennec":
3008         return "org.mozilla.fennec_aurora"
3009     return "org.mozilla.%s" % moz_app_name
3012 set_config("ANDROID_PACKAGE_NAME", android_package_name)
3015 # Miscellaneous options
3016 # ==============================================================
3017 option(env="MOZ_WINCONSOLE", nargs="?", help="Whether we can create a console window.")
3018 set_define("MOZ_WINCONSOLE", True, when=depends("MOZ_WINCONSOLE")(lambda x: x))
3021 # Alternative Crashreporter setting
3022 option(
3023     "--with-crashreporter-url",
3024     env="MOZ_CRASHREPORTER_URL",
3025     default="https://crash-reports.mozilla.com/",
3026     nargs=1,
3027     help="Set an alternative crashreporter url",
3030 set_config(
3031     "MOZ_CRASHREPORTER_URL",
3032     depends("--with-crashreporter-url")(lambda x: x[0].rstrip("/")),
3036 # Crash reporter options
3037 # ==============================================================
3038 @depends(target)
3039 def oxidized_breakpad(target):
3040     if target.kernel == "Linux":
3041         return target.cpu in ("aarch64", "arm", "x86", "x86_64")
3042     return False
3045 set_config("MOZ_OXIDIZED_BREAKPAD", True, when=oxidized_breakpad)
3046 set_define("MOZ_OXIDIZED_BREAKPAD", True, when=oxidized_breakpad)
3049 # Wine
3050 # ==============================================================
3051 @depends(target, host)
3052 def want_wine(target, host):
3053     return target.kernel == "WINNT" and host.kernel != "WINNT"
3056 wine = check_prog(
3057     "WINE",
3058     ["wine64", "wine"],
3059     when=want_wine,
3060     bootstrap="wine/bin",
3063 # DOM Streams
3064 # ==============================================================
3065 # Set this to true so the JS engine knows we're doing a browser build.
3066 set_config("MOZ_DOM_STREAMS", True)
3067 set_define("MOZ_DOM_STREAMS", True)
3069 # libevent
3070 # ==============================================================
3071 with only_when(compile_environment):
3072     system_lib_option(
3073         "--with-system-libevent",
3074         nargs="?",
3075         help="Use system libevent",
3076     )
3078     @depends("--with-system-libevent")
3079     def deprecated_system_libevent_path(value):
3080         if len(value) == 1:
3081             die(
3082                 "--with-system-libevent=PATH is not supported anymore. Please use "
3083                 "--with-system-libevent and set any necessary pkg-config environment variable."
3084             )
3086     pkg_check_modules("MOZ_LIBEVENT", "libevent", when="--with-system-libevent")
3088     set_config("MOZ_SYSTEM_LIBEVENT", True, when="--with-system-libevent")
3091 # Crash reporting
3092 # ==============================================================
3093 @depends(target, developer_options, artifact_builds)
3094 def crashreporter_default(target, developer_options, artifacts):
3095     if target.kernel in ("WINNT", "Darwin"):
3096         return True
3097     if target.kernel == "Linux" and target.cpu in ("x86", "x86_64", "arm", "aarch64"):
3098         # The crash reporter prevents crash stacktraces to be logged in the
3099         # logs on Android, so we leave it out by default in developer builds.
3100         return target.os != "Android" or not developer_options or artifacts
3103 option(
3104     "--enable-crashreporter",
3105     default=crashreporter_default,
3106     help="{Enable|Disable} crash reporting",
3110 set_config("MOZ_CRASHREPORTER", True, when="--enable-crashreporter")
3111 set_define("MOZ_CRASHREPORTER", True, when="--enable-crashreporter")
3113 with only_when(compile_environment):
3114     with only_when("--enable-crashreporter"):
3115         pkg_check_modules(
3116             "MOZ_GTHREAD",
3117             "gthread-2.0",
3118             when=depends(target)(lambda t: t.os == "GNU" and t.kernel == "Linux"),
3119         )
3121         set_config(
3122             "MOZ_CRASHREPORTER_INJECTOR",
3123             True,
3124             when=depends(target)(lambda t: t.os == "WINNT" and t.bitness == 32),
3125         )
3126         set_define(
3127             "MOZ_CRASHREPORTER_INJECTOR",
3128             True,
3129             when=depends(target)(lambda t: t.os == "WINNT" and t.bitness == 32),
3130         )
3133 # If we have any service that uploads data (and requires data submission
3134 # policy alert), set MOZ_DATA_REPORTING.
3135 # ==============================================================
3136 @depends(
3137     "MOZ_TELEMETRY_REPORTING",
3138     "MOZ_SERVICES_HEALTHREPORT",
3139     "--enable-crashreporter",
3140     "MOZ_NORMANDY",
3142 def data_reporting(telemetry, healthreport, crashreporter, normandy):
3143     return telemetry or healthreport or crashreporter or normandy
3146 set_config("MOZ_DATA_REPORTING", True, when=data_reporting)
3147 set_define("MOZ_DATA_REPORTING", True, when=data_reporting)
3150 # Gtk+
3151 # ==============================================================
3152 with only_when(toolkit_gtk):
3153     pkg_check_modules(
3154         "MOZ_GTK3",
3155         "gtk+-3.0 >= 3.14.0 gtk+-unix-print-3.0 glib-2.0 gobject-2.0 gio-unix-2.0",
3156     )
3158     set_define("GDK_VERSION_MIN_REQUIRED", "GDK_VERSION_3_14")
3159     set_define("GDK_VERSION_MAX_ALLOWED", "GDK_VERSION_3_14")
3161     pkg_check_modules("GLIB", "glib-2.0 >= 2.42 gobject-2.0")
3163     set_define("GLIB_VERSION_MIN_REQUIRED", "GLIB_VERSION_2_42")
3164     set_define("GLIB_VERSION_MAX_ALLOWED", "GLIB_VERSION_2_42")
3166     set_define("MOZ_ACCESSIBILITY_ATK", True, when=accessibility)
3168 # DBus
3169 # ==============================================================
3170 with only_when(toolkit_gtk):
3171     option("--disable-dbus", help="Disable dbus support")
3173     with only_when("--enable-dbus"):
3174         pkg_check_modules("MOZ_DBUS", "dbus-1 >= 0.60")
3176         set_config("MOZ_ENABLE_DBUS", True)
3177         set_define("MOZ_ENABLE_DBUS", True)
3180 # Necko's wifi scanner
3181 # ==============================================================
3182 @depends(target)
3183 def necko_wifi_when(target):
3184     return target.os in ("WINNT", "OSX", "DragonFly", "FreeBSD") or (
3185         target.kernel == "Linux" and target.os == "GNU"
3186     )
3189 option("--disable-necko-wifi", help="Disable necko wifi scanner", when=necko_wifi_when)
3191 set_config("NECKO_WIFI", True, when="--enable-necko-wifi")
3192 set_define("NECKO_WIFI", True, when="--enable-necko-wifi")
3195 @depends(
3196     depends("--enable-necko-wifi", when=necko_wifi_when)(lambda x: x),
3197     depends("--enable-dbus", when=toolkit_gtk)(lambda x: x),
3198     when=depends(target)(lambda t: t.os == "GNU" and t.kernel == "Linux"),
3200 def necko_wifi_dbus(necko_wifi, dbus):
3201     if necko_wifi and not dbus:
3202         die(
3203             "Necko WiFi scanning needs DBus on your platform, remove --disable-dbus"
3204             " or use --disable-necko-wifi"
3205         )
3206     return necko_wifi and dbus
3209 set_config("NECKO_WIFI_DBUS", True, when=necko_wifi_dbus)
3210 set_define("NECKO_WIFI_DBUS", True, when=necko_wifi_dbus)
3213 # Frontend JS debug mode
3214 # ==============================================================
3215 option("--enable-debug-js-modules", help="Enable debug mode for frontend JS libraries")
3217 set_config("DEBUG_JS_MODULES", True, when="--enable-debug-js-modules")
3220 # moz_dump_painting
3221 # ==============================================================
3222 option("--enable-dump-painting", help="Enable paint debugging")
3224 set_define(
3225     "MOZ_DUMP_PAINTING",
3226     True,
3227     when=depends("--enable-dump-painting", "--enable-debug")(
3228         lambda painting, debug: painting or debug
3229     ),
3231 set_define("MOZ_LAYERS_HAVE_LOG", True, when="--enable-dump-painting")
3234 # libproxy support
3235 # ==============================================================
3236 with only_when(toolkit_gtk):
3237     system_lib_option("--enable-libproxy", help="Enable libproxy support")
3239     with only_when("--enable-libproxy"):
3240         pkg_check_modules("MOZ_LIBPROXY", "libproxy-1.0")
3242         set_config("MOZ_ENABLE_LIBPROXY", True)
3243         set_define("MOZ_ENABLE_LIBPROXY", True)
3246 # Enable runtime logging
3247 # ==============================================================
3248 set_define("MOZ_LOGGING", True)
3249 set_define("FORCE_PR_LOG", True)
3251 # This will enable logging of addref, release, ctor, dtor.
3252 # ==============================================================
3253 option(
3254     "--enable-logrefcnt",
3255     default=moz_debug,
3256     help="{Enable|Disable} logging of refcounts",
3259 set_define("NS_BUILD_REFCNT_LOGGING", True, when="--enable-logrefcnt")
3262 # NegotiateAuth
3263 # ==============================================================
3264 option("--disable-negotiateauth", help="Disable GSS-API negotiation")
3266 set_config("MOZ_AUTH_EXTENSION", True, when="--enable-negotiateauth")
3267 set_define("MOZ_AUTH_EXTENSION", True, when="--enable-negotiateauth")
3270 # Parental control
3271 # ==============================================================
3272 option("--disable-parental-controls", help="Do not build parental controls")
3274 set_config(
3275     "MOZ_DISABLE_PARENTAL_CONTROLS",
3276     True,
3277     when=depends("--enable-parental-controls")(lambda x: not x),
3279 set_define(
3280     "MOZ_DISABLE_PARENTAL_CONTROLS",
3281     True,
3282     when=depends("--enable-parental-controls")(lambda x: not x),
3286 # Sandboxing support
3287 # ==============================================================
3288 @depends(target, tsan, asan)
3289 def sandbox_default(target, tsan, asan):
3290     # Only enable the sandbox by default on Linux, OpenBSD, macOS, and Windows
3291     if target.kernel == "Linux" and target.os == "GNU":
3292         # Bug 1182565: TSan conflicts with sandboxing on Linux.
3293         # Bug 1287971: LSan also conflicts with sandboxing on Linux.
3294         if tsan or asan:
3295             return False
3296         # Linux sandbox is only available on x86{,_64} and arm{,64}.
3297         return target.cpu in ("x86", "x86_64", "arm", "aarch64")
3298     return target.kernel in ("WINNT", "Darwin", "OpenBSD")
3301 option(
3302     "--enable-sandbox",
3303     default=sandbox_default,
3304     help="{Enable|Disable} sandboxing support",
3307 set_config("MOZ_SANDBOX", True, when="--enable-sandbox")
3308 set_define("MOZ_SANDBOX", True, when="--enable-sandbox")
3310 with only_when(depends(target.kernel)(lambda k: k not in ("Darwin", "WINNT"))):
3311     set_define("MOZ_CONTENT_TEMP_DIR", True, when="--enable-sandbox")
3313 # Searching of system directories for extensions.
3314 # ==============================================================
3315 # Note: this switch is meant to be used for test builds whose behavior should
3316 # not depend on what happens to be installed on the local machine.
3317 option(
3318     "--disable-system-extension-dirs",
3319     help="Disable searching system- and account-global directories for extensions"
3320     " of any kind; use only profile-specific extension directories",
3323 set_define("ENABLE_SYSTEM_EXTENSION_DIRS", True, when="--enable-system-extension-dirs")
3326 # Pixman
3327 # ==============================================================
3328 with only_when(compile_environment):
3329     system_lib_option(
3330         "--enable-system-pixman", help="Use system pixman (located with pkgconfig)"
3331     )
3333     @depends("--enable-system-pixman")
3334     def in_tree_pixman(pixman):
3335         return not pixman
3337     set_config("MOZ_TREE_PIXMAN", True, when=in_tree_pixman)
3338     set_define("MOZ_TREE_PIXMAN", True, when=in_tree_pixman)
3340     pkg_check_modules("MOZ_PIXMAN", "pixman-1 >= 0.36.0", when="--enable-system-pixman")
3341     # Set MOZ_PIXMAN_CFLAGS to an explicit empty value when --enable-system-pixman is *not* used,
3342     # for layout/style/extra-bindgen-flags
3343     set_config("MOZ_PIXMAN_CFLAGS", [], when=in_tree_pixman)
3346 # Universalchardet
3347 # ==============================================================
3348 with only_when(compile_environment):
3349     option("--disable-universalchardet", help="Disable universal encoding detection")
3351     set_config("MOZ_UNIVERSALCHARDET", True, when="--enable-universalchardet")
3354 # Disable zipwriter
3355 # ==============================================================
3356 with only_when(compile_environment):
3357     option("--disable-zipwriter", help="Disable zipwriter component")
3359     set_config("MOZ_ZIPWRITER", True, when="--enable-zipwriter")
3362 # Location of the mozilla user directory
3363 # ==============================================================
3364 with only_when(compile_environment):
3366     @depends(target)
3367     def default_user_appdir(target):
3368         if target.kernel in ("WINNT", "Darwin"):
3369             return "Mozilla"
3370         return ".mozilla"
3372     option(
3373         "--with-user-appdir",
3374         nargs=1,
3375         default=default_user_appdir,
3376         help="Set user-specific appdir",
3377     )
3379     @depends("--with-user-appdir")
3380     def user_appdir(appdir):
3381         if not appdir:
3382             die("--without-user-appdir is not a valid option.")
3383         if "/" in appdir[0]:
3384             die("--with-user-appdir must be a single relative path.")
3385         return '"{}"'.format(appdir[0])
3387     set_define("MOZ_USER_DIR", user_appdir)
3390 # Check for sin_len and sin6_len - used by SCTP; only appears in Mac/*BSD generally
3391 # ==============================================================
3392 with only_when(compile_environment):
3393     have_sin_len = c_compiler.try_compile(
3394         includes=["netinet/in.h"],
3395         body="struct sockaddr_in x; void *foo = (void*) &x.sin_len;",
3396         check_msg="for sin_len in struct sockaddr_in",
3397     )
3398     have_sin6_len = c_compiler.try_compile(
3399         includes=["netinet/in.h"],
3400         body="struct sockaddr_in6 x; void *foo = (void*) &x.sin6_len;",
3401         check_msg="for sin_len6 in struct sockaddr_in6",
3402     )
3403     set_define("HAVE_SIN_LEN", have_sin_len)
3404     set_define("HAVE_SIN6_LEN", have_sin6_len)
3405     # HAVE_CONN_LEN must be the same as HAVE_SIN_LEN and HAVE_SIN6_LEN
3406     set_define("HAVE_SCONN_LEN", have_sin_len & have_sin6_len)
3407     set_define(
3408         "HAVE_SA_LEN",
3409         c_compiler.try_compile(
3410             includes=["netinet/in.h"],
3411             body="struct sockaddr x; void *foo = (void*) &x.sa_len;",
3412             check_msg="for sa_len in struct sockaddr",
3413         ),
3414     )
3417 # Check for pthread_cond_timedwait_monotonic_np
3418 # ==============================================================
3419 with only_when(compile_environment):
3420     set_define(
3421         "HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC",
3422         c_compiler.try_compile(
3423             includes=["pthread.h"],
3424             body="pthread_cond_timedwait_monotonic_np(0, 0, 0);",
3425             # -Werror to catch any "implicit declaration" warning that means the function
3426             # is not supported.
3427             flags=["-Werror=implicit-function-declaration"],
3428             check_msg="for pthread_cond_timedwait_monotonic_np",
3429         ),
3430     )
3433 # Custom dynamic linker for Android
3434 # ==============================================================
3435 with only_when(target_has_linux_kernel & compile_environment):
3436     option(
3437         env="MOZ_LINKER",
3438         default=depends(target.os, when="--enable-jemalloc")(
3439             lambda os: os == "Android"
3440         ),
3441         help="{Enable|Disable} custom dynamic linker",
3442     )
3444     set_config("MOZ_LINKER", True, when="MOZ_LINKER")
3445     set_define("MOZ_LINKER", True, when="MOZ_LINKER")
3446     add_old_configure_assignment("MOZ_LINKER", True, when="MOZ_LINKER")
3448     moz_linker = depends(when="MOZ_LINKER")(lambda: True)
3451 # 32-bits ethtool_cmd.speed
3452 # ==============================================================
3453 with only_when(target_has_linux_kernel & compile_environment):
3454     set_config(
3455         "MOZ_WEBRTC_HAVE_ETHTOOL_SPEED_HI",
3456         c_compiler.try_compile(
3457             includes=["linux/ethtool.h"],
3458             body="struct ethtool_cmd cmd; cmd.speed_hi = 0;",
3459             check_msg="for 32-bits ethtool_cmd.speed",
3460         ),
3461     )
3463 # Gamepad support
3464 # ==============================================================
3465 check_header(
3466     "linux/joystick.h",
3467     onerror=lambda: die(
3468         "Can't find header linux/joystick.h, needed for gamepad support."
3469         " Please install Linux kernel headers."
3470     ),
3471     when=target_has_linux_kernel & compile_environment,
3475 # Smart card support
3476 # ==============================================================
3477 @depends(build_project)
3478 def disable_smart_cards(build_project):
3479     return build_project == "mobile/android"
3482 set_config("MOZ_NO_SMART_CARDS", True, when=disable_smart_cards)
3483 set_define("MOZ_NO_SMART_CARDS", True, when=disable_smart_cards)
3485 # Enable UniFFI fixtures
3486 # ==============================================================
3487 # These are used to test the uniffi-bindgen-gecko-js code generation.  They
3488 # should not be enabled in release builds.
3490 option(
3491     "--enable-uniffi-fixtures",
3492     help="Enable UniFFI Fixtures/Examples",
3495 set_config("MOZ_UNIFFI_FIXTURES", True, when="--enable-uniffi-fixtures")
3497 # System policies
3498 # ==============================================================
3500 option(
3501     "--disable-system-policies",
3502     help="Disable reading policies from Windows registry, macOS's file system attributes, and /etc/firefox",
3505 set_config("MOZ_SYSTEM_POLICIES", True, when="--enable-system-policies")
3507 # Allow disabling the creation a legacy profile
3508 # ==============================================================
3510 option(
3511     "--disable-legacy-profile-creation",
3512     help="Disable the creation a legacy profile, to be used by old versions "
3513     "of Firefox, when no profiles exist.",
3516 set_config("MOZ_CREATE_LEGACY_PROFILE", True, when="--enable-legacy-profile-creation")
3519 # STL wrapping
3520 # ==============================================================
3521 set_config("WRAP_STL_INCLUDES", True)
3522 set_config(
3523     "STL_FLAGS",
3524     depends(build_environment.dist)(lambda dist: [f"-I{dist}/stl_wrappers"]),
3528 # Perl detection
3529 # ==============================================================
3530 @depends(target)
3531 def need_perl(target):
3532     # Ideally, we'd also depend on gnu_as here, but that adds complications.
3533     return target.cpu == "arm"
3536 perl = check_prog("PERL", ("perl5", "perl"), when=need_perl)
3539 @template
3540 def perl_version_check(min_version):
3541     @depends(perl)
3542     @checking("for minimum required perl version >= %s" % min_version)
3543     def get_perl_version(perl):
3544         return Version(
3545             check_cmd_output(
3546                 perl,
3547                 "-e",
3548                 "print $]",
3549                 onerror=lambda: die("Failed to get perl version."),
3550             )
3551         )
3553     @depends(get_perl_version)
3554     def check_perl_version(version):
3555         if version < min_version:
3556             die("Perl %s or higher is required.", min_version)
3558     @depends(perl)
3559     @checking("for full perl installation")
3560     @imports("subprocess")
3561     def has_full_perl_installation(perl):
3562         ret = subprocess.call([perl, "-e", "use Config; exit(!-d $Config{archlib})"])
3563         return ret == 0
3565     @depends(has_full_perl_installation)
3566     def require_full_perl_installation(has_full_perl_installation):
3567         if not has_full_perl_installation:
3568             die(
3569                 "Cannot find Config.pm or $Config{archlib}. "
3570                 "A full perl installation is required."
3571             )
3574 with only_when(need_perl):
3575     perl_version_check("5.006")
3578 # windows-rs as bootstrappable toolchain
3579 # ==============================================================
3580 # The in-tree windows crate's purpose is to avoid vendoring the
3581 # original windows crate, which is too large.
3582 # The ideal solution would be for cargo to allow exceptions to
3583 # vendoring, but it doesn't.
3584 # The adopted solution is to somehow use the crate contents from
3585 # a directory given via the mozbuild config, or bootstrapped.
3587 # Unfortunately, doing `include!(mozbuild::windows_rs_path!("src/lib.rs"))`
3588 # in the crate's lib.rs doesn't work because of
3589 # https://github.com/rust-lang/rust/issues/66920.
3591 # Previous versions of the windows crate had submodules declared
3592 # directly in lib.rs. Annotating each of them with
3593 # `#[path = concat!(mozbuild::windows_rs_path!("path/to/mod.rs"))]`
3594 # unfortunately also didn't work, because of
3595 # https://github.com/rust-lang/rust/issues/48250.
3597 # Thankfully, newer versions of the windows crate now only have an
3598 # `include!` at the end of lib.rs, so we can get away with simply
3599 # replacing it with an `include!` that uses `mozbuild::windows_rs_path!`.
3601 # We ensure that the in-tree contents match what we expect based on
3602 # the original crate.
3603 # The expectations are as such:
3604 # - Cargo.toml is identical to the original one with the addition of the
3605 #   following two lines at the end (after an empty line):
3606 #     [dependencies.mozbuild]
3607 #     version = "0.1"
3608 # - src/lib.rs is mostly identical to the original one, with two notable
3609 #   differences:
3610 #   - the addition of `#![allow(warnings)]` on the first line, because if
3611 #     the crate had been vendored normally, it would not be affected by
3612 #     `-D warnings`, and `#![allow(warnings)]` mimicks that.
3613 #   - the replacement of any
3614 #     `include!("path/file.rs")`
3615 #     with
3616 #     `include!(mozbuild::windows_rs_path!("src/path/file.rs"))`
3617 with only_when(target_is_windows & compile_environment):
3618     option(
3619         env="MOZ_WINDOWS_RS_DIR",
3620         nargs=1,
3621         help="Path to the source of the 'windows' Rust crate",
3622     )
3624     @depends(
3625         "MOZ_WINDOWS_RS_DIR",
3626         bootstrap_path(
3627             "windows-rs",
3628             when=depends("MOZ_WINDOWS_RS_DIR")(lambda x: not x),
3629         ),
3630         build_environment.topsrcdir,
3631     )
3632     @checking("for the windows rust crate source")
3633     @imports(_from="__builtin__", _import="open")
3634     @imports("re")
3635     @imports("toml")
3636     def windows_rs_dir(dir, bootstrapped, topsrcdir):
3637         if bootstrapped:
3638             dir = bootstrapped
3639         elif dir:
3640             dir = dir[0]
3642         raw_cargo_toml = open(
3643             os.path.join(topsrcdir, "build/rust/windows/Cargo.toml")
3644         ).read()
3645         cargo_toml = toml.loads(raw_cargo_toml)
3646         expected_version = cargo_toml["package"]["version"]
3648         if not dir:
3649             raise FatalCheckError(
3650                 "Cannot find the windows rust crate source.\n"
3651                 f"Try downloading it with `cargo download -x windows={expected_version}`\n"
3652                 "(you may need to `cargo install cargo-download` first)\n"
3653                 f"and set `MOZ_WINDOWS_RS_DIR` to location of the `windows-{expected_version}`"
3654                 " directory"
3655             )
3657         raw_cargo_toml_orig = open(os.path.join(dir, "Cargo.toml")).read()
3658         cargo_toml = toml.loads(raw_cargo_toml_orig)
3659         version = cargo_toml["package"]["version"]
3660         if version != expected_version:
3661             raise FatalCheckError(
3662                 f"The windows rust crate source in {dir} contains version "
3663                 f"{version}, but expected {expected_version}."
3664             )
3665         # Now that we've done the basic sanity check, let's go deeper.
3666         DEPENDENCIES = '\n[dependencies.mozbuild]\nversion = "0.1"\n'
3667         if not raw_cargo_toml.endswith(DEPENDENCIES):
3668             configure_error("In-tree windows crate is missing dependency on mozbuild")
3669         if raw_cargo_toml[: -len(DEPENDENCIES)] != raw_cargo_toml_orig:
3670             configure_error("In-tree windows crate Cargo.toml doesn't match original")
3672         lib_rs = open(os.path.join(topsrcdir, "build/rust/windows/src/lib.rs")).read()
3673         lib_rs_orig = open(os.path.join(dir, "src/lib.rs")).read()
3674         lib_rs_expected = "#![allow(warnings)]\n" + re.sub(
3675             r'include!\("([^"]*)"\)',
3676             r'include!(mozbuild::windows_rs_path!("src/\1"))',
3677             lib_rs_orig,
3678         )
3679         if lib_rs != lib_rs_expected:
3680             configure_error("In-tree windows crate lib.rs doesn't match original")
3682         return dir
3684     set_config("MOZ_WINDOWS_RS_DIR", windows_rs_dir)