Bug 1942239 - Add option to explicitly enable incremental origin initialization in...
[gecko.git] / toolkit / moz.configure
blob5873dbec0a6d264afbbd6a28e5d1c14f9de06bf1
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/.
7 # App-specific project settings
10 project_flag(
11     env="MOZ_APP_ID",
12     nargs=1,
13     help='Used for application.ini\'s "ID" field, and crash reporter server url',
17 @depends("MOZ_APP_ID", build_project)
18 def check_moz_app_id(moz_app_id, build_project):
19     if not moz_app_id:
20         die(f"No value for MOZ_APP_ID in project '{build_project}'")
23 project_flag(
24     env="MOZ_APP_VENDOR",
25     nargs=1,
26     help='Used for application.ini\'s "Vendor" field, which also impacts profile location and user-visible fields',
29 project_flag(
30     env="MOZ_APP_UA_NAME",
31     default="",
32     nargs=1,
33     help="Application name in the User Agent string",
36 project_flag(
37     env="MOZ_DEVTOOLS",
38     default="server",
39     choices=("all", "server"),
40     nargs=1,
41     help="Which devtools version should be built",
45 option(
46     env="MOZ_STUB_INSTALLER",
47     help="Produce a stub installer",
49 set_config("MOZ_STUB_INSTALLER", True, when="MOZ_STUB_INSTALLER")
52 project_flag(
53     env="MOZ_PROFILE_MIGRATOR",
54     help="Enable profile migrator",
57 project_flag(
58     env="BROWSER_CHROME_URL",
59     default="",
60     nargs=1,
61     set_as_define=True,
62     help="Markup for a single browser window",
64 set_define(
65     "BROWSER_CHROME_URL_QUOTED",
66     depends("BROWSER_CHROME_URL")(lambda v: f'"{v[0]}"' if v else ""),
69 # External builds (specifically Ubuntu) may drop the hg repo information, so we allow to
70 # explicitly set the repository and changeset information in.
71 option(env="MOZ_SOURCE_REPO", nargs=1, help="Project source repository")
72 set_config("MOZ_SOURCE_REPO", depends_if("MOZ_SOURCE_REPO")(lambda src: src[0]))
73 option(env="MOZ_SOURCE_CHANGESET", nargs=1, help="Source changeset")
74 set_config("MOZ_SOURCE_CHANGESET", depends_if("MOZ_SOURCE_CHANGESET")(lambda v: v[0]))
76 option(
77     env="MOZ_INCLUDE_SOURCE_INFO",
78     # Build revisions should always be present in official builds
79     default=mozilla_official,
80     help="Include build repository informations",
82 set_config("MOZ_INCLUDE_SOURCE_INFO", True, when="MOZ_INCLUDE_SOURCE_INFO")
84 option(
85     "--with-distribution-id",
86     nargs=1,
87     default="org.mozilla",
88     help="Set distribution-specific id",
90 set_config("MOZ_DISTRIBUTION_ID", depends("--with-distribution-id")(lambda v: v[0]))
91 add_old_configure_assignment(
92     "MOZ_DISTRIBUTION_ID", depends("--with-distribution-id")(lambda v: v[0])
96 @depends("MOZ_APP_VENDOR", build_project)
97 def check_moz_app_vendor(moz_app_vendor, build_project):
98     if not moz_app_vendor:
99         die(f"No value for MOZ_APP_VENDOR in project '{build_project}'")
102 # Set the MOZ_CONFIGURE_OPTIONS variable with all the options that
103 # were passed somehow (environment, command line, mozconfig)
104 @dependable
105 @imports(_from="mozbuild.shellutil", _import="quote")
106 @imports(_from="mozbuild.util", _import="ensure_unicode")
107 @imports(_from="mozbuild.util", _import="system_encoding")
108 @imports("__sandbox__")
109 def all_configure_options():
110     result = []
111     previous = None
112     for option in __sandbox__._options.values():
113         # __sandbox__._options contains items for both option.name and
114         # option.env. But it's also an OrderedDict, meaning both are
115         # consecutive.
116         # Also ignore OLD_CONFIGURE and MOZCONFIG because they're not
117         # interesting.
118         if option == previous or option.env in ("OLD_CONFIGURE", "MOZCONFIG"):
119             continue
120         previous = option
121         value = __sandbox__._value_for(option)
122         # We only want options that were explicitly given on the command
123         # line, the environment, or mozconfig, and that differ from the
124         # defaults.
125         if (
126             value is not None
127             and value.origin not in ("default", "implied")
128             and value != option.default
129         ):
130             result.append(
131                 ensure_unicode(__sandbox__._raw_options[option], system_encoding)
132             )
133         # We however always include options that are sent to old configure
134         # because we don't know their actual defaults. (Keep the conditions
135         # separate for ease of understanding and ease of removal)
136         elif (
137             option.help == "Help missing for old configure options"
138             and option in __sandbox__._raw_options
139         ):
140             result.append(
141                 ensure_unicode(__sandbox__._raw_options[option], system_encoding)
142             )
144     # We shouldn't need this, but currently, quote will return a byte string
145     # if result is empty, and that's not wanted here.
146     if not result:
147         return ""
149     return quote(*result)
152 set_config("MOZ_CONFIGURE_OPTIONS", all_configure_options)
155 @depends(target)
156 def fold_libs(target):
157     return target.os in ("WINNT", "OSX", "iOS", "Android")
160 set_config("MOZ_FOLD_LIBS", fold_libs)
162 # Profiling
163 # ==============================================================
164 # Some of the options here imply an option from js/moz.configure,
165 # so, need to be declared before the include.
167 option("--disable-gecko-profiler", help="Disable the Gecko profiler")
170 @depends("--disable-gecko-profiler", target)
171 def gecko_profiler(enable_gecko_profiler, target):
172     if not enable_gecko_profiler:
173         return False
175     if target.os == "Android":
176         return target.cpu in ("aarch64", "arm", "x86", "x86_64")
177     elif target.kernel == "Linux":
178         return target.cpu in ("aarch64", "arm", "x86", "x86_64", "mips64")
179     elif target.kernel == "FreeBSD":
180         return target.cpu in ("aarch64", "x86_64")
181     return target.kernel in ("Darwin", "WINNT")
184 @depends(gecko_profiler)
185 def gecko_profiler_define(value):
186     if value:
187         return True
190 set_config("MOZ_GECKO_PROFILER", gecko_profiler_define)
191 set_define("MOZ_GECKO_PROFILER", gecko_profiler_define)
194 # Enable perfetto on Android if gecko profiling is enabled and only for
195 # nightly builds. Linux support requires at least linux-headers-3.18 for <linux/vm_sockets.h>
196 set_config(
197     "MOZ_PERFETTO", gecko_profiler_define, when=target_is_android & milestone.is_nightly
199 set_define(
200     "MOZ_PERFETTO", gecko_profiler_define, when=target_is_android & milestone.is_nightly
204 # Whether code to parse ELF binaries should be compiled for the Gecko profiler
205 # (for symbol table dumping).
206 @depends(gecko_profiler, target)
207 def gecko_profiler_parse_elf(value, target):
208     # Currently we only want to build this code on Linux (including Android) and BSD.
209     # For Android, this is in order to dump symbols from Android system, where
210     # on other platforms there exist alternatives that don't require bloating
211     # up our binary size. For Linux more generally, we use this in profile
212     # pre-symbolication support, since MozDescribeCodeAddress doesn't do
213     # anything useful on that platform. (Ideally, we would update
214     # MozDescribeCodeAddress to call into some Rust crates that parse ELF and
215     # DWARF data, but build system issues currently prevent Rust from being
216     # used in mozglue.)
217     if value and (target.kernel == "Linux" or target.kernel == "FreeBSD"):
218         return True
221 set_config("MOZ_GECKO_PROFILER_PARSE_ELF", gecko_profiler_parse_elf)
223 # enable this by default if the profiler is enabled
224 # Note: also requires jemalloc
225 set_config("MOZ_PROFILER_MEMORY", gecko_profiler_define)
226 set_define("MOZ_PROFILER_MEMORY", gecko_profiler_define)
229 @depends(
230     "--enable-debug",
231     milestone,
232     build_project,
233     # Artifact builds are included because the downloaded artifacts can
234     # have DMD enabled.
235     when=artifact_builds | depends(when="--enable-replace-malloc")(lambda: True),
237 def dmd_default(debug, milestone, build_project):
238     return bool(build_project == "browser" and (debug or milestone.is_nightly))
241 option(
242     "--enable-dmd",
243     env="MOZ_DMD",
244     default=dmd_default,
245     help="{Enable|Disable} Dark Matter Detector (heap profiler). "
246     "Also enables jemalloc, replace-malloc and profiling",
250 @depends("--enable-dmd")
251 def dmd(value):
252     if value:
253         return True
256 set_config("MOZ_DMD", dmd)
257 set_define("MOZ_DMD", dmd)
258 imply_option("--enable-profiling", dmd)
259 imply_option("--enable-jemalloc", dmd, when=compile_environment)
260 imply_option("--enable-replace-malloc", dmd, when=compile_environment)
263 # midir-based Web MIDI support
264 # ==============================================================
265 @depends(target)
266 def midir_linux_support(target):
267     return (
268         target.kernel == "Linux" and target.os != "Android" and target.cpu != "riscv64"
269     )
272 @depends(target, midir_linux_support)
273 def midir_support(target, midir_linux_support):
274     if target.os in ("WINNT", "OSX") or midir_linux_support:
275         return True
278 set_config("MOZ_WEBMIDI_MIDIR_IMPL", midir_support)
281 # Enable various cubeb backends
282 # ==============================================================
283 @depends(target)
284 def audio_backends_default(target):
285     if target.os == "Android":
286         return (
287             "aaudio",
288             "opensl",
289         )
290     elif target.os in ("DragonFly", "FreeBSD", "SunOS"):
291         return ("oss",)
292     elif target.os == "OpenBSD":
293         return ("sndio",)
294     elif target.kernel == "Darwin":
295         return ("audiounit",)
296     elif target.os == "NetBSD":
297         return ("sunaudio",)
298     elif target.os == "SunOS":
299         return ("sunaudio",)
300     elif target.os == "WINNT":
301         return ("wasapi",)
302     else:
303         return ("pulseaudio",)
306 option(
307     "--enable-audio-backends",
308     nargs="+",
309     choices=(
310         "aaudio",
311         "alsa",
312         "audiounit",
313         "jack",
314         "opensl",
315         "oss",
316         "pulseaudio",
317         "sndio",
318         "sunaudio",
319         "wasapi",
320     ),
321     default=audio_backends_default,
322     help="{Enable|Disable} various cubeb backends",
326 @depends("--enable-audio-backends", target)
327 def imply_aaudio(values, target):
328     if any("aaudio" in value for value in values) and target.os != "Android":
329         die("Cannot enable AAudio on %s", target.os)
330     return any("aaudio" in value for value in values) or None
333 @depends("--enable-audio-backends", target)
334 def imply_alsa(values, target):
335     if (
336         any("alsa" in value for value in values)
337         and target.kernel != "Linux"
338         and target.os != "FreeBSD"
339     ):
340         die("Cannot enable ALSA on %s", target.os)
341     return any("alsa" in value for value in values) or None
344 @depends("--enable-audio-backends", target)
345 def imply_audiounit(values, target):
346     if any("audiounit" in value for value in values) and target.kernel != "Darwin":
347         die("Cannot enable AudioUnit on %s", target.os)
348     return any("audiounit" in value for value in values) or None
351 @depends("--enable-audio-backends")
352 def imply_jack(values):
353     return any("jack" in value for value in values) or None
356 @depends("--enable-audio-backends", target)
357 def imply_opensl(values, target):
358     if any("opensl" in value for value in values) and target.os != "Android":
359         die("Cannot enable OpenSL on %s", target.os)
360     return any("opensl" in value for value in values) or None
363 @depends("--enable-audio-backends", target)
364 def imply_oss(values, target):
365     if any("oss" in value for value in values) and (
366         target.os in ("Android", "OSX", "iOS", "WINNT")
367     ):
368         die("Cannot enable OSS on %s", target.os)
369     return any("oss" in value for value in values) or None
372 @depends("--enable-audio-backends", target)
373 def imply_pulseaudio(values, target):
374     if any("pulseaudio" in value for value in values) and (
375         target.os in ("Android", "OSX", "iOS", "WINNT")
376     ):
377         die("Cannot enable PulseAudio on %s", target.os)
378     return any("pulseaudio" in value for value in values) or None
381 @depends("--enable-audio-backends", target)
382 def imply_sndio(values, target):
383     if any("sndio" in value for value in values) and (
384         target.os in ("Android", "OSX", "iOS", "WINNT")
385     ):
386         die("Cannot enable sndio on %s", target.os)
387     return any("sndio" in value for value in values) or None
390 @depends("--enable-audio-backends", target)
391 def imply_sunaudio(values, target):
392     if any("sunaudio" in value for value in values) and (
393         target.os != "NetBSD" and target.os != "SunOS"
394     ):
395         die("Cannot enable sunaudio on %s", target.os)
396     return any("sunaudio" in value for value in values) or None
399 @depends("--enable-audio-backends", target)
400 def imply_wasapi(values, target):
401     if any("wasapi" in value for value in values) and target.os != "WINNT":
402         die("Cannot enable WASAPI on %s", target.os)
403     return any("wasapi" in value for value in values) or None
406 set_config("MOZ_AAUDIO", imply_aaudio, when="--enable-audio-backends")
408 imply_option(
409     "--enable-alsa", imply_alsa, reason="--enable-audio-backends", when=use_pkg_config
412 set_config("MOZ_AUDIOUNIT_RUST", imply_audiounit, when="--enable-audio-backends")
414 imply_option(
415     "--enable-jack", imply_jack, reason="--enable-audio-backends", when=use_pkg_config
418 set_config("MOZ_OPENSL", imply_opensl, when="--enable-audio-backends")
420 set_config("MOZ_OSS", imply_oss, when="--enable-audio-backends")
422 imply_option(
423     "--enable-pulseaudio",
424     imply_pulseaudio,
425     reason="--enable-audio-backends",
426     when=use_pkg_config,
429 imply_option(
430     "--enable-sndio", imply_sndio, reason="--enable-audio-backends", when=use_pkg_config
433 set_config("MOZ_SUNAUDIO", imply_sunaudio, when="--enable-audio-backends")
435 set_config("MOZ_WASAPI", imply_wasapi, when="--enable-audio-backends")
437 # ALSA cubeb backend
438 # ==============================================================
439 option(
440     "--enable-alsa",
441     env="MOZ_ALSA",
442     help="Enable ALSA audio backend",
443     when=use_pkg_config,
447 @depends("--enable-alsa", when=use_pkg_config)
448 def enable_alsa_option(enable_alsa):
449     return enable_alsa
452 @depends(enable_alsa_option, midir_linux_support)
453 def enable_alsa_or_midir_linux_support(alsa_enabled, midir_linux_support):
454     return alsa_enabled or midir_linux_support
457 pkg_check_modules("MOZ_ALSA", "alsa", when=enable_alsa_or_midir_linux_support)
459 set_config("MOZ_ALSA", True, when="--enable-alsa")
460 set_define("MOZ_ALSA", True, when="--enable-alsa")
462 # JACK cubeb backend
463 # ==============================================================
464 system_lib_option(
465     "--enable-jack",
466     env="MOZ_JACK",
467     help="Enable JACK audio backend",
468     when=use_pkg_config,
471 jack = pkg_check_modules("MOZ_JACK", "jack", when="--enable-jack")
473 set_config("MOZ_JACK", depends_if(jack)(lambda _: True))
475 # PulseAudio cubeb backend
476 # ==============================================================
477 option(
478     "--enable-pulseaudio",
479     env="MOZ_PULSEAUDIO",
480     help="{Enable|Disable} PulseAudio audio backend",
481     when=use_pkg_config,
484 pulseaudio = pkg_check_modules("MOZ_PULSEAUDIO", "libpulse", when="--enable-pulseaudio")
486 set_config("MOZ_PULSEAUDIO", depends_if(pulseaudio)(lambda _: True))
487 set_define("MOZ_PULSEAUDIO", depends_if(pulseaudio)(lambda _: True))
489 # sndio cubeb backend
490 # ==============================================================
491 system_lib_option(
492     "--enable-sndio",
493     env="MOZ_SNDIO",
494     help="Enable sndio audio backend",
495     when=use_pkg_config,
498 sndio = pkg_check_modules("MOZ_SNDIO", "sndio", when="--enable-sndio")
500 set_config("MOZ_SNDIO", depends_if(sndio)(lambda _: True))
502 # Javascript engine
503 # ==============================================================
504 include("../js/moz.configure")
507 # NodeJS
508 # ==============================================================
509 include("../build/moz.configure/node.configure")
511 # JsonCpp
512 # ==============================================================
513 set_define("JSON_USE_EXCEPTION", 0)
515 # L10N
516 # ==============================================================
517 option("--with-l10n-base", nargs=1, env="L10NBASEDIR", help="Path to l10n repositories")
520 @depends("--with-l10n-base", "MOZ_AUTOMATION", build_environment)
521 @imports(_from="os.path", _import="isdir")
522 @imports(_from="os.path", _import="expanduser")
523 @imports(_from="os", _import="environ")
524 def l10n_base(value, automation, build_env):
525     if value:
526         path = value[0]
527         if not isdir(path):
528             die("Invalid value --with-l10n-base, %s doesn't exist", path)
529     elif automation:
530         path = os.path.join(build_env.topsrcdir, "../l10n-central")
531     else:
532         path = os.path.join(
533             environ.get(
534                 "MOZBUILD_STATE_PATH", expanduser(os.path.join("~", ".mozbuild"))
535             ),
536             "l10n-central",
537         )
538     return os.path.realpath(os.path.abspath(path))
541 set_config("L10NBASEDIR", l10n_base)
544 # Default toolkit
545 # ==============================================================
546 @depends(target)
547 def toolkit_choices(target):
548     if target.os == "WINNT":
549         return ("cairo-windows",)
550     elif target.os == "OSX":
551         return ("cairo-cocoa",)
552     elif target.os == "iOS":
553         return ("cairo-uikit",)
554     elif target.os == "Android":
555         return ("cairo-android",)
556     else:
557         # cairo-gtk3 - X11 backend with optional Wayland backend (auto detected)
558         # cairo-gtk3-wayland - Wayland backend with optional X11 backend (auto detected)
559         # cairo-gtk3-x11-wayland - builds explicitly with X11 & Wayland backends
560         return (
561             "cairo-gtk3",
562             "cairo-gtk3-wayland",
563             "cairo-gtk3-x11-wayland",
564             "cairo-gtk3-wayland-only",
565             "cairo-gtk3-x11-only",
566         )
569 @depends(toolkit_choices)
570 def toolkit_default(choices):
571     return choices[0]
574 option(
575     "--enable-default-toolkit",
576     nargs=1,
577     choices=toolkit_choices,
578     default=toolkit_default,
579     help="Select default toolkit",
583 @depends("--enable-default-toolkit")
584 def full_toolkit(value):
585     if value:
586         return value[0]
589 @depends(full_toolkit)
590 def toolkit(toolkit):
591     if toolkit.startswith("cairo-gtk3"):
592         widget_toolkit = "gtk"
593     else:
594         widget_toolkit = toolkit.replace("cairo-", "")
595     return widget_toolkit
598 set_config("MOZ_WIDGET_TOOLKIT", toolkit)
601 @depends(toolkit)
602 def toolkit_define(toolkit):
603     if toolkit != "windows":
604         return "MOZ_WIDGET_%s" % toolkit.upper()
607 set_define(toolkit_define, True)
610 @depends(toolkit)
611 def toolkit_gtk(toolkit):
612     return toolkit == "gtk"
615 @depends(toolkit_gtk, full_toolkit)
616 def toolkit_gtk_x11(toolkit_gtk, full_toolkit):
617     return toolkit_gtk and full_toolkit != "cairo-gtk3-wayland-only"
620 @depends(full_toolkit)
621 def toolkit_gtk_x11_optional(full_toolkit):
622     return full_toolkit == "cairo-gtk3-wayland"
625 @depends(toolkit_gtk, full_toolkit)
626 def toolkit_gtk_wayland(toolkit_gtk, full_toolkit):
627     return toolkit_gtk and full_toolkit != "cairo-gtk3-x11-only"
630 @depends(full_toolkit)
631 def toolkit_gtk_wayland_optional(full_toolkit):
632     return full_toolkit == "cairo-gtk3"
635 # Wayland support
636 # ==============================================================
637 wayland_headers = pkg_check_modules(
638     "MOZ_WAYLAND",
639     "gtk+-wayland-3.0 >= 3.14 xkbcommon >= 0.4.1",
640     allow_missing=toolkit_gtk_wayland_optional,
641     when=toolkit_gtk_wayland,
645 @depends(wayland_headers, toolkit_gtk, artifact_builds, toolkit_gtk_wayland)
646 def wayland_headers(wayland, toolkit_gtk, artifacts, toolkit_gtk_wayland):
647     if not toolkit_gtk_wayland:
648         return False
649     if toolkit_gtk and artifacts:
650         return True
651     return wayland
654 set_config("MOZ_WAYLAND", depends_if(wayland_headers)(lambda _: True))
655 set_define("MOZ_WAYLAND", depends_if(wayland_headers)(lambda _: True))
658 # Hardware-accelerated video decode with VAAPI and V4L2 on Linux
659 # ==============================================================
660 set_config("MOZ_ENABLE_VAAPI", True, when=toolkit_gtk)
661 set_define("MOZ_ENABLE_VAAPI", True, when=toolkit_gtk)
664 @depends(target, toolkit_gtk)
665 def v4l2(target, toolkit_gtk):
666     # V4L2 decode is only used in GTK/Linux and generally only appears on
667     # embedded SOCs.
668     if target.cpu in ("arm", "aarch64", "riscv64") and toolkit_gtk:
669         return True
672 set_config("MOZ_ENABLE_V4L2", True, when=v4l2)
673 set_define("MOZ_ENABLE_V4L2", True, when=v4l2)
675 # GL Provider
676 # ==============================================================
677 option("--with-gl-provider", nargs=1, help="Set GL provider backend type")
680 @depends("--with-gl-provider")
681 def gl_provider(value):
682     if value:
683         return value[0]
686 @depends(gl_provider)
687 def gl_provider_define(provider):
688     if provider:
689         return "GLContextProvider%s" % provider
692 set_define("MOZ_GL_PROVIDER", gl_provider_define)
695 @depends(gl_provider, toolkit_gtk)
696 def gl_default_provider(value, toolkit_gtk):
697     if value:
698         return value
699     elif toolkit_gtk:
700         return "EGL"
703 set_config("MOZ_GL_PROVIDER", gl_provider)
704 set_config("MOZ_GL_DEFAULT_PROVIDER", gl_default_provider)
707 @depends(gl_default_provider)
708 def gl_provider_define(provider):
709     if provider:
710         return "GL_PROVIDER_%s" % provider
713 set_define(gl_provider_define, True)
716 # PDF printing
717 # ==============================================================
718 @depends(toolkit)
719 def pdf_printing(toolkit):
720     if toolkit in ("windows", "gtk", "android"):
721         return True
724 set_config("MOZ_PDF_PRINTING", pdf_printing)
725 set_define("MOZ_PDF_PRINTING", pdf_printing)
727 # Fontconfig Freetype
728 # ==============================================================
729 option(env="USE_FC_FREETYPE", help="Force-enable the use of fontconfig freetype")
732 @depends("USE_FC_FREETYPE", toolkit)
733 def fc_freetype(value, toolkit):
734     if value or (toolkit == "gtk" and value.origin == "default"):
735         return True
738 set_define("USE_FC_FREETYPE", fc_freetype)
740 # Pango
741 # ==============================================================
742 pkg_check_modules("MOZ_PANGO", "pango >= 1.22.0", when=toolkit_gtk)
744 # Fontconfig
745 # ==============================================================
746 fontconfig_info = pkg_check_modules(
747     "_FONTCONFIG", "fontconfig >= 2.7.0", when=fc_freetype
751 @depends(fc_freetype)
752 def check_for_freetype2(fc_freetype):
753     if fc_freetype:
754         return True
757 # Check for freetype2. Flags are combined with fontconfig flags.
758 freetype2_info = pkg_check_modules(
759     "_FT2", "freetype2 >= 9.10.3", when=check_for_freetype2
763 @depends(fontconfig_info, freetype2_info)
764 def freetype2_combined_info(fontconfig_info, freetype2_info):
765     if not freetype2_info:
766         return
767     if not fontconfig_info:
768         return freetype2_info
769     return namespace(
770         cflags=freetype2_info.cflags + fontconfig_info.cflags,
771         libs=freetype2_info.libs + fontconfig_info.libs,
772     )
775 set_define("MOZ_HAVE_FREETYPE2", depends_if(freetype2_info)(lambda _: True))
778 # Apple platform decoder support
779 # ==============================================================
780 @depends(toolkit)
781 def applemedia(toolkit):
782     if toolkit in ("cocoa", "uikit"):
783         return True
786 set_config("MOZ_APPLEMEDIA", applemedia)
787 set_define("MOZ_APPLEMEDIA", applemedia)
789 # Windows Media Foundation support
790 # ==============================================================
791 option("--disable-wmf", help="Disable support for Windows Media Foundation")
794 @depends("--disable-wmf", target, "--help")
795 def wmf(value, target, _):
796     enabled = bool(value)
797     if value.origin == "default":
798         # Enable Windows Media Foundation support by default.
799         # Note our minimum SDK version is Windows 7 SDK, so we are (currently)
800         # guaranteed to have a recent-enough SDK to build WMF.
801         enabled = target.os == "WINNT"
802     if enabled and target.os != "WINNT":
803         die("Cannot enable Windows Media Foundation support on %s", target.os)
804     if enabled:
805         return True
808 @depends(artifact_builds, c_compiler, when=wmf)
809 def wmfmediaengine(artifact_builds, c_compiler):
810     if c_compiler:
811         return c_compiler.type == "clang-cl"
812     return bool(artifact_builds)
815 set_config("MOZ_WMF", wmf)
816 set_define("MOZ_WMF", wmf)
818 set_config("MOZ_WMF_MEDIA_ENGINE", True, when=wmfmediaengine)
819 set_define("MOZ_WMF_MEDIA_ENGINE", True, when=wmfmediaengine)
821 # FFmpeg H264/AAC Decoding Support
822 # ==============================================================
823 option("--disable-ffmpeg", help="Disable FFmpeg for fragmented H264/AAC decoding")
826 @depends("--disable-ffmpeg", target)
827 def ffmpeg(value, target):
828     enabled = bool(value)
829     if value.origin == "default":
830         enabled = target.os not in ("Android", "WINNT")
831     if enabled:
832         return True
835 set_config("MOZ_FFMPEG", ffmpeg)
836 set_define("MOZ_FFMPEG", ffmpeg)
838 # AV1 Video Codec Support
839 # ==============================================================
840 option("--disable-av1", help="Disable av1 video support")
843 @depends("--enable-av1")
844 def av1(value):
845     if value:
846         return True
849 option("--with-system-av1", help="Use system av1 (located with pkg-config)")
851 pkg_check_modules("MOZ_SYSTEM_LIBAOM", "aom >= 3.0.0", when="--with-system-av1")
852 pkg_check_modules("MOZ_SYSTEM_LIBDAV1D", "dav1d >= 1.2.1", when="--with-system-av1")
855 @depends(target, "--with-system-av1", when=av1 & compile_environment)
856 def dav1d_asm(target, system_av1):
857     if not system_av1 and target.cpu in ("arm", "aarch64", "x86", "x86_64"):
858         return True
861 @depends(target, "--with-system-av1", when=av1 & compile_environment)
862 def dav1d_nasm(target, system_av1):
863     if not system_av1 and target.cpu in ("x86", "x86_64"):
864         return namespace(version="2.14", what="AV1")
867 set_config("MOZ_DAV1D_ASM", dav1d_asm)
868 set_define("MOZ_DAV1D_ASM", dav1d_asm)
869 set_config("MOZ_AV1", av1)
870 set_define("MOZ_AV1", av1)
871 set_config("MOZ_SYSTEM_AV1", True, when="--with-system-av1")
873 # JXL Image Codec Support
874 # ==============================================================
875 option("--disable-jxl", help="Disable jxl image support")
878 @depends("--disable-jxl", milestone.is_nightly)
879 def jxl(value, is_nightly):
880     if is_nightly and value:
881         return True
884 set_config("MOZ_JXL", jxl)
885 set_define("MOZ_JXL", jxl)
887 set_config("MOZ_SAMPLE_TYPE_FLOAT32", True)
888 set_define("MOZ_SAMPLE_TYPE_FLOAT32", True)
890 set_config("MOZ_VORBIS", True)
892 option(
893     "--disable-real-time-tracing",
894     help="Disable tracing of real-time audio callbacks",
897 set_config("MOZ_REAL_TIME_TRACING", True, when="--enable-real-time-tracing")
898 set_define("MOZ_REAL_TIME_TRACING", True, when="--enable-real-time-tracing")
900 # OpenMAX IL Decoding Support
901 # ==============================================================
902 option("--enable-openmax", help="Enable OpenMAX IL for video/audio decoding")
905 @depends("--enable-openmax")
906 def openmax(value):
907     enabled = bool(value)
908     if enabled:
909         return True
912 set_config("MOZ_OMX", openmax)
913 set_define("MOZ_OMX", openmax)
916 # EME Support
917 # ==============================================================
918 @depends(target, wmf)
919 def eme_choices(target, wmf):
920     if (
921         target.kernel in ("WINNT", "Linux")
922         and target.os != "Android"
923         and target.cpu in ("x86", "x86_64")
924     ):
925         if wmf:
926             return ("widevine", "wmfcdm")
927         return ("widevine",)
928     if target.kernel == "WINNT" and target.cpu == "aarch64":
929         return ("widevine",)
930     if target.os in ("OSX"):
931         return ("widevine",)
934 # Widevine is enabled by default in desktop browser builds.
935 @depends(build_project, eme_choices)
936 def eme_default(build_project, choices):
937     if build_project == "browser":
938         return choices
941 option(
942     "--enable-eme",
943     nargs="+",
944     choices=eme_choices,
945     default=eme_default,
946     when=eme_choices,
947     help="{Enable|Disable} support for Encrypted Media Extensions",
951 @depends("--enable-eme", when=eme_choices)
952 def eme_modules(value):
953     return value
956 # Fallback to an empty list when eme_choices is empty, setting eme_modules to
957 # None.
958 set_config("MOZ_EME_MODULES", eme_modules | dependable([]))
961 # Media Foundation CDM support
962 # ==============================================================
963 @depends(eme_modules, when=wmfmediaengine)
964 def wmfcdm(modules):
965     if "wmfcdm" in modules:
966         return True
969 set_config("MOZ_WMF_CDM", True, when=wmfcdm)
970 set_define("MOZ_WMF_CDM", True, when=wmfcdm)
973 option(
974     name="--enable-chrome-format",
975     help="Select FORMAT of chrome files during packaging",
976     nargs=1,
977     choices=("omni", "jar", "flat"),
978     default="omni",
982 @depends("--enable-chrome-format")
983 def packager_format(value):
984     return value[0]
987 set_config("MOZ_PACKAGER_FORMAT", packager_format)
989 # The packager minifies two different types of files: non-JS (mostly property
990 # files for l10n), and JS.  Setting MOZ_PACKAGER_MINIFY only minifies the
991 # former.  Firefox doesn't yet minify JS, due to concerns about debuggability.
993 # Also, the JS minification setup really only works correctly on Android:
994 # we need extra setup to use the newly-built shell for Linux and Windows,
995 # and cross-compilation for macOS requires some extra care.
998 @depends(target_is_android, "--enable-debug", milestone.is_nightly)
999 def enable_minify_default(is_android, debug, is_nightly):
1000     if is_android and not debug and not is_nightly:
1001         return ("properties", "js")
1002     return ("properties",)
1005 option(
1006     name="--enable-minify",
1007     help="Select types of files to minify during packaging",
1008     nargs="*",
1009     choices=("properties", "js"),
1010     default=enable_minify_default,
1014 @depends("--enable-minify")
1015 def enable_minify(value):
1016     if "js" in value and "properties" not in value:
1017         die("--enable-minify=js requires --enable-minify=properties.")
1018     return namespace(
1019         properties="properties" in value,
1020         js="js" in value,
1021     )
1024 set_config("MOZ_PACKAGER_MINIFY", True, when=enable_minify.properties)
1025 set_config("MOZ_PACKAGER_MINIFY_JS", True, when=enable_minify.js)
1028 @depends(host, build_project)
1029 def jar_maker_format(host, build_project):
1030     # Multilocales for mobile/android use the same mergedirs for all locales,
1031     # so we can't use symlinks for those builds.
1032     if host.os == "WINNT" or build_project == "mobile/android":
1033         return "flat"
1034     return "symlink"
1037 set_config("MOZ_JAR_MAKER_FILE_FORMAT", jar_maker_format)
1040 @depends(toolkit)
1041 def omnijar_name(toolkit):
1042     # Fennec's static resources live in the assets/ folder of the
1043     # APK.  Adding a path to the name here works because we only
1044     # have one omnijar file in the final package (which is not the
1045     # case on desktop).
1046     return "assets/omni.ja" if toolkit == "android" else "omni.ja"
1049 set_config("OMNIJAR_NAME", omnijar_name)
1051 project_flag("MOZ_PLACES", help="Build Places if required", set_as_define=True)
1053 project_flag(
1054     "MOZ_SERVICES_HEALTHREPORT",
1055     help="Build Firefox Health Reporter Service",
1056     set_as_define=True,
1059 project_flag(
1060     "MOZ_NORMANDY",
1061     help="Enable Normandy recipe runner",
1062     set_as_define=True,
1065 project_flag("MOZ_SERVICES_SYNC", help="Build Sync Services if required")
1067 project_flag(
1068     "MOZ_GECKOVIEW_HISTORY",
1069     help="Enable Geckoview History instead of Places",
1070     set_as_define=True,
1074 # Child Process Name for IPC
1075 # ==============================================================
1076 @depends(toolkit, bin_suffix(target))
1077 def moz_child_process_name(toolkit, bin_suffix):
1078     if toolkit != "android":
1079         return f"plugin-container{bin_suffix}"
1080     else:
1081         # We want to let Android unpack the file at install time, but it only
1082         # does so if the file is named libsomething.so. The lib/ path is also
1083         # required because the unpacked file will be under the lib/ subdirectory
1084         # and will need to be executed from that path.
1085         return "libplugin-container.so"
1088 set_config("MOZ_CHILD_PROCESS_NAME", moz_child_process_name)
1090 with only_when(target_is_osx):
1091     set_config("MOZ_CHILD_PROCESS_BUNDLE", "plugin-container.app/Contents/MacOS/")
1092     set_config(
1093         "MOZ_CHILD_PROCESS_BUNDLEID",
1094         depends("--with-distribution-id")(lambda v: f"{v[0]}.plugincontainer"),
1095     )
1096     set_config("MOZ_CHILD_PROCESS_BUNDLENAME", "plugin-container.app")
1098 # Profile Management
1099 # ==============================================================
1100 # Selectable profiles are enabled by default.
1102 set_define("MOZ_SELECTABLE_PROFILES", True)
1103 set_config("MOZ_SELECTABLE_PROFILES", True)
1105 project_flag(
1106     "MOZ_DEDICATED_PROFILES",
1107     help="Enable dedicated profiles per install",
1108     set_as_define=True,
1111 project_flag(
1112     "MOZ_BLOCK_PROFILE_DOWNGRADE",
1113     help="Block users from starting profiles last used by a newer build",
1114     set_as_define=True,
1118 @depends("MOZ_PLACES", "MOZ_GECKOVIEW_HISTORY")
1119 def check_places_and_geckoview_history(places, geckoview_history):
1120     if places and geckoview_history:
1121         die("Cannot use MOZ_GECKOVIEW_HISTORY alongside MOZ_PLACES.")
1122     if not places and not geckoview_history:
1123         die("One of MOZ_GECKOVIEW_HISTORY or MOZ_PLACES must be set.")
1126 option(
1127     env="MOZ_TELEMETRY_REPORTING",
1128     default=mozilla_official,
1129     help="Enable telemetry reporting",
1132 set_define("MOZ_TELEMETRY_REPORTING", True, when="MOZ_TELEMETRY_REPORTING")
1135 @depends("MOZ_TELEMETRY_REPORTING", milestone.is_nightly)
1136 def telemetry_on_by_default(reporting, is_nightly):
1137     return reporting and is_nightly
1140 set_define("MOZ_TELEMETRY_ON_BY_DEFAULT", True, when=telemetry_on_by_default)
1142 # Miscellaneous programs
1143 # ==============================================================
1145 check_prog("TAR", ("gnutar", "gtar", "tar"))
1146 check_prog("UNZIP", ("unzip",))
1148 # Key files
1149 # ==============================================================
1150 include("../build/moz.configure/keyfiles.configure")
1152 simple_keyfile("Mozilla API")
1154 simple_keyfile("Google Location Service API")
1156 simple_keyfile("Google Safebrowsing API")
1158 id_and_secret_keyfile("Bing API")
1160 simple_keyfile("Adjust SDK")
1162 id_and_secret_keyfile("Leanplum SDK")
1164 simple_keyfile("Pocket API")
1167 # WebRender Debugger integration
1168 # ==============================================================
1170 option(
1171     "--enable-webrender-debugger", help="Build the websocket debug server in WebRender"
1174 set_config(
1175     "MOZ_WEBRENDER_DEBUGGER", depends_if("--enable-webrender-debugger")(lambda _: True)
1178 # Additional system headers defined at the application level
1179 # ==============================================================
1181 option(
1182     "--enable-app-system-headers",
1183     env="MOZ_APP_SYSTEM_HEADERS",
1184     help="Use additional system headers defined in $MOZ_BUILD_APP/app-system-headers.mozbuild",
1188 @depends("--enable-app-system-headers")
1189 def app_system_headers(value):
1190     if value:
1191         return True
1194 set_config("MOZ_APP_SYSTEM_HEADERS", app_system_headers)
1197 # Printing
1198 # ==============================================================
1199 @depends(target)
1200 def printing_default(target):
1201     return target.os != "iOS"
1204 option(
1205     "--disable-printing",
1206     default=printing_default,
1207     help="{Enable|Disable} printing support",
1211 @depends("--disable-printing")
1212 def printing(value):
1213     if value:
1214         return True
1217 set_config("NS_PRINTING", printing)
1218 set_define("NS_PRINTING", printing)
1219 set_define("NS_PRINT_PREVIEW", printing)
1222 # Speech-dispatcher support
1223 # ==============================================================
1224 @depends(toolkit)
1225 def no_speechd_on_non_gtk(toolkit):
1226     if toolkit != "gtk":
1227         return False
1230 imply_option(
1231     "--enable-synth-speechd", no_speechd_on_non_gtk, reason="--enable-default-toolkit"
1234 option("--disable-synth-speechd", help="Disable speech-dispatcher support")
1236 set_config("MOZ_SYNTH_SPEECHD", depends_if("--disable-synth-speechd")(lambda _: True))
1238 # Speech API
1239 # ==============================================================
1240 option("--disable-webspeech", help="Disable support for HTML Speech API")
1243 @depends("--disable-webspeech")
1244 def webspeech(value):
1245     if value:
1246         return True
1249 set_config("MOZ_WEBSPEECH", webspeech)
1250 set_define("MOZ_WEBSPEECH", webspeech)
1252 # Speech API test backend
1253 # ==============================================================
1254 option(
1255     "--enable-webspeechtestbackend",
1256     default=webspeech,
1257     help="{Enable|Disable} support for HTML Speech API Test Backend",
1261 @depends_if("--enable-webspeechtestbackend")
1262 def webspeech_test_backend(value):
1263     return True
1266 set_config("MOZ_WEBSPEECH_TEST_BACKEND", webspeech_test_backend)
1267 set_define("MOZ_WEBSPEECH_TEST_BACKEND", webspeech_test_backend)
1270 # Graphics
1271 # ==============================================================
1272 @depends(target, milestone)
1273 def skia_pdf_default(target, milestone):
1274     return milestone.is_nightly and target.os != "WINNT"
1277 option("--enable-skia-pdf", default=skia_pdf_default, help="{Enable|Disable} Skia PDF")
1279 set_config("MOZ_ENABLE_SKIA_PDF", True, when="--enable-skia-pdf")
1280 set_define("MOZ_ENABLE_SKIA_PDF", True, when="--enable-skia-pdf")
1282 set_config(
1283     "SKIA_INCLUDES",
1284     [
1285         "/gfx/skia",
1286         "/gfx/skia/skia",
1287     ],
1290 system_lib_option(
1291     "--with-system-webp",
1292     help="Use system libwebp (located with pkgconfig)",
1293     when=use_pkg_config,
1296 system_webp = pkg_check_modules(
1297     "MOZ_WEBP", "libwebp >= 1.0.2 libwebpdemux >= 1.0.2", when="--with-system-webp"
1300 set_config("MOZ_SYSTEM_WEBP", depends(when=system_webp)(lambda: True))
1303 # Build Freetype in the tree
1304 # ==============================================================
1305 @depends(target, "--enable-skia-pdf")
1306 def tree_freetype(target, skia_pdf):
1307     if target.os == "Android" or (skia_pdf and target.os == "WINNT"):
1308         return True
1311 set_define("MOZ_TREE_FREETYPE", tree_freetype)
1312 set_config("MOZ_TREE_FREETYPE", tree_freetype)
1314 set_define("HAVE_FT_GLYPHSLOT_EMBOLDEN", tree_freetype)
1315 set_define("HAVE_FT_LOAD_SFNT_TABLE", tree_freetype)
1318 @depends(freetype2_combined_info, tree_freetype, build_environment)
1319 def ft2_info(freetype2_combined_info, tree_freetype, build_env):
1320     if tree_freetype:
1321         return namespace(
1322             cflags=("-I%s/modules/freetype2/include" % build_env.topsrcdir,), libs=()
1323         )
1324     if freetype2_combined_info:
1325         return freetype2_combined_info
1328 set_config("FT2_LIBS", ft2_info.libs)
1331 @depends(target, tree_freetype, freetype2_info)
1332 def enable_cairo_ft(target, tree_freetype, freetype2_info):
1333     # Avoid defining MOZ_ENABLE_CAIRO_FT on Windows platforms because
1334     # "cairo-ft-font.c" includes <dlfcn.h>, which only exists on posix platforms
1335     return freetype2_info or (tree_freetype and target.os != "WINNT")
1338 set_config("MOZ_ENABLE_CAIRO_FT", True, when=enable_cairo_ft)
1339 set_config("CAIRO_FT_CFLAGS", ft2_info.cflags, when=enable_cairo_ft)
1342 # WebDriver (HTTP / BiDi)
1343 # ==============================================================
1345 # WebDriver is a remote control interface that enables introspection and
1346 # control of user agents. It provides a platform- and language-neutral wire
1347 # protocol as a way for out-of-process programs to remotely instruct the
1348 # behavior of web browsers.
1350 # The Gecko implementation is backed by Marionette and Remote Agent.
1351 # Both protocols are not really toolkit features, as much as Gecko engine
1352 # features. But they are enabled based on the toolkit, so here it lives.
1354 # Marionette remote protocol
1355 # -----------------------------------------------------------
1357 # Marionette is the Gecko remote protocol used for various remote control,
1358 # automation, and testing purposes throughout Gecko-based applications like
1359 # Firefox, Thunderbird, and any mobile browser built upon GeckoView.
1361 # It also backs ../testing/geckodriver, which is Mozilla's WebDriver
1362 # implementation.
1364 # The source of Marionette lives in ../remote/marionette.
1366 # For more information, see:
1367 # https://firefox-source-docs.mozilla.org/testing/marionette/index.html
1369 # Remote Agent (WebDriver BiDi / partial CDP)
1370 # -----------------------------------------------------------
1372 # The primary purpose is the implementation of the WebDriver BiDi specification.
1373 # But it also complements the existing Firefox Developer Tools Remote Debugging
1374 # Protocol (RDP) by implementing a subset of the Chrome DevTools Protocol (CDP).
1376 # The source of Remote Agent lives in ../remote.
1378 # For more information, see:
1379 # https://firefox-source-docs.mozilla.org/remote/index.html
1382 option(
1383     "--disable-webdriver",
1384     help="Disable support for WebDriver remote protocols",
1388 @depends("--disable-webdriver")
1389 def webdriver(enabled):
1390     if enabled:
1391         return True
1394 set_config("ENABLE_WEBDRIVER", webdriver)
1395 set_define("ENABLE_WEBDRIVER", webdriver)
1398 # geckodriver WebDriver implementation
1399 # ==============================================================
1401 # Turn off geckodriver for build configs we don't handle yet,
1402 # but allow --enable-geckodriver to override when compile environment is available.
1403 # --disable-tests implies disabling geckodriver.
1404 # Disable building in CI
1407 @depends(
1408     "--enable-tests", target, cross_compiling, hazard_analysis, asan, "MOZ_AUTOMATION"
1410 def geckodriver_default(enable_tests, target, cross_compile, hazard, asan, automation):
1411     if not enable_tests:
1412         return False
1413     if hazard or target.os == "Android" or (asan and cross_compile):
1414         return False
1415     if automation:
1416         return False
1417     return True
1420 option(
1421     "--enable-geckodriver",
1422     default=geckodriver_default,
1423     when="--enable-compile-environment",
1424     help="{Build|Do not build} geckodriver",
1428 @depends("--enable-geckodriver", when="--enable-compile-environment")
1429 def geckodriver(enabled):
1430     if enabled:
1431         return True
1434 set_config("MOZ_GECKODRIVER", geckodriver)
1437 # WebRTC
1438 # ========================================================
1439 @depends(target)
1440 def webrtc_default(target):
1441     # Turn off webrtc for OS's we don't handle yet, but allow
1442     # --enable-webrtc to override.
1443     os_match = target.kernel in (
1444         "Linux",
1445         "WINNT",
1446         "DragonFly",
1447         "FreeBSD",
1448         "kFreeBSD",
1449         "NetBSD",
1450         "OpenBSD",
1451     )
1453     if not os_match:
1454         os_match = target.os in ("OSX",)
1456     cpu_match = target.cpu in (
1457         "x86_64",
1458         "arm",
1459         "aarch64",
1460         "x86",
1461         "ia64",
1462         "mips32",
1463         "mips64",
1464         "ppc",
1465         "ppc64",
1466         "riscv64",
1467     )
1469     return os_match and cpu_match and target.endianness == "little"
1472 option(
1473     "--disable-webrtc",
1474     default=webrtc_default,
1475     help="{Enable|Disable} support for WebRTC",
1479 @depends("--disable-webrtc")
1480 def webrtc(enabled):
1481     if enabled:
1482         return True
1485 set_config("MOZ_WEBRTC", webrtc)
1486 set_define("MOZ_WEBRTC", webrtc)
1487 set_config("MOZ_SCTP", webrtc)
1488 set_config("MOZ_SRTP", webrtc)
1489 set_config("MOZ_WEBRTC_SIGNALING", webrtc)
1490 set_config("MOZ_PEERCONNECTION", webrtc)
1491 set_define("MOZ_PEERCONNECTION", webrtc)
1492 # MOZ_WEBRTC_ASSERT_ALWAYS turns on a number of safety asserts in
1493 # opt/production builds (via MOZ_CRASH())
1494 set_config("MOZ_WEBRTC_ASSERT_ALWAYS", webrtc)
1495 set_define("MOZ_WEBRTC_ASSERT_ALWAYS", webrtc)
1497 # RAW media
1498 # ==============================================================
1501 @depends(target, webrtc)
1502 def raw_media_default(target, webrtc):
1503     if target.os == "Android":
1504         return True
1505     if webrtc:
1506         return True
1509 option(
1510     "--enable-raw",
1511     default=raw_media_default,
1512     help="{Enable|Disable} support for RAW media",
1515 set_define("MOZ_RAW", depends_if("--enable-raw")(lambda _: True))
1518 # X11
1519 # ==============================================================
1520 @depends(webrtc, when=toolkit_gtk)
1521 def x11_libs(webrtc):
1522     libs = [
1523         "x11",
1524         "xcb",
1525         "xcb-shm",
1526         "x11-xcb",
1527         "xext",
1528         "xrandr >= 1.4.0",
1529     ]
1530     if webrtc:
1531         # third_party/libwebrtc/webrtc/webrtc_gn/moz.build adds those
1532         # manually, ensure they're available.
1533         libs += [
1534             "xcomposite",
1535             "xcursor",
1536             "xdamage",
1537             "xfixes",
1538             "xi",
1539         ]
1540     return libs
1543 x11 = pkg_check_modules(
1544     "MOZ_X11",
1545     x11_libs,
1546     allow_missing=toolkit_gtk_x11_optional,
1547     when=toolkit_gtk_x11,
1548     config=False,  # set after the OpenBSD hook below
1552 @depends(x11, target_is_openbsd)
1553 def moz_x11_libs(x11, target_is_openbsd):
1554     if not x11:
1555         return []
1556     if target_is_openbsd:
1557         rpath = tuple(
1558             f"-Wl,-rpath-link,{flag[2:]}" for flag in x11.libs if flag.startswith("-L")
1559         )
1560     else:
1561         rpath = ()
1562     return x11.libs + rpath
1565 set_config("MOZ_X11_CFLAGS", x11.cflags)
1566 set_config("MOZ_X11_LIBS", moz_x11_libs)
1567 set_config("MOZ_X11", True, when=x11)
1568 set_define("MOZ_X11", True, when=x11)
1570 pkg_check_modules(
1571     "MOZ_X11_SM",
1572     ["ice", "sm"],
1573     cflags_only=True,
1574     allow_missing=toolkit_gtk_x11_optional,
1575     when=toolkit_gtk_x11,
1579 # ASan Reporter Addon
1580 # ==============================================================
1581 option(
1582     "--enable-address-sanitizer-reporter",
1583     help="Enable Address Sanitizer Reporter Extension",
1587 @depends("--enable-address-sanitizer-reporter")
1588 def enable_asan_reporter(value):
1589     if value:
1590         return True
1593 set_config("MOZ_ASAN_REPORTER", enable_asan_reporter)
1594 set_define("MOZ_ASAN_REPORTER", enable_asan_reporter)
1596 # Checks for library functions
1597 # ==============================================================
1598 with only_when(compile_environment & depends(target.os)(lambda os: os != "WINNT")):
1599     set_define("HAVE_STAT64", check_symbol("stat64"))
1600     set_define("HAVE_LSTAT64", check_symbol("lstat64"))
1601     set_define("HAVE_TRUNCATE64", check_symbol("truncate64"))
1602     set_define("HAVE_STATVFS64", check_symbol("statvfs64"))
1603     set_define("HAVE_STATVFS", check_symbol("statvfs"))
1604     set_define("HAVE_STATFS64", check_symbol("statfs64"))
1605     set_define("HAVE_STATFS", check_symbol("statfs"))
1606     set_define("HAVE_LUTIMES", check_symbol("lutimes"))
1607     set_define("HAVE_POSIX_FADVISE", check_symbol("posix_fadvise"))
1608     set_define("HAVE_POSIX_FALLOCATE", check_symbol("posix_fallocate"))
1609     set_define("HAVE_EVENTFD", check_symbol("eventfd"))
1611     have_arc4random = check_symbol("arc4random")
1612     set_define("HAVE_ARC4RANDOM", have_arc4random)
1613     set_define("HAVE_ARC4RANDOM_BUF", check_symbol("arc4random_buf"))
1614     set_define("HAVE_MALLINFO", check_symbol("mallinfo"))
1616 # Checks for headers
1617 # ==============================================================
1618 with only_when(compile_environment & depends(target.os)(lambda os: os != "WINNT")):
1619     set_define("HAVE_SYSIOCCOM_H", check_header("sys/ioccom.h"))
1621 # Elfhack
1622 # ==============================================================
1623 with only_when("--enable-compile-environment"):
1625     @depends(host, target)
1626     def has_elfhack(host, target):
1627         return (
1628             target.kernel == "Linux"
1629             and host.kernel == "Linux"
1630             and target.cpu in ("arm", "aarch64", "x86", "x86_64")
1631         )
1633     option(
1634         "--disable-elf-hack",
1635         nargs="?",
1636         choices=("legacy", "relr"),
1637         help="{Enable|Disable} elf hacks",
1638         when=has_elfhack,
1639     )
1641     @depends("--enable-elf-hack", when=has_elfhack)
1642     def may_enable_legacy_elfhack(enable):
1643         if enable and enable != ("relr",):
1644             return enable
1646     @depends("--enable-elf-hack", when=has_elfhack)
1647     def may_enable_relrhack(enable):
1648         if enable and enable != ("legacy",):
1649             return enable
1651     @depends(
1652         have_arc4random,
1653         android_version,
1654         when=target_has_linux_kernel,
1655     )
1656     def may_use_pack_relative_relocs(have_arc4random, android_version):
1657         # Packed relative relocations are only supported on Android since
1658         # version 11 (API 30), and in glibc since version 2.36.
1659         # glibc 2.36 also added the arc4random function, which is our proxy
1660         # to detect this (or newer) version being used.
1661         # When targetting those newer versions, we allow ourselves to use
1662         # packed relative relocations rather than elfhack.
1663         if android_version:
1664             return android_version >= 30
1665         return have_arc4random
1667     @depends(
1668         c_compiler,
1669         extra_toolchain_flags,
1670         linker_ldflags,
1671         readelf,
1672         when=may_use_pack_relative_relocs | may_enable_relrhack,
1673     )
1674     @checking("for -z pack-relative-relocs option to ld", bool)
1675     @imports(_from="__builtin__", _import="FileNotFoundError")
1676     @imports("os")
1677     @imports("textwrap")
1678     def has_pack_relative_relocs(
1679         c_compiler,
1680         extra_toolchain_flags,
1681         linker_ldflags,
1682         readelf,
1683     ):
1684         with create_temporary_file(suffix=".out") as path:
1685             pack_rel_relocs = ["-Wl,-z,pack-relative-relocs"]
1686             if (
1687                 try_invoke_compiler(
1688                     # No configure_cache because it would not create the
1689                     # expected output file.
1690                     None,
1691                     [c_compiler.compiler] + c_compiler.flags,
1692                     c_compiler.language,
1693                     # The resulting binary is expected to have relative
1694                     # relocations, the `ptr` variable attempts to ensure
1695                     # there is at least one. This requires the executable
1696                     # being built as position independent.
1697                     "int main() { return 0; }\nint (*ptr)() = main;",
1698                     pack_rel_relocs
1699                     + ["-pie", "-o", path]
1700                     + (extra_toolchain_flags or [])
1701                     + linker_ldflags,
1702                     wrapper=c_compiler.wrapper,
1703                     onerror=lambda: None,
1704                 )
1705                 is not None
1706             ):
1707                 # BFD ld ignores options it doesn't understand. So check
1708                 # that we did get packed relative relocations (DT_RELR).
1709                 env = os.environ.copy()
1710                 env["LANG"] = "C"
1711                 dyn = check_cmd_output(readelf, "-d", path, env=env).splitlines()
1712                 tags = [
1713                     int(l.split()[0], 16) for l in dyn if l.strip().startswith("0x")
1714                 ]
1715                 # Older versions of readelf don't know about DT_RELR but will
1716                 # still display the tag number.
1717                 if 0x23 in tags:
1718                     needed = [l for l in dyn if l.split()[1:2] == ["(NEEDED)"]]
1719                     is_glibc = any(l.endswith("[libc.so.6]") for l in needed)
1720                     # The mold linker doesn't add a GLIBC_ABI_DT_RELR version
1721                     # dependency, which ld.so doesn't like.
1722                     # https://github.com/rui314/mold/issues/653#issuecomment-1670274638
1723                     if is_glibc:
1724                         versions = check_cmd_output(readelf, "-V", path, env=env)
1725                         if "GLIBC_ABI_DT_RELR" in versions.split():
1726                             return pack_rel_relocs
1727                     else:
1728                         return pack_rel_relocs
1730     @depends(
1731         has_pack_relative_relocs,
1732         may_enable_legacy_elfhack,
1733         may_enable_relrhack,
1734         may_use_pack_relative_relocs,
1735         when=has_pack_relative_relocs,
1736     )
1737     def pack_relative_relocs_flags(
1738         flags,
1739         may_enable_legacy_elfhack,
1740         may_enable_relrhack,
1741         may_use_pack_relative_relocs,
1742     ):
1743         # When relrhack is enabled, we don't pass the flag to the linker because
1744         # relrhack will take care of it.
1745         if may_enable_relrhack and may_enable_relrhack.origin != "default":
1746             return None
1747         # if elfhack is explicitly enabled instead of relrhack, we prioritize it
1748         # over packed relative relocs.
1749         if may_enable_legacy_elfhack and may_enable_legacy_elfhack.origin != "default":
1750             return None
1751         if may_use_pack_relative_relocs:
1752             return flags
1754     @depends(
1755         select_linker,
1756         pack_relative_relocs_flags,
1757         has_pack_relative_relocs,
1758         may_enable_legacy_elfhack,
1759         may_enable_relrhack,
1760         when=has_elfhack,
1761     )
1762     def which_elf_hack(
1763         linker,
1764         pack_relative_relocs_flags,
1765         has_pack_relative_relocs,
1766         may_enable_legacy_elfhack,
1767         may_enable_relrhack,
1768     ):
1769         if pack_relative_relocs_flags:
1770             return
1771         if may_enable_relrhack:
1772             if has_pack_relative_relocs:
1773                 return "relr"
1774             elif (
1775                 may_enable_relrhack.origin != "default"
1776                 and not may_enable_legacy_elfhack
1777             ):
1778                 die(
1779                     "Cannot enable relrhack without linker support for -z pack-relative-relocs"
1780                 )
1781         if may_enable_legacy_elfhack:
1782             if linker and linker.KIND in ("lld", "mold"):
1783                 if may_enable_legacy_elfhack.origin != "default":
1784                     die(
1785                         f"Cannot enable elfhack with {linker.KIND}."
1786                         " Use --enable-linker=bfd, --enable-linker=gold, or --disable-elf-hack"
1787                     )
1788             else:
1789                 return "legacy"
1791     set_config(
1792         "USE_ELF_HACK", True, when=depends(which_elf_hack)(lambda x: x == "legacy")
1793     )
1795     use_relrhack = depends(which_elf_hack)(lambda x: x == "relr")
1796     set_config("RELRHACK", True, when=use_relrhack)
1798     @depends(c_compiler, linker_ldflags, when=use_relrhack)
1799     def relrhack_real_linker(c_compiler, linker_ldflags):
1800         ld = "ld"
1801         for flag in linker_ldflags:
1802             if flag.startswith("-fuse-ld="):
1803                 ld = "ld." + flag[len("-fuse-ld=") :]
1804         ld = check_cmd_output(
1805             c_compiler.compiler, f"--print-prog-name={ld}", *c_compiler.flags
1806         )
1807         return ld.rstrip()
1809     @depends(relrhack_real_linker, when=use_relrhack)
1810     def relrhack_linker(ld):
1811         return os.path.basename(ld)
1813     set_config("RELRHACK_LINKER", relrhack_linker)
1815     std_filesystem = host_cxx_compiler.try_run(
1816         header="#include <filesystem>",
1817         body='auto foo = std::filesystem::absolute("");',
1818         flags=host_linker_ldflags,
1819         when=use_relrhack,
1820         onerror=lambda: None,
1821     )
1823     stdcxxfs = host_cxx_compiler.try_run(
1824         header="#include <filesystem>",
1825         body='auto foo = std::filesystem::absolute("");',
1826         flags=depends(host_linker_ldflags)(
1827             lambda flags: (flags or []) + ["-lstdc++fs"]
1828         ),
1829         check_msg="whether std::filesystem requires -lstdc++fs",
1830         when=use_relrhack & depends(std_filesystem)(lambda x: not x),
1831         onerror=lambda: None,
1832     )
1834     set_config("RELRHACK_LIBS", ["stdc++fs"], when=stdcxxfs)
1836     @depends(build_environment, relrhack_real_linker, when=use_relrhack)
1837     def relrhack_ldflags(build_env, ld):
1838         flags = [
1839             "-B",
1840             os.path.join(build_env.topobjdir, "build", "unix", "elfhack"),
1841         ]
1842         if os.path.basename(ld) != ld:
1843             flags.append(f"-Wl,--real-linker,{ld}")
1844         return flags
1846     set_config("RELRHACK_LDFLAGS", relrhack_ldflags)
1849 @depends(build_environment)
1850 def idl_roots(build_env):
1851     return namespace(
1852         ipdl_root=os.path.join(build_env.topobjdir, "ipc", "ipdl"),
1853         webidl_root=os.path.join(build_env.topobjdir, "dom", "bindings"),
1854         xpcom_root=os.path.join(build_env.topobjdir, "xpcom", "components"),
1855     )
1858 set_config("WEBIDL_ROOT", idl_roots.webidl_root)
1859 set_config("IPDL_ROOT", idl_roots.ipdl_root)
1860 set_config("XPCOM_ROOT", idl_roots.xpcom_root)
1862 # Proxy bypass protection
1863 # ==============================================================
1865 option(
1866     "--enable-proxy-bypass-protection",
1867     help="Prevent suspected or confirmed proxy bypasses",
1871 @depends_if("--enable-proxy-bypass-protection")
1872 def proxy_bypass_protection(_):
1873     return True
1876 set_config("MOZ_PROXY_BYPASS_PROTECTION", proxy_bypass_protection)
1877 set_define("MOZ_PROXY_BYPASS_PROTECTION", proxy_bypass_protection)
1879 # Proxy direct failover
1880 # ==============================================================
1882 option(
1883     "--disable-proxy-direct-failover",
1884     help="Disable direct failover for system requests",
1888 @depends_if("--disable-proxy-direct-failover")
1889 def proxy_direct_failover(value):
1890     if value:
1891         return True
1894 set_config("MOZ_PROXY_DIRECT_FAILOVER", proxy_direct_failover)
1895 set_define("MOZ_PROXY_DIRECT_FAILOVER", proxy_direct_failover)
1897 # MIDL
1898 # ==============================================================
1901 @depends(c_compiler, toolchain_prefix)
1902 def midl_names(c_compiler, toolchain_prefix):
1903     if c_compiler and c_compiler.type in ["gcc", "clang"]:
1904         # mingw
1905         widl = ("widl",)
1906         if toolchain_prefix:
1907             prefixed = tuple("%s%s" % (p, "widl") for p in toolchain_prefix)
1908             widl = prefixed + widl
1909         return widl
1911     return ("midl.exe",)
1914 @depends(target, "--enable-compile-environment")
1915 def check_for_midl(target, compile_environment):
1916     if target.os != "WINNT":
1917         return
1919     if compile_environment:
1920         return True
1923 midl = check_prog(
1924     "MIDL",
1925     midl_names,
1926     when=check_for_midl,
1927     allow_missing=True,
1928     paths=sdk_bin_path,
1929     # MIDL being used from a python wrapper script, we can live with it
1930     # having spaces.
1931     allow_spaces=True,
1934 option(env="MIDL_FLAGS", nargs=1, help="Extra flags to pass to MIDL")
1937 @depends(
1938     "MIDL_FLAGS",
1939     target,
1940     midl,
1941     when=depends(midl, target)(lambda m, t: m and t.kernel == "WINNT"),
1943 def midl_flags(flags, target, midl):
1944     if flags:
1945         flags = flags[0].split()
1946     else:
1947         flags = []
1949     if not midl.endswith("widl"):
1950         env = {
1951             "x86": "win32",
1952             "x86_64": "x64",
1953             "aarch64": "arm64",
1954         }[target.cpu]
1955         return flags + ["-nologo", "-no_cpp", "-env", env]
1957     # widl
1958     return (
1959         flags
1960         + {
1961             "x86": ["--win32", "-m32"],
1962             "x86_64": ["--win64", "-m64"],
1963         }[target.cpu]
1964     )
1967 set_config("MIDL_FLAGS", midl_flags)
1969 # Accessibility
1970 # ==============================================================
1972 option("--disable-accessibility", help="Disable accessibility support")
1975 @depends("--enable-accessibility", check_for_midl, midl, c_compiler)
1976 def accessibility(value, check_for_midl, midl, c_compiler):
1977     enabled = bool(value)
1979     if not enabled:
1980         return
1982     if check_for_midl and not midl:
1983         if c_compiler and c_compiler.type in ("gcc", "clang"):
1984             die(
1985                 "You have accessibility enabled, but widl could not be found. "
1986                 "Add --disable-accessibility to your mozconfig or install widl. "
1987                 "See https://developer.mozilla.org/en-US/docs/Cross_Compile_Mozilla_for_Mingw32 for details."
1988             )
1989         else:
1990             die(
1991                 "MIDL could not be found. "
1992                 "Building accessibility without MIDL is not supported."
1993             )
1995     return enabled
1998 set_config("ACCESSIBILITY", accessibility)
1999 set_define("ACCESSIBILITY", accessibility)
2002 @depends(moz_debug, developer_options)
2003 def a11y_log(debug, developer_options):
2004     return debug or developer_options
2007 set_config("A11Y_LOG", True, when=a11y_log)
2008 set_define("A11Y_LOG", True, when=a11y_log)
2011 # Addon signing
2012 # ==============================================================
2013 @depends(milestone)
2014 def require_signing(milestone):
2015     return milestone.is_release_or_beta and not milestone.is_esr
2018 option(
2019     env="MOZ_REQUIRE_SIGNING",
2020     default=require_signing,
2021     help="Enforce that add-ons are signed by the trusted root",
2024 set_config("MOZ_REQUIRE_SIGNING", True, when="MOZ_REQUIRE_SIGNING")
2025 set_define("MOZ_REQUIRE_SIGNING", True, when="MOZ_REQUIRE_SIGNING")
2027 option(
2028     "--with-unsigned-addon-scopes",
2029     nargs="+",
2030     choices=("app", "system"),
2031     help="Addon scopes where signature is not required",
2035 @depends("--with-unsigned-addon-scopes")
2036 def unsigned_addon_scopes(scopes):
2037     return namespace(
2038         app="app" in scopes or None,
2039         system="system" in scopes or None,
2040     )
2043 set_config("MOZ_UNSIGNED_APP_SCOPE", unsigned_addon_scopes.app)
2044 set_config("MOZ_UNSIGNED_SYSTEM_SCOPE", unsigned_addon_scopes.system)
2047 # Addon sideloading
2048 # ==============================================================
2049 option(
2050     "--allow-addon-sideload",
2051     default=milestone.is_esr,
2052     help="Addon sideloading is allowed",
2056 set_config("MOZ_ALLOW_ADDON_SIDELOAD", True, when="--allow-addon-sideload")
2058 # WebExtensions API WebIDL bindings
2059 # ==============================================================
2062 @depends(milestone)
2063 def extensions_webidl_bindings_default(milestone):
2064     # Only enable the webidl bindings for the WebExtensions APIs
2065     # in Nightly.
2066     return milestone.is_nightly
2069 option(
2070     "--enable-extensions-webidl-bindings",
2071     default=extensions_webidl_bindings_default,
2072     help="{Enable|Disable} building experimental WebExtensions WebIDL bindings",
2076 @depends("--enable-extensions-webidl-bindings")
2077 def extensions_webidl_enabled(value):
2078     return bool(value)
2081 set_config("MOZ_WEBEXT_WEBIDL_ENABLED", extensions_webidl_enabled)
2083 # Launcher process (Windows only)
2084 # ==============================================================
2087 @depends(target)
2088 def launcher_process_default(target):
2089     return target.os == "WINNT"
2092 option(
2093     "--enable-launcher-process",
2094     default=launcher_process_default,
2095     help="{Enable|Disable} launcher process by default",
2099 @depends("--enable-launcher-process", target)
2100 def launcher(value, target):
2101     enabled = bool(value)
2102     if enabled and target.os != "WINNT":
2103         die("Cannot enable launcher process on %s", target.os)
2104     if enabled:
2105         return True
2108 set_config("MOZ_LAUNCHER_PROCESS", launcher)
2109 set_define("MOZ_LAUNCHER_PROCESS", launcher)
2111 # llvm-dlltool (Windows only)
2112 # ==============================================================
2115 @depends(build_project, target, "--enable-compile-environment")
2116 def check_for_llvm_dlltool(build_project, target, compile_environment):
2117     if build_project != "browser":
2118         return
2120     if target.os != "WINNT":
2121         return
2123     return compile_environment
2126 llvm_dlltool = check_prog(
2127     "LLVM_DLLTOOL",
2128     ("llvm-dlltool",),
2129     what="llvm-dlltool",
2130     when=check_for_llvm_dlltool,
2131     paths=clang_search_path,
2135 @depends(target, when=llvm_dlltool)
2136 def llvm_dlltool_flags(target):
2137     arch = {
2138         "x86": "i386",
2139         "x86_64": "i386:x86-64",
2140         "aarch64": "arm64",
2141     }[target.cpu]
2143     return ["-m", arch]
2146 set_config("LLVM_DLLTOOL_FLAGS", llvm_dlltool_flags)
2148 # BITS download (Windows only)
2149 # ==============================================================
2151 option(
2152     "--enable-bits-download",
2153     when=target_is_windows,
2154     default=target_is_windows,
2155     help="{Enable|Disable} building BITS download support",
2158 set_define(
2159     "MOZ_BITS_DOWNLOAD",
2160     depends_if("--enable-bits-download", when=target_is_windows)(lambda _: True),
2162 set_config(
2163     "MOZ_BITS_DOWNLOAD",
2164     depends_if("--enable-bits-download", when=target_is_windows)(lambda _: True),
2167 # Bundled fonts on desktop platform
2168 # ==============================================================
2171 @depends(target)
2172 def bundled_fonts_default(target):
2173     return target.os == "WINNT" or target.kernel == "Linux"
2176 @depends(build_project)
2177 def allow_bundled_fonts(project):
2178     return project == "browser" or project == "comm/mail"
2181 option(
2182     "--enable-bundled-fonts",
2183     default=bundled_fonts_default,
2184     when=allow_bundled_fonts,
2185     help="{Enable|Disable} support for bundled fonts on desktop platforms",
2188 set_define(
2189     "MOZ_BUNDLED_FONTS",
2190     depends_if("--enable-bundled-fonts", when=allow_bundled_fonts)(lambda _: True),
2193 # Reflow counting
2194 # ==============================================================
2197 @depends(moz_debug)
2198 def reflow_perf(debug):
2199     if debug:
2200         return True
2203 option(
2204     "--enable-reflow-perf",
2205     default=reflow_perf,
2206     help="{Enable|Disable} reflow performance tracing",
2209 # The difference in conditions here comes from the initial implementation
2210 # in old-configure, which was unexplained there as well.
2211 set_define("MOZ_REFLOW_PERF", depends_if("--enable-reflow-perf")(lambda _: True))
2212 set_define("MOZ_REFLOW_PERF_DSP", reflow_perf)
2214 # Layout debugger
2215 # ==============================================================
2218 @depends(moz_debug)
2219 def layout_debugger(debug):
2220     if debug:
2221         return True
2224 option(
2225     "--enable-layout-debugger",
2226     default=layout_debugger,
2227     help="{Enable|Disable} layout debugger",
2230 set_config("MOZ_LAYOUT_DEBUGGER", True, when="--enable-layout-debugger")
2231 set_define("MOZ_LAYOUT_DEBUGGER", True, when="--enable-layout-debugger")
2234 # Shader Compiler for Windows (and MinGW Cross Compile)
2235 # ==============================================================
2237 with only_when(compile_environment):
2238     fxc = check_prog(
2239         "FXC",
2240         ("fxc.exe", "fxc2.exe"),
2241         when=depends(target)(lambda t: t.kernel == "WINNT"),
2242         paths=sdk_bin_path,
2243         # FXC being used from a python wrapper script, we can live with it
2244         # having spaces.
2245         allow_spaces=True,
2246     )
2249 # VPX
2250 # ===
2252 with only_when(compile_environment):
2253     system_lib_option(
2254         "--with-system-libvpx",
2255         help="Use system libvpx (located with pkgconfig)",
2256         when=use_pkg_config,
2257     )
2259     @depends("--with-system-libvpx", when=use_pkg_config)
2260     def with_system_libvpx_option(with_system_libvpx):
2261         return with_system_libvpx
2263     with only_when("--with-system-libvpx"):
2264         vpx = pkg_check_modules("MOZ_LIBVPX", "vpx >= 1.10.0")
2266         check_header(
2267             "vpx/vpx_decoder.h",
2268             flags=vpx.cflags,
2269             onerror=lambda: die(
2270                 "Couldn't find vpx/vpx_decoder.h, which is required to build "
2271                 "with system libvpx. Use --without-system-libvpx to build "
2272                 "with in-tree libvpx."
2273             ),
2274         )
2276         check_symbol(
2277             "vpx_codec_dec_init_ver",
2278             flags=vpx.libs,
2279             onerror=lambda: die(
2280                 "--with-system-libvpx requested but symbol vpx_codec_dec_init_ver "
2281                 "not found"
2282             ),
2283         )
2285         set_config("MOZ_SYSTEM_LIBVPX", True)
2287     @depends(with_system_libvpx_option, target)
2288     def in_tree_vpx(system_libvpx, target):
2289         if system_libvpx:
2290             return
2292         arm_asm = (target.cpu == "arm") or None
2293         return namespace(arm_asm=arm_asm)
2295     @depends(target, when=in_tree_vpx)
2296     def vpx_nasm(target):
2297         if target.cpu in ("x86", "x86_64"):
2298             if target.kernel == "WINNT":
2299                 # Version 2.03 is needed for automatic safeseh support.
2300                 return namespace(version="2.03", what="VPX")
2301             return namespace(what="VPX")
2303     @depends(in_tree_vpx, vpx_nasm, target, neon_flags)
2304     def vpx_as_flags(vpx, vpx_nasm, target, neon_flags):
2305         if vpx and vpx.arm_asm:
2306             # These flags are a lie; they're just used to enable the requisite
2307             # opcodes; actual arch detection is done at runtime.
2308             return neon_flags
2309         elif vpx and vpx_nasm and target.os != "WINNT" and target.cpu != "x86_64":
2310             return ("-DPIC",)
2312     set_config("VPX_USE_NASM", True, when=vpx_nasm)
2313     set_config("VPX_ASFLAGS", vpx_as_flags)
2316 # JPEG
2317 # ====
2319 with only_when(compile_environment):
2320     system_lib_option(
2321         "--with-system-jpeg",
2322         nargs="?",
2323         help="Use system libjpeg (installed at given prefix)",
2324     )
2326     @depends_if("--with-system-jpeg")
2327     def jpeg_flags(value):
2328         if len(value):
2329             return namespace(
2330                 cflags=("-I%s/include" % value[0],),
2331                 ldflags=("-L%s/lib" % value[0], "-ljpeg"),
2332             )
2333         return namespace(
2334             ldflags=("-ljpeg",),
2335         )
2337     with only_when("--with-system-jpeg"):
2338         check_symbol(
2339             "jpeg_destroy_compress",
2340             flags=jpeg_flags.ldflags,
2341             onerror=lambda: die(
2342                 "--with-system-jpeg requested but symbol "
2343                 "jpeg_destroy_compress not found."
2344             ),
2345         )
2347         c_compiler.try_compile(
2348             includes=[
2349                 "stdio.h",
2350                 "sys/types.h",
2351                 "jpeglib.h",
2352             ],
2353             body="""
2354                 #if JPEG_LIB_VERSION < 62
2355                 #error Insufficient JPEG library version
2356                 #endif
2357             """,
2358             flags=jpeg_flags.cflags,
2359             check_msg="for sufficient jpeg library version",
2360             onerror=lambda: die(
2361                 "Insufficient JPEG library version for "
2362                 "--with-system-jpeg (62 required)"
2363             ),
2364         )
2366         c_compiler.try_compile(
2367             includes=[
2368                 "stdio.h",
2369                 "sys/types.h",
2370                 "jpeglib.h",
2371             ],
2372             body="""
2373                 #ifndef JCS_EXTENSIONS
2374                 #error libjpeg-turbo JCS_EXTENSIONS required
2375                 #endif
2376             """,
2377             flags=jpeg_flags.cflags,
2378             check_msg="for sufficient libjpeg-turbo JCS_EXTENSIONS",
2379             onerror=lambda: die(
2380                 "libjpeg-turbo JCS_EXTENSIONS required for " "--with-system-jpeg"
2381             ),
2382         )
2384         set_config("MOZ_JPEG_CFLAGS", jpeg_flags.cflags)
2385         set_config("MOZ_JPEG_LIBS", jpeg_flags.ldflags)
2387     @depends("--with-system-jpeg", target, neon_flags)
2388     def in_tree_jpeg_arm(system_jpeg, target, neon_flags):
2389         if system_jpeg:
2390             return
2392         if target.cpu == "arm":
2393             return neon_flags
2394         elif target.cpu == "aarch64":
2395             return ("-march=armv8-a",)
2397     @depends("--with-system-jpeg", target)
2398     def in_tree_jpeg_mips64(system_jpeg, target):
2399         if system_jpeg:
2400             return
2402         if target.cpu == "mips64":
2403             return ("-Wa,-mloongson-mmi", "-mloongson-ext")
2405     # Compiler check from https://github.com/libjpeg-turbo/libjpeg-turbo/blob/57ba02a408a9a55ccff25aae8b164632a3a4f177/simd/CMakeLists.txt#L419
2406     jpeg_mips64_mmi = c_compiler.try_compile(
2407         body='int c = 0, a = 0, b = 0; asm("paddb %0, %1, %2" : "=f" (c) : "f" (a), "f" (b));',
2408         check_msg="for loongson mmi support",
2409         flags=in_tree_jpeg_mips64,
2410         when=in_tree_jpeg_mips64,
2411     )
2413     @depends(
2414         "--with-system-jpeg",
2415         target,
2416         in_tree_jpeg_arm,
2417         in_tree_jpeg_mips64,
2418         jpeg_mips64_mmi,
2419     )
2420     def in_tree_jpeg(
2421         system_jpeg, target, in_tree_jpeg_arm, in_tree_jpeg_mips64, jpeg_mips64_mmi
2422     ):
2423         if system_jpeg:
2424             return
2426         if target.cpu in ("arm", "aarch64"):
2427             return in_tree_jpeg_arm
2428         elif target.kernel == "Darwin":
2429             if target.cpu == "x86":
2430                 return ("-DPIC", "-DMACHO")
2431             elif target.cpu == "x86_64":
2432                 return ("-D__x86_64__", "-DPIC", "-DMACHO")
2433         elif target.kernel == "WINNT":
2434             if target.cpu == "x86":
2435                 return ("-DPIC", "-DWIN32")
2436             elif target.cpu == "x86_64":
2437                 return ("-D__x86_64__", "-DPIC", "-DWIN64", "-DMSVC")
2438         elif target.cpu == "mips32":
2439             return ("-mdspr2",)
2440         elif target.cpu == "mips64" and jpeg_mips64_mmi:
2441             return in_tree_jpeg_mips64
2442         elif target.cpu == "x86":
2443             return ("-DPIC", "-DELF")
2444         elif target.cpu == "x86_64":
2445             return ("-D__x86_64__", "-DPIC", "-DELF")
2447     @depends(target, when=depends("--with-system-jpeg")(lambda x: not x))
2448     def jpeg_nasm(target):
2449         if target.cpu in ("x86", "x86_64"):
2450             # libjpeg-turbo 2.0.6 requires nasm 2.10.
2451             return namespace(version="2.10", what="JPEG")
2453     # Compiler checks from https://github.com/libjpeg-turbo/libjpeg-turbo/blob/57ba02a408a9a55ccff25aae8b164632a3a4f177/simd/CMakeLists.txt#L258
2454     jpeg_arm_neon_vld1_s16_x3 = c_compiler.try_compile(
2455         includes=["arm_neon.h"],
2456         body="int16_t input[12] = {}; int16x4x3_t output = vld1_s16_x3(input);",
2457         check_msg="for vld1_s16_x3 in arm_neon.h",
2458         flags=in_tree_jpeg_arm,
2459         when=in_tree_jpeg_arm,
2460     )
2462     jpeg_arm_neon_vld1_u16_x2 = c_compiler.try_compile(
2463         includes=["arm_neon.h"],
2464         body="uint16_t input[8] = {}; uint16x4x2_t output = vld1_u16_x2(input);",
2465         check_msg="for vld1_u16_x2 in arm_neon.h",
2466         flags=in_tree_jpeg_arm,
2467         when=in_tree_jpeg_arm,
2468     )
2470     jpeg_arm_neon_vld1q_u8_x4 = c_compiler.try_compile(
2471         includes=["arm_neon.h"],
2472         body="uint8_t input[64] = {}; uint8x16x4_t output = vld1q_u8_x4(input);",
2473         check_msg="for vld1q_u8_x4 in arm_neon.h",
2474         flags=in_tree_jpeg_arm,
2475         when=in_tree_jpeg_arm,
2476     )
2478     set_config("LIBJPEG_TURBO_USE_NASM", True, when=jpeg_nasm)
2479     set_config("LIBJPEG_TURBO_SIMD_FLAGS", in_tree_jpeg)
2480     set_config("LIBJPEG_TURBO_HAVE_VLD1_S16_X3", jpeg_arm_neon_vld1_s16_x3)
2481     set_config("LIBJPEG_TURBO_HAVE_VLD1_U16_X2", jpeg_arm_neon_vld1_u16_x2)
2482     set_config("LIBJPEG_TURBO_HAVE_VLD1Q_U8_X4", jpeg_arm_neon_vld1q_u8_x4)
2483     set_config(
2484         "LIBJPEG_TURBO_NEON_INTRINSICS",
2485         jpeg_arm_neon_vld1_s16_x3
2486         & jpeg_arm_neon_vld1_u16_x2
2487         & jpeg_arm_neon_vld1q_u8_x4,
2488     )
2490     set_config("MOZ_SYSTEM_JPEG", True, when="--with-system-jpeg")
2493 # PNG
2494 # ===
2495 with only_when(compile_environment):
2496     system_lib_option(
2497         "--with-system-png",
2498         nargs="?",
2499         help="Use system libpng",
2500         when=use_pkg_config,
2501     )
2503     @depends("--with-system-png", when=use_pkg_config)
2504     def deprecated_system_png_path(value):
2505         if len(value) == 1:
2506             die(
2507                 "--with-system-png=PATH is not supported anymore. Please use "
2508                 "--with-system-png and set any necessary pkg-config environment variable."
2509             )
2511     png = pkg_check_modules("MOZ_PNG", "libpng >= 1.6.45", when="--with-system-png")
2513     check_symbol(
2514         "png_get_acTL",
2515         flags=png.libs,
2516         onerror=lambda: die(
2517             "--with-system-png won't work because the system's libpng doesn't have APNG support"
2518         ),
2519         when="--with-system-png",
2520     )
2522     set_config("MOZ_SYSTEM_PNG", True, when="--with-system-png")
2525 # FFmpeg's ffvpx configuration
2526 # ==============================================================
2529 @depends(target)
2530 def ffvpx(target):
2531     use_nasm = True
2532     audio_only = False
2533     flags = []
2535     # This enables audio and video codecs paths on Windows  x86 and x86_64,
2536     # macOS (all arch), and Linux x86_64. On other arch / OS combinations,
2537     # only audio codecs are enabled.
2538     if target.kernel == "WINNT":
2539         if target.cpu == "x86":
2540             # 32-bit windows need to prefix symbols with an underscore.
2541             flags = ["-DPIC", "-DWIN32", "-DPREFIX", "-Pconfig_win32.asm"]
2542         elif target.cpu == "x86_64":
2543             flags = [
2544                 "-D__x86_64__",
2545                 "-DPIC",
2546                 "-DWIN64",
2547                 "-DMSVC",
2548                 "-Pconfig_win64.asm",
2549             ]
2550         elif target.cpu == "aarch64":
2551             flags = ["-DPIC", "-DWIN64"]
2552             use_nasm = False
2553     elif target.kernel == "Darwin":
2554         # 32/64-bit macosx assemblers need to prefix symbols with an
2555         # underscore.
2556         flags = ["-DPIC", "-DMACHO", "-DPREFIX"]
2557         if target.cpu == "x86_64":
2558             flags += [
2559                 "-D__x86_64__",
2560                 "-Pconfig_darwin64.asm",
2561             ]
2562         elif target.cpu == "aarch64":
2563             use_nasm = False
2564     elif target.cpu == "x86_64":
2565         flags = ["-D__x86_64__", "-DPIC", "-DELF", "-Pconfig_unix64.asm"]
2566     else:
2567         audio_only = True
2569     if audio_only:
2570         use_nasm = False
2572     return namespace(
2573         use_nasm=use_nasm,
2574         audio_only=audio_only,
2575         flags=flags,
2576     )
2579 @depends(when=ffvpx.use_nasm)
2580 def ffvpx_nasm():
2581     # nasm 2.10 for AVX-2 support.
2582     return namespace(version="2.10", what="FFVPX")
2585 # ffvpx_nasm can't indirectly depend on vpx_as_flags, because it depends
2586 # on a compiler test, so we have to do a little bit of dance here.
2587 @depends(ffvpx, vpx_as_flags, target)
2588 def ffvpx(ffvpx, vpx_as_flags, target):
2589     if ffvpx and vpx_as_flags and target.cpu in ("arm", "aarch64"):
2590         ffvpx.flags.extend(vpx_as_flags)
2591     return ffvpx
2594 set_config("MOZ_FFVPX_AUDIOONLY", True, when=ffvpx.audio_only)
2595 set_define("MOZ_FFVPX_AUDIOONLY", True, when=ffvpx.audio_only)
2596 set_config("FFVPX_ASFLAGS", ffvpx.flags)
2597 set_config("FFVPX_USE_NASM", True, when=ffvpx.use_nasm)
2600 # nasm detection
2601 # ==============================================================
2602 @depends(dav1d_nasm, vpx_nasm, jpeg_nasm, ffvpx_nasm, when=compile_environment)
2603 def need_nasm(*requirements):
2604     requires = {
2605         x.what: x.version if hasattr(x, "version") else True for x in requirements if x
2606     }
2607     if requires:
2608         items = sorted(requires.keys())
2609         if len(items) > 1:
2610             what = " and ".join((", ".join(items[:-1]), items[-1]))
2611         else:
2612             what = items[0]
2613         versioned = {k: v for (k, v) in requires.items() if v is not True}
2614         return namespace(what=what, versioned=versioned)
2617 nasm = check_prog(
2618     "NASM",
2619     ["nasm"],
2620     allow_missing=True,
2621     bootstrap="nasm",
2622     when=need_nasm,
2626 @depends(nasm, need_nasm.what)
2627 def check_nasm(nasm, what):
2628     if not nasm and what:
2629         die("Nasm is required to build with %s, but it was not found." % what)
2630     return nasm
2633 @depends_if(check_nasm)
2634 @checking("nasm version")
2635 def nasm_version(nasm):
2636     version = (
2637         check_cmd_output(nasm, "-v", onerror=lambda: die("Failed to get nasm version."))
2638         .splitlines()[0]
2639         .split()[2]
2640     )
2641     return Version(version)
2644 @depends(nasm_version, need_nasm.versioned, when=need_nasm.versioned)
2645 def check_nasm_version(nasm_version, versioned):
2646     by_version = sorted(versioned.items(), key=lambda x: x[1])
2647     what, version = by_version[-1]
2648     if nasm_version < version:
2649         die(
2650             "Nasm version %s or greater is required to build with %s." % (version, what)
2651         )
2652     return nasm_version
2655 @depends(target, when=check_nasm_version)
2656 def nasm_asflags(target):
2657     asflags = {
2658         ("Darwin", "x86"): ["-f", "macho32"],
2659         ("Darwin", "x86_64"): ["-f", "macho64"],
2660         ("WINNT", "x86"): ["-f", "win32"],
2661         ("WINNT", "x86_64"): ["-f", "win64"],
2662     }.get((target.kernel, target.cpu), None)
2663     if asflags is None:
2664         # We're assuming every x86 platform we support that's
2665         # not Windows or Mac is ELF.
2666         if target.cpu == "x86":
2667             asflags = ["-f", "elf32"]
2668         elif target.cpu == "x86_64":
2669             asflags = ["-f", "elf64"]
2670     return asflags
2673 set_config("NASM_ASFLAGS", nasm_asflags)
2676 # ANGLE OpenGL->D3D translator for WebGL
2677 # ==============================================================
2679 with only_when(compile_environment & target_is_windows):
2680     set_config("MOZ_ANGLE_RENDERER", True)
2682 with only_when(target_is_windows):
2683     option(
2684         "--enable-dxcompiler",
2685         default=milestone.is_nightly,
2686         help="{Enable|Disable} DXC for WebGPU on Windows",
2687     )
2689     @depends("--enable-dxcompiler", target, artifact_builds, valid_windows_sdk_dir)
2690     @checking("for dxcompiler.dll and dxil.dll")
2691     @imports("os.path")
2692     def dxcompiler(enable_dxc, target, artifact, windows_sdk_dir):
2693         if not windows_sdk_dir and not artifact:
2694             return namespace(enabled=False)
2695         if not enable_dxc:
2696             return namespace(enabled=False)
2697         arch = {
2698             "x86_64": "x64",
2699             "aarch64": "arm64",
2700         }.get(target.cpu, target.cpu)
2702         dxc_name = "dxcompiler.dll"
2703         dxil_name = "dxil.dll"
2704         dxc_path = ""
2705         dxil_path = ""
2706         if not artifact:
2707             sdk_d3d_path = os.path.join(windows_sdk_dir.path, "Redist", "D3D", arch)
2708             dxc_path = os.path.join(sdk_d3d_path, dxc_name)
2709             dxil_path = os.path.join(sdk_d3d_path, dxil_name)
2710             if not os.path.exists(dxc_path):
2711                 die("Could not find dxcompiler.dll at {}", dxc_path)
2712             if not os.path.exists(dxil_path):
2713                 die("Could not find dxil.dll at {}", dxil_path)
2715         return namespace(
2716             enabled=True,
2717             from_sdk=not artifact,
2718             dxc_name=dxc_name,
2719             dxc_path=dxc_path,
2720             dxil_name=dxil_name,
2721             dxil_path=dxil_path,
2722         )
2724     with only_when(dxcompiler.enabled):
2725         set_config("MOZ_DXCOMPILER", True)
2726         set_define("MOZ_DXCOMPILER", 1)
2727         set_define("MOZ_DXC_DLL_NAME", dxcompiler.dxc_name)
2728         set_define("MOZ_DXIL_DLL_NAME", dxcompiler.dxil_name)
2729         with only_when(dxcompiler.from_sdk):
2730             set_config("MOZ_DXC_DLL_PATH", dxcompiler.dxc_path)
2731             set_config("MOZ_DXIL_DLL_PATH", dxcompiler.dxil_path)
2734 # Remoting protocol support
2735 # ==============================================================
2738 @depends(toolkit)
2739 def has_remote(toolkit):
2740     if toolkit in ("gtk", "windows", "cocoa"):
2741         return True
2744 set_config("MOZ_HAS_REMOTE", has_remote)
2745 set_define("MOZ_HAS_REMOTE", has_remote)
2747 # RLBox Library Sandboxing wasm support
2748 # ==============================================================
2751 def wasm_sandboxing_libraries():
2752     return (
2753         "graphite",
2754         "ogg",
2755         "hunspell",
2756         "expat",
2757         "woff2",
2758         "soundtouch",
2759     )
2762 @depends(dependable(wasm_sandboxing_libraries), build_project)
2763 def default_wasm_sandboxing_libraries(libraries, build_project):
2764     if build_project != "tools/rusttests":
2765         non_default_libs = {}
2767         return tuple(l for l in libraries if l not in non_default_libs)
2770 option(
2771     "--with-wasm-sandboxed-libraries",
2772     env="WASM_SANDBOXED_LIBRARIES",
2773     help="{Enable wasm sandboxing for the selected libraries|Disable wasm sandboxing}",
2774     nargs="+",
2775     choices=dependable(wasm_sandboxing_libraries),
2776     default=default_wasm_sandboxing_libraries,
2780 @depends("--with-wasm-sandboxed-libraries")
2781 def requires_wasm_sandboxing(libraries):
2782     if libraries:
2783         return True
2786 set_config("MOZ_USING_WASM_SANDBOXING", requires_wasm_sandboxing)
2787 set_define("MOZ_USING_WASM_SANDBOXING", requires_wasm_sandboxing)
2789 with only_when(requires_wasm_sandboxing & compile_environment):
2790     option(
2791         "--with-wasi-sysroot",
2792         env="WASI_SYSROOT",
2793         nargs=1,
2794         help="Path to wasi sysroot for wasm sandboxing",
2795     )
2797     @depends("--with-wasi-sysroot", requires_wasm_sandboxing)
2798     def bootstrap_wasi_sysroot(wasi_sysroot, requires_wasm_sandboxing):
2799         return requires_wasm_sandboxing and not wasi_sysroot
2801     @depends(
2802         "--with-wasi-sysroot",
2803         bootstrap_path("sysroot-wasm32-wasi", when=bootstrap_wasi_sysroot),
2804     )
2805     @imports("os")
2806     def wasi_sysroot(wasi_sysroot, bootstrapped_sysroot):
2807         if not wasi_sysroot:
2808             return bootstrapped_sysroot
2810         wasi_sysroot = wasi_sysroot[0]
2811         if not os.path.isdir(wasi_sysroot):
2812             die("Argument to --with-wasi-sysroot must be a directory")
2813         if not os.path.isabs(wasi_sysroot):
2814             die("Argument to --with-wasi-sysroot must be an absolute path")
2816         return wasi_sysroot
2818     @depends(wasi_sysroot)
2819     def wasi_sysroot_flags(wasi_sysroot):
2820         if wasi_sysroot:
2821             log.info("Using wasi sysroot in %s", wasi_sysroot)
2822             return ["--sysroot=%s" % wasi_sysroot]
2823         return []
2825     set_config("WASI_SYSROOT", wasi_sysroot)
2827     def wasm_compiler_with_flags(compiler, sysroot_flags):
2828         if compiler:
2829             return (
2830                 compiler.wrapper + [compiler.compiler] + compiler.flags + sysroot_flags
2831             )
2833     @template
2834     def wasm_compiler_error(msg):
2835         @depends("--with-wasm-sandboxed-libraries")
2836         def wasm_compiler_error(sandboxed_libs):
2837             suggest_disable = ""
2838             if sandboxed_libs.origin == "default":
2839                 suggest_disable = " Or build with --without-wasm-sandboxed-libraries."
2840             return lambda: die(msg + suggest_disable)
2842         return wasm_compiler_error
2844     @template
2845     def check_wasm_compiler(compiler, language):
2846         compiler.try_compile(
2847             includes=["cstring" if language == "C++" else "string.h"],
2848             flags=wasi_sysroot_flags,
2849             check_msg="the wasm %s compiler can find wasi headers" % language,
2850             onerror=wasm_compiler_error(
2851                 "Cannot find wasi headers or problem with the wasm compiler. "
2852                 "Please fix the problem."
2853             ),
2854         )
2856         compiler.try_run(
2857             flags=wasi_sysroot_flags,
2858             check_msg="the wasm %s linker can find wasi libraries" % language,
2859             onerror=wasm_compiler_error(
2860                 "Cannot find wasi libraries or problem with the wasm linker. "
2861                 "Please fix the problem."
2862             ),
2863         )
2865     wasm_cc = compiler("C", wasm, other_compiler=c_compiler)
2866     check_wasm_compiler(wasm_cc, "C")
2868     @depends(wasm_cc, wasi_sysroot_flags)
2869     def wasm_cc_with_flags(wasm_cc, wasi_sysroot_flags):
2870         return wasm_compiler_with_flags(wasm_cc, wasi_sysroot_flags)
2872     set_config("WASM_CC", wasm_cc_with_flags)
2874     wasm_cxx = compiler(
2875         "C++",
2876         wasm,
2877         c_compiler=wasm_cc,
2878         other_compiler=cxx_compiler,
2879         other_c_compiler=c_compiler,
2880     )
2881     check_wasm_compiler(wasm_cxx, "C++")
2883     @depends(wasm_cxx, wasi_sysroot_flags)
2884     def wasm_cxx_with_flags(wasm_cxx, wasi_sysroot_flags):
2885         return wasm_compiler_with_flags(wasm_cxx, wasi_sysroot_flags)
2887     set_config("WASM_CXX", wasm_cxx_with_flags)
2889     wasm_compile_flags = dependable(["-fno-exceptions", "-fno-strict-aliasing"])
2890     option(env="WASM_CFLAGS", nargs=1, help="Options to pass to WASM_CC")
2892     @depends("WASM_CFLAGS", wasm_compile_flags)
2893     def wasm_cflags(value, wasm_compile_flags):
2894         if value:
2895             return wasm_compile_flags + value
2896         else:
2897             return wasm_compile_flags
2899     set_config("WASM_CFLAGS", wasm_cflags)
2901     option(env="WASM_CXXFLAGS", nargs=1, help="Options to pass to WASM_CXX")
2903     @depends("WASM_CXXFLAGS", wasm_compile_flags)
2904     def wasm_cxxflags(value, wasm_compile_flags):
2905         if value:
2906             return wasm_compile_flags + value
2907         else:
2908             return wasm_compile_flags
2910     set_config("WASM_CXXFLAGS", wasm_cxxflags)
2913 @depends("--with-wasm-sandboxed-libraries")
2914 def wasm_sandboxing(libraries):
2915     if not libraries:
2916         return
2918     return namespace(**{name: True for name in libraries})
2921 @template
2922 def wasm_sandboxing_config_defines():
2923     for lib in wasm_sandboxing_libraries():
2924         set_config(
2925             "MOZ_WASM_SANDBOXING_%s" % lib.upper(), getattr(wasm_sandboxing, lib)
2926         )
2927         set_define(
2928             "MOZ_WASM_SANDBOXING_%s" % lib.upper(), getattr(wasm_sandboxing, lib)
2929         )
2932 wasm_sandboxing_config_defines()
2935 with only_when(compile_environment & wasm_sandboxing.hunspell):
2936     clock_in_wasi_sysroot = wasm_cc.try_run(
2937         header="#include <time.h>",
2938         body="clock();",
2939         check_msg="for clock() in wasi sysroot",
2940         flags=depends(wasi_sysroot_flags)(
2941             lambda sysroot_flags: ["-Werror"] + sysroot_flags
2942         ),
2943     )
2945     wasi_emulated_clock = wasm_cc.try_run(
2946         header="#include <time.h>",
2947         body="clock();",
2948         check_msg="for emulated clock() in wasi sysroot",
2949         flags=depends(wasi_sysroot_flags)(
2950             lambda sysroot_flags: [
2951                 "-Werror",
2952                 "-D_WASI_EMULATED_PROCESS_CLOCKS",
2953                 "-lwasi-emulated-process-clocks",
2954             ]
2955             + sysroot_flags
2956         ),
2957         when=depends(clock_in_wasi_sysroot)(lambda x: not x),
2958         onerror=lambda: die("Can't find clock() in wasi sysroot."),
2959     )
2961     set_config("MOZ_WASI_EMULATED_CLOCK", True, when=wasi_emulated_clock)
2964 # Auxiliary files persistence on application close
2965 # ==============================================================
2967 option(
2968     "--enable-disk-remnant-avoidance",
2969     help="Prevent persistence of auxiliary files on application close",
2973 set_config(
2974     "MOZ_AVOID_DISK_REMNANT_ON_CLOSE",
2975     True,
2976     when="--enable-disk-remnant-avoidance",
2980 # Glean SDK Integration Crate
2981 # ==============================================================
2984 @depends(target)
2985 def glean_android(target):
2986     return target.os == "Android"
2989 set_config("MOZ_GLEAN_ANDROID", True, when=glean_android)
2990 set_define("MOZ_GLEAN_ANDROID", True, when=glean_android)
2993 # dump_syms
2994 # ==============================================================
2996 check_prog(
2997     "DUMP_SYMS",
2998     ["dump_syms"],
2999     allow_missing=True,
3000     bootstrap="dump_syms",
3001     when=compile_environment,
3005 @depends(valid_windows_sdk_dir, host)
3006 @imports(_from="os", _import="environ")
3007 def pdbstr_paths(valid_windows_sdk_dir, host):
3008     if not valid_windows_sdk_dir:
3009         return
3011     vc_host = {
3012         "x86": "x86",
3013         "x86_64": "x64",
3014         "aarch64": "arm64",
3015     }.get(host.cpu)
3017     return [
3018         environ["PATH"],
3019         os.path.join(valid_windows_sdk_dir.path, "Debuggers", vc_host, "srcsrv"),
3020     ]
3023 @depends("MOZ_AUTOMATION", c_compiler)
3024 def allow_missing_wintools(automation, c_compiler):
3025     if not automation:
3026         return True
3027     if c_compiler and c_compiler.type != "clang-cl":
3028         return True
3031 check_prog(
3032     "PDBSTR",
3033     ["pdbstr.exe"],
3034     allow_missing=allow_missing_wintools,
3035     when=compile_environment & target_is_windows,
3036     paths=pdbstr_paths,
3037     allow_spaces=True,
3041 check_prog(
3042     "WINCHECKSEC",
3043     ["winchecksec.exe", "winchecksec"],
3044     bootstrap="winchecksec",
3045     allow_missing=allow_missing_wintools,
3046     when=compile_environment & target_is_windows,
3050 # Fork server
3051 @depends(target, build_project)
3052 def forkserver_default(target, build_project):
3053     return build_project == "browser" and (
3054         (target.os == "GNU" and target.kernel == "Linux")
3055         or target.os == "FreeBSD"
3056         or target.os == "OpenBSD"
3057     )
3060 option(
3061     "--enable-forkserver",
3062     default=forkserver_default,
3063     env="MOZ_ENABLE_FORKSERVER",
3064     help="{Enable|Disable} fork server",
3068 @depends("--enable-forkserver", target)
3069 def forkserver_flag(value, target):
3070     if (
3071         target.os == "Android"
3072         or (target.os == "GNU" and target.kernel == "Linux")
3073         or target.os == "FreeBSD"
3074         or target.os == "OpenBSD"
3075     ):
3076         return bool(value)
3077     pass
3080 set_config("MOZ_ENABLE_FORKSERVER", forkserver_flag)
3081 set_define("MOZ_ENABLE_FORKSERVER", forkserver_flag, forkserver_flag)
3083 # Crash Reporter
3084 # ==============================================================
3086 with only_when(compile_environment & target_has_linux_kernel):
3087     # Check if we need to use the breakpad_getcontext fallback.
3088     getcontext = check_symbol("getcontext")
3089     set_config("HAVE_GETCONTEXT", getcontext)
3090     set_define("HAVE_GETCONTEXT", getcontext)
3092 # NSS
3093 # ==============================================================
3094 include("../build/moz.configure/nss.configure")
3097 # Enable or disable running in background task mode: headless for
3098 # periodic, short-lived, maintenance tasks.
3099 # ==============================================================================
3100 option(
3101     "--disable-backgroundtasks",
3102     help="Disable running in background task mode",
3104 set_config("MOZ_BACKGROUNDTASKS", True, when="--enable-backgroundtasks")
3105 set_define("MOZ_BACKGROUNDTASKS", True, when="--enable-backgroundtasks")
3108 # Update-related programs: updater, maintenance service, update agent,
3109 # default browser agent.
3110 # ==============================================================
3111 include("../build/moz.configure/update-programs.configure")
3114 # Mobile optimizations
3115 # ==============================================================
3116 option(
3117     "--enable-mobile-optimize",
3118     default=target_is_android,
3119     help="{Enable|Disable} mobile optimizations",
3122 set_define("MOZ_GFX_OPTIMIZE_MOBILE", True, when="--enable-mobile-optimize")
3124 # Pref extensions
3125 # ==============================================================
3126 option("--disable-pref-extensions", help="Disable pref extensions such as autoconfig")
3127 set_config("MOZ_PREF_EXTENSIONS", True, when="--enable-pref-extensions")
3129 # Offer a way to disable the startup cache
3130 # ==============================================================
3131 option("--disable-startupcache", help="Disable startup cache")
3134 @depends("--enable-startupcache")
3135 def enable_startupcache(value):
3136     if value:
3137         return True
3140 set_define(
3141     "MOZ_DISABLE_STARTUPCACHE", True, when=depends(enable_startupcache)(lambda x: not x)
3145 # Branding
3146 # ==============================================================
3147 option(
3148     env="MOZ_APP_REMOTINGNAME",
3149     nargs=1,
3150     help="Used for the internal program name, which affects profile name "
3151     "and remoting. If not set, defaults to MOZ_APP_NAME if the update channel "
3152     "is release, and MOZ_APP_NAME-MOZ_UPDATE_CHANNEL otherwise",
3156 @depends("MOZ_APP_REMOTINGNAME", moz_app_name, update_channel)
3157 def moz_app_remotingname(value, moz_app_name, update_channel):
3158     if value:
3159         return value[0]
3160     if update_channel == "release":
3161         return moz_app_name
3162     return moz_app_name + "-" + update_channel
3165 set_config("MOZ_APP_REMOTINGNAME", moz_app_remotingname)
3167 option(
3168     env="ANDROID_PACKAGE_NAME",
3169     nargs=1,
3170     help="Name of the Android package (default org.mozilla.$MOZ_APP_NAME)",
3174 @depends("ANDROID_PACKAGE_NAME", moz_app_name)
3175 def android_package_name(value, moz_app_name):
3176     if value:
3177         return value[0]
3178     if moz_app_name == "fennec":
3179         return "org.mozilla.fennec_aurora"
3180     return "org.mozilla.%s" % moz_app_name
3183 set_config("ANDROID_PACKAGE_NAME", android_package_name)
3186 # Miscellaneous options
3187 # ==============================================================
3188 option(env="MOZ_WINCONSOLE", nargs="?", help="Whether we can create a console window")
3189 set_define("MOZ_WINCONSOLE", True, when=depends("MOZ_WINCONSOLE")(lambda x: x))
3192 # Alternative Crashreporter setting
3193 option(
3194     "--with-crashreporter-url",
3195     env="MOZ_CRASHREPORTER_URL",
3196     default="https://crash-reports.mozilla.com/",
3197     nargs=1,
3198     help="Set an alternative crashreporter url",
3201 set_config(
3202     "MOZ_CRASHREPORTER_URL",
3203     depends("--with-crashreporter-url")(lambda x: x[0].rstrip("/")),
3207 # Crash reporter options
3208 # ==============================================================
3209 @depends(target)
3210 def oxidized_breakpad(target):
3211     if target.kernel == "Linux":
3212         return target.cpu in ("aarch64", "arm", "x86", "x86_64")
3213     return False
3216 set_config("MOZ_OXIDIZED_BREAKPAD", True, when=oxidized_breakpad)
3217 set_define("MOZ_OXIDIZED_BREAKPAD", True, when=oxidized_breakpad)
3219 # Environment variable to mock the crashreporter for testing
3220 option(env="MOZ_CRASHREPORTER_MOCK", help="Mock the crashreporter to test native GUIs")
3221 set_config("MOZ_CRASHREPORTER_MOCK", True, when="MOZ_CRASHREPORTER_MOCK")
3224 # Wine
3225 # ==============================================================
3226 @depends(target, host)
3227 def want_wine(target, host):
3228     return target.kernel == "WINNT" and host.kernel != "WINNT"
3231 wine = check_prog(
3232     "WINE",
3233     ["wine64", "wine"],
3234     when=want_wine,
3235     bootstrap="wine/bin",
3238 # libevent
3239 # ==============================================================
3240 with only_when(compile_environment):
3241     system_lib_option(
3242         "--with-system-libevent",
3243         nargs="?",
3244         help="Use system libevent",
3245         when=use_pkg_config,
3246     )
3248     @depends("--with-system-libevent", when=use_pkg_config)
3249     def deprecated_system_libevent_path(value):
3250         if len(value) == 1:
3251             die(
3252                 "--with-system-libevent=PATH is not supported anymore. Please use "
3253                 "--with-system-libevent and set any necessary pkg-config environment variable."
3254             )
3256     pkg_check_modules("MOZ_LIBEVENT", "libevent", when="--with-system-libevent")
3258     set_config("MOZ_SYSTEM_LIBEVENT", True, when="--with-system-libevent")
3261 # Crash reporting
3262 # ==============================================================
3263 @depends(target, developer_options, artifact_builds)
3264 def crashreporter_default(target, developer_options, artifacts):
3265     if target.os in ("WINNT", "OSX"):
3266         return True
3267     if target.kernel == "Linux" and target.cpu in ("x86", "x86_64", "arm", "aarch64"):
3268         # The crash reporter prevents crash stacktraces to be logged in the
3269         # logs on Android, so we leave it out by default in developer builds.
3270         return target.os != "Android" or not developer_options or artifacts
3273 option(
3274     "--enable-crashreporter",
3275     default=crashreporter_default,
3276     help="{Enable|Disable} crash reporting",
3280 set_config("MOZ_CRASHREPORTER", True, when="--enable-crashreporter")
3281 set_define("MOZ_CRASHREPORTER", True, when="--enable-crashreporter")
3283 with only_when(compile_environment):
3284     with only_when("--enable-crashreporter"):
3285         pkg_check_modules(
3286             "MOZ_GTHREAD",
3287             "gthread-2.0",
3288             when=depends(target)(lambda t: t.os == "GNU" and t.kernel == "Linux"),
3289         )
3292 # If we have any service that uploads data (and requires data submission
3293 # policy alert), set MOZ_DATA_REPORTING.
3294 # ==============================================================
3295 @depends(
3296     "MOZ_TELEMETRY_REPORTING",
3297     "MOZ_SERVICES_HEALTHREPORT",
3298     "--enable-crashreporter",
3299     "MOZ_NORMANDY",
3301 def data_reporting(telemetry, healthreport, crashreporter, normandy):
3302     return telemetry or healthreport or crashreporter or normandy
3305 set_config("MOZ_DATA_REPORTING", True, when=data_reporting)
3306 set_define("MOZ_DATA_REPORTING", True, when=data_reporting)
3309 # Gtk+
3310 # ==============================================================
3311 with only_when(toolkit_gtk):
3312     pkg_check_modules(
3313         "MOZ_GTK3",
3314         "gtk+-3.0 >= 3.14.0 gtk+-unix-print-3.0 glib-2.0 gobject-2.0 gio-unix-2.0",
3315     )
3317     set_define("GDK_VERSION_MIN_REQUIRED", "GDK_VERSION_3_14")
3318     set_define("GDK_VERSION_MAX_ALLOWED", "GDK_VERSION_3_14")
3320     pkg_check_modules("GLIB", "glib-2.0 >= 2.42 gobject-2.0")
3322     set_define("GLIB_VERSION_MIN_REQUIRED", "GLIB_VERSION_2_42")
3323     set_define("GLIB_VERSION_MAX_ALLOWED", "GLIB_VERSION_2_42")
3325     set_define("MOZ_ACCESSIBILITY_ATK", True, when=accessibility)
3327 # DBus
3328 # ==============================================================
3329 with only_when(toolkit_gtk):
3330     option("--disable-dbus", help="Disable dbus support", when=use_pkg_config)
3332     @depends("--enable-dbus", when=use_pkg_config)
3333     def enable_dbus_option(enable_dbus):
3334         return enable_dbus
3336     with only_when(enable_dbus_option):
3337         pkg_check_modules("MOZ_DBUS", "dbus-1 >= 0.60")
3339         set_config("MOZ_ENABLE_DBUS", True)
3340         set_define("MOZ_ENABLE_DBUS", True)
3343 # Necko's wifi scanner
3344 # ==============================================================
3345 @depends(target)
3346 def necko_wifi_when(target):
3347     return target.os in ("WINNT", "OSX", "DragonFly", "FreeBSD") or (
3348         target.kernel == "Linux" and target.os == "GNU"
3349     )
3352 option("--disable-necko-wifi", help="Disable necko wifi scanner", when=necko_wifi_when)
3354 set_config("NECKO_WIFI", True, when="--enable-necko-wifi")
3355 set_define("NECKO_WIFI", True, when="--enable-necko-wifi")
3358 @depends(
3359     depends("--enable-necko-wifi", when=necko_wifi_when)(lambda x: x),
3360     depends(enable_dbus_option, when=toolkit_gtk)(lambda x: x),
3361     when=use_pkg_config
3362     & depends(target)(lambda t: t.os == "GNU" and t.kernel == "Linux"),
3364 def necko_wifi_dbus(necko_wifi, dbus):
3365     if necko_wifi and not dbus:
3366         die(
3367             "Necko WiFi scanning needs DBus on your platform, remove --disable-dbus"
3368             " or use --disable-necko-wifi"
3369         )
3370     return necko_wifi and dbus
3373 set_config("NECKO_WIFI_DBUS", True, when=necko_wifi_dbus)
3374 set_define("NECKO_WIFI_DBUS", True, when=necko_wifi_dbus)
3377 # Frontend JS debug mode
3378 # ==============================================================
3379 option("--enable-debug-js-modules", help="Enable debug mode for frontend JS libraries")
3381 set_config("DEBUG_JS_MODULES", True, when="--enable-debug-js-modules")
3384 # moz_dump_painting
3385 # ==============================================================
3386 option("--enable-dump-painting", help="Enable paint debugging")
3388 set_define(
3389     "MOZ_DUMP_PAINTING",
3390     True,
3391     when=depends("--enable-dump-painting", "--enable-debug")(
3392         lambda painting, debug: painting or debug
3393     ),
3395 set_define("MOZ_LAYERS_HAVE_LOG", True, when="--enable-dump-painting")
3398 # libproxy support
3399 # ==============================================================
3400 with only_when(toolkit_gtk):
3401     system_lib_option(
3402         "--enable-libproxy",
3403         help="Enable libproxy support",
3404         when=use_pkg_config,
3405     )
3407     with only_when("--enable-libproxy"):
3408         pkg_check_modules("MOZ_LIBPROXY", "libproxy-1.0")
3410         set_config("MOZ_ENABLE_LIBPROXY", True)
3413 # Enable runtime logging
3414 # ==============================================================
3415 set_define("MOZ_LOGGING", True)
3416 set_define("FORCE_PR_LOG", True)
3418 # This will enable logging of addref, release, ctor, dtor.
3419 # ==============================================================
3420 option(
3421     "--enable-logrefcnt",
3422     default=moz_debug,
3423     help="{Enable|Disable} logging of refcounts",
3426 set_define("NS_BUILD_REFCNT_LOGGING", True, when="--enable-logrefcnt")
3429 # NegotiateAuth
3430 # ==============================================================
3431 option("--disable-negotiateauth", help="Disable GSS-API negotiation")
3433 set_config("MOZ_AUTH_EXTENSION", True, when="--enable-negotiateauth")
3434 set_define("MOZ_AUTH_EXTENSION", True, when="--enable-negotiateauth")
3437 # Parental control
3438 # ==============================================================
3439 option("--disable-parental-controls", help="Do not build parental controls")
3441 set_config(
3442     "MOZ_DISABLE_PARENTAL_CONTROLS",
3443     True,
3444     when=depends("--enable-parental-controls")(lambda x: not x),
3446 set_define(
3447     "MOZ_DISABLE_PARENTAL_CONTROLS",
3448     True,
3449     when=depends("--enable-parental-controls")(lambda x: not x),
3452 # Automation renaming
3453 # ==============================================================
3455 with only_when("MOZ_AUTOMATION"):
3456     option(env="MOZ_SIMPLE_PACKAGE_NAME", nargs=1, help="Package name override")
3457     set_config(
3458         "MOZ_SIMPLE_PACKAGE_NAME", depends_if("MOZ_SIMPLE_PACKAGE_NAME")(lambda x: x[0])
3459     )
3460     option(env="MOZ_PKG_SPECIAL", nargs=1, help="Name of special moz flavor")
3461     set_config("MOZ_PKG_SPECIAL", depends_if("MOZ_PKG_SPECIAL")(lambda x: x[0]))
3464 # OSX Packaging
3465 # ==============================================================
3467 with only_when(target_is_osx):
3468     option(
3469         "--with-macbundlename-prefix",
3470         nargs=1,
3471         help="Prefix for the mac bundle name",
3472     )
3474     @depends_if("--with-macbundlename-prefix")
3475     def mac_bundle_name(value):
3476         return value[0]
3478     add_old_configure_assignment("MOZ_MACBUNDLE_NAME_PREFIX", mac_bundle_name)
3480     option(env="DMG_TOOL", nargs=1, help="Path to the dmg tool")
3481     set_config("DMG_TOOL", depends_if("DMG_TOOL")(lambda x: x[0]))
3484 # JS Packaging
3485 # ==============================================================
3487 option(
3488     env="MOZ_PACKAGE_JSSHELL",
3489     help="Whether the installer bundles the JS shell",
3491 set_config("MOZ_PACKAGE_JSSHELL", depends_if("MOZ_PACKAGE_JSSHELL")(lambda x: bool(x)))
3494 # Sandboxing support
3495 # ==============================================================
3496 @depends(target, tsan, asan)
3497 def sandbox_default(target, tsan, asan):
3498     # Only enable the sandbox by default on Linux, OpenBSD, macOS, and Windows
3499     if target.kernel == "Linux" and target.os == "GNU":
3500         # Bug 1182565: TSan conflicts with sandboxing on Linux.
3501         # Bug 1287971: LSan also conflicts with sandboxing on Linux.
3502         if tsan or asan:
3503             return False
3504         # Linux sandbox is only available on x86{,_64} and arm{,64}.
3505         return target.cpu in ("x86", "x86_64", "arm", "aarch64")
3506     return target.kernel in ("WINNT", "Darwin", "OpenBSD")
3509 option(
3510     "--enable-sandbox",
3511     default=sandbox_default,
3512     help="{Enable|Disable} sandboxing support",
3515 set_config("MOZ_SANDBOX", True, when="--enable-sandbox")
3516 set_define("MOZ_SANDBOX", True, when="--enable-sandbox")
3518 # Searching of system directories for extensions.
3519 # ==============================================================
3520 # Note: this switch is meant to be used for test builds whose behavior should
3521 # not depend on what happens to be installed on the local machine.
3522 option(
3523     "--disable-system-extension-dirs",
3524     help="Disable searching system- and account-global directories for extensions"
3525     " of any kind; use only profile-specific extension directories",
3528 set_define("ENABLE_SYSTEM_EXTENSION_DIRS", True, when="--enable-system-extension-dirs")
3531 # Pixman
3532 # ==============================================================
3533 with only_when(compile_environment):
3534     system_lib_option(
3535         "--enable-system-pixman",
3536         help="Use system pixman (located with pkgconfig)",
3537         when=use_pkg_config,
3538     )
3540     @depends("--enable-system-pixman", when=use_pkg_config)
3541     def enable_system_pixman_option(enable_system_pixman):
3542         return enable_system_pixman
3544     @depends(enable_system_pixman_option)
3545     def in_tree_pixman(pixman):
3546         return not pixman
3548     set_config("MOZ_TREE_PIXMAN", True, when=in_tree_pixman)
3549     set_define("MOZ_TREE_PIXMAN", True, when=in_tree_pixman)
3551     pkg_check_modules("MOZ_PIXMAN", "pixman-1 >= 0.40.0", when="--enable-system-pixman")
3552     # Set MOZ_PIXMAN_CFLAGS to an explicit empty value when --enable-system-pixman is *not* used,
3553     # for layout/style/extra-bindgen-flags
3554     set_config("MOZ_PIXMAN_CFLAGS", [], when=in_tree_pixman)
3557 # Universalchardet
3558 # ==============================================================
3559 with only_when(compile_environment):
3560     option("--disable-universalchardet", help="Disable universal encoding detection")
3562     set_config("MOZ_UNIVERSALCHARDET", True, when="--enable-universalchardet")
3565 # Disable zipwriter
3566 # ==============================================================
3567 with only_when(compile_environment):
3568     option("--disable-zipwriter", help="Disable zipwriter component")
3570     set_config("MOZ_ZIPWRITER", True, when="--enable-zipwriter")
3573 # Location of the mozilla user directory
3574 # ==============================================================
3575 with only_when(compile_environment):
3577     @depends(target)
3578     def default_user_appdir(target):
3579         if target.kernel in ("WINNT", "Darwin"):
3580             return "Mozilla"
3581         return ".mozilla"
3583     option(
3584         "--with-user-appdir",
3585         nargs=1,
3586         default=default_user_appdir,
3587         help="Set user-specific appdir",
3588     )
3590     @depends("--with-user-appdir")
3591     def user_appdir(appdir):
3592         if not appdir:
3593             die("--without-user-appdir is not a valid option.")
3594         if "/" in appdir[0]:
3595             die("--with-user-appdir must be a single relative path.")
3596         return '"{}"'.format(appdir[0])
3598     set_define("MOZ_USER_DIR", user_appdir)
3601 # Check for sin_len and sin6_len - used by SCTP; only appears in Mac/*BSD generally
3602 # ==============================================================
3603 with only_when(compile_environment):
3604     have_sin_len = c_compiler.try_compile(
3605         includes=["netinet/in.h"],
3606         body="struct sockaddr_in x; void *foo = (void*) &x.sin_len;",
3607         check_msg="for sin_len in struct sockaddr_in",
3608     )
3609     have_sin6_len = c_compiler.try_compile(
3610         includes=["netinet/in.h"],
3611         body="struct sockaddr_in6 x; void *foo = (void*) &x.sin6_len;",
3612         check_msg="for sin_len6 in struct sockaddr_in6",
3613     )
3614     set_define("HAVE_SIN_LEN", have_sin_len)
3615     set_define("HAVE_SIN6_LEN", have_sin6_len)
3616     # HAVE_CONN_LEN must be the same as HAVE_SIN_LEN and HAVE_SIN6_LEN
3617     set_define("HAVE_SCONN_LEN", have_sin_len & have_sin6_len)
3618     set_define(
3619         "HAVE_SA_LEN",
3620         c_compiler.try_compile(
3621             includes=["netinet/in.h"],
3622             body="struct sockaddr x; void *foo = (void*) &x.sa_len;",
3623             check_msg="for sa_len in struct sockaddr",
3624         ),
3625     )
3628 # Check for pthread_cond_timedwait_monotonic_np
3629 # ==============================================================
3630 with only_when(compile_environment):
3631     set_define(
3632         "HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC",
3633         c_compiler.try_compile(
3634             includes=["pthread.h"],
3635             body="pthread_cond_timedwait_monotonic_np(0, 0, 0);",
3636             # -Werror to catch any "implicit declaration" warning that means the function
3637             # is not supported.
3638             flags=["-Werror=implicit-function-declaration"],
3639             check_msg="for pthread_cond_timedwait_monotonic_np",
3640         ),
3641     )
3644 # Custom dynamic linker for Android
3645 # ==============================================================
3646 with only_when(target_has_linux_kernel & compile_environment):
3647     option(
3648         env="MOZ_LINKER",
3649         default=depends(target.os, when="--enable-jemalloc")(
3650             lambda os: os == "Android"
3651         ),
3652         help="{Enable|Disable} custom dynamic linker",
3653     )
3655     set_config("MOZ_LINKER", True, when="MOZ_LINKER")
3656     set_define("MOZ_LINKER", True, when="MOZ_LINKER")
3658     # gold emits wrong sysv-style elf hash tables when building both sysv and
3659     # GNU style tables. https://sourceware.org/bugzilla/show_bug.cgi?id=13597
3660     # Since the linker only understands the sysv ones, no need to build the
3661     # GNU style tables anyways.
3662     check_and_add_linker_flag("-Wl,--hash-style=sysv", when="MOZ_LINKER")
3665 # 32-bits ethtool_cmd.speed
3666 # ==============================================================
3667 with only_when(target_has_linux_kernel & compile_environment):
3668     set_config(
3669         "MOZ_WEBRTC_HAVE_ETHTOOL_SPEED_HI",
3670         c_compiler.try_compile(
3671             includes=["linux/ethtool.h"],
3672             body="struct ethtool_cmd cmd; cmd.speed_hi = 0;",
3673             check_msg="for 32-bits ethtool_cmd.speed",
3674         ),
3675     )
3678 # Smart card support
3679 # ==============================================================
3680 @depends(build_project)
3681 def disable_smart_cards(build_project):
3682     return build_project == "mobile/android"
3685 set_config("MOZ_NO_SMART_CARDS", True, when=disable_smart_cards)
3686 set_define("MOZ_NO_SMART_CARDS", True, when=disable_smart_cards)
3688 # Enable UniFFI fixtures
3689 # ==============================================================
3690 # These are used to test the uniffi-bindgen-gecko-js code generation.  They
3691 # should not be enabled in release builds.
3693 option(
3694     "--enable-uniffi-fixtures",
3695     help="Enable UniFFI Fixtures/Examples",
3698 set_config("MOZ_UNIFFI_FIXTURES", True, when="--enable-uniffi-fixtures")
3700 # System policies
3701 # ==============================================================
3703 option(
3704     "--disable-system-policies",
3705     help="Disable reading policies from Windows registry, macOS's file system attributes, and /etc/firefox",
3708 set_config("MOZ_SYSTEM_POLICIES", True, when="--enable-system-policies")
3710 # Allow disabling the creation a legacy profile
3711 # ==============================================================
3713 option(
3714     "--disable-legacy-profile-creation",
3715     help="Disable the creation a legacy profile, to be used by old versions "
3716     "of Firefox, when no profiles exist",
3719 set_config("MOZ_CREATE_LEGACY_PROFILE", True, when="--enable-legacy-profile-creation")
3722 # STL wrapping
3723 # ==============================================================
3724 set_config("WRAP_STL_INCLUDES", True)
3725 set_config(
3726     "STL_FLAGS",
3727     depends(build_environment.dist)(lambda dist: [f"-I{dist}/stl_wrappers"]),
3731 # Perl detection
3732 # ==============================================================
3733 @depends(target)
3734 def need_perl(target):
3735     # Ideally, we'd also depend on gnu_as here, but that adds complications.
3736     return target.cpu == "arm"
3739 perl = check_prog("PERL", ("perl5", "perl"), when=need_perl)
3742 @template
3743 def perl_version_check(min_version):
3744     @depends(perl)
3745     @checking("for minimum required perl version >= %s" % min_version)
3746     def get_perl_version(perl):
3747         return Version(
3748             check_cmd_output(
3749                 perl,
3750                 "-e",
3751                 "print $]",
3752                 onerror=lambda: die("Failed to get perl version."),
3753             )
3754         )
3756     @depends(get_perl_version)
3757     def check_perl_version(version):
3758         if version < min_version:
3759             die("Perl %s or higher is required.", min_version)
3761     @depends(perl)
3762     @checking("for full perl installation")
3763     @imports("subprocess")
3764     def has_full_perl_installation(perl):
3765         ret = subprocess.call([perl, "-e", "use Config; exit(!-d $Config{archlib})"])
3766         return ret == 0
3768     @depends(has_full_perl_installation)
3769     def require_full_perl_installation(has_full_perl_installation):
3770         if not has_full_perl_installation:
3771             die(
3772                 "Cannot find Config.pm or $Config{archlib}. "
3773                 "A full perl installation is required."
3774             )
3777 with only_when(need_perl):
3778     perl_version_check("5.006")
3781 # windows-rs as bootstrappable toolchain
3782 # ==============================================================
3783 # The in-tree windows crate's purpose is to avoid vendoring the
3784 # original windows crate, which is too large.
3785 # The ideal solution would be for cargo to allow exceptions to
3786 # vendoring, but it doesn't.
3787 # The adopted solution is to somehow use the crate contents from
3788 # a directory given via the mozbuild config, or bootstrapped.
3790 # Unfortunately, doing `include!(mozbuild::windows_rs_path!("src/lib.rs"))`
3791 # in the crate's lib.rs, where `mozbuild::windows_rs_path!()` builds
3792 # a path relative to MOZ_WINDOWS_RS_DIR defined below, doesn't work
3793 # because of https://github.com/rust-lang/rust/issues/66920.
3795 # Previous versions of the windows crate had submodules declared
3796 # directly in lib.rs. Annotating each of them with
3797 # `#[path = concat!(mozbuild::windows_rs_path!("path/to/mod.rs"))]`
3798 # unfortunately also didn't work, because of
3799 # https://github.com/rust-lang/rust/issues/48250.
3801 # Thankfully, newer versions of the windows crate now only have an
3802 # `include!` at the end of lib.rs, so we can get away with simply
3803 # replacing it with an `include!` that uses `mozbuild::windows_rs_path!`.
3805 # Well, that was only true up to a certain point, and even newer versions
3806 # are back to using a submodule declared directly in lib.rs.
3807 # To work around that, we use a macro in the mozbuild crate that
3808 # expands to
3809 # ```
3810 # #[path = "/full/path/to/windows-rs/src/lib.rs"]
3811 # mod lib;
3812 # pub use lib::*;
3813 # ```
3814 # where the path is generated at build time instead of relying on more
3815 # macros. This creates a submodule and re-exports everything it contains,
3816 # making the crate appear as the original crate to its users.
3818 # We ensure that the in-tree contents match what we expect based on
3819 # the original crate.
3820 # The expectations are as such:
3821 # - Cargo.toml is identical to the original one with the addition of the
3822 #   following two lines at the end (after an empty line):
3823 #     [dependencies.mozbuild]
3824 #     version = "0.1"
3825 with only_when(target_is_windows & compile_environment):
3826     option(
3827         env="MOZ_WINDOWS_RS_DIR",
3828         nargs=1,
3829         help="Path to the source of the 'windows' Rust crate",
3830     )
3832     @depends(
3833         "MOZ_WINDOWS_RS_DIR",
3834         bootstrap_path(
3835             "windows-rs",
3836             when=depends("MOZ_WINDOWS_RS_DIR")(lambda x: not x),
3837         ),
3838         build_environment.topsrcdir,
3839     )
3840     @checking("for the windows rust crate source")
3841     @imports(_from="__builtin__", _import="open")
3842     @imports("re")
3843     @imports("toml")
3844     def windows_rs_dir(dir, bootstrapped, topsrcdir):
3845         if bootstrapped:
3846             dir = bootstrapped
3847         elif dir:
3848             dir = dir[0]
3850         raw_cargo_toml = open(
3851             os.path.join(topsrcdir, "build/rust/windows/Cargo.toml")
3852         ).read()
3853         cargo_toml = toml.loads(raw_cargo_toml)
3854         expected_version = cargo_toml["package"]["version"]
3856         if not dir:
3857             raise FatalCheckError(
3858                 "Cannot find the windows rust crate source.\n"
3859                 f"Try downloading it with `cargo download -x windows={expected_version}`\n"
3860                 "(you may need to `cargo install cargo-download` first)\n"
3861                 f"and set `MOZ_WINDOWS_RS_DIR` to location of the `windows-{expected_version}`"
3862                 " directory"
3863             )
3865         raw_cargo_toml_orig = open(os.path.join(dir, "Cargo.toml")).read()
3866         cargo_toml = toml.loads(raw_cargo_toml_orig)
3867         version = cargo_toml["package"]["version"]
3868         if version != expected_version:
3869             raise FatalCheckError(
3870                 f"The windows rust crate source in {dir} contains version "
3871                 f"{version}, but expected {expected_version}."
3872             )
3873         # Now that we've done the basic sanity check, let's go deeper.
3874         DEPENDENCIES = '\n[dependencies.mozbuild]\nversion = "0.1"\n'
3875         if not raw_cargo_toml.endswith(DEPENDENCIES):
3876             configure_error("In-tree windows crate is missing dependency on mozbuild")
3877         if raw_cargo_toml[: -len(DEPENDENCIES)] != raw_cargo_toml_orig:
3878             configure_error("In-tree windows crate Cargo.toml doesn't match original")
3880         return dir
3882     set_config("MOZ_WINDOWS_RS_DIR", windows_rs_dir)