Backed out changeset 7ac06c7aba78 (bug 1851717) for causing talos failures. a=backout
[gecko.git] / toolkit / moz.configure
blobc87034a19f785f9805ff61d1211086dd83b35ece
1 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
2 # vim: set filetype=python:
3 # This Source Code Form is subject to the terms of the Mozilla Public
4 # License, v. 2.0. If a copy of the MPL was not distributed with this
5 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 # Set the MOZ_CONFIGURE_OPTIONS variable with all the options that
9 # were passed somehow (environment, command line, mozconfig)
10 @dependable
11 @imports(_from="mozbuild.shellutil", _import="quote")
12 @imports(_from="mozbuild.util", _import="ensure_unicode")
13 @imports(_from="mozbuild.util", _import="system_encoding")
14 @imports("__sandbox__")
15 def all_configure_options():
16     result = []
17     previous = None
18     for option in __sandbox__._options.values():
19         # __sandbox__._options contains items for both option.name and
20         # option.env. But it's also an OrderedDict, meaning both are
21         # consecutive.
22         # Also ignore OLD_CONFIGURE and MOZCONFIG because they're not
23         # interesting.
24         if option == previous or option.env in ("OLD_CONFIGURE", "MOZCONFIG"):
25             continue
26         previous = option
27         value = __sandbox__._value_for(option)
28         # We only want options that were explicitly given on the command
29         # line, the environment, or mozconfig, and that differ from the
30         # defaults.
31         if (
32             value is not None
33             and value.origin not in ("default", "implied")
34             and value != option.default
35         ):
36             result.append(
37                 ensure_unicode(__sandbox__._raw_options[option], system_encoding)
38             )
39         # We however always include options that are sent to old configure
40         # because we don't know their actual defaults. (Keep the conditions
41         # separate for ease of understanding and ease of removal)
42         elif (
43             option.help == "Help missing for old configure options"
44             and option in __sandbox__._raw_options
45         ):
46             result.append(
47                 ensure_unicode(__sandbox__._raw_options[option], system_encoding)
48             )
50     # We shouldn't need this, but currently, quote will return a byte string
51     # if result is empty, and that's not wanted here.
52     if not result:
53         return ""
55     return quote(*result)
58 set_config("MOZ_CONFIGURE_OPTIONS", all_configure_options)
61 @depends(target)
62 def fold_libs(target):
63     return target.os in ("WINNT", "OSX", "Android")
66 set_config("MOZ_FOLD_LIBS", fold_libs)
68 # Profiling
69 # ==============================================================
70 # Some of the options here imply an option from js/moz.configure,
71 # so, need to be declared before the include.
73 option(
74     "--enable-jprof",
75     env="MOZ_JPROF",
76     help="Enable jprof profiling tool (needs mozilla/tools/jprof)",
80 @depends("--enable-jprof")
81 def jprof(value):
82     if value:
83         return True
86 set_config("MOZ_JPROF", jprof)
87 set_define("MOZ_JPROF", jprof)
88 imply_option("--enable-profiling", jprof)
91 @depends(target)
92 def gecko_profiler(target):
93     if target.os == "Android":
94         return target.cpu in ("aarch64", "arm", "x86", "x86_64")
95     elif target.kernel == "Linux":
96         return target.cpu in ("aarch64", "arm", "x86", "x86_64", "mips64")
97     elif target.kernel == "FreeBSD":
98         return target.cpu in ("aarch64", "x86_64")
99     return target.os in ("OSX", "WINNT")
102 @depends(gecko_profiler)
103 def gecko_profiler_define(value):
104     if value:
105         return True
108 set_config("MOZ_GECKO_PROFILER", gecko_profiler_define)
109 set_define("MOZ_GECKO_PROFILER", gecko_profiler_define)
112 # Whether code to parse ELF binaries should be compiled for the Gecko profiler
113 # (for symbol table dumping).
114 @depends(gecko_profiler, target)
115 def gecko_profiler_parse_elf(value, target):
116     # Currently we only want to build this code on Linux (including Android) and BSD.
117     # For Android, this is in order to dump symbols from Android system, where
118     # on other platforms there exist alternatives that don't require bloating
119     # up our binary size. For Linux more generally, we use this in profile
120     # pre-symbolication support, since MozDescribeCodeAddress doesn't do
121     # anything useful on that platform. (Ideally, we would update
122     # MozDescribeCodeAddress to call into some Rust crates that parse ELF and
123     # DWARF data, but build system issues currently prevent Rust from being
124     # used in mozglue.)
125     if value and (target.kernel == "Linux" or target.kernel == "FreeBSD"):
126         return True
129 set_config("MOZ_GECKO_PROFILER_PARSE_ELF", gecko_profiler_parse_elf)
130 set_define("MOZ_GECKO_PROFILER_PARSE_ELF", gecko_profiler_parse_elf)
132 # enable this by default if the profiler is enabled
133 # Note: also requires jemalloc
134 set_config("MOZ_PROFILER_MEMORY", gecko_profiler_define)
135 set_define("MOZ_PROFILER_MEMORY", gecko_profiler_define)
138 @depends(
139     "--enable-debug",
140     milestone,
141     build_project,
142     # Artifact builds are included because the downloaded artifacts can
143     # have DMD enabled.
144     when=artifact_builds | depends(when="--enable-replace-malloc")(lambda: True),
146 def dmd_default(debug, milestone, build_project):
147     return bool(build_project == "browser" and (debug or milestone.is_nightly))
150 option(
151     "--enable-dmd",
152     env="MOZ_DMD",
153     default=dmd_default,
154     help="{Enable|Disable} Dark Matter Detector (heap profiler). "
155     "Also enables jemalloc, replace-malloc and profiling",
159 @depends("--enable-dmd")
160 def dmd(value):
161     if value:
162         return True
165 set_config("MOZ_DMD", dmd)
166 set_define("MOZ_DMD", dmd)
167 imply_option("--enable-profiling", dmd)
168 imply_option("--enable-jemalloc", dmd, when=compile_environment)
169 imply_option("--enable-replace-malloc", dmd, when=compile_environment)
172 # midir-based Web MIDI support
173 # ==============================================================
174 @depends(target)
175 def midir_linux_support(target):
176     return (
177         target.kernel == "Linux" and target.os != "Android" and target.cpu != "riscv64"
178     )
181 @depends(target, midir_linux_support)
182 def midir_support(target, midir_linux_support):
183     if target.os in ("WINNT", "OSX") or midir_linux_support:
184         return True
187 set_config("MOZ_WEBMIDI_MIDIR_IMPL", midir_support)
190 # Enable various cubeb backends
191 # ==============================================================
192 @depends(target)
193 def audio_backends_default(target):
194     if target.os == "Android":
195         return (
196             "aaudio",
197             "opensl",
198         )
199     elif target.os in ("DragonFly", "FreeBSD", "SunOS"):
200         return ("oss",)
201     elif target.os == "OpenBSD":
202         return ("sndio",)
203     elif target.os == "OSX":
204         return ("audiounit",)
205     elif target.os == "NetBSD":
206         return ("sunaudio",)
207     elif target.os == "SunOS":
208         return ("sunaudio",)
209     elif target.os == "WINNT":
210         return ("wasapi",)
211     else:
212         return ("pulseaudio",)
215 option(
216     "--enable-audio-backends",
217     nargs="+",
218     choices=(
219         "aaudio",
220         "alsa",
221         "audiounit",
222         "jack",
223         "opensl",
224         "oss",
225         "pulseaudio",
226         "sndio",
227         "sunaudio",
228         "wasapi",
229     ),
230     default=audio_backends_default,
231     help="{Enable|Disable} various cubeb backends",
235 @depends("--enable-audio-backends", target)
236 def imply_aaudio(values, target):
237     if any("aaudio" in value for value in values) and target.os != "Android":
238         die("Cannot enable AAudio on %s", target.os)
239     return any("aaudio" in value for value in values) or None
242 @depends("--enable-audio-backends", target)
243 def imply_alsa(values, target):
244     if (
245         any("alsa" in value for value in values)
246         and target.kernel != "Linux"
247         and target.os != "FreeBSD"
248     ):
249         die("Cannot enable ALSA on %s", target.os)
250     return any("alsa" in value for value in values) or None
253 @depends("--enable-audio-backends", target)
254 def imply_audiounit(values, target):
255     if (
256         any("audiounit" in value for value in values)
257         and target.os != "OSX"
258         and target.kernel != "Darwin"
259     ):
260         die("Cannot enable AudioUnit on %s", target.os)
261     return any("audiounit" in value for value in values) or None
264 @depends("--enable-audio-backends")
265 def imply_jack(values):
266     return any("jack" in value for value in values) or None
269 @depends("--enable-audio-backends", target)
270 def imply_opensl(values, target):
271     if any("opensl" in value for value in values) and target.os != "Android":
272         die("Cannot enable OpenSL on %s", target.os)
273     return any("opensl" in value for value in values) or None
276 @depends("--enable-audio-backends", target)
277 def imply_oss(values, target):
278     if any("oss" in value for value in values) and (
279         target.os == "Android" or target.os == "OSX" or target.os == "WINNT"
280     ):
281         die("Cannot enable OSS on %s", target.os)
282     return any("oss" in value for value in values) or None
285 @depends("--enable-audio-backends", target)
286 def imply_pulseaudio(values, target):
287     if any("pulseaudio" in value for value in values) and (
288         target.os == "Android" or target.os == "OSX" or target.os == "WINNT"
289     ):
290         die("Cannot enable PulseAudio on %s", target.os)
291     return any("pulseaudio" in value for value in values) or None
294 @depends("--enable-audio-backends", target)
295 def imply_sndio(values, target):
296     if any("sndio" in value for value in values) and (
297         target.os == "Android" or target.os == "OSX" or target.os == "WINNT"
298     ):
299         die("Cannot enable sndio on %s", target.os)
300     return any("sndio" in value for value in values) or None
303 @depends("--enable-audio-backends", target)
304 def imply_sunaudio(values, target):
305     if any("sunaudio" in value for value in values) and (
306         target.os != "NetBSD" and target.os != "SunOS"
307     ):
308         die("Cannot enable sunaudio on %s", target.os)
309     return any("sunaudio" in value for value in values) or None
312 @depends("--enable-audio-backends", target)
313 def imply_wasapi(values, target):
314     if any("wasapi" in value for value in values) and target.os != "WINNT":
315         die("Cannot enable WASAPI on %s", target.os)
316     return any("wasapi" in value for value in values) or None
319 set_config("MOZ_AAUDIO", imply_aaudio, when="--enable-audio-backends")
321 imply_option("--enable-alsa", imply_alsa, reason="--enable-audio-backends")
323 set_config("MOZ_AUDIOUNIT_RUST", imply_audiounit, when="--enable-audio-backends")
325 imply_option("--enable-jack", imply_jack, reason="--enable-audio-backends")
327 set_config("MOZ_OPENSL", imply_opensl, when="--enable-audio-backends")
329 set_config("MOZ_OSS", imply_oss, when="--enable-audio-backends")
331 imply_option("--enable-pulseaudio", imply_pulseaudio, reason="--enable-audio-backends")
333 imply_option("--enable-sndio", imply_sndio, reason="--enable-audio-backends")
335 set_config("MOZ_SUNAUDIO", imply_sunaudio, when="--enable-audio-backends")
337 set_config("MOZ_WASAPI", imply_wasapi, when="--enable-audio-backends")
339 # ALSA cubeb backend
340 # ==============================================================
341 option("--enable-alsa", env="MOZ_ALSA", help="Enable ALSA audio backend.")
344 @depends("--enable-alsa", midir_linux_support)
345 def enable_alsa_or_midir_linux_support(alsa_enabled, midir_linux_support):
346     return alsa_enabled or midir_linux_support
349 pkg_check_modules("MOZ_ALSA", "alsa", when=enable_alsa_or_midir_linux_support)
351 set_config("MOZ_ALSA", True, when="--enable-alsa")
352 set_define("MOZ_ALSA", True, when="--enable-alsa")
354 # JACK cubeb backend
355 # ==============================================================
356 system_lib_option("--enable-jack", env="MOZ_JACK", help="Enable JACK audio backend.")
358 jack = pkg_check_modules("MOZ_JACK", "jack", when="--enable-jack")
360 set_config("MOZ_JACK", depends_if(jack)(lambda _: True))
362 # PulseAudio cubeb backend
363 # ==============================================================
364 option(
365     "--enable-pulseaudio",
366     env="MOZ_PULSEAUDIO",
367     help="{Enable|Disable} PulseAudio audio backend.",
370 pulseaudio = pkg_check_modules("MOZ_PULSEAUDIO", "libpulse", when="--enable-pulseaudio")
372 set_config("MOZ_PULSEAUDIO", depends_if(pulseaudio)(lambda _: True))
373 set_define("MOZ_PULSEAUDIO", depends_if(pulseaudio)(lambda _: True))
375 # sndio cubeb backend
376 # ==============================================================
377 system_lib_option("--enable-sndio", env="MOZ_SNDIO", help="Enable sndio audio backend.")
379 sndio = pkg_check_modules("MOZ_SNDIO", "sndio", when="--enable-sndio")
381 set_config("MOZ_SNDIO", depends_if(sndio)(lambda _: True))
383 # Javascript engine
384 # ==============================================================
385 include("../js/moz.configure")
388 # NodeJS
389 # ==============================================================
390 include("../build/moz.configure/node.configure")
392 # JsonCpp
393 # ==============================================================
394 set_define("JSON_USE_EXCEPTION", 0)
396 # L10N
397 # ==============================================================
398 option("--with-l10n-base", nargs=1, env="L10NBASEDIR", help="Path to l10n repositories")
401 @depends("--with-l10n-base", "MOZ_AUTOMATION", build_environment)
402 @imports(_from="os.path", _import="isdir")
403 @imports(_from="os.path", _import="expanduser")
404 @imports(_from="os", _import="environ")
405 def l10n_base(value, automation, build_env):
406     if value:
407         path = value[0]
408         if not isdir(path):
409             die("Invalid value --with-l10n-base, %s doesn't exist", path)
410     elif automation:
411         path = os.path.join(build_env.topsrcdir, "../l10n-central")
412     else:
413         path = os.path.join(
414             environ.get(
415                 "MOZBUILD_STATE_PATH", expanduser(os.path.join("~", ".mozbuild"))
416             ),
417             "l10n-central",
418         )
419     return os.path.realpath(os.path.abspath(path))
422 set_config("L10NBASEDIR", l10n_base)
425 # Default toolkit
426 # ==============================================================
427 @depends(target)
428 def toolkit_choices(target):
429     if target.os == "WINNT":
430         return ("cairo-windows",)
431     elif target.os == "OSX":
432         return ("cairo-cocoa",)
433     elif target.os == "Android":
434         return ("cairo-android",)
435     else:
436         # cairo-gtk3 - X11 backend with optional Wayland backend (auto detected)
437         # cairo-gtk3-wayland - Wayland backend with optional X11 backend (auto detected)
438         # cairo-gtk3-x11-wayland - builds explicitly with X11 & Wayland backends
439         return (
440             "cairo-gtk3",
441             "cairo-gtk3-wayland",
442             "cairo-gtk3-x11-wayland",
443             "cairo-gtk3-wayland-only",
444             "cairo-gtk3-x11-only",
445         )
448 @depends(toolkit_choices)
449 def toolkit_default(choices):
450     return choices[0]
453 option(
454     "--enable-default-toolkit",
455     nargs=1,
456     choices=toolkit_choices,
457     default=toolkit_default,
458     help="Select default toolkit",
462 @depends("--enable-default-toolkit")
463 def full_toolkit(value):
464     if value:
465         return value[0]
468 @depends(full_toolkit)
469 def toolkit(toolkit):
470     if toolkit.startswith("cairo-gtk3"):
471         widget_toolkit = "gtk"
472     else:
473         widget_toolkit = toolkit.replace("cairo-", "")
474     return widget_toolkit
477 set_config("MOZ_WIDGET_TOOLKIT", toolkit)
478 add_old_configure_assignment("MOZ_WIDGET_TOOLKIT", toolkit)
481 @depends(toolkit)
482 def toolkit_define(toolkit):
483     if toolkit != "windows":
484         return "MOZ_WIDGET_%s" % toolkit.upper()
487 set_define(toolkit_define, True)
490 @depends(toolkit)
491 def toolkit_gtk(toolkit):
492     return toolkit == "gtk"
495 @depends(toolkit_gtk, full_toolkit)
496 def toolkit_gtk_x11(toolkit_gtk, full_toolkit):
497     return toolkit_gtk and full_toolkit != "cairo-gtk3-wayland-only"
500 @depends(full_toolkit)
501 def toolkit_gtk_x11_optional(full_toolkit):
502     return full_toolkit == "cairo-gtk3-wayland"
505 @depends(toolkit_gtk, full_toolkit)
506 def toolkit_gtk_wayland(toolkit_gtk, full_toolkit):
507     return toolkit_gtk and full_toolkit != "cairo-gtk3-x11-only"
510 @depends(full_toolkit)
511 def toolkit_gtk_wayland_optional(full_toolkit):
512     return full_toolkit == "cairo-gtk3"
515 # Wayland support
516 # ==============================================================
517 wayland_headers = pkg_check_modules(
518     "MOZ_WAYLAND",
519     "gtk+-wayland-3.0 >= 3.14 xkbcommon >= 0.4.1",
520     allow_missing=toolkit_gtk_wayland_optional,
521     when=toolkit_gtk_wayland,
525 @depends(wayland_headers, toolkit_gtk, artifact_builds, toolkit_gtk_wayland)
526 def wayland_headers(wayland, toolkit_gtk, artifacts, toolkit_gtk_wayland):
527     if not toolkit_gtk_wayland:
528         return False
529     if toolkit_gtk and artifacts:
530         return True
531     return wayland
534 set_config("MOZ_WAYLAND", depends_if(wayland_headers)(lambda _: True))
535 set_define("MOZ_WAYLAND", depends_if(wayland_headers)(lambda _: True))
538 # Hardware-accelerated video decode with VAAPI and V4L2 on Linux
539 # ==============================================================
540 @depends(target, toolkit_gtk)
541 def vaapi(target, toolkit_gtk):
542     # VAAPI is mostly used on x86(-64) but is sometimes used on ARM/ARM64 SOCs.
543     if target.cpu in ("arm", "aarch64", "x86", "x86_64") and toolkit_gtk:
544         return True
547 @depends(target, toolkit_gtk)
548 def v4l2(target, toolkit_gtk):
549     # V4L2 decode is only used in GTK/Linux and generally only appears on
550     # embedded SOCs.
551     if target.cpu in ("arm", "aarch64", "riscv64") and toolkit_gtk:
552         return True
555 set_config("MOZ_ENABLE_VAAPI", True, when=vaapi)
556 set_config("MOZ_ENABLE_V4L2", True, when=v4l2)
557 set_define("MOZ_ENABLE_VAAPI", True, when=vaapi)
558 set_define("MOZ_ENABLE_V4L2", True, when=v4l2)
561 # GL Provider
562 # ==============================================================
563 option("--with-gl-provider", nargs=1, help="Set GL provider backend type")
566 @depends("--with-gl-provider")
567 def gl_provider(value):
568     if value:
569         return value[0]
572 @depends(gl_provider)
573 def gl_provider_define(provider):
574     if provider:
575         return "GLContextProvider%s" % provider
578 set_define("MOZ_GL_PROVIDER", gl_provider_define)
581 @depends(gl_provider, toolkit_gtk)
582 def gl_default_provider(value, toolkit_gtk):
583     if value:
584         return value
585     elif toolkit_gtk:
586         return "EGL"
589 set_config("MOZ_GL_PROVIDER", gl_provider)
590 set_config("MOZ_GL_DEFAULT_PROVIDER", gl_default_provider)
593 @depends(gl_default_provider)
594 def gl_provider_define(provider):
595     if provider:
596         return "GL_PROVIDER_%s" % provider
599 set_define(gl_provider_define, True)
602 # PDF printing
603 # ==============================================================
604 @depends(toolkit)
605 def pdf_printing(toolkit):
606     if toolkit in ("windows", "gtk", "android"):
607         return True
610 set_config("MOZ_PDF_PRINTING", pdf_printing)
611 set_define("MOZ_PDF_PRINTING", pdf_printing)
614 # Event loop instrumentation
615 # ==============================================================
616 option(env="MOZ_INSTRUMENT_EVENT_LOOP", help="Force-enable event loop instrumentation")
619 @depends("MOZ_INSTRUMENT_EVENT_LOOP", toolkit)
620 def instrument_event_loop(value, toolkit):
621     if value or (
622         toolkit in ("windows", "gtk", "cocoa", "android") and value.origin == "default"
623     ):
624         return True
627 set_config("MOZ_INSTRUMENT_EVENT_LOOP", instrument_event_loop)
628 set_define("MOZ_INSTRUMENT_EVENT_LOOP", instrument_event_loop)
631 # Fontconfig Freetype
632 # ==============================================================
633 option(env="USE_FC_FREETYPE", help="Force-enable the use of fontconfig freetype")
636 @depends("USE_FC_FREETYPE", toolkit)
637 def fc_freetype(value, toolkit):
638     if value or (toolkit == "gtk" and value.origin == "default"):
639         return True
642 set_define("USE_FC_FREETYPE", fc_freetype)
644 # Pango
645 # ==============================================================
646 pkg_check_modules("MOZ_PANGO", "pango >= 1.22.0", when=toolkit_gtk)
648 # Fontconfig
649 # ==============================================================
650 fontconfig_info = pkg_check_modules(
651     "_FONTCONFIG", "fontconfig >= 2.7.0", when=fc_freetype
655 @depends(fc_freetype)
656 def check_for_freetype2(fc_freetype):
657     if fc_freetype:
658         return True
661 # Check for freetype2. Flags are combined with fontconfig flags.
662 freetype2_info = pkg_check_modules(
663     "_FT2", "freetype2 >= 9.10.3", when=check_for_freetype2
667 @depends(fontconfig_info, freetype2_info)
668 def freetype2_combined_info(fontconfig_info, freetype2_info):
669     if not freetype2_info:
670         return
671     if not fontconfig_info:
672         return freetype2_info
673     return namespace(
674         cflags=freetype2_info.cflags + fontconfig_info.cflags,
675         libs=freetype2_info.libs + fontconfig_info.libs,
676     )
679 set_define("MOZ_HAVE_FREETYPE2", depends_if(freetype2_info)(lambda _: True))
682 # Apple platform decoder support
683 # ==============================================================
684 @depends(toolkit)
685 def applemedia(toolkit):
686     if toolkit in ("cocoa", "uikit"):
687         return True
690 set_config("MOZ_APPLEMEDIA", applemedia)
691 set_define("MOZ_APPLEMEDIA", applemedia)
693 # Windows Media Foundation support
694 # ==============================================================
695 option("--disable-wmf", help="Disable support for Windows Media Foundation")
698 @depends("--disable-wmf", target, "--help")
699 def wmf(value, target, _):
700     enabled = bool(value)
701     if value.origin == "default":
702         # Enable Windows Media Foundation support by default.
703         # Note our minimum SDK version is Windows 7 SDK, so we are (currently)
704         # guaranteed to have a recent-enough SDK to build WMF.
705         enabled = target.os == "WINNT"
706     if enabled and target.os != "WINNT":
707         die("Cannot enable Windows Media Foundation support on %s", target.os)
708     if enabled:
709         return True
712 @depends(c_compiler, when=wmf)
713 def wmfmediaengine(c_compiler):
714     return c_compiler and c_compiler.type == "clang-cl"
717 set_config("MOZ_WMF", wmf)
718 set_define("MOZ_WMF", wmf)
720 set_config("MOZ_WMF_MEDIA_ENGINE", True, when=wmfmediaengine)
721 set_define("MOZ_WMF_MEDIA_ENGINE", True, when=wmfmediaengine)
723 # FFmpeg H264/AAC Decoding Support
724 # ==============================================================
725 option("--disable-ffmpeg", help="Disable FFmpeg for fragmented H264/AAC decoding")
728 @depends("--disable-ffmpeg", target)
729 def ffmpeg(value, target):
730     enabled = bool(value)
731     if value.origin == "default":
732         enabled = target.os not in ("Android", "WINNT")
733     if enabled:
734         return True
737 set_config("MOZ_FFMPEG", ffmpeg)
738 set_define("MOZ_FFMPEG", ffmpeg)
740 # AV1 Video Codec Support
741 # ==============================================================
742 option("--disable-av1", help="Disable av1 video support")
745 @depends("--enable-av1")
746 def av1(value):
747     if value:
748         return True
751 @depends(target, when=av1 & compile_environment)
752 def dav1d_asm(target):
753     if target.cpu in ("aarch64", "x86", "x86_64"):
754         return True
757 @depends(target, when=av1 & compile_environment)
758 def dav1d_nasm(target):
759     if target.cpu in ("x86", "x86_64"):
760         return namespace(version="2.14", what="AV1")
763 set_config("MOZ_DAV1D_ASM", dav1d_asm)
764 set_define("MOZ_DAV1D_ASM", dav1d_asm)
765 set_config("MOZ_AV1", av1)
766 set_define("MOZ_AV1", av1)
768 # JXL Image Codec Support
769 # ==============================================================
770 option("--disable-jxl", help="Disable jxl image support")
773 @depends("--disable-jxl", milestone.is_nightly)
774 def jxl(value, is_nightly):
775     if is_nightly and value:
776         return True
779 set_config("MOZ_JXL", jxl)
780 set_define("MOZ_JXL", jxl)
782 set_config("MOZ_SAMPLE_TYPE_FLOAT32", True)
783 set_define("MOZ_SAMPLE_TYPE_FLOAT32", True)
785 set_define("MOZ_VORBIS", True)
786 set_config("MOZ_VORBIS", True)
788 option(
789     "--disable-real-time-tracing",
790     help="Disable tracing of real-time audio callbacks",
793 set_config("MOZ_REAL_TIME_TRACING", True, when="--enable-real-time-tracing")
794 set_define("MOZ_REAL_TIME_TRACING", True, when="--enable-real-time-tracing")
796 # OpenMAX IL Decoding Support
797 # ==============================================================
798 option("--enable-openmax", help="Enable OpenMAX IL for video/audio decoding")
801 @depends("--enable-openmax")
802 def openmax(value):
803     enabled = bool(value)
804     if enabled:
805         return True
808 set_config("MOZ_OMX", openmax)
809 set_define("MOZ_OMX", openmax)
812 # EME Support
813 # ==============================================================
814 @depends(target, wmf)
815 def eme_choices(target, wmf):
816     if (
817         target.kernel in ("WINNT", "Linux")
818         and target.os != "Android"
819         and target.cpu in ("x86", "x86_64")
820     ):
821         if wmf:
822             return ("widevine", "wmfcdm")
823         return ("widevine",)
824     if target.kernel == "WINNT" and target.cpu == "aarch64":
825         return ("widevine",)
826     if target.os in ("OSX"):
827         return ("widevine",)
830 # Widevine is enabled by default in desktop browser builds, except
831 # on aarch64 Windows.
832 @depends(build_project, eme_choices, target)
833 def eme_default(build_project, choices, target):
834     if build_project == "browser":
835         if target.kernel != "WINNT" or target.cpu != "aarch64":
836             return choices
839 option(
840     "--enable-eme",
841     nargs="+",
842     choices=eme_choices,
843     default=eme_default,
844     when=eme_choices,
845     help="{Enable|Disable} support for Encrypted Media Extensions",
849 @depends("--enable-eme", when=eme_choices)
850 def eme_modules(value):
851     return value
854 # Fallback to an empty list when eme_choices is empty, setting eme_modules to
855 # None.
856 set_config("MOZ_EME_MODULES", eme_modules | dependable([]))
859 @depends(eme_modules, target, when=eme_modules)
860 def eme_win32_artifact(modules, target):
861     if "widevine" in modules and target.kernel == "WINNT" and target.cpu == "aarch64":
862         return True
865 set_config("MOZ_EME_WIN32_ARTIFACT", eme_win32_artifact)
868 # Media Foundation CDM support
869 # ==============================================================
870 @depends(eme_modules, when=wmfmediaengine)
871 def wmfcdm(modules):
872     if "wmfcdm" in modules:
873         return True
876 set_config("MOZ_WMF_CDM", True, when=wmfcdm)
877 set_define("MOZ_WMF_CDM", True, when=wmfcdm)
880 option(
881     name="--enable-chrome-format",
882     help="Select FORMAT of chrome files during packaging.",
883     nargs=1,
884     choices=("omni", "jar", "flat"),
885     default="omni",
889 @depends("--enable-chrome-format")
890 def packager_format(value):
891     return value[0]
894 set_config("MOZ_PACKAGER_FORMAT", packager_format)
896 # The packager minifies two different types of files: non-JS (mostly property
897 # files for l10n), and JS.  Setting MOZ_PACKAGER_MINIFY only minifies the
898 # former.  Firefox doesn't yet minify JS, due to concerns about debuggability.
900 # Also, the JS minification setup really only works correctly on Android:
901 # we need extra setup to use the newly-built shell for Linux and Windows,
902 # and cross-compilation for macOS requires some extra care.
905 @depends(target_is_android, "--enable-debug", milestone.is_nightly)
906 def enable_minify_default(is_android, debug, is_nightly):
907     if is_android and not debug and not is_nightly:
908         return ("properties", "js")
909     return ("properties",)
912 option(
913     name="--enable-minify",
914     help="Select types of files to minify during packaging.",
915     nargs="*",
916     choices=("properties", "js"),
917     default=enable_minify_default,
921 @depends("--enable-minify")
922 def enable_minify(value):
923     if "js" in value and "properties" not in value:
924         die("--enable-minify=js requires --enable-minify=properties.")
925     return namespace(
926         properties="properties" in value,
927         js="js" in value,
928     )
931 set_config("MOZ_PACKAGER_MINIFY", True, when=enable_minify.properties)
932 set_config("MOZ_PACKAGER_MINIFY_JS", True, when=enable_minify.js)
935 @depends(host, build_project)
936 def jar_maker_format(host, build_project):
937     # Multilocales for mobile/android use the same mergedirs for all locales,
938     # so we can't use symlinks for those builds.
939     if host.os == "WINNT" or build_project == "mobile/android":
940         return "flat"
941     return "symlink"
944 set_config("MOZ_JAR_MAKER_FILE_FORMAT", jar_maker_format)
947 @depends(toolkit)
948 def omnijar_name(toolkit):
949     # Fennec's static resources live in the assets/ folder of the
950     # APK.  Adding a path to the name here works because we only
951     # have one omnijar file in the final package (which is not the
952     # case on desktop).
953     return "assets/omni.ja" if toolkit == "android" else "omni.ja"
956 set_config("OMNIJAR_NAME", omnijar_name)
958 project_flag("MOZ_PLACES", help="Build Places if required", set_as_define=True)
960 project_flag(
961     "MOZ_SERVICES_HEALTHREPORT",
962     help="Build Firefox Health Reporter Service",
963     set_as_define=True,
966 project_flag(
967     "MOZ_NORMANDY",
968     help="Enable Normandy recipe runner",
969     set_as_define=True,
972 project_flag("MOZ_SERVICES_SYNC", help="Build Sync Services if required")
974 project_flag(
975     "MOZ_ANDROID_HISTORY",
976     help="Enable Android History instead of Places",
977     set_as_define=True,
980 project_flag(
981     "MOZ_DEDICATED_PROFILES",
982     help="Enable dedicated profiles per install",
983     set_as_define=True,
986 project_flag(
987     "MOZ_BLOCK_PROFILE_DOWNGRADE",
988     help="Block users from starting profiles last used by a newer build",
989     set_as_define=True,
993 @depends("MOZ_PLACES", "MOZ_ANDROID_HISTORY")
994 def check_places_and_android_history(places, android_history):
995     if places and android_history:
996         die("Cannot use MOZ_ANDROID_HISTORY alongside MOZ_PLACES.")
999 option(
1000     env="MOZ_TELEMETRY_REPORTING",
1001     default=mozilla_official,
1002     help="Enable telemetry reporting",
1005 set_define("MOZ_TELEMETRY_REPORTING", True, when="MOZ_TELEMETRY_REPORTING")
1008 @depends("MOZ_TELEMETRY_REPORTING", milestone.is_nightly)
1009 def telemetry_on_by_default(reporting, is_nightly):
1010     return reporting and is_nightly
1013 set_define("MOZ_TELEMETRY_ON_BY_DEFAULT", True, when=telemetry_on_by_default)
1016 # gpsd support
1017 # ==============================================================
1018 system_lib_option("--enable-gpsd", env="MOZ_GPSD", help="Enable gpsd support")
1021 @depends("--enable-gpsd")
1022 def gpsd(value):
1023     return bool(value)
1026 system_gpsd = pkg_check_modules("MOZ_GPSD", "libgps >= 3.11", when=gpsd)
1028 set_config("MOZ_GPSD", depends_if(system_gpsd)(lambda _: True))
1030 # Miscellaneous programs
1031 # ==============================================================
1033 check_prog("TAR", ("gnutar", "gtar", "tar"))
1034 check_prog("UNZIP", ("unzip",))
1036 # Key files
1037 # ==============================================================
1038 include("../build/moz.configure/keyfiles.configure")
1040 simple_keyfile("Mozilla API")
1042 simple_keyfile("Google Location Service API")
1044 simple_keyfile("Google Safebrowsing API")
1046 id_and_secret_keyfile("Bing API")
1048 simple_keyfile("Adjust SDK")
1050 id_and_secret_keyfile("Leanplum SDK")
1052 simple_keyfile("Pocket API")
1055 # WebRender Debugger integration
1056 # ==============================================================
1058 option(
1059     "--enable-webrender-debugger", help="Build the websocket debug server in WebRender"
1062 set_config(
1063     "MOZ_WEBRENDER_DEBUGGER", depends_if("--enable-webrender-debugger")(lambda _: True)
1066 # Additional system headers defined at the application level
1067 # ==============================================================
1069 option(
1070     "--enable-app-system-headers",
1071     env="MOZ_APP_SYSTEM_HEADERS",
1072     help="Use additional system headers defined in $MOZ_BUILD_APP/app-system-headers.mozbuild",
1076 @depends("--enable-app-system-headers")
1077 def app_system_headers(value):
1078     if value:
1079         return True
1082 set_config("MOZ_APP_SYSTEM_HEADERS", app_system_headers)
1083 set_define("MOZ_APP_SYSTEM_HEADERS", app_system_headers)
1085 # Printing
1086 # ==============================================================
1087 option("--disable-printing", help="Disable printing support")
1090 @depends("--disable-printing")
1091 def printing(value):
1092     if value:
1093         return True
1096 set_config("NS_PRINTING", printing)
1097 set_define("NS_PRINTING", printing)
1098 set_define("NS_PRINT_PREVIEW", printing)
1101 # Speech-dispatcher support
1102 # ==============================================================
1103 @depends(toolkit)
1104 def no_speechd_on_non_gtk(toolkit):
1105     if toolkit != "gtk":
1106         return False
1109 imply_option(
1110     "--enable-synth-speechd", no_speechd_on_non_gtk, reason="--enable-default-toolkit"
1113 option("--disable-synth-speechd", help="Disable speech-dispatcher support")
1115 set_config("MOZ_SYNTH_SPEECHD", depends_if("--disable-synth-speechd")(lambda _: True))
1117 # Speech API
1118 # ==============================================================
1119 option("--disable-webspeech", help="Disable support for HTML Speech API")
1122 @depends("--disable-webspeech")
1123 def webspeech(value):
1124     if value:
1125         return True
1128 set_config("MOZ_WEBSPEECH", webspeech)
1129 set_define("MOZ_WEBSPEECH", webspeech)
1131 # Speech API test backend
1132 # ==============================================================
1133 option(
1134     "--enable-webspeechtestbackend",
1135     default=webspeech,
1136     help="{Enable|Disable} support for HTML Speech API Test Backend",
1140 @depends_if("--enable-webspeechtestbackend")
1141 def webspeech_test_backend(value):
1142     return True
1145 set_config("MOZ_WEBSPEECH_TEST_BACKEND", webspeech_test_backend)
1146 set_define("MOZ_WEBSPEECH_TEST_BACKEND", webspeech_test_backend)
1149 # Graphics
1150 # ==============================================================
1151 @depends(target, milestone)
1152 def skia_pdf_default(target, milestone):
1153     return milestone.is_nightly and target.os != "WINNT"
1156 option("--enable-skia-pdf", default=skia_pdf_default, help="{Enable|Disable} Skia PDF")
1158 set_config("MOZ_ENABLE_SKIA_PDF", True, when="--enable-skia-pdf")
1159 set_define("MOZ_ENABLE_SKIA_PDF", True, when="--enable-skia-pdf")
1161 set_config(
1162     "SKIA_INCLUDES",
1163     [
1164         "/gfx/skia",
1165         "/gfx/skia/skia",
1166     ],
1169 system_lib_option(
1170     "--with-system-webp", help="Use system libwebp (located with pkgconfig)"
1173 system_webp = pkg_check_modules(
1174     "MOZ_WEBP", "libwebp >= 1.0.2 libwebpdemux >= 1.0.2", when="--with-system-webp"
1177 set_config("MOZ_SYSTEM_WEBP", depends(when=system_webp)(lambda: True))
1180 # Build Freetype in the tree
1181 # ==============================================================
1182 @depends(target, "--enable-skia-pdf")
1183 def tree_freetype(target, skia_pdf):
1184     if target.os == "Android" or (skia_pdf and target.os == "WINNT"):
1185         return True
1188 set_define("MOZ_TREE_FREETYPE", tree_freetype)
1189 set_config("MOZ_TREE_FREETYPE", tree_freetype)
1191 set_define("HAVE_FT_BITMAP_SIZE_Y_PPEM", tree_freetype)
1192 set_define("HAVE_FT_GLYPHSLOT_EMBOLDEN", tree_freetype)
1193 set_define("HAVE_FT_LOAD_SFNT_TABLE", tree_freetype)
1196 @depends(freetype2_combined_info, tree_freetype, build_environment)
1197 def ft2_info(freetype2_combined_info, tree_freetype, build_env):
1198     if tree_freetype:
1199         return namespace(
1200             cflags=("-I%s/modules/freetype2/include" % build_env.topsrcdir,), libs=()
1201         )
1202     if freetype2_combined_info:
1203         return freetype2_combined_info
1206 set_config("FT2_LIBS", ft2_info.libs)
1209 @depends(target, tree_freetype, freetype2_info)
1210 def enable_cairo_ft(target, tree_freetype, freetype2_info):
1211     # Avoid defining MOZ_ENABLE_CAIRO_FT on Windows platforms because
1212     # "cairo-ft-font.c" includes <dlfcn.h>, which only exists on posix platforms
1213     return freetype2_info or (tree_freetype and target.os != "WINNT")
1216 set_config("MOZ_ENABLE_CAIRO_FT", True, when=enable_cairo_ft)
1217 set_config("CAIRO_FT_CFLAGS", ft2_info.cflags, when=enable_cairo_ft)
1220 # WebDriver (HTTP / BiDi)
1221 # ==============================================================
1223 # WebDriver is a remote control interface that enables introspection and
1224 # control of user agents. It provides a platform- and language-neutral wire
1225 # protocol as a way for out-of-process programs to remotely instruct the
1226 # behavior of web browsers.
1228 # The Gecko implementation is backed by Marionette and Remote Agent.
1229 # Both protocols are not really toolkit features, as much as Gecko engine
1230 # features. But they are enabled based on the toolkit, so here it lives.
1232 # Marionette remote protocol
1233 # -----------------------------------------------------------
1235 # Marionette is the Gecko remote protocol used for various remote control,
1236 # automation, and testing purposes throughout Gecko-based applications like
1237 # Firefox, Thunderbird, and any mobile browser built upon GeckoView.
1239 # It also backs ../testing/geckodriver, which is Mozilla's WebDriver
1240 # implementation.
1242 # The source of Marionette lives in ../remote/marionette.
1244 # For more information, see:
1245 # https://firefox-source-docs.mozilla.org/testing/marionette/index.html
1247 # Remote Agent (WebDriver BiDi / partial CDP)
1248 # -----------------------------------------------------------
1250 # The primary purpose is the implementation of the WebDriver BiDi specification.
1251 # But it also complements the existing Firefox Developer Tools Remote Debugging
1252 # Protocol (RDP) by implementing a subset of the Chrome DevTools Protocol (CDP).
1254 # The source of Remote Agent lives in ../remote.
1256 # For more information, see:
1257 # https://firefox-source-docs.mozilla.org/remote/index.html
1260 option(
1261     "--disable-webdriver",
1262     help="Disable support for WebDriver remote protocols",
1266 @depends("--disable-webdriver")
1267 def webdriver(enabled):
1268     if enabled:
1269         return True
1272 set_config("ENABLE_WEBDRIVER", webdriver)
1273 set_define("ENABLE_WEBDRIVER", webdriver)
1276 # geckodriver WebDriver implementation
1277 # ==============================================================
1279 # Turn off geckodriver for build configs we don't handle yet,
1280 # but allow --enable-geckodriver to override when compile environment is available.
1281 # --disable-tests implies disabling geckodriver.
1282 # Disable building in CI
1285 @depends(
1286     "--enable-tests", target, cross_compiling, hazard_analysis, asan, "MOZ_AUTOMATION"
1288 def geckodriver_default(enable_tests, target, cross_compile, hazard, asan, automation):
1289     if not enable_tests:
1290         return False
1291     if hazard or target.os == "Android" or (asan and cross_compile):
1292         return False
1293     if automation:
1294         return False
1295     return True
1298 option(
1299     "--enable-geckodriver",
1300     default=geckodriver_default,
1301     when="--enable-compile-environment",
1302     help="{Build|Do not build} geckodriver",
1306 @depends("--enable-geckodriver", when="--enable-compile-environment")
1307 def geckodriver(enabled):
1308     if enabled:
1309         return True
1312 set_config("MOZ_GECKODRIVER", geckodriver)
1315 # WebRTC
1316 # ========================================================
1317 @depends(target)
1318 def webrtc_default(target):
1319     # Turn off webrtc for OS's we don't handle yet, but allow
1320     # --enable-webrtc to override.
1321     os_match = target.kernel in (
1322         "Linux",
1323         "WINNT",
1324         "DragonFly",
1325         "FreeBSD",
1326         "kFreeBSD",
1327         "NetBSD",
1328         "OpenBSD",
1329     )
1331     if not os_match:
1332         os_match = target.os in ("OSX",)
1334     cpu_match = target.cpu in (
1335         "x86_64",
1336         "arm",
1337         "aarch64",
1338         "x86",
1339         "ia64",
1340         "mips32",
1341         "mips64",
1342         "ppc",
1343         "ppc64",
1344         "riscv64",
1345     )
1347     return os_match and cpu_match and target.endianness == "little"
1350 option(
1351     "--disable-webrtc",
1352     default=webrtc_default,
1353     help="{Enable|Disable} support for WebRTC",
1357 @depends("--disable-webrtc")
1358 def webrtc(enabled):
1359     if enabled:
1360         return True
1363 set_config("MOZ_WEBRTC", webrtc)
1364 set_define("MOZ_WEBRTC", webrtc)
1365 set_config("MOZ_SCTP", webrtc)
1366 set_define("MOZ_SCTP", webrtc)
1367 set_config("MOZ_SRTP", webrtc)
1368 set_define("MOZ_SRTP", webrtc)
1369 set_config("MOZ_WEBRTC_SIGNALING", webrtc)
1370 set_define("MOZ_WEBRTC_SIGNALING", webrtc)
1371 set_config("MOZ_PEERCONNECTION", webrtc)
1372 set_define("MOZ_PEERCONNECTION", webrtc)
1373 # MOZ_WEBRTC_ASSERT_ALWAYS turns on a number of safety asserts in
1374 # opt/production builds (via MOZ_CRASH())
1375 set_config("MOZ_WEBRTC_ASSERT_ALWAYS", webrtc)
1376 set_define("MOZ_WEBRTC_ASSERT_ALWAYS", webrtc)
1378 # RAW media
1379 # ==============================================================
1382 @depends(target, webrtc)
1383 def raw_media_default(target, webrtc):
1384     if target.os == "Android":
1385         return True
1386     if webrtc:
1387         return True
1390 option(
1391     "--enable-raw",
1392     default=raw_media_default,
1393     help="{Enable|Disable} support for RAW media",
1396 set_config("MOZ_RAW", depends_if("--enable-raw")(lambda _: True))
1397 set_define("MOZ_RAW", depends_if("--enable-raw")(lambda _: True))
1400 # X11
1401 # ==============================================================
1402 @depends(webrtc, when=toolkit_gtk)
1403 def x11_libs(webrtc):
1404     libs = [
1405         "x11",
1406         "xcb",
1407         "xcb-shm",
1408         "x11-xcb",
1409         "xext",
1410         "xrandr >= 1.4.0",
1411     ]
1412     if webrtc:
1413         # third_party/libwebrtc/webrtc/webrtc_gn/moz.build adds those
1414         # manually, ensure they're available.
1415         libs += [
1416             "xcomposite",
1417             "xcursor",
1418             "xdamage",
1419             "xfixes",
1420             "xi",
1421             "xtst",
1422         ]
1423     return libs
1426 x11_headers = pkg_check_modules(
1427     "MOZ_X11",
1428     x11_libs,
1429     allow_missing=toolkit_gtk_x11_optional,
1430     when=toolkit_gtk_x11,
1434 set_config("MOZ_X11", True, when=x11_headers)
1435 set_define("MOZ_X11", True, when=x11_headers)
1437 pkg_check_modules(
1438     "MOZ_X11_SM",
1439     ["ice", "sm"],
1440     cflags_only=True,
1441     allow_missing=toolkit_gtk_x11_optional,
1442     when=toolkit_gtk_x11,
1446 # ASan Reporter Addon
1447 # ==============================================================
1448 option(
1449     "--enable-address-sanitizer-reporter",
1450     help="Enable Address Sanitizer Reporter Extension",
1454 @depends("--enable-address-sanitizer-reporter")
1455 def enable_asan_reporter(value):
1456     if value:
1457         return True
1460 set_config("MOZ_ASAN_REPORTER", enable_asan_reporter)
1461 set_define("MOZ_ASAN_REPORTER", enable_asan_reporter)
1463 # Checks for library functions
1464 # ==============================================================
1465 with only_when(compile_environment & depends(target.os)(lambda os: os != "WINNT")):
1466     set_define("HAVE_STAT64", check_symbol("stat64"))
1467     set_define("HAVE_LSTAT64", check_symbol("lstat64"))
1468     set_define("HAVE_TRUNCATE64", check_symbol("truncate64"))
1469     set_define("HAVE_STATVFS64", check_symbol("statvfs64"))
1470     set_define("HAVE_STATVFS", check_symbol("statvfs"))
1471     set_define("HAVE_STATFS64", check_symbol("statfs64"))
1472     set_define("HAVE_STATFS", check_symbol("statfs"))
1473     set_define("HAVE_LUTIMES", check_symbol("lutimes"))
1474     set_define("HAVE_POSIX_FADVISE", check_symbol("posix_fadvise"))
1475     set_define("HAVE_POSIX_FALLOCATE", check_symbol("posix_fallocate"))
1476     set_define("HAVE_EVENTFD", check_symbol("eventfd"))
1478     have_arc4random = check_symbol("arc4random")
1479     set_define("HAVE_ARC4RANDOM", have_arc4random)
1480     set_define("HAVE_ARC4RANDOM_BUF", check_symbol("arc4random_buf"))
1481     set_define("HAVE_MALLINFO", check_symbol("mallinfo"))
1483 # Checks for headers
1484 # ==============================================================
1485 with only_when(compile_environment & depends(target.os)(lambda os: os != "WINNT")):
1486     set_define("HAVE_SYSIOCCOM_H", check_header("sys/ioccom.h"))
1488 # Elfhack
1489 # ==============================================================
1490 with only_when("--enable-compile-environment"):
1492     @depends(host, target)
1493     def has_elfhack(host, target):
1494         return (
1495             target.kernel == "Linux"
1496             and host.kernel == "Linux"
1497             and target.cpu in ("arm", "aarch64", "x86", "x86_64")
1498         )
1500     @depends("--enable-release", enable_linker)
1501     def default_elfhack(release, linker):
1502         # Disable elfhack when explicitly building with --enable-linker=lld
1503         if linker and linker.origin != "default" and linker[0] in ("lld", "mold"):
1504             return False
1505         return bool(release)
1507     option(
1508         "--disable-elf-hack",
1509         default=default_elfhack,
1510         help="{Enable|Disable} elf hacks",
1511         when=has_elfhack,
1512     )
1514     @depends(
1515         have_arc4random,
1516         android_version,
1517         depends("--enable-elf-hack", when=has_elfhack)(lambda x: x),
1518         when=target_has_linux_kernel,
1519     )
1520     def may_use_pack_relative_relocs(have_arc4random, android_version, elfhack):
1521         # Packed relative relocations are only supported on Android since
1522         # version 11 (API 30), and in glibc since version 2.36.
1523         # glibc 2.36 also added the arc4random function, which is our proxy
1524         # to detect this (or newer) version being used.
1525         # When targetting those newer versions, we allow ourselves to use
1526         # packed relative relocations rather than elfhack. We still prefer
1527         # elfhack when explicitly enabled.
1528         if elfhack and elfhack.origin != "default":
1529             return False
1530         if android_version:
1531             return android_version >= 30
1532         return have_arc4random
1534     @depends(
1535         c_compiler,
1536         extra_toolchain_flags,
1537         linker_ldflags,
1538         readelf,
1539         when=may_use_pack_relative_relocs,
1540     )
1541     @checking("for -z pack-relative-relocs option to ld", bool)
1542     @imports(_from="__builtin__", _import="FileNotFoundError")
1543     @imports("os")
1544     @imports(_from="tempfile", _import="mkstemp")
1545     @imports("textwrap")
1546     def pack_relative_relocs(
1547         c_compiler,
1548         extra_toolchain_flags,
1549         linker_ldflags,
1550         readelf,
1551     ):
1552         try:
1553             fd, path = mkstemp(prefix="conftest.")
1554             os.close(fd)
1556             pack_rel_relocs = ["-Wl,-z,pack-relative-relocs"]
1557             if (
1558                 try_invoke_compiler(
1559                     # No configure_cache because it would not create the
1560                     # expected output file.
1561                     None,
1562                     [c_compiler.compiler] + c_compiler.flags,
1563                     c_compiler.language,
1564                     # The resulting binary is expected to have relative
1565                     # relocations, the `ptr` variable attempts to ensure
1566                     # there is at least one. This requires the executable
1567                     # being built as position independent.
1568                     "int main() { return 0; }\nint (*ptr)() = main;",
1569                     pack_rel_relocs
1570                     + ["-pie", "-o", path]
1571                     + (extra_toolchain_flags or [])
1572                     + linker_ldflags,
1573                     wrapper=c_compiler.wrapper,
1574                     onerror=lambda: None,
1575                 )
1576                 is not None
1577             ):
1578                 # BFD ld ignores options it doesn't understand. So check
1579                 # that we did get packed relative relocations (DT_RELR).
1580                 env = os.environ.copy()
1581                 env["LANG"] = "C"
1582                 dyn = check_cmd_output(readelf, "-d", path, env=env).splitlines()
1583                 tags = [
1584                     int(l.split()[0], 16) for l in dyn if l.strip().startswith("0x")
1585                 ]
1586                 # Older versions of readelf don't know about DT_RELR but will
1587                 # still display the tag number.
1588                 if 0x23 in tags:
1589                     needed = [l for l in dyn if l.split()[1:2] == ["(NEEDED)"]]
1590                     is_glibc = any(l.endswith("[libc.so.6]") for l in needed)
1591                     # The mold linker doesn't add a GLIBC_ABI_DT_RELR version
1592                     # dependency, which ld.so doesn't like.
1593                     # https://github.com/rui314/mold/issues/653#issuecomment-1670274638
1594                     if is_glibc:
1595                         versions = check_cmd_output(readelf, "-V", path, env=env)
1596                         if "GLIBC_ABI_DT_RELR" in versions.split():
1597                             return pack_rel_relocs
1598                     else:
1599                         return pack_rel_relocs
1600         finally:
1601             try:
1602                 os.remove(path)
1603             except FileNotFoundError:
1604                 pass
1606     add_old_configure_assignment("PACK_REL_RELOC_FLAGS", pack_relative_relocs)
1608     @depends(
1609         select_linker,
1610         pack_relative_relocs,
1611         "--enable-elf-hack",
1612         when=has_elfhack,
1613     )
1614     def use_elf_hack(linker, pack_relative_relocs, elfhack):
1615         if elfhack:
1616             # If elfhack was not manually enabled and packed relative relocations
1617             # can be used, then don't enable elfhack even if it would normally have.
1618             if elfhack.origin == "default" and pack_relative_relocs:
1619                 return
1620             if linker and linker.KIND == "lld":
1621                 die(
1622                     "Cannot enable elfhack with lld."
1623                     " Use --enable-linker=bfd, --enable-linker=gold, or --disable-elf-hack"
1624                 )
1625             return True
1627     set_config("USE_ELF_HACK", use_elf_hack)
1630 @depends(build_environment)
1631 def idl_roots(build_env):
1632     return namespace(
1633         ipdl_root=os.path.join(build_env.topobjdir, "ipc", "ipdl"),
1634         webidl_root=os.path.join(build_env.topobjdir, "dom", "bindings"),
1635         xpcom_root=os.path.join(build_env.topobjdir, "xpcom", "components"),
1636     )
1639 set_config("WEBIDL_ROOT", idl_roots.webidl_root)
1640 set_config("IPDL_ROOT", idl_roots.ipdl_root)
1641 set_config("XPCOM_ROOT", idl_roots.xpcom_root)
1643 # Proxy bypass protection
1644 # ==============================================================
1646 option(
1647     "--enable-proxy-bypass-protection",
1648     help="Prevent suspected or confirmed proxy bypasses",
1652 @depends_if("--enable-proxy-bypass-protection")
1653 def proxy_bypass_protection(_):
1654     return True
1657 set_config("MOZ_PROXY_BYPASS_PROTECTION", proxy_bypass_protection)
1658 set_define("MOZ_PROXY_BYPASS_PROTECTION", proxy_bypass_protection)
1660 # Proxy direct failover
1661 # ==============================================================
1663 option(
1664     "--disable-proxy-direct-failover",
1665     help="Disable direct failover for system requests",
1669 @depends_if("--disable-proxy-direct-failover")
1670 def proxy_direct_failover(value):
1671     if value:
1672         return True
1675 set_config("MOZ_PROXY_DIRECT_FAILOVER", proxy_direct_failover)
1676 set_define("MOZ_PROXY_DIRECT_FAILOVER", proxy_direct_failover)
1678 # MIDL
1679 # ==============================================================
1682 @depends(c_compiler, toolchain_prefix)
1683 def midl_names(c_compiler, toolchain_prefix):
1684     if c_compiler and c_compiler.type in ["gcc", "clang"]:
1685         # mingw
1686         widl = ("widl",)
1687         if toolchain_prefix:
1688             prefixed = tuple("%s%s" % (p, "widl") for p in toolchain_prefix)
1689             widl = prefixed + widl
1690         return widl
1692     return ("midl.exe",)
1695 @depends(target, "--enable-compile-environment")
1696 def check_for_midl(target, compile_environment):
1697     if target.os != "WINNT":
1698         return
1700     if compile_environment:
1701         return True
1704 midl = check_prog(
1705     "MIDL",
1706     midl_names,
1707     when=check_for_midl,
1708     allow_missing=True,
1709     paths=sdk_bin_path,
1710     # MIDL being used from a python wrapper script, we can live with it
1711     # having spaces.
1712     allow_spaces=True,
1715 option(env="MIDL_FLAGS", nargs=1, help="Extra flags to pass to MIDL")
1718 @depends(
1719     "MIDL_FLAGS",
1720     target,
1721     midl,
1722     when=depends(midl, target)(lambda m, t: m and t.kernel == "WINNT"),
1724 def midl_flags(flags, target, midl):
1725     if flags:
1726         flags = flags[0].split()
1727     else:
1728         flags = []
1730     if not midl.endswith("widl"):
1731         env = {
1732             "x86": "win32",
1733             "x86_64": "x64",
1734             "aarch64": "arm64",
1735         }[target.cpu]
1736         return flags + ["-nologo", "-no_cpp", "-env", env]
1738     # widl
1739     return (
1740         flags
1741         + {
1742             "x86": ["--win32", "-m32"],
1743             "x86_64": ["--win64", "-m64"],
1744         }[target.cpu]
1745     )
1748 set_config("MIDL_FLAGS", midl_flags)
1750 # Accessibility
1751 # ==============================================================
1753 option("--disable-accessibility", help="Disable accessibility support")
1756 @depends("--enable-accessibility", check_for_midl, midl, c_compiler)
1757 def accessibility(value, check_for_midl, midl, c_compiler):
1758     enabled = bool(value)
1760     if not enabled:
1761         return
1763     if check_for_midl and not midl:
1764         if c_compiler and c_compiler.type in ("gcc", "clang"):
1765             die(
1766                 "You have accessibility enabled, but widl could not be found. "
1767                 "Add --disable-accessibility to your mozconfig or install widl. "
1768                 "See https://developer.mozilla.org/en-US/docs/Cross_Compile_Mozilla_for_Mingw32 for details."
1769             )
1770         else:
1771             die(
1772                 "MIDL could not be found. "
1773                 "Building accessibility without MIDL is not supported."
1774             )
1776     return enabled
1779 set_config("ACCESSIBILITY", accessibility)
1780 set_define("ACCESSIBILITY", accessibility)
1783 @depends(moz_debug, developer_options)
1784 def a11y_log(debug, developer_options):
1785     return debug or developer_options
1788 set_config("A11Y_LOG", True, when=a11y_log)
1789 set_define("A11Y_LOG", True, when=a11y_log)
1792 # Addon signing
1793 # ==============================================================
1794 @depends(milestone)
1795 def require_signing(milestone):
1796     return milestone.is_release_or_beta and not milestone.is_esr
1799 option(
1800     env="MOZ_REQUIRE_SIGNING",
1801     default=require_signing,
1802     help="Enforce that add-ons are signed by the trusted root",
1805 set_config("MOZ_REQUIRE_SIGNING", True, when="MOZ_REQUIRE_SIGNING")
1806 set_define("MOZ_REQUIRE_SIGNING", True, when="MOZ_REQUIRE_SIGNING")
1808 option(
1809     "--with-unsigned-addon-scopes",
1810     nargs="+",
1811     choices=("app", "system"),
1812     help="Addon scopes where signature is not required",
1816 @depends("--with-unsigned-addon-scopes")
1817 def unsigned_addon_scopes(scopes):
1818     return namespace(
1819         app="app" in scopes or None,
1820         system="system" in scopes or None,
1821     )
1824 set_config("MOZ_UNSIGNED_APP_SCOPE", unsigned_addon_scopes.app)
1825 set_config("MOZ_UNSIGNED_SYSTEM_SCOPE", unsigned_addon_scopes.system)
1828 # Addon sideloading
1829 # ==============================================================
1830 option(
1831     "--allow-addon-sideload",
1832     default=milestone.is_esr,
1833     help="Addon sideloading is allowed",
1837 set_config("MOZ_ALLOW_ADDON_SIDELOAD", True, when="--allow-addon-sideload")
1839 # WebExtensions API WebIDL bindings
1840 # ==============================================================
1843 @depends(milestone)
1844 def extensions_webidl_bindings_default(milestone):
1845     # Only enable the webidl bindings for the WebExtensions APIs
1846     # in Nightly.
1847     return milestone.is_nightly
1850 option(
1851     "--enable-extensions-webidl-bindings",
1852     default=extensions_webidl_bindings_default,
1853     help="{Enable|Disable} building experimental WebExtensions WebIDL bindings",
1857 @depends("--enable-extensions-webidl-bindings")
1858 def extensions_webidl_enabled(value):
1859     return bool(value)
1862 set_config("MOZ_WEBEXT_WEBIDL_ENABLED", extensions_webidl_enabled)
1864 # Launcher process (Windows only)
1865 # ==============================================================
1868 @depends(target)
1869 def launcher_process_default(target):
1870     return target.os == "WINNT"
1873 option(
1874     "--enable-launcher-process",
1875     default=launcher_process_default,
1876     help="{Enable|Disable} launcher process by default",
1880 @depends("--enable-launcher-process", target)
1881 def launcher(value, target):
1882     enabled = bool(value)
1883     if enabled and target.os != "WINNT":
1884         die("Cannot enable launcher process on %s", target.os)
1885     if enabled:
1886         return True
1889 set_config("MOZ_LAUNCHER_PROCESS", launcher)
1890 set_define("MOZ_LAUNCHER_PROCESS", launcher)
1892 # llvm-dlltool (Windows only)
1893 # ==============================================================
1896 @depends(build_project, target, "--enable-compile-environment")
1897 def check_for_llvm_dlltool(build_project, target, compile_environment):
1898     if build_project != "browser":
1899         return
1901     if target.os != "WINNT":
1902         return
1904     return compile_environment
1907 llvm_dlltool = check_prog(
1908     "LLVM_DLLTOOL",
1909     ("llvm-dlltool",),
1910     what="llvm-dlltool",
1911     when=check_for_llvm_dlltool,
1912     paths=clang_search_path,
1916 @depends(target, when=llvm_dlltool)
1917 def llvm_dlltool_flags(target):
1918     arch = {
1919         "x86": "i386",
1920         "x86_64": "i386:x86-64",
1921         "aarch64": "arm64",
1922     }[target.cpu]
1924     return ["-m", arch]
1927 set_config("LLVM_DLLTOOL_FLAGS", llvm_dlltool_flags)
1929 # BITS download (Windows only)
1930 # ==============================================================
1932 option(
1933     "--enable-bits-download",
1934     when=target_is_windows,
1935     default=target_is_windows,
1936     help="{Enable|Disable} building BITS download support",
1939 set_define(
1940     "MOZ_BITS_DOWNLOAD",
1941     depends_if("--enable-bits-download", when=target_is_windows)(lambda _: True),
1943 set_config(
1944     "MOZ_BITS_DOWNLOAD",
1945     depends_if("--enable-bits-download", when=target_is_windows)(lambda _: True),
1948 # Bundled fonts on desktop platform
1949 # ==============================================================
1952 @depends(target)
1953 def bundled_fonts_default(target):
1954     return target.os == "WINNT" or target.kernel == "Linux"
1957 @depends(build_project)
1958 def allow_bundled_fonts(project):
1959     return project == "browser" or project == "comm/mail"
1962 option(
1963     "--enable-bundled-fonts",
1964     default=bundled_fonts_default,
1965     when=allow_bundled_fonts,
1966     help="{Enable|Disable} support for bundled fonts on desktop platforms",
1969 set_define(
1970     "MOZ_BUNDLED_FONTS",
1971     depends_if("--enable-bundled-fonts", when=allow_bundled_fonts)(lambda _: True),
1974 # Reflow counting
1975 # ==============================================================
1978 @depends(moz_debug)
1979 def reflow_perf(debug):
1980     if debug:
1981         return True
1984 option(
1985     "--enable-reflow-perf",
1986     default=reflow_perf,
1987     help="{Enable|Disable} reflow performance tracing",
1990 # The difference in conditions here comes from the initial implementation
1991 # in old-configure, which was unexplained there as well.
1992 set_define("MOZ_REFLOW_PERF", depends_if("--enable-reflow-perf")(lambda _: True))
1993 set_define("MOZ_REFLOW_PERF_DSP", reflow_perf)
1995 # Layout debugger
1996 # ==============================================================
1999 @depends(moz_debug)
2000 def layout_debugger(debug):
2001     if debug:
2002         return True
2005 option(
2006     "--enable-layout-debugger",
2007     default=layout_debugger,
2008     help="{Enable|Disable} layout debugger",
2011 set_config("MOZ_LAYOUT_DEBUGGER", True, when="--enable-layout-debugger")
2012 set_define("MOZ_LAYOUT_DEBUGGER", True, when="--enable-layout-debugger")
2015 # Shader Compiler for Windows (and MinGW Cross Compile)
2016 # ==============================================================
2018 with only_when(compile_environment):
2019     fxc = check_prog(
2020         "FXC",
2021         ("fxc.exe", "fxc2.exe"),
2022         when=depends(target)(lambda t: t.kernel == "WINNT"),
2023         paths=sdk_bin_path,
2024         # FXC being used from a python wrapper script, we can live with it
2025         # having spaces.
2026         allow_spaces=True,
2027     )
2030 # VPX
2031 # ===
2033 with only_when(compile_environment):
2034     system_lib_option(
2035         "--with-system-libvpx", help="Use system libvpx (located with pkgconfig)"
2036     )
2038     with only_when("--with-system-libvpx"):
2039         vpx = pkg_check_modules("MOZ_LIBVPX", "vpx >= 1.10.0")
2041         check_header(
2042             "vpx/vpx_decoder.h",
2043             flags=vpx.cflags,
2044             onerror=lambda: die(
2045                 "Couldn't find vpx/vpx_decoder.h, which is required to build "
2046                 "with system libvpx. Use --without-system-libvpx to build "
2047                 "with in-tree libvpx."
2048             ),
2049         )
2051         check_symbol(
2052             "vpx_codec_dec_init_ver",
2053             flags=vpx.libs,
2054             onerror=lambda: die(
2055                 "--with-system-libvpx requested but symbol vpx_codec_dec_init_ver "
2056                 "not found"
2057             ),
2058         )
2060         set_config("MOZ_SYSTEM_LIBVPX", True)
2062     @depends("--with-system-libvpx", target)
2063     def in_tree_vpx(system_libvpx, target):
2064         if system_libvpx:
2065             return
2067         arm_asm = (target.cpu == "arm") or None
2068         return namespace(arm_asm=arm_asm)
2070     @depends(target, when=in_tree_vpx)
2071     def vpx_nasm(target):
2072         if target.cpu in ("x86", "x86_64"):
2073             if target.kernel == "WINNT":
2074                 # Version 2.03 is needed for automatic safeseh support.
2075                 return namespace(version="2.03", what="VPX")
2076             return namespace(what="VPX")
2078     @depends(in_tree_vpx, vpx_nasm, target, neon_flags)
2079     def vpx_as_flags(vpx, vpx_nasm, target, neon_flags):
2080         if vpx and vpx.arm_asm:
2081             # These flags are a lie; they're just used to enable the requisite
2082             # opcodes; actual arch detection is done at runtime.
2083             return neon_flags
2084         elif vpx and vpx_nasm and target.os != "WINNT" and target.cpu != "x86_64":
2085             return ("-DPIC",)
2087     set_config("VPX_USE_NASM", True, when=vpx_nasm)
2088     set_config("VPX_ASFLAGS", vpx_as_flags)
2091 # JPEG
2092 # ====
2094 with only_when(compile_environment):
2095     system_lib_option(
2096         "--with-system-jpeg",
2097         nargs="?",
2098         help="Use system libjpeg (installed at given prefix)",
2099     )
2101     @depends_if("--with-system-jpeg")
2102     def jpeg_flags(value):
2103         if len(value):
2104             return namespace(
2105                 cflags=("-I%s/include" % value[0],),
2106                 ldflags=("-L%s/lib" % value[0], "-ljpeg"),
2107             )
2108         return namespace(
2109             ldflags=("-ljpeg",),
2110         )
2112     with only_when("--with-system-jpeg"):
2113         check_symbol(
2114             "jpeg_destroy_compress",
2115             flags=jpeg_flags.ldflags,
2116             onerror=lambda: die(
2117                 "--with-system-jpeg requested but symbol "
2118                 "jpeg_destroy_compress not found."
2119             ),
2120         )
2122         c_compiler.try_compile(
2123             includes=[
2124                 "stdio.h",
2125                 "sys/types.h",
2126                 "jpeglib.h",
2127             ],
2128             body="""
2129                 #if JPEG_LIB_VERSION < 62
2130                 #error Insufficient JPEG library version
2131                 #endif
2132             """,
2133             flags=jpeg_flags.cflags,
2134             check_msg="for sufficient jpeg library version",
2135             onerror=lambda: die(
2136                 "Insufficient JPEG library version for "
2137                 "--with-system-jpeg (62 required)"
2138             ),
2139         )
2141         c_compiler.try_compile(
2142             includes=[
2143                 "stdio.h",
2144                 "sys/types.h",
2145                 "jpeglib.h",
2146             ],
2147             body="""
2148                 #ifndef JCS_EXTENSIONS
2149                 #error libjpeg-turbo JCS_EXTENSIONS required
2150                 #endif
2151             """,
2152             flags=jpeg_flags.cflags,
2153             check_msg="for sufficient libjpeg-turbo JCS_EXTENSIONS",
2154             onerror=lambda: die(
2155                 "libjpeg-turbo JCS_EXTENSIONS required for " "--with-system-jpeg"
2156             ),
2157         )
2159         set_config("MOZ_JPEG_CFLAGS", jpeg_flags.cflags)
2160         set_config("MOZ_JPEG_LIBS", jpeg_flags.ldflags)
2162     @depends("--with-system-jpeg", target, neon_flags)
2163     def in_tree_jpeg_arm(system_jpeg, target, neon_flags):
2164         if system_jpeg:
2165             return
2167         if target.cpu == "arm":
2168             return neon_flags
2169         elif target.cpu == "aarch64":
2170             return ("-march=armv8-a",)
2172     @depends("--with-system-jpeg", target)
2173     def in_tree_jpeg_mips64(system_jpeg, target):
2174         if system_jpeg:
2175             return
2177         if target.cpu == "mips64":
2178             return ("-Wa,-mloongson-mmi", "-mloongson-ext")
2180     # Compiler check from https://github.com/libjpeg-turbo/libjpeg-turbo/blob/57ba02a408a9a55ccff25aae8b164632a3a4f177/simd/CMakeLists.txt#L419
2181     jpeg_mips64_mmi = c_compiler.try_compile(
2182         body='int c = 0, a = 0, b = 0; asm("paddb %0, %1, %2" : "=f" (c) : "f" (a), "f" (b));',
2183         check_msg="for loongson mmi support",
2184         flags=in_tree_jpeg_mips64,
2185         when=in_tree_jpeg_mips64,
2186     )
2188     @depends(
2189         "--with-system-jpeg",
2190         target,
2191         in_tree_jpeg_arm,
2192         in_tree_jpeg_mips64,
2193         jpeg_mips64_mmi,
2194     )
2195     def in_tree_jpeg(
2196         system_jpeg, target, in_tree_jpeg_arm, in_tree_jpeg_mips64, jpeg_mips64_mmi
2197     ):
2198         if system_jpeg:
2199             return
2201         if target.cpu in ("arm", "aarch64"):
2202             return in_tree_jpeg_arm
2203         elif target.kernel == "Darwin":
2204             if target.cpu == "x86":
2205                 return ("-DPIC", "-DMACHO")
2206             elif target.cpu == "x86_64":
2207                 return ("-D__x86_64__", "-DPIC", "-DMACHO")
2208         elif target.kernel == "WINNT":
2209             if target.cpu == "x86":
2210                 return ("-DPIC", "-DWIN32")
2211             elif target.cpu == "x86_64":
2212                 return ("-D__x86_64__", "-DPIC", "-DWIN64", "-DMSVC")
2213         elif target.cpu == "mips32":
2214             return ("-mdspr2",)
2215         elif target.cpu == "mips64" and jpeg_mips64_mmi:
2216             return in_tree_jpeg_mips64
2217         elif target.cpu == "x86":
2218             return ("-DPIC", "-DELF")
2219         elif target.cpu == "x86_64":
2220             return ("-D__x86_64__", "-DPIC", "-DELF")
2222     @depends(target, when=depends("--with-system-jpeg")(lambda x: not x))
2223     def jpeg_nasm(target):
2224         if target.cpu in ("x86", "x86_64"):
2225             # libjpeg-turbo 2.0.6 requires nasm 2.10.
2226             return namespace(version="2.10", what="JPEG")
2228     # Compiler checks from https://github.com/libjpeg-turbo/libjpeg-turbo/blob/57ba02a408a9a55ccff25aae8b164632a3a4f177/simd/CMakeLists.txt#L258
2229     jpeg_arm_neon_vld1_s16_x3 = c_compiler.try_compile(
2230         includes=["arm_neon.h"],
2231         body="int16_t input[12] = {}; int16x4x3_t output = vld1_s16_x3(input);",
2232         check_msg="for vld1_s16_x3 in arm_neon.h",
2233         flags=in_tree_jpeg_arm,
2234         when=in_tree_jpeg_arm,
2235     )
2237     jpeg_arm_neon_vld1_u16_x2 = c_compiler.try_compile(
2238         includes=["arm_neon.h"],
2239         body="uint16_t input[8] = {}; uint16x4x2_t output = vld1_u16_x2(input);",
2240         check_msg="for vld1_u16_x2 in arm_neon.h",
2241         flags=in_tree_jpeg_arm,
2242         when=in_tree_jpeg_arm,
2243     )
2245     jpeg_arm_neon_vld1q_u8_x4 = c_compiler.try_compile(
2246         includes=["arm_neon.h"],
2247         body="uint8_t input[64] = {}; uint8x16x4_t output = vld1q_u8_x4(input);",
2248         check_msg="for vld1q_u8_x4 in arm_neon.h",
2249         flags=in_tree_jpeg_arm,
2250         when=in_tree_jpeg_arm,
2251     )
2253     set_config("LIBJPEG_TURBO_USE_NASM", True, when=jpeg_nasm)
2254     set_config("LIBJPEG_TURBO_SIMD_FLAGS", in_tree_jpeg)
2255     set_config("LIBJPEG_TURBO_HAVE_VLD1_S16_X3", jpeg_arm_neon_vld1_s16_x3)
2256     set_config("LIBJPEG_TURBO_HAVE_VLD1_U16_X2", jpeg_arm_neon_vld1_u16_x2)
2257     set_config("LIBJPEG_TURBO_HAVE_VLD1Q_U8_X4", jpeg_arm_neon_vld1q_u8_x4)
2258     set_config(
2259         "LIBJPEG_TURBO_NEON_INTRINSICS",
2260         jpeg_arm_neon_vld1_s16_x3
2261         & jpeg_arm_neon_vld1_u16_x2
2262         & jpeg_arm_neon_vld1q_u8_x4,
2263     )
2266 # PNG
2267 # ===
2268 with only_when(compile_environment):
2269     system_lib_option(
2270         "--with-system-png",
2271         nargs="?",
2272         help="Use system libpng",
2273     )
2275     @depends("--with-system-png")
2276     def deprecated_system_png_path(value):
2277         if len(value) == 1:
2278             die(
2279                 "--with-system-png=PATH is not supported anymore. Please use "
2280                 "--with-system-png and set any necessary pkg-config environment variable."
2281             )
2283     png = pkg_check_modules("MOZ_PNG", "libpng >= 1.6.35", when="--with-system-png")
2285     check_symbol(
2286         "png_get_acTL",
2287         flags=png.libs,
2288         onerror=lambda: die(
2289             "--with-system-png won't work because the system's libpng doesn't have APNG support"
2290         ),
2291         when="--with-system-png",
2292     )
2294     set_config("MOZ_SYSTEM_PNG", True, when="--with-system-png")
2297 # FFmpeg's ffvpx configuration
2298 # ==============================================================
2299 with only_when(compile_environment):
2301     @depends(target)
2302     def libav_fft(target):
2303         if target.os == "Android" and target.cpu != "arm":
2304             return True
2305         return target.kernel in ("WINNT", "Darwin") or target.cpu == "x86_64"
2307     set_config("MOZ_LIBAV_FFT", depends(when=libav_fft)(lambda: True))
2308     set_define("MOZ_LIBAV_FFT", depends(when=libav_fft)(lambda: True))
2311 # Artifact builds need MOZ_FFVPX defined as if compilation happened.
2312 with only_when(compile_environment | artifact_builds):
2314     @depends(target)
2315     def ffvpx(target):
2316         enable = use_nasm = True
2317         flac_only = False
2318         flags = []
2320         if target.kernel == "WINNT":
2321             if target.cpu == "x86":
2322                 # 32-bit windows need to prefix symbols with an underscore.
2323                 flags = ["-DPIC", "-DWIN32", "-DPREFIX", "-Pconfig_win32.asm"]
2324             elif target.cpu == "x86_64":
2325                 flags = [
2326                     "-D__x86_64__",
2327                     "-DPIC",
2328                     "-DWIN64",
2329                     "-DMSVC",
2330                     "-Pconfig_win64.asm",
2331                 ]
2332             elif target.cpu == "aarch64":
2333                 flags = ["-DPIC", "-DWIN64"]
2334                 use_nasm = False
2335         elif target.kernel == "Darwin":
2336             # 32/64-bit macosx assemblers need to prefix symbols with an
2337             # underscore.
2338             flags = ["-DPIC", "-DMACHO", "-DPREFIX"]
2339             if target.cpu == "x86_64":
2340                 flags += [
2341                     "-D__x86_64__",
2342                     "-Pconfig_darwin64.asm",
2343                 ]
2344             elif target.cpu == "aarch64":
2345                 use_nasm = False
2346         elif target.cpu == "x86_64":
2347             flags = ["-D__x86_64__", "-DPIC", "-DELF", "-Pconfig_unix64.asm"]
2348         elif target.cpu in ("x86", "arm", "aarch64"):
2349             flac_only = True
2350         else:
2351             enable = False
2353         if flac_only or not enable:
2354             use_nasm = False
2356         return namespace(
2357             enable=enable,
2358             use_nasm=use_nasm,
2359             flac_only=flac_only,
2360             flags=flags,
2361         )
2363     @depends(when=ffvpx.use_nasm)
2364     def ffvpx_nasm():
2365         # nasm 2.10 for AVX-2 support.
2366         return namespace(version="2.10", what="FFVPX")
2368     # ffvpx_nasm can't indirectly depend on vpx_as_flags, because it depends
2369     # on a compiler test, so we have to do a little bit of dance here.
2370     @depends(ffvpx, vpx_as_flags, target)
2371     def ffvpx(ffvpx, vpx_as_flags, target):
2372         if ffvpx and vpx_as_flags and target.cpu in ("arm", "aarch64"):
2373             ffvpx.flags.extend(vpx_as_flags)
2374         return ffvpx
2376     set_config("MOZ_FFVPX", True, when=ffvpx.enable)
2377     set_define("MOZ_FFVPX", True, when=ffvpx.enable)
2378     set_config("MOZ_FFVPX_AUDIOONLY", True, when=ffvpx.flac_only)
2379     set_define("MOZ_FFVPX_AUDIOONLY", True, when=ffvpx.flac_only)
2380     set_config("FFVPX_ASFLAGS", ffvpx.flags)
2381     set_config("FFVPX_USE_NASM", True, when=ffvpx.use_nasm)
2384 # nasm detection
2385 # ==============================================================
2386 @depends(dav1d_nasm, vpx_nasm, jpeg_nasm, ffvpx_nasm, when=compile_environment)
2387 def need_nasm(*requirements):
2388     requires = {
2389         x.what: x.version if hasattr(x, "version") else True for x in requirements if x
2390     }
2391     if requires:
2392         items = sorted(requires.keys())
2393         if len(items) > 1:
2394             what = " and ".join((", ".join(items[:-1]), items[-1]))
2395         else:
2396             what = items[0]
2397         versioned = {k: v for (k, v) in requires.items() if v is not True}
2398         return namespace(what=what, versioned=versioned)
2401 nasm = check_prog(
2402     "NASM",
2403     ["nasm"],
2404     allow_missing=True,
2405     bootstrap="nasm",
2406     when=need_nasm,
2410 @depends(nasm, need_nasm.what)
2411 def check_nasm(nasm, what):
2412     if not nasm and what:
2413         die("Nasm is required to build with %s, but it was not found." % what)
2414     return nasm
2417 @depends_if(check_nasm)
2418 @checking("nasm version")
2419 def nasm_version(nasm):
2420     version = (
2421         check_cmd_output(nasm, "-v", onerror=lambda: die("Failed to get nasm version."))
2422         .splitlines()[0]
2423         .split()[2]
2424     )
2425     return Version(version)
2428 @depends(nasm_version, need_nasm.versioned, when=need_nasm.versioned)
2429 def check_nasm_version(nasm_version, versioned):
2430     by_version = sorted(versioned.items(), key=lambda x: x[1])
2431     what, version = by_version[-1]
2432     if nasm_version < version:
2433         die(
2434             "Nasm version %s or greater is required to build with %s." % (version, what)
2435         )
2436     return nasm_version
2439 @depends(target, when=check_nasm_version)
2440 def nasm_asflags(target):
2441     asflags = {
2442         ("OSX", "x86"): ["-f", "macho32"],
2443         ("OSX", "x86_64"): ["-f", "macho64"],
2444         ("WINNT", "x86"): ["-f", "win32"],
2445         ("WINNT", "x86_64"): ["-f", "win64"],
2446     }.get((target.os, target.cpu), None)
2447     if asflags is None:
2448         # We're assuming every x86 platform we support that's
2449         # not Windows or Mac is ELF.
2450         if target.cpu == "x86":
2451             asflags = ["-f", "elf32"]
2452         elif target.cpu == "x86_64":
2453             asflags = ["-f", "elf64"]
2454     return asflags
2457 set_config("NASM_ASFLAGS", nasm_asflags)
2460 # ANGLE OpenGL->D3D translator for WebGL
2461 # ==============================================================
2463 with only_when(compile_environment & target_is_windows):
2464     set_config("MOZ_ANGLE_RENDERER", True)
2466 # Remoting protocol support
2467 # ==============================================================
2470 @depends(toolkit)
2471 def has_remote(toolkit):
2472     if toolkit in ("gtk", "windows", "cocoa"):
2473         return True
2476 set_config("MOZ_HAS_REMOTE", has_remote)
2477 set_define("MOZ_HAS_REMOTE", has_remote)
2479 # RLBox Library Sandboxing wasm support
2480 # ==============================================================
2483 def wasm_sandboxing_libraries():
2484     return (
2485         "graphite",
2486         "ogg",
2487         "hunspell",
2488         "expat",
2489         "woff2",
2490         "soundtouch",
2491     )
2494 @depends(dependable(wasm_sandboxing_libraries), build_project)
2495 def default_wasm_sandboxing_libraries(libraries, build_project):
2496     if build_project != "tools/rusttests":
2497         non_default_libs = {"soundtouch"}
2499         return tuple(l for l in libraries if l not in non_default_libs)
2502 option(
2503     "--with-wasm-sandboxed-libraries",
2504     env="WASM_SANDBOXED_LIBRARIES",
2505     help="{Enable wasm sandboxing for the selected libraries|Disable wasm sandboxing}",
2506     nargs="+",
2507     choices=dependable(wasm_sandboxing_libraries),
2508     default=default_wasm_sandboxing_libraries,
2512 @depends("--with-wasm-sandboxed-libraries")
2513 def requires_wasm_sandboxing(libraries):
2514     if libraries:
2515         return True
2518 set_config("MOZ_USING_WASM_SANDBOXING", requires_wasm_sandboxing)
2519 set_define("MOZ_USING_WASM_SANDBOXING", requires_wasm_sandboxing)
2521 with only_when(requires_wasm_sandboxing & compile_environment):
2522     option(
2523         "--with-wasi-sysroot",
2524         env="WASI_SYSROOT",
2525         nargs=1,
2526         help="Path to wasi sysroot for wasm sandboxing",
2527     )
2529     @depends("--with-wasi-sysroot", requires_wasm_sandboxing)
2530     def bootstrap_wasi_sysroot(wasi_sysroot, requires_wasm_sandboxing):
2531         return requires_wasm_sandboxing and not wasi_sysroot
2533     @depends(
2534         "--with-wasi-sysroot",
2535         bootstrap_path("sysroot-wasm32-wasi", when=bootstrap_wasi_sysroot),
2536     )
2537     @imports("os")
2538     def wasi_sysroot(wasi_sysroot, bootstrapped_sysroot):
2539         if not wasi_sysroot:
2540             return bootstrapped_sysroot
2542         wasi_sysroot = wasi_sysroot[0]
2543         if not os.path.isdir(wasi_sysroot):
2544             die("Argument to --with-wasi-sysroot must be a directory")
2545         if not os.path.isabs(wasi_sysroot):
2546             die("Argument to --with-wasi-sysroot must be an absolute path")
2548         return wasi_sysroot
2550     @depends(wasi_sysroot)
2551     def wasi_sysroot_flags(wasi_sysroot):
2552         if wasi_sysroot:
2553             log.info("Using wasi sysroot in %s", wasi_sysroot)
2554             return ["--sysroot=%s" % wasi_sysroot]
2555         return []
2557     set_config("WASI_SYSROOT", wasi_sysroot)
2559     def wasm_compiler_with_flags(compiler, sysroot_flags):
2560         if compiler:
2561             return (
2562                 compiler.wrapper + [compiler.compiler] + compiler.flags + sysroot_flags
2563             )
2565     @template
2566     def wasm_compiler_error(msg):
2567         @depends("--with-wasm-sandboxed-libraries")
2568         def wasm_compiler_error(sandboxed_libs):
2569             suggest_disable = ""
2570             if sandboxed_libs.origin == "default":
2571                 suggest_disable = " Or build with --without-wasm-sandboxed-libraries."
2572             return lambda: die(msg + suggest_disable)
2574         return wasm_compiler_error
2576     @template
2577     def check_wasm_compiler(compiler, language):
2578         compiler.try_compile(
2579             includes=["cstring" if language == "C++" else "string.h"],
2580             flags=wasi_sysroot_flags,
2581             check_msg="the wasm %s compiler can find wasi headers" % language,
2582             onerror=wasm_compiler_error(
2583                 "Cannot find wasi headers or problem with the wasm compiler. "
2584                 "Please fix the problem."
2585             ),
2586         )
2588         compiler.try_run(
2589             flags=wasi_sysroot_flags,
2590             check_msg="the wasm %s linker can find wasi libraries" % language,
2591             onerror=wasm_compiler_error(
2592                 "Cannot find wasi libraries or problem with the wasm linker. "
2593                 "Please fix the problem."
2594             ),
2595         )
2597     wasm_cc = compiler("C", wasm, other_compiler=c_compiler)
2598     check_wasm_compiler(wasm_cc, "C")
2600     @depends(wasm_cc, wasi_sysroot_flags)
2601     def wasm_cc_with_flags(wasm_cc, wasi_sysroot_flags):
2602         return wasm_compiler_with_flags(wasm_cc, wasi_sysroot_flags)
2604     set_config("WASM_CC", wasm_cc_with_flags)
2606     wasm_cxx = compiler(
2607         "C++",
2608         wasm,
2609         c_compiler=wasm_cc,
2610         other_compiler=cxx_compiler,
2611         other_c_compiler=c_compiler,
2612     )
2613     check_wasm_compiler(wasm_cxx, "C++")
2615     @depends(wasm_cxx, wasi_sysroot_flags)
2616     def wasm_cxx_with_flags(wasm_cxx, wasi_sysroot_flags):
2617         return wasm_compiler_with_flags(wasm_cxx, wasi_sysroot_flags)
2619     set_config("WASM_CXX", wasm_cxx_with_flags)
2621     wasm_compile_flags = dependable(["-fno-exceptions", "-fno-strict-aliasing"])
2622     option(env="WASM_CFLAGS", nargs=1, help="Options to pass to WASM_CC")
2624     @depends("WASM_CFLAGS", wasm_compile_flags)
2625     def wasm_cflags(value, wasm_compile_flags):
2626         if value:
2627             return wasm_compile_flags + value
2628         else:
2629             return wasm_compile_flags
2631     set_config("WASM_CFLAGS", wasm_cflags)
2633     option(env="WASM_CXXFLAGS", nargs=1, help="Options to pass to WASM_CXX")
2635     @depends("WASM_CXXFLAGS", wasm_compile_flags)
2636     def wasm_cxxflags(value, wasm_compile_flags):
2637         if value:
2638             return wasm_compile_flags + value
2639         else:
2640             return wasm_compile_flags
2642     set_config("WASM_CXXFLAGS", wasm_cxxflags)
2645 @depends("--with-wasm-sandboxed-libraries")
2646 def wasm_sandboxing(libraries):
2647     if not libraries:
2648         return
2650     return namespace(**{name: True for name in libraries})
2653 @template
2654 def wasm_sandboxing_config_defines():
2655     for lib in wasm_sandboxing_libraries():
2656         set_config(
2657             "MOZ_WASM_SANDBOXING_%s" % lib.upper(), getattr(wasm_sandboxing, lib)
2658         )
2659         set_define(
2660             "MOZ_WASM_SANDBOXING_%s" % lib.upper(), getattr(wasm_sandboxing, lib)
2661         )
2664 wasm_sandboxing_config_defines()
2667 # new Notification Store implementation
2668 # ==============================================================
2671 @depends(milestone)
2672 def new_notification_store(milestone):
2673     if milestone.is_nightly:
2674         return True
2677 set_config("MOZ_NEW_NOTIFICATION_STORE", True, when=new_notification_store)
2678 set_define("MOZ_NEW_NOTIFICATION_STORE", True, when=new_notification_store)
2681 # Auxiliary files persistence on application close
2682 # ==============================================================
2684 option(
2685     "--enable-disk-remnant-avoidance",
2686     help="Prevent persistence of auxiliary files on application close",
2690 set_config(
2691     "MOZ_AVOID_DISK_REMNANT_ON_CLOSE",
2692     True,
2693     when="--enable-disk-remnant-avoidance",
2697 # Glean SDK Integration Crate
2698 # ==============================================================
2701 @depends(target)
2702 def glean_android(target):
2703     return target.os == "Android"
2706 set_config("MOZ_GLEAN_ANDROID", True, when=glean_android)
2707 set_define("MOZ_GLEAN_ANDROID", True, when=glean_android)
2710 # dump_syms
2711 # ==============================================================
2713 check_prog(
2714     "DUMP_SYMS",
2715     ["dump_syms"],
2716     allow_missing=True,
2717     bootstrap="dump_syms",
2718     when=compile_environment,
2722 @depends(valid_windows_sdk_dir, host)
2723 @imports(_from="os", _import="environ")
2724 def pdbstr_paths(valid_windows_sdk_dir, host):
2725     if not valid_windows_sdk_dir:
2726         return
2728     vc_host = {
2729         "x86": "x86",
2730         "x86_64": "x64",
2731     }.get(host.cpu)
2733     return [
2734         environ["PATH"],
2735         os.path.join(valid_windows_sdk_dir.path, "Debuggers", vc_host, "srcsrv"),
2736     ]
2739 check_prog(
2740     "PDBSTR",
2741     ["pdbstr.exe"],
2742     allow_missing=True,
2743     when=compile_environment & target_is_windows,
2744     paths=pdbstr_paths,
2745     allow_spaces=True,
2749 @depends("MOZ_AUTOMATION", c_compiler)
2750 def allow_missing_winchecksec(automation, c_compiler):
2751     if not automation:
2752         return True
2753     if c_compiler and c_compiler.type != "clang-cl":
2754         return True
2757 check_prog(
2758     "WINCHECKSEC",
2759     ["winchecksec.exe", "winchecksec"],
2760     bootstrap="winchecksec",
2761     allow_missing=allow_missing_winchecksec,
2762     when=compile_environment & target_is_windows,
2766 # Fork server
2767 @depends(target, build_project)
2768 def forkserver_default(target, build_project):
2769     return build_project == "browser" and (
2770         (target.os == "GNU" and target.kernel == "Linux")
2771         or target.os == "FreeBSD"
2772         or target.os == "OpenBSD"
2773     )
2776 option(
2777     "--enable-forkserver",
2778     default=forkserver_default,
2779     env="MOZ_ENABLE_FORKSERVER",
2780     help="{Enable|Disable} fork server",
2784 @depends("--enable-forkserver", target)
2785 def forkserver_flag(value, target):
2786     if (
2787         target.os == "Android"
2788         or (target.os == "GNU" and target.kernel == "Linux")
2789         or target.os == "FreeBSD"
2790         or target.os == "OpenBSD"
2791     ):
2792         return bool(value)
2793     pass
2796 set_config("MOZ_ENABLE_FORKSERVER", forkserver_flag)
2797 set_define("MOZ_ENABLE_FORKSERVER", forkserver_flag, forkserver_flag)
2799 # Crash Reporter
2800 # ==============================================================
2802 with only_when(compile_environment & target_has_linux_kernel):
2803     # Check if we need to use the breakpad_getcontext fallback.
2804     getcontext = check_symbol("getcontext")
2805     set_config("HAVE_GETCONTEXT", getcontext)
2806     set_define("HAVE_GETCONTEXT", getcontext)
2808 # NSS
2809 # ==============================================================
2810 include("../build/moz.configure/nss.configure")
2813 # Enable or disable running in background task mode: headless for
2814 # periodic, short-lived, maintenance tasks.
2815 # ==============================================================================
2816 option(
2817     "--disable-backgroundtasks",
2818     help="Disable running in background task mode",
2820 set_config("MOZ_BACKGROUNDTASKS", True, when="--enable-backgroundtasks")
2821 set_define("MOZ_BACKGROUNDTASKS", True, when="--enable-backgroundtasks")
2824 # Update-related programs: updater, maintenance service, update agent,
2825 # default browser agent.
2826 # ==============================================================
2827 include("../build/moz.configure/update-programs.configure")
2830 # Mobile optimizations
2831 # ==============================================================
2832 option(
2833     "--enable-mobile-optimize",
2834     default=target_is_android,
2835     help="{Enable|Disable} mobile optimizations",
2838 set_define("MOZ_GFX_OPTIMIZE_MOBILE", True, when="--enable-mobile-optimize")
2839 # We ignore "paint will resample" on mobile for performance.
2840 # We may want to revisit this later.
2841 set_define("MOZ_IGNORE_PAINT_WILL_RESAMPLE", True, when="--enable-mobile-optimize")
2843 # Pref extensions
2844 # ==============================================================
2845 option("--disable-pref-extensions", help="Disable pref extensions such as autoconfig")
2846 set_config("MOZ_PREF_EXTENSIONS", True, when="--enable-pref-extensions")
2848 # Offer a way to disable the startup cache
2849 # ==============================================================
2850 option("--disable-startupcache", help="Disable startup cache")
2853 @depends("--enable-startupcache")
2854 def enable_startupcache(value):
2855     if value:
2856         return True
2859 set_define(
2860     "MOZ_DISABLE_STARTUPCACHE", True, when=depends(enable_startupcache)(lambda x: not x)
2864 # Branding
2865 # ==============================================================
2866 option(
2867     env="MOZ_APP_REMOTINGNAME",
2868     nargs=1,
2869     help="Used for the internal program name, which affects profile name "
2870     "and remoting. If not set, defaults to MOZ_APP_NAME if the update channel "
2871     "is release, and MOZ_APP_NAME-MOZ_UPDATE_CHANNEL otherwise.",
2875 @depends("MOZ_APP_REMOTINGNAME", moz_app_name, update_channel)
2876 def moz_app_remotingname(value, moz_app_name, update_channel):
2877     if value:
2878         return value[0]
2879     if update_channel == "release":
2880         return moz_app_name
2881     return moz_app_name + "-" + update_channel
2884 set_config("MOZ_APP_REMOTINGNAME", moz_app_remotingname)
2886 option(
2887     env="ANDROID_PACKAGE_NAME",
2888     nargs=1,
2889     help="Name of the Android package (default org.mozilla.$MOZ_APP_NAME)",
2893 @depends("ANDROID_PACKAGE_NAME", moz_app_name)
2894 def android_package_name(value, moz_app_name):
2895     if value:
2896         return value[0]
2897     if moz_app_name == "fennec":
2898         return "org.mozilla.fennec_aurora"
2899     return "org.mozilla.%s" % moz_app_name
2902 set_config("ANDROID_PACKAGE_NAME", android_package_name)
2905 # Miscellaneous options
2906 # ==============================================================
2907 option(env="MOZ_WINCONSOLE", nargs="?", help="Whether we can create a console window.")
2908 set_define("MOZ_WINCONSOLE", True, when=depends("MOZ_WINCONSOLE")(lambda x: x))
2911 # Alternative Crashreporter setting
2912 option(
2913     "--with-crashreporter-url",
2914     env="MOZ_CRASHREPORTER_URL",
2915     default="https://crash-reports.mozilla.com/",
2916     nargs=1,
2917     help="Set an alternative crashreporter url",
2920 set_config(
2921     "MOZ_CRASHREPORTER_URL",
2922     depends("--with-crashreporter-url")(lambda x: x[0].rstrip("/")),
2926 # Crash reporter options
2927 # ==============================================================
2928 @depends(target)
2929 def oxidized_breakpad(target):
2930     if target.kernel == "Linux":
2931         return target.cpu in ("aarch64", "arm", "x86", "x86_64")
2932     return False
2935 set_config("MOZ_OXIDIZED_BREAKPAD", True, when=oxidized_breakpad)
2936 set_define("MOZ_OXIDIZED_BREAKPAD", True, when=oxidized_breakpad)
2939 # Wine
2940 # ==============================================================
2941 @depends(target, host)
2942 def want_wine(target, host):
2943     return target.kernel == "WINNT" and host.kernel != "WINNT"
2946 wine = check_prog(
2947     "WINE",
2948     ["wine64", "wine"],
2949     when=want_wine,
2950     bootstrap="wine/bin",
2953 # DOM Streams
2954 # ==============================================================
2955 # Set this to true so the JS engine knows we're doing a browser build.
2956 set_config("MOZ_DOM_STREAMS", True)
2957 set_define("MOZ_DOM_STREAMS", True)
2959 # libevent
2960 # ==============================================================
2961 with only_when(compile_environment):
2962     system_lib_option(
2963         "--with-system-libevent",
2964         nargs="?",
2965         help="Use system libevent",
2966     )
2968     @depends("--with-system-libevent")
2969     def deprecated_system_libevent_path(value):
2970         if len(value) == 1:
2971             die(
2972                 "--with-system-libevent=PATH is not supported anymore. Please use "
2973                 "--with-system-libevent and set any necessary pkg-config environment variable."
2974             )
2976     pkg_check_modules("MOZ_LIBEVENT", "libevent", when="--with-system-libevent")
2978     set_config("MOZ_SYSTEM_LIBEVENT", True, when="--with-system-libevent")
2981 # Crash reporting
2982 # ==============================================================
2983 @depends(target, developer_options, artifact_builds)
2984 def crashreporter_default(target, developer_options, artifacts):
2985     if target.kernel in ("WINNT", "Darwin"):
2986         return True
2987     if target.kernel == "Linux" and target.cpu in ("x86", "x86_64", "arm", "aarch64"):
2988         # The crash reporter prevents crash stacktraces to be logged in the
2989         # logs on Android, so we leave it out by default in developer builds.
2990         return target.os != "Android" or not developer_options or artifacts
2993 option(
2994     "--enable-crashreporter",
2995     default=crashreporter_default,
2996     help="{Enable|Disable} crash reporting",
3000 set_config("MOZ_CRASHREPORTER", True, when="--enable-crashreporter")
3001 set_define("MOZ_CRASHREPORTER", True, when="--enable-crashreporter")
3003 with only_when(compile_environment):
3004     with only_when("--enable-crashreporter"):
3005         pkg_check_modules(
3006             "MOZ_GTHREAD",
3007             "gthread-2.0",
3008             when=depends(target)(lambda t: t.os == "GNU" and t.kernel == "Linux"),
3009         )
3011         set_config(
3012             "MOZ_CRASHREPORTER_INJECTOR",
3013             True,
3014             when=depends(target)(lambda t: t.os == "WINNT" and t.bitness == 32),
3015         )
3016         set_define(
3017             "MOZ_CRASHREPORTER_INJECTOR",
3018             True,
3019             when=depends(target)(lambda t: t.os == "WINNT" and t.bitness == 32),
3020         )
3023 # If we have any service that uploads data (and requires data submission
3024 # policy alert), set MOZ_DATA_REPORTING.
3025 # ==============================================================
3026 @depends(
3027     "MOZ_TELEMETRY_REPORTING",
3028     "MOZ_SERVICES_HEALTHREPORT",
3029     "--enable-crashreporter",
3030     "MOZ_NORMANDY",
3032 def data_reporting(telemetry, healthreport, crashreporter, normandy):
3033     return telemetry or healthreport or crashreporter or normandy
3036 set_config("MOZ_DATA_REPORTING", True, when=data_reporting)
3037 set_define("MOZ_DATA_REPORTING", True, when=data_reporting)
3040 # Gtk+
3041 # ==============================================================
3042 with only_when(toolkit_gtk):
3043     pkg_check_modules(
3044         "MOZ_GTK3",
3045         "gtk+-3.0 >= 3.14.0 gtk+-unix-print-3.0 glib-2.0 gobject-2.0 gio-unix-2.0",
3046     )
3048     set_define("GDK_VERSION_MIN_REQUIRED", "GDK_VERSION_3_14")
3049     set_define("GDK_VERSION_MAX_ALLOWED", "GDK_VERSION_3_14")
3051     pkg_check_modules("GLIB", "glib-2.0 >= 2.42 gobject-2.0")
3053     set_define("GLIB_VERSION_MIN_REQUIRED", "GLIB_VERSION_2_42")
3054     set_define("GLIB_VERSION_MAX_ALLOWED", "GLIB_VERSION_2_42")
3056     set_define("MOZ_ACCESSIBILITY_ATK", True, when=accessibility)
3058 # DBus
3059 # ==============================================================
3060 with only_when(toolkit_gtk):
3061     option("--disable-dbus", help="Disable dbus support")
3063     with only_when("--enable-dbus"):
3064         pkg_check_modules("MOZ_DBUS", "dbus-1 >= 0.60")
3065         pkg_check_modules("MOZ_DBUS_GLIB", "dbus-glib-1 >= 0.60")
3067         set_config("MOZ_ENABLE_DBUS", True)
3068         set_define("MOZ_ENABLE_DBUS", True)
3071 # Necko's wifi scanner
3072 # ==============================================================
3073 @depends(target)
3074 def necko_wifi_when(target):
3075     return target.os in ("WINNT", "OSX", "DragonFly", "FreeBSD") or (
3076         target.kernel == "Linux" and target.os == "GNU"
3077     )
3080 option("--disable-necko-wifi", help="Disable necko wifi scanner", when=necko_wifi_when)
3082 set_config("NECKO_WIFI", True, when="--enable-necko-wifi")
3083 set_define("NECKO_WIFI", True, when="--enable-necko-wifi")
3086 @depends(
3087     depends("--enable-necko-wifi", when=necko_wifi_when)(lambda x: x),
3088     depends("--enable-dbus", when=toolkit_gtk)(lambda x: x),
3089     when=depends(target)(lambda t: t.os == "GNU" and t.kernel == "Linux"),
3091 def necko_wifi_dbus(necko_wifi, dbus):
3092     if necko_wifi and not dbus:
3093         die(
3094             "Necko WiFi scanning needs DBus on your platform, remove --disable-dbus"
3095             " or use --disable-necko-wifi"
3096         )
3097     return necko_wifi and dbus
3100 set_config("NECKO_WIFI_DBUS", True, when=necko_wifi_dbus)
3101 set_define("NECKO_WIFI_DBUS", True, when=necko_wifi_dbus)
3104 # Frontend JS debug mode
3105 # ==============================================================
3106 option("--enable-debug-js-modules", help="Enable debug mode for frontend JS libraries")
3108 set_config("DEBUG_JS_MODULES", True, when="--enable-debug-js-modules")
3111 # moz_dump_painting
3112 # ==============================================================
3113 option("--enable-dump-painting", help="Enable paint debugging")
3115 set_define(
3116     "MOZ_DUMP_PAINTING",
3117     True,
3118     when=depends("--enable-dump-painting", "--enable-debug")(
3119         lambda painting, debug: painting or debug
3120     ),
3122 set_define("MOZ_LAYERS_HAVE_LOG", True, when="--enable-dump-painting")
3125 # libproxy support
3126 # ==============================================================
3127 with only_when(toolkit_gtk):
3128     system_lib_option("--enable-libproxy", help="Enable libproxy support")
3130     with only_when("--enable-libproxy"):
3131         pkg_check_modules("MOZ_LIBPROXY", "libproxy-1.0")
3133         set_config("MOZ_ENABLE_LIBPROXY", True)
3134         set_define("MOZ_ENABLE_LIBPROXY", True)
3137 # Enable runtime logging
3138 # ==============================================================
3139 set_define("MOZ_LOGGING", True)
3140 set_define("FORCE_PR_LOG", True)
3142 # This will enable logging of addref, release, ctor, dtor.
3143 # ==============================================================
3144 option(
3145     "--enable-logrefcnt",
3146     default=moz_debug,
3147     help="{Enable|Disable} logging of refcounts",
3150 set_define("NS_BUILD_REFCNT_LOGGING", True, when="--enable-logrefcnt")
3153 # NegotiateAuth
3154 # ==============================================================
3155 option("--disable-negotiateauth", help="Disable GSS-API negotiation")
3157 set_config("MOZ_AUTH_EXTENSION", True, when="--enable-negotiateauth")
3158 set_define("MOZ_AUTH_EXTENSION", True, when="--enable-negotiateauth")
3161 # Parental control
3162 # ==============================================================
3163 option("--disable-parental-controls", help="Do not build parental controls")
3165 set_config(
3166     "MOZ_DISABLE_PARENTAL_CONTROLS",
3167     True,
3168     when=depends("--enable-parental-controls")(lambda x: not x),
3170 set_define(
3171     "MOZ_DISABLE_PARENTAL_CONTROLS",
3172     True,
3173     when=depends("--enable-parental-controls")(lambda x: not x),
3177 # Sandboxing support
3178 # ==============================================================
3179 @depends(target, tsan, asan)
3180 def sandbox_default(target, tsan, asan):
3181     # Only enable the sandbox by default on Linux, OpenBSD, macOS, and Windows
3182     if target.kernel == "Linux" and target.os == "GNU":
3183         # Bug 1182565: TSan conflicts with sandboxing on Linux.
3184         # Bug 1287971: LSan also conflicts with sandboxing on Linux.
3185         if tsan or asan:
3186             return False
3187         # Linux sandbox is only available on x86{,_64} and arm{,64}.
3188         return target.cpu in ("x86", "x86_64", "arm", "aarch64")
3189     return target.kernel in ("WINNT", "Darwin", "OpenBSD")
3192 option(
3193     "--enable-sandbox",
3194     default=sandbox_default,
3195     help="{Enable|Disable} sandboxing support",
3198 set_config("MOZ_SANDBOX", True, when="--enable-sandbox")
3199 set_define("MOZ_SANDBOX", True, when="--enable-sandbox")
3201 with only_when(depends(target.kernel)(lambda k: k not in ("Darwin", "WINNT"))):
3202     set_define("MOZ_CONTENT_TEMP_DIR", True, when="--enable-sandbox")
3204 # Searching of system directories for extensions.
3205 # ==============================================================
3206 # Note: this switch is meant to be used for test builds whose behavior should
3207 # not depend on what happens to be installed on the local machine.
3208 option(
3209     "--disable-system-extension-dirs",
3210     help="Disable searching system- and account-global directories for extensions"
3211     " of any kind; use only profile-specific extension directories",
3214 set_define("ENABLE_SYSTEM_EXTENSION_DIRS", True, when="--enable-system-extension-dirs")
3217 # Pixman
3218 # ==============================================================
3219 with only_when(compile_environment):
3220     system_lib_option(
3221         "--enable-system-pixman", help="Use system pixman (located with pkgconfig)"
3222     )
3224     @depends("--enable-system-pixman")
3225     def in_tree_pixman(pixman):
3226         return not pixman
3228     set_config("MOZ_TREE_PIXMAN", True, when=in_tree_pixman)
3229     set_define("MOZ_TREE_PIXMAN", True, when=in_tree_pixman)
3231     pkg_check_modules("MOZ_PIXMAN", "pixman-1 >= 0.36.0", when="--enable-system-pixman")
3232     # Set MOZ_PIXMAN_CFLAGS to an explicit empty value when --enable-system-pixman is *not* used,
3233     # for layout/style/extra-bindgen-flags
3234     set_config("MOZ_PIXMAN_CFLAGS", [], when=in_tree_pixman)
3237 # Universalchardet
3238 # ==============================================================
3239 with only_when(compile_environment):
3240     option("--disable-universalchardet", help="Disable universal encoding detection")
3242     set_config("MOZ_UNIVERSALCHARDET", True, when="--enable-universalchardet")
3245 # Disable zipwriter
3246 # ==============================================================
3247 with only_when(compile_environment):
3248     option("--disable-zipwriter", help="Disable zipwriter component")
3250     set_config("MOZ_ZIPWRITER", True, when="--enable-zipwriter")
3253 # Location of the mozilla user directory
3254 # ==============================================================
3255 with only_when(compile_environment):
3257     @depends(target)
3258     def default_user_appdir(target):
3259         if target.kernel in ("WINNT", "Darwin"):
3260             return "Mozilla"
3261         return ".mozilla"
3263     option(
3264         "--with-user-appdir",
3265         nargs=1,
3266         default=default_user_appdir,
3267         help="Set user-specific appdir",
3268     )
3270     @depends("--with-user-appdir")
3271     def user_appdir(appdir):
3272         if not appdir:
3273             die("--without-user-appdir is not a valid option.")
3274         if "/" in appdir[0]:
3275             die("--with-user-appdir must be a single relative path.")
3276         return '"{}"'.format(appdir[0])
3278     set_define("MOZ_USER_DIR", user_appdir)
3281 # Check for sin_len and sin6_len - used by SCTP; only appears in Mac/*BSD generally
3282 # ==============================================================
3283 with only_when(compile_environment):
3284     have_sin_len = c_compiler.try_compile(
3285         includes=["netinet/in.h"],
3286         body="struct sockaddr_in x; void *foo = (void*) &x.sin_len;",
3287         check_msg="for sin_len in struct sockaddr_in",
3288     )
3289     have_sin6_len = c_compiler.try_compile(
3290         includes=["netinet/in.h"],
3291         body="struct sockaddr_in6 x; void *foo = (void*) &x.sin6_len;",
3292         check_msg="for sin_len6 in struct sockaddr_in6",
3293     )
3294     set_define("HAVE_SIN_LEN", have_sin_len)
3295     set_define("HAVE_SIN6_LEN", have_sin6_len)
3296     # HAVE_CONN_LEN must be the same as HAVE_SIN_LEN and HAVE_SIN6_LEN
3297     set_define("HAVE_SCONN_LEN", have_sin_len & have_sin6_len)
3298     set_define(
3299         "HAVE_SA_LEN",
3300         c_compiler.try_compile(
3301             includes=["netinet/in.h"],
3302             body="struct sockaddr x; void *foo = (void*) &x.sa_len;",
3303             check_msg="for sa_len in struct sockaddr",
3304         ),
3305     )
3308 # Check for pthread_cond_timedwait_monotonic_np
3309 # ==============================================================
3310 with only_when(compile_environment):
3311     set_define(
3312         "HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC",
3313         c_compiler.try_compile(
3314             includes=["pthread.h"],
3315             body="pthread_cond_timedwait_monotonic_np(0, 0, 0);",
3316             # -Werror to catch any "implicit declaration" warning that means the function
3317             # is not supported.
3318             flags=["-Werror=implicit-function-declaration"],
3319             check_msg="for pthread_cond_timedwait_monotonic_np",
3320         ),
3321     )
3324 # Custom dynamic linker for Android
3325 # ==============================================================
3326 with only_when(target_has_linux_kernel & compile_environment):
3327     option(
3328         env="MOZ_LINKER",
3329         default=depends(target.os, when="--enable-jemalloc")(
3330             lambda os: os == "Android"
3331         ),
3332         help="{Enable|Disable} custom dynamic linker",
3333     )
3335     set_config("MOZ_LINKER", True, when="MOZ_LINKER")
3336     set_define("MOZ_LINKER", True, when="MOZ_LINKER")
3337     add_old_configure_assignment("MOZ_LINKER", True, when="MOZ_LINKER")
3339     moz_linker = depends(when="MOZ_LINKER")(lambda: True)
3342 # 32-bits ethtool_cmd.speed
3343 # ==============================================================
3344 with only_when(target_has_linux_kernel & compile_environment):
3345     set_config(
3346         "MOZ_WEBRTC_HAVE_ETHTOOL_SPEED_HI",
3347         c_compiler.try_compile(
3348             includes=["linux/ethtool.h"],
3349             body="struct ethtool_cmd cmd; cmd.speed_hi = 0;",
3350             check_msg="for 32-bits ethtool_cmd.speed",
3351         ),
3352     )
3354 # Gamepad support
3355 # ==============================================================
3356 check_header(
3357     "linux/joystick.h",
3358     onerror=lambda: die(
3359         "Can't find header linux/joystick.h, needed for gamepad support."
3360         " Please install Linux kernel headers."
3361     ),
3362     when=target_has_linux_kernel & compile_environment,
3366 # Smart card support
3367 # ==============================================================
3368 @depends(build_project)
3369 def disable_smart_cards(build_project):
3370     return build_project == "mobile/android"
3373 set_config("MOZ_NO_SMART_CARDS", True, when=disable_smart_cards)
3374 set_define("MOZ_NO_SMART_CARDS", True, when=disable_smart_cards)
3376 # Enable UniFFI fixtures
3377 # ==============================================================
3378 # These are used to test the uniffi-bindgen-gecko-js code generation.  They
3379 # should not be enabled in release builds.
3381 option(
3382     "--enable-uniffi-fixtures",
3383     help="Enable UniFFI Fixtures/Examples",
3386 set_config("MOZ_UNIFFI_FIXTURES", True, when="--enable-uniffi-fixtures")
3388 # System policies
3389 # ==============================================================
3391 option(
3392     "--disable-system-policies",
3393     help="Disable reading policies from Windows registry, macOS's file system attributes, and /etc/firefox",
3396 set_config("MOZ_SYSTEM_POLICIES", True, when="--enable-system-policies")
3398 # Allow disabling the creation a legacy profile
3399 # ==============================================================
3401 option(
3402     "--disable-legacy-profile-creation",
3403     help="Disable the creation a legacy profile, to be used by old versions "
3404     "of Firefox, when no profiles exist.",
3407 set_config("MOZ_CREATE_LEGACY_PROFILE", True, when="--enable-legacy-profile-creation")
3410 # STL wrapping
3411 # ==============================================================
3412 set_config("WRAP_STL_INCLUDES", True)
3413 set_config(
3414     "STL_FLAGS",
3415     depends(build_environment.dist)(lambda dist: [f"-I{dist}/stl_wrappers"]),
3419 # Perl detection
3420 # ==============================================================
3421 @depends(target)
3422 def need_perl(target):
3423     # Ideally, we'd also depend on gnu_as here, but that adds complications.
3424     return target.cpu == "arm"
3427 perl = check_prog("PERL", ("perl5", "perl"), when=need_perl)
3430 @template
3431 def perl_version_check(min_version):
3432     @depends(perl)
3433     @checking("for minimum required perl version >= %s" % min_version)
3434     def get_perl_version(perl):
3435         return Version(
3436             check_cmd_output(
3437                 perl,
3438                 "-e",
3439                 "print $]",
3440                 onerror=lambda: die("Failed to get perl version."),
3441             )
3442         )
3444     @depends(get_perl_version)
3445     def check_perl_version(version):
3446         if version < min_version:
3447             die("Perl %s or higher is required.", min_version)
3449     @depends(perl)
3450     @checking("for full perl installation")
3451     @imports("subprocess")
3452     def has_full_perl_installation(perl):
3453         ret = subprocess.call([perl, "-e", "use Config; exit(!-d $Config{archlib})"])
3454         return ret == 0
3456     @depends(has_full_perl_installation)
3457     def require_full_perl_installation(has_full_perl_installation):
3458         if not has_full_perl_installation:
3459             die(
3460                 "Cannot find Config.pm or $Config{archlib}. "
3461                 "A full perl installation is required."
3462             )
3465 with only_when(need_perl):
3466     perl_version_check("5.006")