Bug 1880890 [wpt PR 44658] - DOM: Added a few batch-insertion scenarios that are...
[gecko.git] / toolkit / moz.configure
blob215801ef2f71499589047bb3e87b68815e331661
1 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
2 # vim: set filetype=python:
3 # This Source Code Form is subject to the terms of the Mozilla Public
4 # License, v. 2.0. If a copy of the MPL was not distributed with this
5 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 # Set the MOZ_CONFIGURE_OPTIONS variable with all the options that
9 # were passed somehow (environment, command line, mozconfig)
10 @dependable
11 @imports(_from="mozbuild.shellutil", _import="quote")
12 @imports(_from="mozbuild.util", _import="ensure_unicode")
13 @imports(_from="mozbuild.util", _import="system_encoding")
14 @imports("__sandbox__")
15 def all_configure_options():
16     result = []
17     previous = None
18     for option in __sandbox__._options.values():
19         # __sandbox__._options contains items for both option.name and
20         # option.env. But it's also an OrderedDict, meaning both are
21         # consecutive.
22         # Also ignore OLD_CONFIGURE and MOZCONFIG because they're not
23         # interesting.
24         if option == previous or option.env in ("OLD_CONFIGURE", "MOZCONFIG"):
25             continue
26         previous = option
27         value = __sandbox__._value_for(option)
28         # We only want options that were explicitly given on the command
29         # line, the environment, or mozconfig, and that differ from the
30         # defaults.
31         if (
32             value is not None
33             and value.origin not in ("default", "implied")
34             and value != option.default
35         ):
36             result.append(
37                 ensure_unicode(__sandbox__._raw_options[option], system_encoding)
38             )
39         # We however always include options that are sent to old configure
40         # because we don't know their actual defaults. (Keep the conditions
41         # separate for ease of understanding and ease of removal)
42         elif (
43             option.help == "Help missing for old configure options"
44             and option in __sandbox__._raw_options
45         ):
46             result.append(
47                 ensure_unicode(__sandbox__._raw_options[option], system_encoding)
48             )
50     # We shouldn't need this, but currently, quote will return a byte string
51     # if result is empty, and that's not wanted here.
52     if not result:
53         return ""
55     return quote(*result)
58 set_config("MOZ_CONFIGURE_OPTIONS", all_configure_options)
61 @depends(target)
62 def fold_libs(target):
63     return target.os in ("WINNT", "OSX", "iOS", "Android")
66 set_config("MOZ_FOLD_LIBS", fold_libs)
68 # Profiling
69 # ==============================================================
70 # Some of the options here imply an option from js/moz.configure,
71 # so, need to be declared before the include.
73 option(
74     "--enable-jprof",
75     env="MOZ_JPROF",
76     help="Enable jprof profiling tool (needs mozilla/tools/jprof)",
80 @depends("--enable-jprof")
81 def jprof(value):
82     if value:
83         return True
86 set_config("MOZ_JPROF", jprof)
87 set_define("MOZ_JPROF", jprof)
88 imply_option("--enable-profiling", jprof)
90 option("--disable-gecko-profiler", help="Disable the Gecko profiler")
93 @depends("--disable-gecko-profiler", target)
94 def gecko_profiler(enable_gecko_profiler, target):
95     if not enable_gecko_profiler:
96         return False
98     if target.os == "Android":
99         return target.cpu in ("aarch64", "arm", "x86", "x86_64")
100     elif target.kernel == "Linux":
101         return target.cpu in ("aarch64", "arm", "x86", "x86_64", "mips64")
102     elif target.kernel == "FreeBSD":
103         return target.cpu in ("aarch64", "x86_64")
104     return target.os in ("OSX", "WINNT")
107 @depends(gecko_profiler)
108 def gecko_profiler_define(value):
109     if value:
110         return True
113 set_config("MOZ_GECKO_PROFILER", gecko_profiler_define)
114 set_define("MOZ_GECKO_PROFILER", gecko_profiler_define)
117 # Whether code to parse ELF binaries should be compiled for the Gecko profiler
118 # (for symbol table dumping).
119 @depends(gecko_profiler, target)
120 def gecko_profiler_parse_elf(value, target):
121     # Currently we only want to build this code on Linux (including Android) and BSD.
122     # For Android, this is in order to dump symbols from Android system, where
123     # on other platforms there exist alternatives that don't require bloating
124     # up our binary size. For Linux more generally, we use this in profile
125     # pre-symbolication support, since MozDescribeCodeAddress doesn't do
126     # anything useful on that platform. (Ideally, we would update
127     # MozDescribeCodeAddress to call into some Rust crates that parse ELF and
128     # DWARF data, but build system issues currently prevent Rust from being
129     # used in mozglue.)
130     if value and (target.kernel == "Linux" or target.kernel == "FreeBSD"):
131         return True
134 set_config("MOZ_GECKO_PROFILER_PARSE_ELF", gecko_profiler_parse_elf)
135 set_define("MOZ_GECKO_PROFILER_PARSE_ELF", gecko_profiler_parse_elf)
137 # enable this by default if the profiler is enabled
138 # Note: also requires jemalloc
139 set_config("MOZ_PROFILER_MEMORY", gecko_profiler_define)
140 set_define("MOZ_PROFILER_MEMORY", gecko_profiler_define)
143 @depends(
144     "--enable-debug",
145     milestone,
146     build_project,
147     # Artifact builds are included because the downloaded artifacts can
148     # have DMD enabled.
149     when=artifact_builds | depends(when="--enable-replace-malloc")(lambda: True),
151 def dmd_default(debug, milestone, build_project):
152     return bool(build_project == "browser" and (debug or milestone.is_nightly))
155 option(
156     "--enable-dmd",
157     env="MOZ_DMD",
158     default=dmd_default,
159     help="{Enable|Disable} Dark Matter Detector (heap profiler). "
160     "Also enables jemalloc, replace-malloc and profiling",
164 @depends("--enable-dmd")
165 def dmd(value):
166     if value:
167         return True
170 set_config("MOZ_DMD", dmd)
171 set_define("MOZ_DMD", dmd)
172 imply_option("--enable-profiling", dmd)
173 imply_option("--enable-jemalloc", dmd, when=compile_environment)
174 imply_option("--enable-replace-malloc", dmd, when=compile_environment)
177 # midir-based Web MIDI support
178 # ==============================================================
179 @depends(target)
180 def midir_linux_support(target):
181     return (
182         target.kernel == "Linux" and target.os != "Android" and target.cpu != "riscv64"
183     )
186 @depends(target, midir_linux_support)
187 def midir_support(target, midir_linux_support):
188     if target.os in ("WINNT", "OSX") or midir_linux_support:
189         return True
192 set_config("MOZ_WEBMIDI_MIDIR_IMPL", midir_support)
195 # Enable various cubeb backends
196 # ==============================================================
197 @depends(target)
198 def audio_backends_default(target):
199     if target.os == "Android":
200         return (
201             "aaudio",
202             "opensl",
203         )
204     elif target.os in ("DragonFly", "FreeBSD", "SunOS"):
205         return ("oss",)
206     elif target.os == "OpenBSD":
207         return ("sndio",)
208     elif target.os == "OSX":
209         return ("audiounit",)
210     elif target.os == "iOS":
211         return None
212     elif target.os == "NetBSD":
213         return ("sunaudio",)
214     elif target.os == "SunOS":
215         return ("sunaudio",)
216     elif target.os == "WINNT":
217         return ("wasapi",)
218     else:
219         return ("pulseaudio",)
222 option(
223     "--enable-audio-backends",
224     nargs="+",
225     choices=(
226         "aaudio",
227         "alsa",
228         "audiounit",
229         "jack",
230         "opensl",
231         "oss",
232         "pulseaudio",
233         "sndio",
234         "sunaudio",
235         "wasapi",
236     ),
237     default=audio_backends_default,
238     help="{Enable|Disable} various cubeb backends",
242 @depends("--enable-audio-backends", target)
243 def imply_aaudio(values, target):
244     if any("aaudio" in value for value in values) and target.os != "Android":
245         die("Cannot enable AAudio on %s", target.os)
246     return any("aaudio" in value for value in values) or None
249 @depends("--enable-audio-backends", target)
250 def imply_alsa(values, target):
251     if (
252         any("alsa" in value for value in values)
253         and target.kernel != "Linux"
254         and target.os != "FreeBSD"
255     ):
256         die("Cannot enable ALSA on %s", target.os)
257     return any("alsa" in value for value in values) or None
260 @depends("--enable-audio-backends", target)
261 def imply_audiounit(values, target):
262     if (
263         any("audiounit" in value for value in values)
264         and target.os != "OSX"
265         and target.kernel != "Darwin"
266     ):
267         die("Cannot enable AudioUnit on %s", target.os)
268     return any("audiounit" in value for value in values) or None
271 @depends("--enable-audio-backends")
272 def imply_jack(values):
273     return any("jack" in value for value in values) or None
276 @depends("--enable-audio-backends", target)
277 def imply_opensl(values, target):
278     if any("opensl" in value for value in values) and target.os != "Android":
279         die("Cannot enable OpenSL on %s", target.os)
280     return any("opensl" in value for value in values) or None
283 @depends("--enable-audio-backends", target)
284 def imply_oss(values, target):
285     if any("oss" in value for value in values) and (
286         target.os in ("Android", "OSX", "iOS", "WINNT")
287     ):
288         die("Cannot enable OSS on %s", target.os)
289     return any("oss" in value for value in values) or None
292 @depends("--enable-audio-backends", target)
293 def imply_pulseaudio(values, target):
294     if any("pulseaudio" in value for value in values) and (
295         target.os in ("Android", "OSX", "iOS", "WINNT")
296     ):
297         die("Cannot enable PulseAudio on %s", target.os)
298     return any("pulseaudio" in value for value in values) or None
301 @depends("--enable-audio-backends", target)
302 def imply_sndio(values, target):
303     if any("sndio" in value for value in values) and (
304         target.os in ("Android", "OSX", "iOS", "WINNT")
305     ):
306         die("Cannot enable sndio on %s", target.os)
307     return any("sndio" in value for value in values) or None
310 @depends("--enable-audio-backends", target)
311 def imply_sunaudio(values, target):
312     if any("sunaudio" in value for value in values) and (
313         target.os != "NetBSD" and target.os != "SunOS"
314     ):
315         die("Cannot enable sunaudio on %s", target.os)
316     return any("sunaudio" in value for value in values) or None
319 @depends("--enable-audio-backends", target)
320 def imply_wasapi(values, target):
321     if any("wasapi" in value for value in values) and target.os != "WINNT":
322         die("Cannot enable WASAPI on %s", target.os)
323     return any("wasapi" in value for value in values) or None
326 set_config("MOZ_AAUDIO", imply_aaudio, when="--enable-audio-backends")
328 imply_option("--enable-alsa", imply_alsa, reason="--enable-audio-backends")
330 set_config("MOZ_AUDIOUNIT_RUST", imply_audiounit, when="--enable-audio-backends")
332 imply_option("--enable-jack", imply_jack, reason="--enable-audio-backends")
334 set_config("MOZ_OPENSL", imply_opensl, when="--enable-audio-backends")
336 set_config("MOZ_OSS", imply_oss, when="--enable-audio-backends")
338 imply_option("--enable-pulseaudio", imply_pulseaudio, reason="--enable-audio-backends")
340 imply_option("--enable-sndio", imply_sndio, reason="--enable-audio-backends")
342 set_config("MOZ_SUNAUDIO", imply_sunaudio, when="--enable-audio-backends")
344 set_config("MOZ_WASAPI", imply_wasapi, when="--enable-audio-backends")
346 # ALSA cubeb backend
347 # ==============================================================
348 option("--enable-alsa", env="MOZ_ALSA", help="Enable ALSA audio backend.")
351 @depends("--enable-alsa", midir_linux_support)
352 def enable_alsa_or_midir_linux_support(alsa_enabled, midir_linux_support):
353     return alsa_enabled or midir_linux_support
356 pkg_check_modules("MOZ_ALSA", "alsa", when=enable_alsa_or_midir_linux_support)
358 set_config("MOZ_ALSA", True, when="--enable-alsa")
359 set_define("MOZ_ALSA", True, when="--enable-alsa")
361 # JACK cubeb backend
362 # ==============================================================
363 system_lib_option("--enable-jack", env="MOZ_JACK", help="Enable JACK audio backend.")
365 jack = pkg_check_modules("MOZ_JACK", "jack", when="--enable-jack")
367 set_config("MOZ_JACK", depends_if(jack)(lambda _: True))
369 # PulseAudio cubeb backend
370 # ==============================================================
371 option(
372     "--enable-pulseaudio",
373     env="MOZ_PULSEAUDIO",
374     help="{Enable|Disable} PulseAudio audio backend.",
377 pulseaudio = pkg_check_modules("MOZ_PULSEAUDIO", "libpulse", when="--enable-pulseaudio")
379 set_config("MOZ_PULSEAUDIO", depends_if(pulseaudio)(lambda _: True))
380 set_define("MOZ_PULSEAUDIO", depends_if(pulseaudio)(lambda _: True))
382 # sndio cubeb backend
383 # ==============================================================
384 system_lib_option("--enable-sndio", env="MOZ_SNDIO", help="Enable sndio audio backend.")
386 sndio = pkg_check_modules("MOZ_SNDIO", "sndio", when="--enable-sndio")
388 set_config("MOZ_SNDIO", depends_if(sndio)(lambda _: True))
390 # Javascript engine
391 # ==============================================================
392 include("../js/moz.configure")
395 # NodeJS
396 # ==============================================================
397 include("../build/moz.configure/node.configure")
399 # JsonCpp
400 # ==============================================================
401 set_define("JSON_USE_EXCEPTION", 0)
403 # L10N
404 # ==============================================================
405 option("--with-l10n-base", nargs=1, env="L10NBASEDIR", help="Path to l10n repositories")
408 @depends("--with-l10n-base", "MOZ_AUTOMATION", build_environment)
409 @imports(_from="os.path", _import="isdir")
410 @imports(_from="os.path", _import="expanduser")
411 @imports(_from="os", _import="environ")
412 def l10n_base(value, automation, build_env):
413     if value:
414         path = value[0]
415         if not isdir(path):
416             die("Invalid value --with-l10n-base, %s doesn't exist", path)
417     elif automation:
418         path = os.path.join(build_env.topsrcdir, "../l10n-central")
419     else:
420         path = os.path.join(
421             environ.get(
422                 "MOZBUILD_STATE_PATH", expanduser(os.path.join("~", ".mozbuild"))
423             ),
424             "l10n-central",
425         )
426     return os.path.realpath(os.path.abspath(path))
429 set_config("L10NBASEDIR", l10n_base)
432 # Default toolkit
433 # ==============================================================
434 @depends(target)
435 def toolkit_choices(target):
436     if target.os == "WINNT":
437         return ("cairo-windows",)
438     elif target.os == "OSX":
439         return ("cairo-cocoa",)
440     elif target.os == "iOS":
441         return ("cairo-uikit",)
442     elif target.os == "Android":
443         return ("cairo-android",)
444     else:
445         # cairo-gtk3 - X11 backend with optional Wayland backend (auto detected)
446         # cairo-gtk3-wayland - Wayland backend with optional X11 backend (auto detected)
447         # cairo-gtk3-x11-wayland - builds explicitly with X11 & Wayland backends
448         return (
449             "cairo-gtk3",
450             "cairo-gtk3-wayland",
451             "cairo-gtk3-x11-wayland",
452             "cairo-gtk3-wayland-only",
453             "cairo-gtk3-x11-only",
454         )
457 @depends(toolkit_choices)
458 def toolkit_default(choices):
459     return choices[0]
462 option(
463     "--enable-default-toolkit",
464     nargs=1,
465     choices=toolkit_choices,
466     default=toolkit_default,
467     help="Select default toolkit",
471 @depends("--enable-default-toolkit")
472 def full_toolkit(value):
473     if value:
474         return value[0]
477 @depends(full_toolkit)
478 def toolkit(toolkit):
479     if toolkit.startswith("cairo-gtk3"):
480         widget_toolkit = "gtk"
481     else:
482         widget_toolkit = toolkit.replace("cairo-", "")
483     return widget_toolkit
486 set_config("MOZ_WIDGET_TOOLKIT", toolkit)
487 add_old_configure_assignment("MOZ_WIDGET_TOOLKIT", toolkit)
490 @depends(toolkit)
491 def toolkit_define(toolkit):
492     if toolkit != "windows":
493         return "MOZ_WIDGET_%s" % toolkit.upper()
496 set_define(toolkit_define, True)
499 @depends(toolkit)
500 def toolkit_gtk(toolkit):
501     return toolkit == "gtk"
504 @depends(toolkit_gtk, full_toolkit)
505 def toolkit_gtk_x11(toolkit_gtk, full_toolkit):
506     return toolkit_gtk and full_toolkit != "cairo-gtk3-wayland-only"
509 @depends(full_toolkit)
510 def toolkit_gtk_x11_optional(full_toolkit):
511     return full_toolkit == "cairo-gtk3-wayland"
514 @depends(toolkit_gtk, full_toolkit)
515 def toolkit_gtk_wayland(toolkit_gtk, full_toolkit):
516     return toolkit_gtk and full_toolkit != "cairo-gtk3-x11-only"
519 @depends(full_toolkit)
520 def toolkit_gtk_wayland_optional(full_toolkit):
521     return full_toolkit == "cairo-gtk3"
524 # Wayland support
525 # ==============================================================
526 wayland_headers = pkg_check_modules(
527     "MOZ_WAYLAND",
528     "gtk+-wayland-3.0 >= 3.14 xkbcommon >= 0.4.1",
529     allow_missing=toolkit_gtk_wayland_optional,
530     when=toolkit_gtk_wayland,
534 @depends(wayland_headers, toolkit_gtk, artifact_builds, toolkit_gtk_wayland)
535 def wayland_headers(wayland, toolkit_gtk, artifacts, toolkit_gtk_wayland):
536     if not toolkit_gtk_wayland:
537         return False
538     if toolkit_gtk and artifacts:
539         return True
540     return wayland
543 set_config("MOZ_WAYLAND", depends_if(wayland_headers)(lambda _: True))
544 set_define("MOZ_WAYLAND", depends_if(wayland_headers)(lambda _: True))
547 # Hardware-accelerated video decode with VAAPI and V4L2 on Linux
548 # ==============================================================
549 set_config("MOZ_ENABLE_VAAPI", True, when=toolkit_gtk)
550 set_define("MOZ_ENABLE_VAAPI", True, when=toolkit_gtk)
553 @depends(target, toolkit_gtk)
554 def v4l2(target, toolkit_gtk):
555     # V4L2 decode is only used in GTK/Linux and generally only appears on
556     # embedded SOCs.
557     if target.cpu in ("arm", "aarch64", "riscv64") and toolkit_gtk:
558         return True
561 set_config("MOZ_ENABLE_V4L2", True, when=v4l2)
562 set_define("MOZ_ENABLE_V4L2", True, when=v4l2)
564 # GL Provider
565 # ==============================================================
566 option("--with-gl-provider", nargs=1, help="Set GL provider backend type")
569 @depends("--with-gl-provider")
570 def gl_provider(value):
571     if value:
572         return value[0]
575 @depends(gl_provider)
576 def gl_provider_define(provider):
577     if provider:
578         return "GLContextProvider%s" % provider
581 set_define("MOZ_GL_PROVIDER", gl_provider_define)
584 @depends(gl_provider, toolkit_gtk)
585 def gl_default_provider(value, toolkit_gtk):
586     if value:
587         return value
588     elif toolkit_gtk:
589         return "EGL"
592 set_config("MOZ_GL_PROVIDER", gl_provider)
593 set_config("MOZ_GL_DEFAULT_PROVIDER", gl_default_provider)
596 @depends(gl_default_provider)
597 def gl_provider_define(provider):
598     if provider:
599         return "GL_PROVIDER_%s" % provider
602 set_define(gl_provider_define, True)
605 # PDF printing
606 # ==============================================================
607 @depends(toolkit)
608 def pdf_printing(toolkit):
609     if toolkit in ("windows", "gtk", "android"):
610         return True
613 set_config("MOZ_PDF_PRINTING", pdf_printing)
614 set_define("MOZ_PDF_PRINTING", pdf_printing)
617 # Event loop instrumentation
618 # ==============================================================
619 option(env="MOZ_INSTRUMENT_EVENT_LOOP", help="Force-enable event loop instrumentation")
622 @depends("MOZ_INSTRUMENT_EVENT_LOOP", toolkit)
623 def instrument_event_loop(value, toolkit):
624     if value or (
625         toolkit in ("windows", "gtk", "cocoa", "android") and value.origin == "default"
626     ):
627         return True
630 set_config("MOZ_INSTRUMENT_EVENT_LOOP", instrument_event_loop)
631 set_define("MOZ_INSTRUMENT_EVENT_LOOP", instrument_event_loop)
634 # Fontconfig Freetype
635 # ==============================================================
636 option(env="USE_FC_FREETYPE", help="Force-enable the use of fontconfig freetype")
639 @depends("USE_FC_FREETYPE", toolkit)
640 def fc_freetype(value, toolkit):
641     if value or (toolkit == "gtk" and value.origin == "default"):
642         return True
645 set_define("USE_FC_FREETYPE", fc_freetype)
647 # Pango
648 # ==============================================================
649 pkg_check_modules("MOZ_PANGO", "pango >= 1.22.0", when=toolkit_gtk)
651 # Fontconfig
652 # ==============================================================
653 fontconfig_info = pkg_check_modules(
654     "_FONTCONFIG", "fontconfig >= 2.7.0", when=fc_freetype
658 @depends(fc_freetype)
659 def check_for_freetype2(fc_freetype):
660     if fc_freetype:
661         return True
664 # Check for freetype2. Flags are combined with fontconfig flags.
665 freetype2_info = pkg_check_modules(
666     "_FT2", "freetype2 >= 9.10.3", when=check_for_freetype2
670 @depends(fontconfig_info, freetype2_info)
671 def freetype2_combined_info(fontconfig_info, freetype2_info):
672     if not freetype2_info:
673         return
674     if not fontconfig_info:
675         return freetype2_info
676     return namespace(
677         cflags=freetype2_info.cflags + fontconfig_info.cflags,
678         libs=freetype2_info.libs + fontconfig_info.libs,
679     )
682 set_define("MOZ_HAVE_FREETYPE2", depends_if(freetype2_info)(lambda _: True))
685 # Apple platform decoder support
686 # ==============================================================
687 @depends(toolkit)
688 def applemedia(toolkit):
689     if toolkit in ("cocoa", "uikit"):
690         return True
693 set_config("MOZ_APPLEMEDIA", applemedia)
694 set_define("MOZ_APPLEMEDIA", applemedia)
696 # Windows Media Foundation support
697 # ==============================================================
698 option("--disable-wmf", help="Disable support for Windows Media Foundation")
701 @depends("--disable-wmf", target, "--help")
702 def wmf(value, target, _):
703     enabled = bool(value)
704     if value.origin == "default":
705         # Enable Windows Media Foundation support by default.
706         # Note our minimum SDK version is Windows 7 SDK, so we are (currently)
707         # guaranteed to have a recent-enough SDK to build WMF.
708         enabled = target.os == "WINNT"
709     if enabled and target.os != "WINNT":
710         die("Cannot enable Windows Media Foundation support on %s", target.os)
711     if enabled:
712         return True
715 @depends(artifact_builds, c_compiler, when=wmf)
716 def wmfmediaengine(artifact_builds, c_compiler):
717     if c_compiler:
718         return c_compiler.type == "clang-cl"
719     return bool(artifact_builds)
722 set_config("MOZ_WMF", wmf)
723 set_define("MOZ_WMF", wmf)
725 set_config("MOZ_WMF_MEDIA_ENGINE", True, when=wmfmediaengine)
726 set_define("MOZ_WMF_MEDIA_ENGINE", True, when=wmfmediaengine)
728 # FFmpeg H264/AAC Decoding Support
729 # ==============================================================
730 option("--disable-ffmpeg", help="Disable FFmpeg for fragmented H264/AAC decoding")
733 @depends("--disable-ffmpeg", target)
734 def ffmpeg(value, target):
735     enabled = bool(value)
736     if value.origin == "default":
737         enabled = target.os not in ("Android", "WINNT")
738     if enabled:
739         return True
742 set_config("MOZ_FFMPEG", ffmpeg)
743 set_define("MOZ_FFMPEG", ffmpeg)
745 # AV1 Video Codec Support
746 # ==============================================================
747 option("--disable-av1", help="Disable av1 video support")
750 @depends("--enable-av1")
751 def av1(value):
752     if value:
753         return True
756 @depends(target, when=av1 & compile_environment)
757 def dav1d_asm(target):
758     if target.cpu in ("aarch64", "x86", "x86_64"):
759         return True
762 @depends(target, when=av1 & compile_environment)
763 def dav1d_nasm(target):
764     if target.cpu in ("x86", "x86_64"):
765         return namespace(version="2.14", what="AV1")
768 set_config("MOZ_DAV1D_ASM", dav1d_asm)
769 set_define("MOZ_DAV1D_ASM", dav1d_asm)
770 set_config("MOZ_AV1", av1)
771 set_define("MOZ_AV1", av1)
773 # JXL Image Codec Support
774 # ==============================================================
775 option("--disable-jxl", help="Disable jxl image support")
778 @depends("--disable-jxl", milestone.is_nightly)
779 def jxl(value, is_nightly):
780     if is_nightly and value:
781         return True
784 set_config("MOZ_JXL", jxl)
785 set_define("MOZ_JXL", jxl)
787 set_config("MOZ_SAMPLE_TYPE_FLOAT32", True)
788 set_define("MOZ_SAMPLE_TYPE_FLOAT32", True)
790 set_define("MOZ_VORBIS", True)
791 set_config("MOZ_VORBIS", True)
793 option(
794     "--disable-real-time-tracing",
795     help="Disable tracing of real-time audio callbacks",
798 set_config("MOZ_REAL_TIME_TRACING", True, when="--enable-real-time-tracing")
799 set_define("MOZ_REAL_TIME_TRACING", True, when="--enable-real-time-tracing")
801 # OpenMAX IL Decoding Support
802 # ==============================================================
803 option("--enable-openmax", help="Enable OpenMAX IL for video/audio decoding")
806 @depends("--enable-openmax")
807 def openmax(value):
808     enabled = bool(value)
809     if enabled:
810         return True
813 set_config("MOZ_OMX", openmax)
814 set_define("MOZ_OMX", openmax)
817 # EME Support
818 # ==============================================================
819 @depends(target, wmf)
820 def eme_choices(target, wmf):
821     if (
822         target.kernel in ("WINNT", "Linux")
823         and target.os != "Android"
824         and target.cpu in ("x86", "x86_64")
825     ):
826         if wmf:
827             return ("widevine", "wmfcdm")
828         return ("widevine",)
829     if target.kernel == "WINNT" and target.cpu == "aarch64":
830         return ("widevine",)
831     if target.os in ("OSX"):
832         return ("widevine",)
835 # Widevine is enabled by default in desktop browser builds.
836 @depends(build_project, eme_choices)
837 def eme_default(build_project, choices):
838     if build_project == "browser":
839         return choices
842 option(
843     "--enable-eme",
844     nargs="+",
845     choices=eme_choices,
846     default=eme_default,
847     when=eme_choices,
848     help="{Enable|Disable} support for Encrypted Media Extensions",
852 @depends("--enable-eme", when=eme_choices)
853 def eme_modules(value):
854     return value
857 # Fallback to an empty list when eme_choices is empty, setting eme_modules to
858 # None.
859 set_config("MOZ_EME_MODULES", eme_modules | dependable([]))
862 # Media Foundation CDM support
863 # ==============================================================
864 @depends(eme_modules, when=wmfmediaengine)
865 def wmfcdm(modules):
866     if "wmfcdm" in modules:
867         return True
870 set_config("MOZ_WMF_CDM", True, when=wmfcdm)
871 set_define("MOZ_WMF_CDM", True, when=wmfcdm)
874 option(
875     name="--enable-chrome-format",
876     help="Select FORMAT of chrome files during packaging.",
877     nargs=1,
878     choices=("omni", "jar", "flat"),
879     default="omni",
883 @depends("--enable-chrome-format")
884 def packager_format(value):
885     return value[0]
888 set_config("MOZ_PACKAGER_FORMAT", packager_format)
890 # The packager minifies two different types of files: non-JS (mostly property
891 # files for l10n), and JS.  Setting MOZ_PACKAGER_MINIFY only minifies the
892 # former.  Firefox doesn't yet minify JS, due to concerns about debuggability.
894 # Also, the JS minification setup really only works correctly on Android:
895 # we need extra setup to use the newly-built shell for Linux and Windows,
896 # and cross-compilation for macOS requires some extra care.
899 @depends(target_is_android, "--enable-debug", milestone.is_nightly)
900 def enable_minify_default(is_android, debug, is_nightly):
901     if is_android and not debug and not is_nightly:
902         return ("properties", "js")
903     return ("properties",)
906 option(
907     name="--enable-minify",
908     help="Select types of files to minify during packaging.",
909     nargs="*",
910     choices=("properties", "js"),
911     default=enable_minify_default,
915 @depends("--enable-minify")
916 def enable_minify(value):
917     if "js" in value and "properties" not in value:
918         die("--enable-minify=js requires --enable-minify=properties.")
919     return namespace(
920         properties="properties" in value,
921         js="js" in value,
922     )
925 set_config("MOZ_PACKAGER_MINIFY", True, when=enable_minify.properties)
926 set_config("MOZ_PACKAGER_MINIFY_JS", True, when=enable_minify.js)
929 @depends(host, build_project)
930 def jar_maker_format(host, build_project):
931     # Multilocales for mobile/android use the same mergedirs for all locales,
932     # so we can't use symlinks for those builds.
933     if host.os == "WINNT" or build_project == "mobile/android":
934         return "flat"
935     return "symlink"
938 set_config("MOZ_JAR_MAKER_FILE_FORMAT", jar_maker_format)
941 @depends(toolkit)
942 def omnijar_name(toolkit):
943     # Fennec's static resources live in the assets/ folder of the
944     # APK.  Adding a path to the name here works because we only
945     # have one omnijar file in the final package (which is not the
946     # case on desktop).
947     return "assets/omni.ja" if toolkit == "android" else "omni.ja"
950 set_config("OMNIJAR_NAME", omnijar_name)
952 project_flag("MOZ_PLACES", help="Build Places if required", set_as_define=True)
954 project_flag(
955     "MOZ_SERVICES_HEALTHREPORT",
956     help="Build Firefox Health Reporter Service",
957     set_as_define=True,
960 project_flag(
961     "MOZ_NORMANDY",
962     help="Enable Normandy recipe runner",
963     set_as_define=True,
966 project_flag("MOZ_SERVICES_SYNC", help="Build Sync Services if required")
968 project_flag(
969     "MOZ_ANDROID_HISTORY",
970     help="Enable Android History instead of Places",
971     set_as_define=True,
974 project_flag(
975     "MOZ_DEDICATED_PROFILES",
976     help="Enable dedicated profiles per install",
977     set_as_define=True,
980 project_flag(
981     "MOZ_BLOCK_PROFILE_DOWNGRADE",
982     help="Block users from starting profiles last used by a newer build",
983     set_as_define=True,
987 @depends("MOZ_PLACES", "MOZ_ANDROID_HISTORY")
988 def check_places_and_android_history(places, android_history):
989     if places and android_history:
990         die("Cannot use MOZ_ANDROID_HISTORY alongside MOZ_PLACES.")
991     if not places and not android_history:
992         die("One of MOZ_ANDROID_HISTORY or MOZ_PLACES must be set.")
995 option(
996     env="MOZ_TELEMETRY_REPORTING",
997     default=mozilla_official,
998     help="Enable telemetry reporting",
1001 set_define("MOZ_TELEMETRY_REPORTING", True, when="MOZ_TELEMETRY_REPORTING")
1004 @depends("MOZ_TELEMETRY_REPORTING", milestone.is_nightly)
1005 def telemetry_on_by_default(reporting, is_nightly):
1006     return reporting and is_nightly
1009 set_define("MOZ_TELEMETRY_ON_BY_DEFAULT", True, when=telemetry_on_by_default)
1012 # gpsd support
1013 # ==============================================================
1014 system_lib_option("--enable-gpsd", env="MOZ_GPSD", help="Enable gpsd support")
1017 @depends("--enable-gpsd")
1018 def gpsd(value):
1019     return bool(value)
1022 system_gpsd = pkg_check_modules("MOZ_GPSD", "libgps >= 3.11", when=gpsd)
1024 set_config("MOZ_GPSD", depends_if(system_gpsd)(lambda _: True))
1026 # Miscellaneous programs
1027 # ==============================================================
1029 check_prog("TAR", ("gnutar", "gtar", "tar"))
1030 check_prog("UNZIP", ("unzip",))
1032 # Key files
1033 # ==============================================================
1034 include("../build/moz.configure/keyfiles.configure")
1036 simple_keyfile("Mozilla API")
1038 simple_keyfile("Google Location Service API")
1040 simple_keyfile("Google Safebrowsing API")
1042 id_and_secret_keyfile("Bing API")
1044 simple_keyfile("Adjust SDK")
1046 id_and_secret_keyfile("Leanplum SDK")
1048 simple_keyfile("Pocket API")
1051 # WebRender Debugger integration
1052 # ==============================================================
1054 option(
1055     "--enable-webrender-debugger", help="Build the websocket debug server in WebRender"
1058 set_config(
1059     "MOZ_WEBRENDER_DEBUGGER", depends_if("--enable-webrender-debugger")(lambda _: True)
1062 # Additional system headers defined at the application level
1063 # ==============================================================
1065 option(
1066     "--enable-app-system-headers",
1067     env="MOZ_APP_SYSTEM_HEADERS",
1068     help="Use additional system headers defined in $MOZ_BUILD_APP/app-system-headers.mozbuild",
1072 @depends("--enable-app-system-headers")
1073 def app_system_headers(value):
1074     if value:
1075         return True
1078 set_config("MOZ_APP_SYSTEM_HEADERS", app_system_headers)
1079 set_define("MOZ_APP_SYSTEM_HEADERS", app_system_headers)
1082 # Printing
1083 # ==============================================================
1084 @depends(target)
1085 def printing_default(target):
1086     return target.os != "iOS"
1089 option(
1090     "--disable-printing",
1091     default=printing_default,
1092     help="{Enable|Disable} printing support",
1096 @depends("--disable-printing")
1097 def printing(value):
1098     if value:
1099         return True
1102 set_config("NS_PRINTING", printing)
1103 set_define("NS_PRINTING", printing)
1104 set_define("NS_PRINT_PREVIEW", printing)
1107 # Speech-dispatcher support
1108 # ==============================================================
1109 @depends(toolkit)
1110 def no_speechd_on_non_gtk(toolkit):
1111     if toolkit != "gtk":
1112         return False
1115 imply_option(
1116     "--enable-synth-speechd", no_speechd_on_non_gtk, reason="--enable-default-toolkit"
1119 option("--disable-synth-speechd", help="Disable speech-dispatcher support")
1121 set_config("MOZ_SYNTH_SPEECHD", depends_if("--disable-synth-speechd")(lambda _: True))
1123 # Speech API
1124 # ==============================================================
1125 option("--disable-webspeech", help="Disable support for HTML Speech API")
1128 @depends("--disable-webspeech")
1129 def webspeech(value):
1130     if value:
1131         return True
1134 set_config("MOZ_WEBSPEECH", webspeech)
1135 set_define("MOZ_WEBSPEECH", webspeech)
1137 # Speech API test backend
1138 # ==============================================================
1139 option(
1140     "--enable-webspeechtestbackend",
1141     default=webspeech,
1142     help="{Enable|Disable} support for HTML Speech API Test Backend",
1146 @depends_if("--enable-webspeechtestbackend")
1147 def webspeech_test_backend(value):
1148     return True
1151 set_config("MOZ_WEBSPEECH_TEST_BACKEND", webspeech_test_backend)
1152 set_define("MOZ_WEBSPEECH_TEST_BACKEND", webspeech_test_backend)
1155 # Graphics
1156 # ==============================================================
1157 @depends(target, milestone)
1158 def skia_pdf_default(target, milestone):
1159     return milestone.is_nightly and target.os != "WINNT"
1162 option("--enable-skia-pdf", default=skia_pdf_default, help="{Enable|Disable} Skia PDF")
1164 set_config("MOZ_ENABLE_SKIA_PDF", True, when="--enable-skia-pdf")
1165 set_define("MOZ_ENABLE_SKIA_PDF", True, when="--enable-skia-pdf")
1167 set_config(
1168     "SKIA_INCLUDES",
1169     [
1170         "/gfx/skia",
1171         "/gfx/skia/skia",
1172     ],
1175 system_lib_option(
1176     "--with-system-webp", help="Use system libwebp (located with pkgconfig)"
1179 system_webp = pkg_check_modules(
1180     "MOZ_WEBP", "libwebp >= 1.0.2 libwebpdemux >= 1.0.2", when="--with-system-webp"
1183 set_config("MOZ_SYSTEM_WEBP", depends(when=system_webp)(lambda: True))
1186 # Build Freetype in the tree
1187 # ==============================================================
1188 @depends(target, "--enable-skia-pdf")
1189 def tree_freetype(target, skia_pdf):
1190     if target.os == "Android" or (skia_pdf and target.os == "WINNT"):
1191         return True
1194 set_define("MOZ_TREE_FREETYPE", tree_freetype)
1195 set_config("MOZ_TREE_FREETYPE", tree_freetype)
1197 set_define("HAVE_FT_BITMAP_SIZE_Y_PPEM", tree_freetype)
1198 set_define("HAVE_FT_GLYPHSLOT_EMBOLDEN", tree_freetype)
1199 set_define("HAVE_FT_LOAD_SFNT_TABLE", tree_freetype)
1202 @depends(freetype2_combined_info, tree_freetype, build_environment)
1203 def ft2_info(freetype2_combined_info, tree_freetype, build_env):
1204     if tree_freetype:
1205         return namespace(
1206             cflags=("-I%s/modules/freetype2/include" % build_env.topsrcdir,), libs=()
1207         )
1208     if freetype2_combined_info:
1209         return freetype2_combined_info
1212 set_config("FT2_LIBS", ft2_info.libs)
1215 @depends(target, tree_freetype, freetype2_info)
1216 def enable_cairo_ft(target, tree_freetype, freetype2_info):
1217     # Avoid defining MOZ_ENABLE_CAIRO_FT on Windows platforms because
1218     # "cairo-ft-font.c" includes <dlfcn.h>, which only exists on posix platforms
1219     return freetype2_info or (tree_freetype and target.os != "WINNT")
1222 set_config("MOZ_ENABLE_CAIRO_FT", True, when=enable_cairo_ft)
1223 set_config("CAIRO_FT_CFLAGS", ft2_info.cflags, when=enable_cairo_ft)
1226 # WebDriver (HTTP / BiDi)
1227 # ==============================================================
1229 # WebDriver is a remote control interface that enables introspection and
1230 # control of user agents. It provides a platform- and language-neutral wire
1231 # protocol as a way for out-of-process programs to remotely instruct the
1232 # behavior of web browsers.
1234 # The Gecko implementation is backed by Marionette and Remote Agent.
1235 # Both protocols are not really toolkit features, as much as Gecko engine
1236 # features. But they are enabled based on the toolkit, so here it lives.
1238 # Marionette remote protocol
1239 # -----------------------------------------------------------
1241 # Marionette is the Gecko remote protocol used for various remote control,
1242 # automation, and testing purposes throughout Gecko-based applications like
1243 # Firefox, Thunderbird, and any mobile browser built upon GeckoView.
1245 # It also backs ../testing/geckodriver, which is Mozilla's WebDriver
1246 # implementation.
1248 # The source of Marionette lives in ../remote/marionette.
1250 # For more information, see:
1251 # https://firefox-source-docs.mozilla.org/testing/marionette/index.html
1253 # Remote Agent (WebDriver BiDi / partial CDP)
1254 # -----------------------------------------------------------
1256 # The primary purpose is the implementation of the WebDriver BiDi specification.
1257 # But it also complements the existing Firefox Developer Tools Remote Debugging
1258 # Protocol (RDP) by implementing a subset of the Chrome DevTools Protocol (CDP).
1260 # The source of Remote Agent lives in ../remote.
1262 # For more information, see:
1263 # https://firefox-source-docs.mozilla.org/remote/index.html
1266 option(
1267     "--disable-webdriver",
1268     help="Disable support for WebDriver remote protocols",
1272 @depends("--disable-webdriver")
1273 def webdriver(enabled):
1274     if enabled:
1275         return True
1278 set_config("ENABLE_WEBDRIVER", webdriver)
1279 set_define("ENABLE_WEBDRIVER", webdriver)
1282 # geckodriver WebDriver implementation
1283 # ==============================================================
1285 # Turn off geckodriver for build configs we don't handle yet,
1286 # but allow --enable-geckodriver to override when compile environment is available.
1287 # --disable-tests implies disabling geckodriver.
1288 # Disable building in CI
1291 @depends(
1292     "--enable-tests", target, cross_compiling, hazard_analysis, asan, "MOZ_AUTOMATION"
1294 def geckodriver_default(enable_tests, target, cross_compile, hazard, asan, automation):
1295     if not enable_tests:
1296         return False
1297     if hazard or target.os == "Android" or (asan and cross_compile):
1298         return False
1299     if automation:
1300         return False
1301     return True
1304 option(
1305     "--enable-geckodriver",
1306     default=geckodriver_default,
1307     when="--enable-compile-environment",
1308     help="{Build|Do not build} geckodriver",
1312 @depends("--enable-geckodriver", when="--enable-compile-environment")
1313 def geckodriver(enabled):
1314     if enabled:
1315         return True
1318 set_config("MOZ_GECKODRIVER", geckodriver)
1321 # WebRTC
1322 # ========================================================
1323 @depends(target)
1324 def webrtc_default(target):
1325     # Turn off webrtc for OS's we don't handle yet, but allow
1326     # --enable-webrtc to override.
1327     os_match = target.kernel in (
1328         "Linux",
1329         "WINNT",
1330         "DragonFly",
1331         "FreeBSD",
1332         "kFreeBSD",
1333         "NetBSD",
1334         "OpenBSD",
1335     )
1337     if not os_match:
1338         os_match = target.os in ("OSX",)
1340     cpu_match = target.cpu in (
1341         "x86_64",
1342         "arm",
1343         "aarch64",
1344         "x86",
1345         "ia64",
1346         "mips32",
1347         "mips64",
1348         "ppc",
1349         "ppc64",
1350         "riscv64",
1351     )
1353     return os_match and cpu_match and target.endianness == "little"
1356 option(
1357     "--disable-webrtc",
1358     default=webrtc_default,
1359     help="{Enable|Disable} support for WebRTC",
1363 @depends("--disable-webrtc")
1364 def webrtc(enabled):
1365     if enabled:
1366         return True
1369 set_config("MOZ_WEBRTC", webrtc)
1370 set_define("MOZ_WEBRTC", webrtc)
1371 set_config("MOZ_SCTP", webrtc)
1372 set_define("MOZ_SCTP", webrtc)
1373 set_config("MOZ_SRTP", webrtc)
1374 set_define("MOZ_SRTP", webrtc)
1375 set_config("MOZ_WEBRTC_SIGNALING", webrtc)
1376 set_define("MOZ_WEBRTC_SIGNALING", webrtc)
1377 set_config("MOZ_PEERCONNECTION", webrtc)
1378 set_define("MOZ_PEERCONNECTION", webrtc)
1379 # MOZ_WEBRTC_ASSERT_ALWAYS turns on a number of safety asserts in
1380 # opt/production builds (via MOZ_CRASH())
1381 set_config("MOZ_WEBRTC_ASSERT_ALWAYS", webrtc)
1382 set_define("MOZ_WEBRTC_ASSERT_ALWAYS", webrtc)
1384 # RAW media
1385 # ==============================================================
1388 @depends(target, webrtc)
1389 def raw_media_default(target, webrtc):
1390     if target.os == "Android":
1391         return True
1392     if webrtc:
1393         return True
1396 option(
1397     "--enable-raw",
1398     default=raw_media_default,
1399     help="{Enable|Disable} support for RAW media",
1402 set_config("MOZ_RAW", depends_if("--enable-raw")(lambda _: True))
1403 set_define("MOZ_RAW", depends_if("--enable-raw")(lambda _: True))
1406 # X11
1407 # ==============================================================
1408 @depends(webrtc, when=toolkit_gtk)
1409 def x11_libs(webrtc):
1410     libs = [
1411         "x11",
1412         "xcb",
1413         "xcb-shm",
1414         "x11-xcb",
1415         "xext",
1416         "xrandr >= 1.4.0",
1417     ]
1418     if webrtc:
1419         # third_party/libwebrtc/webrtc/webrtc_gn/moz.build adds those
1420         # manually, ensure they're available.
1421         libs += [
1422             "xcomposite",
1423             "xcursor",
1424             "xdamage",
1425             "xfixes",
1426             "xi",
1427         ]
1428     return libs
1431 x11_headers = pkg_check_modules(
1432     "MOZ_X11",
1433     x11_libs,
1434     allow_missing=toolkit_gtk_x11_optional,
1435     when=toolkit_gtk_x11,
1439 set_config("MOZ_X11", True, when=x11_headers)
1440 set_define("MOZ_X11", True, when=x11_headers)
1442 pkg_check_modules(
1443     "MOZ_X11_SM",
1444     ["ice", "sm"],
1445     cflags_only=True,
1446     allow_missing=toolkit_gtk_x11_optional,
1447     when=toolkit_gtk_x11,
1451 # ASan Reporter Addon
1452 # ==============================================================
1453 option(
1454     "--enable-address-sanitizer-reporter",
1455     help="Enable Address Sanitizer Reporter Extension",
1459 @depends("--enable-address-sanitizer-reporter")
1460 def enable_asan_reporter(value):
1461     if value:
1462         return True
1465 set_config("MOZ_ASAN_REPORTER", enable_asan_reporter)
1466 set_define("MOZ_ASAN_REPORTER", enable_asan_reporter)
1468 # Checks for library functions
1469 # ==============================================================
1470 with only_when(compile_environment & depends(target.os)(lambda os: os != "WINNT")):
1471     set_define("HAVE_STAT64", check_symbol("stat64"))
1472     set_define("HAVE_LSTAT64", check_symbol("lstat64"))
1473     set_define("HAVE_TRUNCATE64", check_symbol("truncate64"))
1474     set_define("HAVE_STATVFS64", check_symbol("statvfs64"))
1475     set_define("HAVE_STATVFS", check_symbol("statvfs"))
1476     set_define("HAVE_STATFS64", check_symbol("statfs64"))
1477     set_define("HAVE_STATFS", check_symbol("statfs"))
1478     set_define("HAVE_LUTIMES", check_symbol("lutimes"))
1479     set_define("HAVE_POSIX_FADVISE", check_symbol("posix_fadvise"))
1480     set_define("HAVE_POSIX_FALLOCATE", check_symbol("posix_fallocate"))
1481     set_define("HAVE_EVENTFD", check_symbol("eventfd"))
1483     have_arc4random = check_symbol("arc4random")
1484     set_define("HAVE_ARC4RANDOM", have_arc4random)
1485     set_define("HAVE_ARC4RANDOM_BUF", check_symbol("arc4random_buf"))
1486     set_define("HAVE_MALLINFO", check_symbol("mallinfo"))
1488 # Checks for headers
1489 # ==============================================================
1490 with only_when(compile_environment & depends(target.os)(lambda os: os != "WINNT")):
1491     set_define("HAVE_SYSIOCCOM_H", check_header("sys/ioccom.h"))
1493 # Elfhack
1494 # ==============================================================
1495 with only_when("--enable-compile-environment"):
1497     @depends(host, target)
1498     def has_elfhack(host, target):
1499         return (
1500             target.kernel == "Linux"
1501             and host.kernel == "Linux"
1502             and target.cpu in ("arm", "aarch64", "x86", "x86_64")
1503         )
1505     option(
1506         "--disable-elf-hack",
1507         nargs="?",
1508         choices=("legacy", "relr"),
1509         help="{Enable|Disable} elf hacks",
1510         when=has_elfhack,
1511     )
1513     @depends("--enable-elf-hack", when=has_elfhack)
1514     def may_enable_legacy_elfhack(enable):
1515         if enable and enable != ("relr",):
1516             return enable
1518     @depends("--enable-elf-hack", when=has_elfhack)
1519     def may_enable_relrhack(enable):
1520         if enable and enable != ("legacy",):
1521             return enable
1523     @depends(
1524         have_arc4random,
1525         android_version,
1526         when=target_has_linux_kernel,
1527     )
1528     def may_use_pack_relative_relocs(have_arc4random, android_version):
1529         # Packed relative relocations are only supported on Android since
1530         # version 11 (API 30), and in glibc since version 2.36.
1531         # glibc 2.36 also added the arc4random function, which is our proxy
1532         # to detect this (or newer) version being used.
1533         # When targetting those newer versions, we allow ourselves to use
1534         # packed relative relocations rather than elfhack.
1535         if android_version:
1536             return android_version >= 30
1537         return have_arc4random
1539     @depends(
1540         c_compiler,
1541         extra_toolchain_flags,
1542         linker_ldflags,
1543         readelf,
1544         when=may_use_pack_relative_relocs | may_enable_relrhack,
1545     )
1546     @checking("for -z pack-relative-relocs option to ld", bool)
1547     @imports(_from="__builtin__", _import="FileNotFoundError")
1548     @imports("os")
1549     @imports(_from="tempfile", _import="mkstemp")
1550     @imports("textwrap")
1551     def has_pack_relative_relocs(
1552         c_compiler,
1553         extra_toolchain_flags,
1554         linker_ldflags,
1555         readelf,
1556     ):
1557         try:
1558             fd, path = mkstemp(prefix="conftest.")
1559             os.close(fd)
1561             pack_rel_relocs = ["-Wl,-z,pack-relative-relocs"]
1562             if (
1563                 try_invoke_compiler(
1564                     # No configure_cache because it would not create the
1565                     # expected output file.
1566                     None,
1567                     [c_compiler.compiler] + c_compiler.flags,
1568                     c_compiler.language,
1569                     # The resulting binary is expected to have relative
1570                     # relocations, the `ptr` variable attempts to ensure
1571                     # there is at least one. This requires the executable
1572                     # being built as position independent.
1573                     "int main() { return 0; }\nint (*ptr)() = main;",
1574                     pack_rel_relocs
1575                     + ["-pie", "-o", path]
1576                     + (extra_toolchain_flags or [])
1577                     + linker_ldflags,
1578                     wrapper=c_compiler.wrapper,
1579                     onerror=lambda: None,
1580                 )
1581                 is not None
1582             ):
1583                 # BFD ld ignores options it doesn't understand. So check
1584                 # that we did get packed relative relocations (DT_RELR).
1585                 env = os.environ.copy()
1586                 env["LANG"] = "C"
1587                 dyn = check_cmd_output(readelf, "-d", path, env=env).splitlines()
1588                 tags = [
1589                     int(l.split()[0], 16) for l in dyn if l.strip().startswith("0x")
1590                 ]
1591                 # Older versions of readelf don't know about DT_RELR but will
1592                 # still display the tag number.
1593                 if 0x23 in tags:
1594                     needed = [l for l in dyn if l.split()[1:2] == ["(NEEDED)"]]
1595                     is_glibc = any(l.endswith("[libc.so.6]") for l in needed)
1596                     # The mold linker doesn't add a GLIBC_ABI_DT_RELR version
1597                     # dependency, which ld.so doesn't like.
1598                     # https://github.com/rui314/mold/issues/653#issuecomment-1670274638
1599                     if is_glibc:
1600                         versions = check_cmd_output(readelf, "-V", path, env=env)
1601                         if "GLIBC_ABI_DT_RELR" in versions.split():
1602                             return pack_rel_relocs
1603                     else:
1604                         return pack_rel_relocs
1605         finally:
1606             try:
1607                 os.remove(path)
1608             except FileNotFoundError:
1609                 pass
1611     @depends(
1612         has_pack_relative_relocs,
1613         may_enable_legacy_elfhack,
1614         may_enable_relrhack,
1615         may_use_pack_relative_relocs,
1616         when=has_pack_relative_relocs,
1617     )
1618     def pack_relative_relocs_flags(
1619         flags,
1620         may_enable_legacy_elfhack,
1621         may_enable_relrhack,
1622         may_use_pack_relative_relocs,
1623     ):
1624         # When relrhack is enabled, we don't pass the flag to the linker because
1625         # relrhack will take care of it.
1626         if may_enable_relrhack and may_enable_relrhack.origin != "default":
1627             return None
1628         # if elfhack is explicitly enabled instead of relrhack, we prioritize it
1629         # over packed relative relocs.
1630         if may_enable_legacy_elfhack and may_enable_legacy_elfhack.origin != "default":
1631             return None
1632         if may_use_pack_relative_relocs:
1633             return flags
1635     add_old_configure_assignment("PACK_REL_RELOC_FLAGS", pack_relative_relocs_flags)
1637     @depends(
1638         select_linker,
1639         pack_relative_relocs_flags,
1640         has_pack_relative_relocs,
1641         may_enable_legacy_elfhack,
1642         may_enable_relrhack,
1643         when=has_elfhack,
1644     )
1645     def which_elf_hack(
1646         linker,
1647         pack_relative_relocs_flags,
1648         has_pack_relative_relocs,
1649         may_enable_legacy_elfhack,
1650         may_enable_relrhack,
1651     ):
1652         if pack_relative_relocs_flags:
1653             return
1654         if may_enable_relrhack:
1655             if has_pack_relative_relocs:
1656                 return "relr"
1657             elif (
1658                 may_enable_relrhack.origin != "default"
1659                 and not may_enable_legacy_elfhack
1660             ):
1661                 die(
1662                     "Cannot enable relrhack without linker support for -z pack-relative-relocs"
1663                 )
1664         if may_enable_legacy_elfhack:
1665             if linker and linker.KIND in ("lld", "mold"):
1666                 if may_enable_legacy_elfhack.origin != "default":
1667                     die(
1668                         f"Cannot enable elfhack with {linker.KIND}."
1669                         " Use --enable-linker=bfd, --enable-linker=gold, or --disable-elf-hack"
1670                     )
1671             else:
1672                 return "legacy"
1674     set_config(
1675         "USE_ELF_HACK", True, when=depends(which_elf_hack)(lambda x: x == "legacy")
1676     )
1678     use_relrhack = depends(which_elf_hack)(lambda x: x == "relr")
1679     set_config("RELRHACK", True, when=use_relrhack)
1681     @depends(c_compiler, linker_ldflags, when=use_relrhack)
1682     def relrhack_real_linker(c_compiler, linker_ldflags):
1683         ld = "ld"
1684         for flag in linker_ldflags:
1685             if flag.startswith("-fuse-ld="):
1686                 ld = "ld." + flag[len("-fuse-ld=") :]
1687         ld = check_cmd_output(
1688             c_compiler.compiler, f"--print-prog-name={ld}", *c_compiler.flags
1689         )
1690         return ld.rstrip()
1692     @depends(relrhack_real_linker, when=use_relrhack)
1693     def relrhack_linker(ld):
1694         return os.path.basename(ld)
1696     set_config("RELRHACK_LINKER", relrhack_linker)
1698     std_filesystem = host_cxx_compiler.try_run(
1699         header="#include <filesystem>",
1700         body='auto foo = std::filesystem::absolute("");',
1701         flags=host_linker_ldflags,
1702         when=use_relrhack,
1703         onerror=lambda: None,
1704     )
1706     stdcxxfs = host_cxx_compiler.try_run(
1707         header="#include <filesystem>",
1708         body='auto foo = std::filesystem::absolute("");',
1709         flags=depends(host_linker_ldflags)(
1710             lambda flags: (flags or []) + ["-lstdc++fs"]
1711         ),
1712         check_msg="whether std::filesystem requires -lstdc++fs",
1713         when=use_relrhack & depends(std_filesystem)(lambda x: not x),
1714         onerror=lambda: None,
1715     )
1717     set_config("RELRHACK_LIBS", ["stdc++fs"], when=stdcxxfs)
1719     @depends(build_environment, relrhack_real_linker, when=use_relrhack)
1720     def relrhack_ldflags(build_env, ld):
1721         flags = [
1722             "-B",
1723             os.path.join(build_env.topobjdir, "build", "unix", "elfhack"),
1724         ]
1725         if os.path.basename(ld) != ld:
1726             flags.append(f"-Wl,--real-linker,{ld}")
1727         return flags
1729     set_config("RELRHACK_LDFLAGS", relrhack_ldflags)
1732 @depends(build_environment)
1733 def idl_roots(build_env):
1734     return namespace(
1735         ipdl_root=os.path.join(build_env.topobjdir, "ipc", "ipdl"),
1736         webidl_root=os.path.join(build_env.topobjdir, "dom", "bindings"),
1737         xpcom_root=os.path.join(build_env.topobjdir, "xpcom", "components"),
1738     )
1741 set_config("WEBIDL_ROOT", idl_roots.webidl_root)
1742 set_config("IPDL_ROOT", idl_roots.ipdl_root)
1743 set_config("XPCOM_ROOT", idl_roots.xpcom_root)
1745 # Proxy bypass protection
1746 # ==============================================================
1748 option(
1749     "--enable-proxy-bypass-protection",
1750     help="Prevent suspected or confirmed proxy bypasses",
1754 @depends_if("--enable-proxy-bypass-protection")
1755 def proxy_bypass_protection(_):
1756     return True
1759 set_config("MOZ_PROXY_BYPASS_PROTECTION", proxy_bypass_protection)
1760 set_define("MOZ_PROXY_BYPASS_PROTECTION", proxy_bypass_protection)
1762 # Proxy direct failover
1763 # ==============================================================
1765 option(
1766     "--disable-proxy-direct-failover",
1767     help="Disable direct failover for system requests",
1771 @depends_if("--disable-proxy-direct-failover")
1772 def proxy_direct_failover(value):
1773     if value:
1774         return True
1777 set_config("MOZ_PROXY_DIRECT_FAILOVER", proxy_direct_failover)
1778 set_define("MOZ_PROXY_DIRECT_FAILOVER", proxy_direct_failover)
1780 # MIDL
1781 # ==============================================================
1784 @depends(c_compiler, toolchain_prefix)
1785 def midl_names(c_compiler, toolchain_prefix):
1786     if c_compiler and c_compiler.type in ["gcc", "clang"]:
1787         # mingw
1788         widl = ("widl",)
1789         if toolchain_prefix:
1790             prefixed = tuple("%s%s" % (p, "widl") for p in toolchain_prefix)
1791             widl = prefixed + widl
1792         return widl
1794     return ("midl.exe",)
1797 @depends(target, "--enable-compile-environment")
1798 def check_for_midl(target, compile_environment):
1799     if target.os != "WINNT":
1800         return
1802     if compile_environment:
1803         return True
1806 midl = check_prog(
1807     "MIDL",
1808     midl_names,
1809     when=check_for_midl,
1810     allow_missing=True,
1811     paths=sdk_bin_path,
1812     # MIDL being used from a python wrapper script, we can live with it
1813     # having spaces.
1814     allow_spaces=True,
1817 option(env="MIDL_FLAGS", nargs=1, help="Extra flags to pass to MIDL")
1820 @depends(
1821     "MIDL_FLAGS",
1822     target,
1823     midl,
1824     when=depends(midl, target)(lambda m, t: m and t.kernel == "WINNT"),
1826 def midl_flags(flags, target, midl):
1827     if flags:
1828         flags = flags[0].split()
1829     else:
1830         flags = []
1832     if not midl.endswith("widl"):
1833         env = {
1834             "x86": "win32",
1835             "x86_64": "x64",
1836             "aarch64": "arm64",
1837         }[target.cpu]
1838         return flags + ["-nologo", "-no_cpp", "-env", env]
1840     # widl
1841     return (
1842         flags
1843         + {
1844             "x86": ["--win32", "-m32"],
1845             "x86_64": ["--win64", "-m64"],
1846         }[target.cpu]
1847     )
1850 set_config("MIDL_FLAGS", midl_flags)
1852 # Accessibility
1853 # ==============================================================
1855 option("--disable-accessibility", help="Disable accessibility support")
1858 @depends("--enable-accessibility", check_for_midl, midl, c_compiler)
1859 def accessibility(value, check_for_midl, midl, c_compiler):
1860     enabled = bool(value)
1862     if not enabled:
1863         return
1865     if check_for_midl and not midl:
1866         if c_compiler and c_compiler.type in ("gcc", "clang"):
1867             die(
1868                 "You have accessibility enabled, but widl could not be found. "
1869                 "Add --disable-accessibility to your mozconfig or install widl. "
1870                 "See https://developer.mozilla.org/en-US/docs/Cross_Compile_Mozilla_for_Mingw32 for details."
1871             )
1872         else:
1873             die(
1874                 "MIDL could not be found. "
1875                 "Building accessibility without MIDL is not supported."
1876             )
1878     return enabled
1881 set_config("ACCESSIBILITY", accessibility)
1882 set_define("ACCESSIBILITY", accessibility)
1885 @depends(moz_debug, developer_options)
1886 def a11y_log(debug, developer_options):
1887     return debug or developer_options
1890 set_config("A11Y_LOG", True, when=a11y_log)
1891 set_define("A11Y_LOG", True, when=a11y_log)
1894 # Addon signing
1895 # ==============================================================
1896 @depends(milestone)
1897 def require_signing(milestone):
1898     return milestone.is_release_or_beta and not milestone.is_esr
1901 option(
1902     env="MOZ_REQUIRE_SIGNING",
1903     default=require_signing,
1904     help="Enforce that add-ons are signed by the trusted root",
1907 set_config("MOZ_REQUIRE_SIGNING", True, when="MOZ_REQUIRE_SIGNING")
1908 set_define("MOZ_REQUIRE_SIGNING", True, when="MOZ_REQUIRE_SIGNING")
1910 option(
1911     "--with-unsigned-addon-scopes",
1912     nargs="+",
1913     choices=("app", "system"),
1914     help="Addon scopes where signature is not required",
1918 @depends("--with-unsigned-addon-scopes")
1919 def unsigned_addon_scopes(scopes):
1920     return namespace(
1921         app="app" in scopes or None,
1922         system="system" in scopes or None,
1923     )
1926 set_config("MOZ_UNSIGNED_APP_SCOPE", unsigned_addon_scopes.app)
1927 set_config("MOZ_UNSIGNED_SYSTEM_SCOPE", unsigned_addon_scopes.system)
1930 # Addon sideloading
1931 # ==============================================================
1932 option(
1933     "--allow-addon-sideload",
1934     default=milestone.is_esr,
1935     help="Addon sideloading is allowed",
1939 set_config("MOZ_ALLOW_ADDON_SIDELOAD", True, when="--allow-addon-sideload")
1941 # WebExtensions API WebIDL bindings
1942 # ==============================================================
1945 @depends(milestone)
1946 def extensions_webidl_bindings_default(milestone):
1947     # Only enable the webidl bindings for the WebExtensions APIs
1948     # in Nightly.
1949     return milestone.is_nightly
1952 option(
1953     "--enable-extensions-webidl-bindings",
1954     default=extensions_webidl_bindings_default,
1955     help="{Enable|Disable} building experimental WebExtensions WebIDL bindings",
1959 @depends("--enable-extensions-webidl-bindings")
1960 def extensions_webidl_enabled(value):
1961     return bool(value)
1964 set_config("MOZ_WEBEXT_WEBIDL_ENABLED", extensions_webidl_enabled)
1966 # Launcher process (Windows only)
1967 # ==============================================================
1970 @depends(target)
1971 def launcher_process_default(target):
1972     return target.os == "WINNT"
1975 option(
1976     "--enable-launcher-process",
1977     default=launcher_process_default,
1978     help="{Enable|Disable} launcher process by default",
1982 @depends("--enable-launcher-process", target)
1983 def launcher(value, target):
1984     enabled = bool(value)
1985     if enabled and target.os != "WINNT":
1986         die("Cannot enable launcher process on %s", target.os)
1987     if enabled:
1988         return True
1991 set_config("MOZ_LAUNCHER_PROCESS", launcher)
1992 set_define("MOZ_LAUNCHER_PROCESS", launcher)
1994 # llvm-dlltool (Windows only)
1995 # ==============================================================
1998 @depends(build_project, target, "--enable-compile-environment")
1999 def check_for_llvm_dlltool(build_project, target, compile_environment):
2000     if build_project != "browser":
2001         return
2003     if target.os != "WINNT":
2004         return
2006     return compile_environment
2009 llvm_dlltool = check_prog(
2010     "LLVM_DLLTOOL",
2011     ("llvm-dlltool",),
2012     what="llvm-dlltool",
2013     when=check_for_llvm_dlltool,
2014     paths=clang_search_path,
2018 @depends(target, when=llvm_dlltool)
2019 def llvm_dlltool_flags(target):
2020     arch = {
2021         "x86": "i386",
2022         "x86_64": "i386:x86-64",
2023         "aarch64": "arm64",
2024     }[target.cpu]
2026     return ["-m", arch]
2029 set_config("LLVM_DLLTOOL_FLAGS", llvm_dlltool_flags)
2031 # BITS download (Windows only)
2032 # ==============================================================
2034 option(
2035     "--enable-bits-download",
2036     when=target_is_windows,
2037     default=target_is_windows,
2038     help="{Enable|Disable} building BITS download support",
2041 set_define(
2042     "MOZ_BITS_DOWNLOAD",
2043     depends_if("--enable-bits-download", when=target_is_windows)(lambda _: True),
2045 set_config(
2046     "MOZ_BITS_DOWNLOAD",
2047     depends_if("--enable-bits-download", when=target_is_windows)(lambda _: True),
2050 # Bundled fonts on desktop platform
2051 # ==============================================================
2054 @depends(target)
2055 def bundled_fonts_default(target):
2056     return target.os == "WINNT" or target.kernel == "Linux"
2059 @depends(build_project)
2060 def allow_bundled_fonts(project):
2061     return project == "browser" or project == "comm/mail"
2064 option(
2065     "--enable-bundled-fonts",
2066     default=bundled_fonts_default,
2067     when=allow_bundled_fonts,
2068     help="{Enable|Disable} support for bundled fonts on desktop platforms",
2071 set_define(
2072     "MOZ_BUNDLED_FONTS",
2073     depends_if("--enable-bundled-fonts", when=allow_bundled_fonts)(lambda _: True),
2076 # Reflow counting
2077 # ==============================================================
2080 @depends(moz_debug)
2081 def reflow_perf(debug):
2082     if debug:
2083         return True
2086 option(
2087     "--enable-reflow-perf",
2088     default=reflow_perf,
2089     help="{Enable|Disable} reflow performance tracing",
2092 # The difference in conditions here comes from the initial implementation
2093 # in old-configure, which was unexplained there as well.
2094 set_define("MOZ_REFLOW_PERF", depends_if("--enable-reflow-perf")(lambda _: True))
2095 set_define("MOZ_REFLOW_PERF_DSP", reflow_perf)
2097 # Layout debugger
2098 # ==============================================================
2101 @depends(moz_debug)
2102 def layout_debugger(debug):
2103     if debug:
2104         return True
2107 option(
2108     "--enable-layout-debugger",
2109     default=layout_debugger,
2110     help="{Enable|Disable} layout debugger",
2113 set_config("MOZ_LAYOUT_DEBUGGER", True, when="--enable-layout-debugger")
2114 set_define("MOZ_LAYOUT_DEBUGGER", True, when="--enable-layout-debugger")
2117 # Shader Compiler for Windows (and MinGW Cross Compile)
2118 # ==============================================================
2120 with only_when(compile_environment):
2121     fxc = check_prog(
2122         "FXC",
2123         ("fxc.exe", "fxc2.exe"),
2124         when=depends(target)(lambda t: t.kernel == "WINNT"),
2125         paths=sdk_bin_path,
2126         # FXC being used from a python wrapper script, we can live with it
2127         # having spaces.
2128         allow_spaces=True,
2129     )
2132 # VPX
2133 # ===
2135 with only_when(compile_environment):
2136     system_lib_option(
2137         "--with-system-libvpx", help="Use system libvpx (located with pkgconfig)"
2138     )
2140     with only_when("--with-system-libvpx"):
2141         vpx = pkg_check_modules("MOZ_LIBVPX", "vpx >= 1.10.0")
2143         check_header(
2144             "vpx/vpx_decoder.h",
2145             flags=vpx.cflags,
2146             onerror=lambda: die(
2147                 "Couldn't find vpx/vpx_decoder.h, which is required to build "
2148                 "with system libvpx. Use --without-system-libvpx to build "
2149                 "with in-tree libvpx."
2150             ),
2151         )
2153         check_symbol(
2154             "vpx_codec_dec_init_ver",
2155             flags=vpx.libs,
2156             onerror=lambda: die(
2157                 "--with-system-libvpx requested but symbol vpx_codec_dec_init_ver "
2158                 "not found"
2159             ),
2160         )
2162         set_config("MOZ_SYSTEM_LIBVPX", True)
2164     @depends("--with-system-libvpx", target)
2165     def in_tree_vpx(system_libvpx, target):
2166         if system_libvpx:
2167             return
2169         arm_asm = (target.cpu == "arm") or None
2170         return namespace(arm_asm=arm_asm)
2172     @depends(target, when=in_tree_vpx)
2173     def vpx_nasm(target):
2174         if target.cpu in ("x86", "x86_64"):
2175             if target.kernel == "WINNT":
2176                 # Version 2.03 is needed for automatic safeseh support.
2177                 return namespace(version="2.03", what="VPX")
2178             return namespace(what="VPX")
2180     @depends(in_tree_vpx, vpx_nasm, target, neon_flags)
2181     def vpx_as_flags(vpx, vpx_nasm, target, neon_flags):
2182         if vpx and vpx.arm_asm:
2183             # These flags are a lie; they're just used to enable the requisite
2184             # opcodes; actual arch detection is done at runtime.
2185             return neon_flags
2186         elif vpx and vpx_nasm and target.os != "WINNT" and target.cpu != "x86_64":
2187             return ("-DPIC",)
2189     set_config("VPX_USE_NASM", True, when=vpx_nasm)
2190     set_config("VPX_ASFLAGS", vpx_as_flags)
2193 # JPEG
2194 # ====
2196 with only_when(compile_environment):
2197     system_lib_option(
2198         "--with-system-jpeg",
2199         nargs="?",
2200         help="Use system libjpeg (installed at given prefix)",
2201     )
2203     @depends_if("--with-system-jpeg")
2204     def jpeg_flags(value):
2205         if len(value):
2206             return namespace(
2207                 cflags=("-I%s/include" % value[0],),
2208                 ldflags=("-L%s/lib" % value[0], "-ljpeg"),
2209             )
2210         return namespace(
2211             ldflags=("-ljpeg",),
2212         )
2214     with only_when("--with-system-jpeg"):
2215         check_symbol(
2216             "jpeg_destroy_compress",
2217             flags=jpeg_flags.ldflags,
2218             onerror=lambda: die(
2219                 "--with-system-jpeg requested but symbol "
2220                 "jpeg_destroy_compress not found."
2221             ),
2222         )
2224         c_compiler.try_compile(
2225             includes=[
2226                 "stdio.h",
2227                 "sys/types.h",
2228                 "jpeglib.h",
2229             ],
2230             body="""
2231                 #if JPEG_LIB_VERSION < 62
2232                 #error Insufficient JPEG library version
2233                 #endif
2234             """,
2235             flags=jpeg_flags.cflags,
2236             check_msg="for sufficient jpeg library version",
2237             onerror=lambda: die(
2238                 "Insufficient JPEG library version for "
2239                 "--with-system-jpeg (62 required)"
2240             ),
2241         )
2243         c_compiler.try_compile(
2244             includes=[
2245                 "stdio.h",
2246                 "sys/types.h",
2247                 "jpeglib.h",
2248             ],
2249             body="""
2250                 #ifndef JCS_EXTENSIONS
2251                 #error libjpeg-turbo JCS_EXTENSIONS required
2252                 #endif
2253             """,
2254             flags=jpeg_flags.cflags,
2255             check_msg="for sufficient libjpeg-turbo JCS_EXTENSIONS",
2256             onerror=lambda: die(
2257                 "libjpeg-turbo JCS_EXTENSIONS required for " "--with-system-jpeg"
2258             ),
2259         )
2261         set_config("MOZ_JPEG_CFLAGS", jpeg_flags.cflags)
2262         set_config("MOZ_JPEG_LIBS", jpeg_flags.ldflags)
2264     @depends("--with-system-jpeg", target, neon_flags)
2265     def in_tree_jpeg_arm(system_jpeg, target, neon_flags):
2266         if system_jpeg:
2267             return
2269         if target.cpu == "arm":
2270             return neon_flags
2271         elif target.cpu == "aarch64":
2272             return ("-march=armv8-a",)
2274     @depends("--with-system-jpeg", target)
2275     def in_tree_jpeg_mips64(system_jpeg, target):
2276         if system_jpeg:
2277             return
2279         if target.cpu == "mips64":
2280             return ("-Wa,-mloongson-mmi", "-mloongson-ext")
2282     # Compiler check from https://github.com/libjpeg-turbo/libjpeg-turbo/blob/57ba02a408a9a55ccff25aae8b164632a3a4f177/simd/CMakeLists.txt#L419
2283     jpeg_mips64_mmi = c_compiler.try_compile(
2284         body='int c = 0, a = 0, b = 0; asm("paddb %0, %1, %2" : "=f" (c) : "f" (a), "f" (b));',
2285         check_msg="for loongson mmi support",
2286         flags=in_tree_jpeg_mips64,
2287         when=in_tree_jpeg_mips64,
2288     )
2290     @depends(
2291         "--with-system-jpeg",
2292         target,
2293         in_tree_jpeg_arm,
2294         in_tree_jpeg_mips64,
2295         jpeg_mips64_mmi,
2296     )
2297     def in_tree_jpeg(
2298         system_jpeg, target, in_tree_jpeg_arm, in_tree_jpeg_mips64, jpeg_mips64_mmi
2299     ):
2300         if system_jpeg:
2301             return
2303         if target.cpu in ("arm", "aarch64"):
2304             return in_tree_jpeg_arm
2305         elif target.kernel == "Darwin":
2306             if target.cpu == "x86":
2307                 return ("-DPIC", "-DMACHO")
2308             elif target.cpu == "x86_64":
2309                 return ("-D__x86_64__", "-DPIC", "-DMACHO")
2310         elif target.kernel == "WINNT":
2311             if target.cpu == "x86":
2312                 return ("-DPIC", "-DWIN32")
2313             elif target.cpu == "x86_64":
2314                 return ("-D__x86_64__", "-DPIC", "-DWIN64", "-DMSVC")
2315         elif target.cpu == "mips32":
2316             return ("-mdspr2",)
2317         elif target.cpu == "mips64" and jpeg_mips64_mmi:
2318             return in_tree_jpeg_mips64
2319         elif target.cpu == "x86":
2320             return ("-DPIC", "-DELF")
2321         elif target.cpu == "x86_64":
2322             return ("-D__x86_64__", "-DPIC", "-DELF")
2324     @depends(target, when=depends("--with-system-jpeg")(lambda x: not x))
2325     def jpeg_nasm(target):
2326         if target.cpu in ("x86", "x86_64"):
2327             # libjpeg-turbo 2.0.6 requires nasm 2.10.
2328             return namespace(version="2.10", what="JPEG")
2330     # Compiler checks from https://github.com/libjpeg-turbo/libjpeg-turbo/blob/57ba02a408a9a55ccff25aae8b164632a3a4f177/simd/CMakeLists.txt#L258
2331     jpeg_arm_neon_vld1_s16_x3 = c_compiler.try_compile(
2332         includes=["arm_neon.h"],
2333         body="int16_t input[12] = {}; int16x4x3_t output = vld1_s16_x3(input);",
2334         check_msg="for vld1_s16_x3 in arm_neon.h",
2335         flags=in_tree_jpeg_arm,
2336         when=in_tree_jpeg_arm,
2337     )
2339     jpeg_arm_neon_vld1_u16_x2 = c_compiler.try_compile(
2340         includes=["arm_neon.h"],
2341         body="uint16_t input[8] = {}; uint16x4x2_t output = vld1_u16_x2(input);",
2342         check_msg="for vld1_u16_x2 in arm_neon.h",
2343         flags=in_tree_jpeg_arm,
2344         when=in_tree_jpeg_arm,
2345     )
2347     jpeg_arm_neon_vld1q_u8_x4 = c_compiler.try_compile(
2348         includes=["arm_neon.h"],
2349         body="uint8_t input[64] = {}; uint8x16x4_t output = vld1q_u8_x4(input);",
2350         check_msg="for vld1q_u8_x4 in arm_neon.h",
2351         flags=in_tree_jpeg_arm,
2352         when=in_tree_jpeg_arm,
2353     )
2355     set_config("LIBJPEG_TURBO_USE_NASM", True, when=jpeg_nasm)
2356     set_config("LIBJPEG_TURBO_SIMD_FLAGS", in_tree_jpeg)
2357     set_config("LIBJPEG_TURBO_HAVE_VLD1_S16_X3", jpeg_arm_neon_vld1_s16_x3)
2358     set_config("LIBJPEG_TURBO_HAVE_VLD1_U16_X2", jpeg_arm_neon_vld1_u16_x2)
2359     set_config("LIBJPEG_TURBO_HAVE_VLD1Q_U8_X4", jpeg_arm_neon_vld1q_u8_x4)
2360     set_config(
2361         "LIBJPEG_TURBO_NEON_INTRINSICS",
2362         jpeg_arm_neon_vld1_s16_x3
2363         & jpeg_arm_neon_vld1_u16_x2
2364         & jpeg_arm_neon_vld1q_u8_x4,
2365     )
2368 # PNG
2369 # ===
2370 with only_when(compile_environment):
2371     system_lib_option(
2372         "--with-system-png",
2373         nargs="?",
2374         help="Use system libpng",
2375     )
2377     @depends("--with-system-png")
2378     def deprecated_system_png_path(value):
2379         if len(value) == 1:
2380             die(
2381                 "--with-system-png=PATH is not supported anymore. Please use "
2382                 "--with-system-png and set any necessary pkg-config environment variable."
2383             )
2385     png = pkg_check_modules("MOZ_PNG", "libpng >= 1.6.35", when="--with-system-png")
2387     check_symbol(
2388         "png_get_acTL",
2389         flags=png.libs,
2390         onerror=lambda: die(
2391             "--with-system-png won't work because the system's libpng doesn't have APNG support"
2392         ),
2393         when="--with-system-png",
2394     )
2396     set_config("MOZ_SYSTEM_PNG", True, when="--with-system-png")
2399 # FFmpeg's ffvpx configuration
2400 # ==============================================================
2402 # Artifact builds need MOZ_FFVPX defined as if compilation happened.
2403 with only_when(compile_environment | artifact_builds):
2405     @depends(target)
2406     def ffvpx(target):
2407         enable = use_nasm = True
2408         flac_only = False
2409         flags = []
2411         if target.kernel == "WINNT":
2412             if target.cpu == "x86":
2413                 # 32-bit windows need to prefix symbols with an underscore.
2414                 flags = ["-DPIC", "-DWIN32", "-DPREFIX", "-Pconfig_win32.asm"]
2415             elif target.cpu == "x86_64":
2416                 flags = [
2417                     "-D__x86_64__",
2418                     "-DPIC",
2419                     "-DWIN64",
2420                     "-DMSVC",
2421                     "-Pconfig_win64.asm",
2422                 ]
2423             elif target.cpu == "aarch64":
2424                 flags = ["-DPIC", "-DWIN64"]
2425                 use_nasm = False
2426         elif target.kernel == "Darwin":
2427             # 32/64-bit macosx assemblers need to prefix symbols with an
2428             # underscore.
2429             flags = ["-DPIC", "-DMACHO", "-DPREFIX"]
2430             if target.cpu == "x86_64":
2431                 flags += [
2432                     "-D__x86_64__",
2433                     "-Pconfig_darwin64.asm",
2434                 ]
2435             elif target.cpu == "aarch64":
2436                 use_nasm = False
2437         elif target.cpu == "x86_64":
2438             flags = ["-D__x86_64__", "-DPIC", "-DELF", "-Pconfig_unix64.asm"]
2439         elif target.cpu in ("x86", "arm", "aarch64"):
2440             flac_only = True
2441         else:
2442             enable = False
2444         if flac_only or not enable:
2445             use_nasm = False
2447         return namespace(
2448             enable=enable,
2449             use_nasm=use_nasm,
2450             flac_only=flac_only,
2451             flags=flags,
2452         )
2454     @depends(when=ffvpx.use_nasm)
2455     def ffvpx_nasm():
2456         # nasm 2.10 for AVX-2 support.
2457         return namespace(version="2.10", what="FFVPX")
2459     # ffvpx_nasm can't indirectly depend on vpx_as_flags, because it depends
2460     # on a compiler test, so we have to do a little bit of dance here.
2461     @depends(ffvpx, vpx_as_flags, target)
2462     def ffvpx(ffvpx, vpx_as_flags, target):
2463         if ffvpx and vpx_as_flags and target.cpu in ("arm", "aarch64"):
2464             ffvpx.flags.extend(vpx_as_flags)
2465         return ffvpx
2467     set_config("MOZ_FFVPX", True, when=ffvpx.enable)
2468     set_define("MOZ_FFVPX", True, when=ffvpx.enable)
2469     set_config("MOZ_FFVPX_AUDIOONLY", True, when=ffvpx.flac_only)
2470     set_define("MOZ_FFVPX_AUDIOONLY", True, when=ffvpx.flac_only)
2471     set_config("FFVPX_ASFLAGS", ffvpx.flags)
2472     set_config("FFVPX_USE_NASM", True, when=ffvpx.use_nasm)
2475 # nasm detection
2476 # ==============================================================
2477 @depends(dav1d_nasm, vpx_nasm, jpeg_nasm, ffvpx_nasm, when=compile_environment)
2478 def need_nasm(*requirements):
2479     requires = {
2480         x.what: x.version if hasattr(x, "version") else True for x in requirements if x
2481     }
2482     if requires:
2483         items = sorted(requires.keys())
2484         if len(items) > 1:
2485             what = " and ".join((", ".join(items[:-1]), items[-1]))
2486         else:
2487             what = items[0]
2488         versioned = {k: v for (k, v) in requires.items() if v is not True}
2489         return namespace(what=what, versioned=versioned)
2492 nasm = check_prog(
2493     "NASM",
2494     ["nasm"],
2495     allow_missing=True,
2496     bootstrap="nasm",
2497     when=need_nasm,
2501 @depends(nasm, need_nasm.what)
2502 def check_nasm(nasm, what):
2503     if not nasm and what:
2504         die("Nasm is required to build with %s, but it was not found." % what)
2505     return nasm
2508 @depends_if(check_nasm)
2509 @checking("nasm version")
2510 def nasm_version(nasm):
2511     version = (
2512         check_cmd_output(nasm, "-v", onerror=lambda: die("Failed to get nasm version."))
2513         .splitlines()[0]
2514         .split()[2]
2515     )
2516     return Version(version)
2519 @depends(nasm_version, need_nasm.versioned, when=need_nasm.versioned)
2520 def check_nasm_version(nasm_version, versioned):
2521     by_version = sorted(versioned.items(), key=lambda x: x[1])
2522     what, version = by_version[-1]
2523     if nasm_version < version:
2524         die(
2525             "Nasm version %s or greater is required to build with %s." % (version, what)
2526         )
2527     return nasm_version
2530 @depends(target, when=check_nasm_version)
2531 def nasm_asflags(target):
2532     asflags = {
2533         ("Darwin", "x86"): ["-f", "macho32"],
2534         ("Darwin", "x86_64"): ["-f", "macho64"],
2535         ("WINNT", "x86"): ["-f", "win32"],
2536         ("WINNT", "x86_64"): ["-f", "win64"],
2537     }.get((target.kernel, target.cpu), None)
2538     if asflags is None:
2539         # We're assuming every x86 platform we support that's
2540         # not Windows or Mac is ELF.
2541         if target.cpu == "x86":
2542             asflags = ["-f", "elf32"]
2543         elif target.cpu == "x86_64":
2544             asflags = ["-f", "elf64"]
2545     return asflags
2548 set_config("NASM_ASFLAGS", nasm_asflags)
2551 # ANGLE OpenGL->D3D translator for WebGL
2552 # ==============================================================
2554 with only_when(compile_environment & target_is_windows):
2555     set_config("MOZ_ANGLE_RENDERER", True)
2557 # Remoting protocol support
2558 # ==============================================================
2561 @depends(toolkit)
2562 def has_remote(toolkit):
2563     if toolkit in ("gtk", "windows", "cocoa"):
2564         return True
2567 set_config("MOZ_HAS_REMOTE", has_remote)
2568 set_define("MOZ_HAS_REMOTE", has_remote)
2570 # RLBox Library Sandboxing wasm support
2571 # ==============================================================
2574 def wasm_sandboxing_libraries():
2575     return (
2576         "graphite",
2577         "ogg",
2578         "hunspell",
2579         "expat",
2580         "woff2",
2581         "soundtouch",
2582     )
2585 @depends(dependable(wasm_sandboxing_libraries), build_project)
2586 def default_wasm_sandboxing_libraries(libraries, build_project):
2587     if build_project != "tools/rusttests":
2588         non_default_libs = {}
2590         return tuple(l for l in libraries if l not in non_default_libs)
2593 option(
2594     "--with-wasm-sandboxed-libraries",
2595     env="WASM_SANDBOXED_LIBRARIES",
2596     help="{Enable wasm sandboxing for the selected libraries|Disable wasm sandboxing}",
2597     nargs="+",
2598     choices=dependable(wasm_sandboxing_libraries),
2599     default=default_wasm_sandboxing_libraries,
2603 @depends("--with-wasm-sandboxed-libraries")
2604 def requires_wasm_sandboxing(libraries):
2605     if libraries:
2606         return True
2609 set_config("MOZ_USING_WASM_SANDBOXING", requires_wasm_sandboxing)
2610 set_define("MOZ_USING_WASM_SANDBOXING", requires_wasm_sandboxing)
2612 with only_when(requires_wasm_sandboxing & compile_environment):
2613     option(
2614         "--with-wasi-sysroot",
2615         env="WASI_SYSROOT",
2616         nargs=1,
2617         help="Path to wasi sysroot for wasm sandboxing",
2618     )
2620     @depends("--with-wasi-sysroot", requires_wasm_sandboxing)
2621     def bootstrap_wasi_sysroot(wasi_sysroot, requires_wasm_sandboxing):
2622         return requires_wasm_sandboxing and not wasi_sysroot
2624     @depends(
2625         "--with-wasi-sysroot",
2626         bootstrap_path("sysroot-wasm32-wasi", when=bootstrap_wasi_sysroot),
2627     )
2628     @imports("os")
2629     def wasi_sysroot(wasi_sysroot, bootstrapped_sysroot):
2630         if not wasi_sysroot:
2631             return bootstrapped_sysroot
2633         wasi_sysroot = wasi_sysroot[0]
2634         if not os.path.isdir(wasi_sysroot):
2635             die("Argument to --with-wasi-sysroot must be a directory")
2636         if not os.path.isabs(wasi_sysroot):
2637             die("Argument to --with-wasi-sysroot must be an absolute path")
2639         return wasi_sysroot
2641     @depends(wasi_sysroot)
2642     def wasi_sysroot_flags(wasi_sysroot):
2643         if wasi_sysroot:
2644             log.info("Using wasi sysroot in %s", wasi_sysroot)
2645             return ["--sysroot=%s" % wasi_sysroot]
2646         return []
2648     set_config("WASI_SYSROOT", wasi_sysroot)
2650     def wasm_compiler_with_flags(compiler, sysroot_flags):
2651         if compiler:
2652             return (
2653                 compiler.wrapper + [compiler.compiler] + compiler.flags + sysroot_flags
2654             )
2656     @template
2657     def wasm_compiler_error(msg):
2658         @depends("--with-wasm-sandboxed-libraries")
2659         def wasm_compiler_error(sandboxed_libs):
2660             suggest_disable = ""
2661             if sandboxed_libs.origin == "default":
2662                 suggest_disable = " Or build with --without-wasm-sandboxed-libraries."
2663             return lambda: die(msg + suggest_disable)
2665         return wasm_compiler_error
2667     @template
2668     def check_wasm_compiler(compiler, language):
2669         compiler.try_compile(
2670             includes=["cstring" if language == "C++" else "string.h"],
2671             flags=wasi_sysroot_flags,
2672             check_msg="the wasm %s compiler can find wasi headers" % language,
2673             onerror=wasm_compiler_error(
2674                 "Cannot find wasi headers or problem with the wasm compiler. "
2675                 "Please fix the problem."
2676             ),
2677         )
2679         compiler.try_run(
2680             flags=wasi_sysroot_flags,
2681             check_msg="the wasm %s linker can find wasi libraries" % language,
2682             onerror=wasm_compiler_error(
2683                 "Cannot find wasi libraries or problem with the wasm linker. "
2684                 "Please fix the problem."
2685             ),
2686         )
2688     wasm_cc = compiler("C", wasm, other_compiler=c_compiler)
2689     check_wasm_compiler(wasm_cc, "C")
2691     @depends(wasm_cc, wasi_sysroot_flags)
2692     def wasm_cc_with_flags(wasm_cc, wasi_sysroot_flags):
2693         return wasm_compiler_with_flags(wasm_cc, wasi_sysroot_flags)
2695     set_config("WASM_CC", wasm_cc_with_flags)
2697     wasm_cxx = compiler(
2698         "C++",
2699         wasm,
2700         c_compiler=wasm_cc,
2701         other_compiler=cxx_compiler,
2702         other_c_compiler=c_compiler,
2703     )
2704     check_wasm_compiler(wasm_cxx, "C++")
2706     @depends(wasm_cxx, wasi_sysroot_flags)
2707     def wasm_cxx_with_flags(wasm_cxx, wasi_sysroot_flags):
2708         return wasm_compiler_with_flags(wasm_cxx, wasi_sysroot_flags)
2710     set_config("WASM_CXX", wasm_cxx_with_flags)
2712     wasm_compile_flags = dependable(["-fno-exceptions", "-fno-strict-aliasing"])
2713     option(env="WASM_CFLAGS", nargs=1, help="Options to pass to WASM_CC")
2715     @depends("WASM_CFLAGS", wasm_compile_flags)
2716     def wasm_cflags(value, wasm_compile_flags):
2717         if value:
2718             return wasm_compile_flags + value
2719         else:
2720             return wasm_compile_flags
2722     set_config("WASM_CFLAGS", wasm_cflags)
2724     option(env="WASM_CXXFLAGS", nargs=1, help="Options to pass to WASM_CXX")
2726     @depends("WASM_CXXFLAGS", wasm_compile_flags)
2727     def wasm_cxxflags(value, wasm_compile_flags):
2728         if value:
2729             return wasm_compile_flags + value
2730         else:
2731             return wasm_compile_flags
2733     set_config("WASM_CXXFLAGS", wasm_cxxflags)
2736 @depends("--with-wasm-sandboxed-libraries")
2737 def wasm_sandboxing(libraries):
2738     if not libraries:
2739         return
2741     return namespace(**{name: True for name in libraries})
2744 @template
2745 def wasm_sandboxing_config_defines():
2746     for lib in wasm_sandboxing_libraries():
2747         set_config(
2748             "MOZ_WASM_SANDBOXING_%s" % lib.upper(), getattr(wasm_sandboxing, lib)
2749         )
2750         set_define(
2751             "MOZ_WASM_SANDBOXING_%s" % lib.upper(), getattr(wasm_sandboxing, lib)
2752         )
2755 wasm_sandboxing_config_defines()
2758 with only_when(compile_environment & wasm_sandboxing.hunspell):
2759     clock_in_wasi_sysroot = wasm_cc.try_run(
2760         header="#include <time.h>",
2761         body="clock();",
2762         check_msg="for clock() in wasi sysroot",
2763         flags=depends(wasi_sysroot_flags)(
2764             lambda sysroot_flags: ["-Werror"] + sysroot_flags
2765         ),
2766     )
2768     wasi_emulated_clock = wasm_cc.try_run(
2769         header="#include <time.h>",
2770         body="clock();",
2771         check_msg="for emulated clock() in wasi sysroot",
2772         flags=depends(wasi_sysroot_flags)(
2773             lambda sysroot_flags: [
2774                 "-Werror",
2775                 "-D_WASI_EMULATED_PROCESS_CLOCKS",
2776                 "-lwasi-emulated-process-clocks",
2777             ]
2778             + sysroot_flags
2779         ),
2780         when=depends(clock_in_wasi_sysroot)(lambda x: not x),
2781         onerror=lambda: die("Can't find clock() in wasi sysroot."),
2782     )
2784     set_config("MOZ_WASI_EMULATED_CLOCK", True, when=wasi_emulated_clock)
2787 # new Notification Store implementation
2788 # ==============================================================
2791 @depends(milestone)
2792 def new_notification_store(milestone):
2793     if milestone.is_nightly:
2794         return True
2797 set_config("MOZ_NEW_NOTIFICATION_STORE", True, when=new_notification_store)
2798 set_define("MOZ_NEW_NOTIFICATION_STORE", True, when=new_notification_store)
2801 # Auxiliary files persistence on application close
2802 # ==============================================================
2804 option(
2805     "--enable-disk-remnant-avoidance",
2806     help="Prevent persistence of auxiliary files on application close",
2810 set_config(
2811     "MOZ_AVOID_DISK_REMNANT_ON_CLOSE",
2812     True,
2813     when="--enable-disk-remnant-avoidance",
2817 # Glean SDK Integration Crate
2818 # ==============================================================
2821 @depends(target)
2822 def glean_android(target):
2823     return target.os == "Android"
2826 set_config("MOZ_GLEAN_ANDROID", True, when=glean_android)
2827 set_define("MOZ_GLEAN_ANDROID", True, when=glean_android)
2830 # dump_syms
2831 # ==============================================================
2833 check_prog(
2834     "DUMP_SYMS",
2835     ["dump_syms"],
2836     allow_missing=True,
2837     bootstrap="dump_syms",
2838     when=compile_environment,
2842 @depends(valid_windows_sdk_dir, host)
2843 @imports(_from="os", _import="environ")
2844 def pdbstr_paths(valid_windows_sdk_dir, host):
2845     if not valid_windows_sdk_dir:
2846         return
2848     vc_host = {
2849         "x86": "x86",
2850         "x86_64": "x64",
2851     }.get(host.cpu)
2853     return [
2854         environ["PATH"],
2855         os.path.join(valid_windows_sdk_dir.path, "Debuggers", vc_host, "srcsrv"),
2856     ]
2859 check_prog(
2860     "PDBSTR",
2861     ["pdbstr.exe"],
2862     allow_missing=True,
2863     when=compile_environment & target_is_windows,
2864     paths=pdbstr_paths,
2865     allow_spaces=True,
2869 @depends("MOZ_AUTOMATION", c_compiler)
2870 def allow_missing_winchecksec(automation, c_compiler):
2871     if not automation:
2872         return True
2873     if c_compiler and c_compiler.type != "clang-cl":
2874         return True
2877 check_prog(
2878     "WINCHECKSEC",
2879     ["winchecksec.exe", "winchecksec"],
2880     bootstrap="winchecksec",
2881     allow_missing=allow_missing_winchecksec,
2882     when=compile_environment & target_is_windows,
2886 # Fork server
2887 @depends(target, build_project)
2888 def forkserver_default(target, build_project):
2889     return build_project == "browser" and (
2890         (target.os == "GNU" and target.kernel == "Linux")
2891         or target.os == "FreeBSD"
2892         or target.os == "OpenBSD"
2893     )
2896 option(
2897     "--enable-forkserver",
2898     default=forkserver_default,
2899     env="MOZ_ENABLE_FORKSERVER",
2900     help="{Enable|Disable} fork server",
2904 @depends("--enable-forkserver", target)
2905 def forkserver_flag(value, target):
2906     if (
2907         target.os == "Android"
2908         or (target.os == "GNU" and target.kernel == "Linux")
2909         or target.os == "FreeBSD"
2910         or target.os == "OpenBSD"
2911     ):
2912         return bool(value)
2913     pass
2916 set_config("MOZ_ENABLE_FORKSERVER", forkserver_flag)
2917 set_define("MOZ_ENABLE_FORKSERVER", forkserver_flag, forkserver_flag)
2919 # Crash Reporter
2920 # ==============================================================
2922 with only_when(compile_environment & target_has_linux_kernel):
2923     # Check if we need to use the breakpad_getcontext fallback.
2924     getcontext = check_symbol("getcontext")
2925     set_config("HAVE_GETCONTEXT", getcontext)
2926     set_define("HAVE_GETCONTEXT", getcontext)
2928 # NSS
2929 # ==============================================================
2930 include("../build/moz.configure/nss.configure")
2933 # Enable or disable running in background task mode: headless for
2934 # periodic, short-lived, maintenance tasks.
2935 # ==============================================================================
2936 option(
2937     "--disable-backgroundtasks",
2938     help="Disable running in background task mode",
2940 set_config("MOZ_BACKGROUNDTASKS", True, when="--enable-backgroundtasks")
2941 set_define("MOZ_BACKGROUNDTASKS", True, when="--enable-backgroundtasks")
2944 # Update-related programs: updater, maintenance service, update agent,
2945 # default browser agent.
2946 # ==============================================================
2947 include("../build/moz.configure/update-programs.configure")
2950 # Mobile optimizations
2951 # ==============================================================
2952 option(
2953     "--enable-mobile-optimize",
2954     default=target_is_android,
2955     help="{Enable|Disable} mobile optimizations",
2958 set_define("MOZ_GFX_OPTIMIZE_MOBILE", True, when="--enable-mobile-optimize")
2959 # We ignore "paint will resample" on mobile for performance.
2960 # We may want to revisit this later.
2961 set_define("MOZ_IGNORE_PAINT_WILL_RESAMPLE", True, when="--enable-mobile-optimize")
2963 # Pref extensions
2964 # ==============================================================
2965 option("--disable-pref-extensions", help="Disable pref extensions such as autoconfig")
2966 set_config("MOZ_PREF_EXTENSIONS", True, when="--enable-pref-extensions")
2968 # Offer a way to disable the startup cache
2969 # ==============================================================
2970 option("--disable-startupcache", help="Disable startup cache")
2973 @depends("--enable-startupcache")
2974 def enable_startupcache(value):
2975     if value:
2976         return True
2979 set_define(
2980     "MOZ_DISABLE_STARTUPCACHE", True, when=depends(enable_startupcache)(lambda x: not x)
2984 # Branding
2985 # ==============================================================
2986 option(
2987     env="MOZ_APP_REMOTINGNAME",
2988     nargs=1,
2989     help="Used for the internal program name, which affects profile name "
2990     "and remoting. If not set, defaults to MOZ_APP_NAME if the update channel "
2991     "is release, and MOZ_APP_NAME-MOZ_UPDATE_CHANNEL otherwise.",
2995 @depends("MOZ_APP_REMOTINGNAME", moz_app_name, update_channel)
2996 def moz_app_remotingname(value, moz_app_name, update_channel):
2997     if value:
2998         return value[0]
2999     if update_channel == "release":
3000         return moz_app_name
3001     return moz_app_name + "-" + update_channel
3004 set_config("MOZ_APP_REMOTINGNAME", moz_app_remotingname)
3006 option(
3007     env="ANDROID_PACKAGE_NAME",
3008     nargs=1,
3009     help="Name of the Android package (default org.mozilla.$MOZ_APP_NAME)",
3013 @depends("ANDROID_PACKAGE_NAME", moz_app_name)
3014 def android_package_name(value, moz_app_name):
3015     if value:
3016         return value[0]
3017     if moz_app_name == "fennec":
3018         return "org.mozilla.fennec_aurora"
3019     return "org.mozilla.%s" % moz_app_name
3022 set_config("ANDROID_PACKAGE_NAME", android_package_name)
3025 # Miscellaneous options
3026 # ==============================================================
3027 option(env="MOZ_WINCONSOLE", nargs="?", help="Whether we can create a console window.")
3028 set_define("MOZ_WINCONSOLE", True, when=depends("MOZ_WINCONSOLE")(lambda x: x))
3031 # Alternative Crashreporter setting
3032 option(
3033     "--with-crashreporter-url",
3034     env="MOZ_CRASHREPORTER_URL",
3035     default="https://crash-reports.mozilla.com/",
3036     nargs=1,
3037     help="Set an alternative crashreporter url",
3040 set_config(
3041     "MOZ_CRASHREPORTER_URL",
3042     depends("--with-crashreporter-url")(lambda x: x[0].rstrip("/")),
3046 # Crash reporter options
3047 # ==============================================================
3048 @depends(target)
3049 def oxidized_breakpad(target):
3050     if target.kernel == "Linux":
3051         return target.cpu in ("aarch64", "arm", "x86", "x86_64")
3052     return False
3055 set_config("MOZ_OXIDIZED_BREAKPAD", True, when=oxidized_breakpad)
3056 set_define("MOZ_OXIDIZED_BREAKPAD", True, when=oxidized_breakpad)
3059 # Wine
3060 # ==============================================================
3061 @depends(target, host)
3062 def want_wine(target, host):
3063     return target.kernel == "WINNT" and host.kernel != "WINNT"
3066 wine = check_prog(
3067     "WINE",
3068     ["wine64", "wine"],
3069     when=want_wine,
3070     bootstrap="wine/bin",
3073 # DOM Streams
3074 # ==============================================================
3075 # Set this to true so the JS engine knows we're doing a browser build.
3076 set_config("MOZ_DOM_STREAMS", True)
3077 set_define("MOZ_DOM_STREAMS", True)
3079 # libevent
3080 # ==============================================================
3081 with only_when(compile_environment):
3082     system_lib_option(
3083         "--with-system-libevent",
3084         nargs="?",
3085         help="Use system libevent",
3086     )
3088     @depends("--with-system-libevent")
3089     def deprecated_system_libevent_path(value):
3090         if len(value) == 1:
3091             die(
3092                 "--with-system-libevent=PATH is not supported anymore. Please use "
3093                 "--with-system-libevent and set any necessary pkg-config environment variable."
3094             )
3096     pkg_check_modules("MOZ_LIBEVENT", "libevent", when="--with-system-libevent")
3098     set_config("MOZ_SYSTEM_LIBEVENT", True, when="--with-system-libevent")
3101 # Crash reporting
3102 # ==============================================================
3103 @depends(target, developer_options, artifact_builds)
3104 def crashreporter_default(target, developer_options, artifacts):
3105     if target.os in ("WINNT", "OSX"):
3106         return True
3107     if target.kernel == "Linux" and target.cpu in ("x86", "x86_64", "arm", "aarch64"):
3108         # The crash reporter prevents crash stacktraces to be logged in the
3109         # logs on Android, so we leave it out by default in developer builds.
3110         return target.os != "Android" or not developer_options or artifacts
3113 option(
3114     "--enable-crashreporter",
3115     default=crashreporter_default,
3116     help="{Enable|Disable} crash reporting",
3120 set_config("MOZ_CRASHREPORTER", True, when="--enable-crashreporter")
3121 set_define("MOZ_CRASHREPORTER", True, when="--enable-crashreporter")
3123 with only_when(compile_environment):
3124     with only_when("--enable-crashreporter"):
3125         pkg_check_modules(
3126             "MOZ_GTHREAD",
3127             "gthread-2.0",
3128             when=depends(target)(lambda t: t.os == "GNU" and t.kernel == "Linux"),
3129         )
3131         set_config(
3132             "MOZ_CRASHREPORTER_INJECTOR",
3133             True,
3134             when=depends(target)(lambda t: t.os == "WINNT" and t.bitness == 32),
3135         )
3136         set_define(
3137             "MOZ_CRASHREPORTER_INJECTOR",
3138             True,
3139             when=depends(target)(lambda t: t.os == "WINNT" and t.bitness == 32),
3140         )
3143 # If we have any service that uploads data (and requires data submission
3144 # policy alert), set MOZ_DATA_REPORTING.
3145 # ==============================================================
3146 @depends(
3147     "MOZ_TELEMETRY_REPORTING",
3148     "MOZ_SERVICES_HEALTHREPORT",
3149     "--enable-crashreporter",
3150     "MOZ_NORMANDY",
3152 def data_reporting(telemetry, healthreport, crashreporter, normandy):
3153     return telemetry or healthreport or crashreporter or normandy
3156 set_config("MOZ_DATA_REPORTING", True, when=data_reporting)
3157 set_define("MOZ_DATA_REPORTING", True, when=data_reporting)
3160 # Gtk+
3161 # ==============================================================
3162 with only_when(toolkit_gtk):
3163     pkg_check_modules(
3164         "MOZ_GTK3",
3165         "gtk+-3.0 >= 3.14.0 gtk+-unix-print-3.0 glib-2.0 gobject-2.0 gio-unix-2.0",
3166     )
3168     set_define("GDK_VERSION_MIN_REQUIRED", "GDK_VERSION_3_14")
3169     set_define("GDK_VERSION_MAX_ALLOWED", "GDK_VERSION_3_14")
3171     pkg_check_modules("GLIB", "glib-2.0 >= 2.42 gobject-2.0")
3173     set_define("GLIB_VERSION_MIN_REQUIRED", "GLIB_VERSION_2_42")
3174     set_define("GLIB_VERSION_MAX_ALLOWED", "GLIB_VERSION_2_42")
3176     set_define("MOZ_ACCESSIBILITY_ATK", True, when=accessibility)
3178 # DBus
3179 # ==============================================================
3180 with only_when(toolkit_gtk):
3181     option("--disable-dbus", help="Disable dbus support")
3183     with only_when("--enable-dbus"):
3184         pkg_check_modules("MOZ_DBUS", "dbus-1 >= 0.60")
3186         set_config("MOZ_ENABLE_DBUS", True)
3187         set_define("MOZ_ENABLE_DBUS", True)
3190 # Necko's wifi scanner
3191 # ==============================================================
3192 @depends(target)
3193 def necko_wifi_when(target):
3194     return target.os in ("WINNT", "OSX", "DragonFly", "FreeBSD") or (
3195         target.kernel == "Linux" and target.os == "GNU"
3196     )
3199 option("--disable-necko-wifi", help="Disable necko wifi scanner", when=necko_wifi_when)
3201 set_config("NECKO_WIFI", True, when="--enable-necko-wifi")
3202 set_define("NECKO_WIFI", True, when="--enable-necko-wifi")
3205 @depends(
3206     depends("--enable-necko-wifi", when=necko_wifi_when)(lambda x: x),
3207     depends("--enable-dbus", when=toolkit_gtk)(lambda x: x),
3208     when=depends(target)(lambda t: t.os == "GNU" and t.kernel == "Linux"),
3210 def necko_wifi_dbus(necko_wifi, dbus):
3211     if necko_wifi and not dbus:
3212         die(
3213             "Necko WiFi scanning needs DBus on your platform, remove --disable-dbus"
3214             " or use --disable-necko-wifi"
3215         )
3216     return necko_wifi and dbus
3219 set_config("NECKO_WIFI_DBUS", True, when=necko_wifi_dbus)
3220 set_define("NECKO_WIFI_DBUS", True, when=necko_wifi_dbus)
3223 # Frontend JS debug mode
3224 # ==============================================================
3225 option("--enable-debug-js-modules", help="Enable debug mode for frontend JS libraries")
3227 set_config("DEBUG_JS_MODULES", True, when="--enable-debug-js-modules")
3230 # moz_dump_painting
3231 # ==============================================================
3232 option("--enable-dump-painting", help="Enable paint debugging")
3234 set_define(
3235     "MOZ_DUMP_PAINTING",
3236     True,
3237     when=depends("--enable-dump-painting", "--enable-debug")(
3238         lambda painting, debug: painting or debug
3239     ),
3241 set_define("MOZ_LAYERS_HAVE_LOG", True, when="--enable-dump-painting")
3244 # libproxy support
3245 # ==============================================================
3246 with only_when(toolkit_gtk):
3247     system_lib_option("--enable-libproxy", help="Enable libproxy support")
3249     with only_when("--enable-libproxy"):
3250         pkg_check_modules("MOZ_LIBPROXY", "libproxy-1.0")
3252         set_config("MOZ_ENABLE_LIBPROXY", True)
3253         set_define("MOZ_ENABLE_LIBPROXY", True)
3256 # Enable runtime logging
3257 # ==============================================================
3258 set_define("MOZ_LOGGING", True)
3259 set_define("FORCE_PR_LOG", True)
3261 # This will enable logging of addref, release, ctor, dtor.
3262 # ==============================================================
3263 option(
3264     "--enable-logrefcnt",
3265     default=moz_debug,
3266     help="{Enable|Disable} logging of refcounts",
3269 set_define("NS_BUILD_REFCNT_LOGGING", True, when="--enable-logrefcnt")
3272 # NegotiateAuth
3273 # ==============================================================
3274 option("--disable-negotiateauth", help="Disable GSS-API negotiation")
3276 set_config("MOZ_AUTH_EXTENSION", True, when="--enable-negotiateauth")
3277 set_define("MOZ_AUTH_EXTENSION", True, when="--enable-negotiateauth")
3280 # Parental control
3281 # ==============================================================
3282 option("--disable-parental-controls", help="Do not build parental controls")
3284 set_config(
3285     "MOZ_DISABLE_PARENTAL_CONTROLS",
3286     True,
3287     when=depends("--enable-parental-controls")(lambda x: not x),
3289 set_define(
3290     "MOZ_DISABLE_PARENTAL_CONTROLS",
3291     True,
3292     when=depends("--enable-parental-controls")(lambda x: not x),
3296 # Sandboxing support
3297 # ==============================================================
3298 @depends(target, tsan, asan)
3299 def sandbox_default(target, tsan, asan):
3300     # Only enable the sandbox by default on Linux, OpenBSD, macOS, and Windows
3301     if target.kernel == "Linux" and target.os == "GNU":
3302         # Bug 1182565: TSan conflicts with sandboxing on Linux.
3303         # Bug 1287971: LSan also conflicts with sandboxing on Linux.
3304         if tsan or asan:
3305             return False
3306         # Linux sandbox is only available on x86{,_64} and arm{,64}.
3307         return target.cpu in ("x86", "x86_64", "arm", "aarch64")
3308     return target.kernel in ("WINNT", "Darwin", "OpenBSD")
3311 option(
3312     "--enable-sandbox",
3313     default=sandbox_default,
3314     help="{Enable|Disable} sandboxing support",
3317 set_config("MOZ_SANDBOX", True, when="--enable-sandbox")
3318 set_define("MOZ_SANDBOX", True, when="--enable-sandbox")
3320 with only_when(depends(target.kernel)(lambda k: k not in ("Darwin", "WINNT"))):
3321     set_define("MOZ_CONTENT_TEMP_DIR", True, when="--enable-sandbox")
3323 # Searching of system directories for extensions.
3324 # ==============================================================
3325 # Note: this switch is meant to be used for test builds whose behavior should
3326 # not depend on what happens to be installed on the local machine.
3327 option(
3328     "--disable-system-extension-dirs",
3329     help="Disable searching system- and account-global directories for extensions"
3330     " of any kind; use only profile-specific extension directories",
3333 set_define("ENABLE_SYSTEM_EXTENSION_DIRS", True, when="--enable-system-extension-dirs")
3336 # Pixman
3337 # ==============================================================
3338 with only_when(compile_environment):
3339     system_lib_option(
3340         "--enable-system-pixman", help="Use system pixman (located with pkgconfig)"
3341     )
3343     @depends("--enable-system-pixman")
3344     def in_tree_pixman(pixman):
3345         return not pixman
3347     set_config("MOZ_TREE_PIXMAN", True, when=in_tree_pixman)
3348     set_define("MOZ_TREE_PIXMAN", True, when=in_tree_pixman)
3350     pkg_check_modules("MOZ_PIXMAN", "pixman-1 >= 0.36.0", when="--enable-system-pixman")
3351     # Set MOZ_PIXMAN_CFLAGS to an explicit empty value when --enable-system-pixman is *not* used,
3352     # for layout/style/extra-bindgen-flags
3353     set_config("MOZ_PIXMAN_CFLAGS", [], when=in_tree_pixman)
3356 # Universalchardet
3357 # ==============================================================
3358 with only_when(compile_environment):
3359     option("--disable-universalchardet", help="Disable universal encoding detection")
3361     set_config("MOZ_UNIVERSALCHARDET", True, when="--enable-universalchardet")
3364 # Disable zipwriter
3365 # ==============================================================
3366 with only_when(compile_environment):
3367     option("--disable-zipwriter", help="Disable zipwriter component")
3369     set_config("MOZ_ZIPWRITER", True, when="--enable-zipwriter")
3372 # Location of the mozilla user directory
3373 # ==============================================================
3374 with only_when(compile_environment):
3376     @depends(target)
3377     def default_user_appdir(target):
3378         if target.kernel in ("WINNT", "Darwin"):
3379             return "Mozilla"
3380         return ".mozilla"
3382     option(
3383         "--with-user-appdir",
3384         nargs=1,
3385         default=default_user_appdir,
3386         help="Set user-specific appdir",
3387     )
3389     @depends("--with-user-appdir")
3390     def user_appdir(appdir):
3391         if not appdir:
3392             die("--without-user-appdir is not a valid option.")
3393         if "/" in appdir[0]:
3394             die("--with-user-appdir must be a single relative path.")
3395         return '"{}"'.format(appdir[0])
3397     set_define("MOZ_USER_DIR", user_appdir)
3400 # Check for sin_len and sin6_len - used by SCTP; only appears in Mac/*BSD generally
3401 # ==============================================================
3402 with only_when(compile_environment):
3403     have_sin_len = c_compiler.try_compile(
3404         includes=["netinet/in.h"],
3405         body="struct sockaddr_in x; void *foo = (void*) &x.sin_len;",
3406         check_msg="for sin_len in struct sockaddr_in",
3407     )
3408     have_sin6_len = c_compiler.try_compile(
3409         includes=["netinet/in.h"],
3410         body="struct sockaddr_in6 x; void *foo = (void*) &x.sin6_len;",
3411         check_msg="for sin_len6 in struct sockaddr_in6",
3412     )
3413     set_define("HAVE_SIN_LEN", have_sin_len)
3414     set_define("HAVE_SIN6_LEN", have_sin6_len)
3415     # HAVE_CONN_LEN must be the same as HAVE_SIN_LEN and HAVE_SIN6_LEN
3416     set_define("HAVE_SCONN_LEN", have_sin_len & have_sin6_len)
3417     set_define(
3418         "HAVE_SA_LEN",
3419         c_compiler.try_compile(
3420             includes=["netinet/in.h"],
3421             body="struct sockaddr x; void *foo = (void*) &x.sa_len;",
3422             check_msg="for sa_len in struct sockaddr",
3423         ),
3424     )
3427 # Check for pthread_cond_timedwait_monotonic_np
3428 # ==============================================================
3429 with only_when(compile_environment):
3430     set_define(
3431         "HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC",
3432         c_compiler.try_compile(
3433             includes=["pthread.h"],
3434             body="pthread_cond_timedwait_monotonic_np(0, 0, 0);",
3435             # -Werror to catch any "implicit declaration" warning that means the function
3436             # is not supported.
3437             flags=["-Werror=implicit-function-declaration"],
3438             check_msg="for pthread_cond_timedwait_monotonic_np",
3439         ),
3440     )
3443 # Custom dynamic linker for Android
3444 # ==============================================================
3445 with only_when(target_has_linux_kernel & compile_environment):
3446     option(
3447         env="MOZ_LINKER",
3448         default=depends(target.os, when="--enable-jemalloc")(
3449             lambda os: os == "Android"
3450         ),
3451         help="{Enable|Disable} custom dynamic linker",
3452     )
3454     set_config("MOZ_LINKER", True, when="MOZ_LINKER")
3455     set_define("MOZ_LINKER", True, when="MOZ_LINKER")
3456     add_old_configure_assignment("MOZ_LINKER", True, when="MOZ_LINKER")
3458     moz_linker = depends(when="MOZ_LINKER")(lambda: True)
3461 # 32-bits ethtool_cmd.speed
3462 # ==============================================================
3463 with only_when(target_has_linux_kernel & compile_environment):
3464     set_config(
3465         "MOZ_WEBRTC_HAVE_ETHTOOL_SPEED_HI",
3466         c_compiler.try_compile(
3467             includes=["linux/ethtool.h"],
3468             body="struct ethtool_cmd cmd; cmd.speed_hi = 0;",
3469             check_msg="for 32-bits ethtool_cmd.speed",
3470         ),
3471     )
3473 # Gamepad support
3474 # ==============================================================
3475 check_header(
3476     "linux/joystick.h",
3477     onerror=lambda: die(
3478         "Can't find header linux/joystick.h, needed for gamepad support."
3479         " Please install Linux kernel headers."
3480     ),
3481     when=target_has_linux_kernel & compile_environment,
3485 # Smart card support
3486 # ==============================================================
3487 @depends(build_project)
3488 def disable_smart_cards(build_project):
3489     return build_project == "mobile/android"
3492 set_config("MOZ_NO_SMART_CARDS", True, when=disable_smart_cards)
3493 set_define("MOZ_NO_SMART_CARDS", True, when=disable_smart_cards)
3495 # Enable UniFFI fixtures
3496 # ==============================================================
3497 # These are used to test the uniffi-bindgen-gecko-js code generation.  They
3498 # should not be enabled in release builds.
3500 option(
3501     "--enable-uniffi-fixtures",
3502     help="Enable UniFFI Fixtures/Examples",
3505 set_config("MOZ_UNIFFI_FIXTURES", True, when="--enable-uniffi-fixtures")
3507 # System policies
3508 # ==============================================================
3510 option(
3511     "--disable-system-policies",
3512     help="Disable reading policies from Windows registry, macOS's file system attributes, and /etc/firefox",
3515 set_config("MOZ_SYSTEM_POLICIES", True, when="--enable-system-policies")
3517 # Allow disabling the creation a legacy profile
3518 # ==============================================================
3520 option(
3521     "--disable-legacy-profile-creation",
3522     help="Disable the creation a legacy profile, to be used by old versions "
3523     "of Firefox, when no profiles exist.",
3526 set_config("MOZ_CREATE_LEGACY_PROFILE", True, when="--enable-legacy-profile-creation")
3529 # STL wrapping
3530 # ==============================================================
3531 set_config("WRAP_STL_INCLUDES", True)
3532 set_config(
3533     "STL_FLAGS",
3534     depends(build_environment.dist)(lambda dist: [f"-I{dist}/stl_wrappers"]),
3538 # Perl detection
3539 # ==============================================================
3540 @depends(target)
3541 def need_perl(target):
3542     # Ideally, we'd also depend on gnu_as here, but that adds complications.
3543     return target.cpu == "arm"
3546 perl = check_prog("PERL", ("perl5", "perl"), when=need_perl)
3549 @template
3550 def perl_version_check(min_version):
3551     @depends(perl)
3552     @checking("for minimum required perl version >= %s" % min_version)
3553     def get_perl_version(perl):
3554         return Version(
3555             check_cmd_output(
3556                 perl,
3557                 "-e",
3558                 "print $]",
3559                 onerror=lambda: die("Failed to get perl version."),
3560             )
3561         )
3563     @depends(get_perl_version)
3564     def check_perl_version(version):
3565         if version < min_version:
3566             die("Perl %s or higher is required.", min_version)
3568     @depends(perl)
3569     @checking("for full perl installation")
3570     @imports("subprocess")
3571     def has_full_perl_installation(perl):
3572         ret = subprocess.call([perl, "-e", "use Config; exit(!-d $Config{archlib})"])
3573         return ret == 0
3575     @depends(has_full_perl_installation)
3576     def require_full_perl_installation(has_full_perl_installation):
3577         if not has_full_perl_installation:
3578             die(
3579                 "Cannot find Config.pm or $Config{archlib}. "
3580                 "A full perl installation is required."
3581             )
3584 with only_when(need_perl):
3585     perl_version_check("5.006")
3588 # windows-rs as bootstrappable toolchain
3589 # ==============================================================
3590 # The in-tree windows crate's purpose is to avoid vendoring the
3591 # original windows crate, which is too large.
3592 # The ideal solution would be for cargo to allow exceptions to
3593 # vendoring, but it doesn't.
3594 # The adopted solution is to somehow use the crate contents from
3595 # a directory given via the mozbuild config, or bootstrapped.
3597 # Unfortunately, doing `include!(mozbuild::windows_rs_path!("src/lib.rs"))`
3598 # in the crate's lib.rs doesn't work because of
3599 # https://github.com/rust-lang/rust/issues/66920.
3601 # Previous versions of the windows crate had submodules declared
3602 # directly in lib.rs. Annotating each of them with
3603 # `#[path = concat!(mozbuild::windows_rs_path!("path/to/mod.rs"))]`
3604 # unfortunately also didn't work, because of
3605 # https://github.com/rust-lang/rust/issues/48250.
3607 # Thankfully, newer versions of the windows crate now only have an
3608 # `include!` at the end of lib.rs, so we can get away with simply
3609 # replacing it with an `include!` that uses `mozbuild::windows_rs_path!`.
3611 # We ensure that the in-tree contents match what we expect based on
3612 # the original crate.
3613 # The expectations are as such:
3614 # - Cargo.toml is identical to the original one with the addition of the
3615 #   following two lines at the end (after an empty line):
3616 #     [dependencies.mozbuild]
3617 #     version = "0.1"
3618 # - src/lib.rs is mostly identical to the original one, with two notable
3619 #   differences:
3620 #   - the addition of `#![allow(warnings)]` on the first line, because if
3621 #     the crate had been vendored normally, it would not be affected by
3622 #     `-D warnings`, and `#![allow(warnings)]` mimicks that.
3623 #   - the replacement of any
3624 #     `include!("path/file.rs")`
3625 #     with
3626 #     `include!(mozbuild::windows_rs_path!("src/path/file.rs"))`
3627 with only_when(target_is_windows & compile_environment):
3628     option(
3629         env="MOZ_WINDOWS_RS_DIR",
3630         nargs=1,
3631         help="Path to the source of the 'windows' Rust crate",
3632     )
3634     @depends(
3635         "MOZ_WINDOWS_RS_DIR",
3636         bootstrap_path(
3637             "windows-rs",
3638             when=depends("MOZ_WINDOWS_RS_DIR")(lambda x: not x),
3639         ),
3640         build_environment.topsrcdir,
3641     )
3642     @checking("for the windows rust crate source")
3643     @imports(_from="__builtin__", _import="open")
3644     @imports("re")
3645     @imports("toml")
3646     def windows_rs_dir(dir, bootstrapped, topsrcdir):
3647         if bootstrapped:
3648             dir = bootstrapped
3649         elif dir:
3650             dir = dir[0]
3652         raw_cargo_toml = open(
3653             os.path.join(topsrcdir, "build/rust/windows/Cargo.toml")
3654         ).read()
3655         cargo_toml = toml.loads(raw_cargo_toml)
3656         expected_version = cargo_toml["package"]["version"]
3658         if not dir:
3659             raise FatalCheckError(
3660                 "Cannot find the windows rust crate source.\n"
3661                 f"Try downloading it with `cargo download -x windows={expected_version}`\n"
3662                 "(you may need to `cargo install cargo-download` first)\n"
3663                 f"and set `MOZ_WINDOWS_RS_DIR` to location of the `windows-{expected_version}`"
3664                 " directory"
3665             )
3667         raw_cargo_toml_orig = open(os.path.join(dir, "Cargo.toml")).read()
3668         cargo_toml = toml.loads(raw_cargo_toml_orig)
3669         version = cargo_toml["package"]["version"]
3670         if version != expected_version:
3671             raise FatalCheckError(
3672                 f"The windows rust crate source in {dir} contains version "
3673                 f"{version}, but expected {expected_version}."
3674             )
3675         # Now that we've done the basic sanity check, let's go deeper.
3676         DEPENDENCIES = '\n[dependencies.mozbuild]\nversion = "0.1"\n'
3677         if not raw_cargo_toml.endswith(DEPENDENCIES):
3678             configure_error("In-tree windows crate is missing dependency on mozbuild")
3679         if raw_cargo_toml[: -len(DEPENDENCIES)] != raw_cargo_toml_orig:
3680             configure_error("In-tree windows crate Cargo.toml doesn't match original")
3682         lib_rs = open(os.path.join(topsrcdir, "build/rust/windows/src/lib.rs")).read()
3683         lib_rs_orig = open(os.path.join(dir, "src/lib.rs")).read()
3684         lib_rs_expected = "#![allow(warnings)]\n" + re.sub(
3685             r'include!\("([^"]*)"\)',
3686             r'include!(mozbuild::windows_rs_path!("src/\1"))',
3687             lib_rs_orig,
3688         )
3689         if lib_rs != lib_rs_expected:
3690             configure_error("In-tree windows crate lib.rs doesn't match original")
3692         return dir
3694     set_config("MOZ_WINDOWS_RS_DIR", windows_rs_dir)