no bug - Import translations from android-l10n r=release a=l10n CLOSED TREE
[gecko.git] / toolkit / moz.configure
blob4638de3028e0450f5eac30e5a1c8594fdf702e50
1 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
2 # vim: set filetype=python:
3 # This Source Code Form is subject to the terms of the Mozilla Public
4 # License, v. 2.0. If a copy of the MPL was not distributed with this
5 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 # Set the MOZ_CONFIGURE_OPTIONS variable with all the options that
9 # were passed somehow (environment, command line, mozconfig)
10 @dependable
11 @imports(_from="mozbuild.shellutil", _import="quote")
12 @imports(_from="mozbuild.util", _import="ensure_unicode")
13 @imports(_from="mozbuild.util", _import="system_encoding")
14 @imports("__sandbox__")
15 def all_configure_options():
16     result = []
17     previous = None
18     for option in __sandbox__._options.values():
19         # __sandbox__._options contains items for both option.name and
20         # option.env. But it's also an OrderedDict, meaning both are
21         # consecutive.
22         # Also ignore OLD_CONFIGURE and MOZCONFIG because they're not
23         # interesting.
24         if option == previous or option.env in ("OLD_CONFIGURE", "MOZCONFIG"):
25             continue
26         previous = option
27         value = __sandbox__._value_for(option)
28         # We only want options that were explicitly given on the command
29         # line, the environment, or mozconfig, and that differ from the
30         # defaults.
31         if (
32             value is not None
33             and value.origin not in ("default", "implied")
34             and value != option.default
35         ):
36             result.append(
37                 ensure_unicode(__sandbox__._raw_options[option], system_encoding)
38             )
39         # We however always include options that are sent to old configure
40         # because we don't know their actual defaults. (Keep the conditions
41         # separate for ease of understanding and ease of removal)
42         elif (
43             option.help == "Help missing for old configure options"
44             and option in __sandbox__._raw_options
45         ):
46             result.append(
47                 ensure_unicode(__sandbox__._raw_options[option], system_encoding)
48             )
50     # We shouldn't need this, but currently, quote will return a byte string
51     # if result is empty, and that's not wanted here.
52     if not result:
53         return ""
55     return quote(*result)
58 set_config("MOZ_CONFIGURE_OPTIONS", all_configure_options)
61 @depends(target)
62 def fold_libs(target):
63     return target.os in ("WINNT", "OSX", "iOS", "Android")
66 set_config("MOZ_FOLD_LIBS", fold_libs)
68 # Profiling
69 # ==============================================================
70 # Some of the options here imply an option from js/moz.configure,
71 # so, need to be declared before the include.
73 option(
74     "--enable-jprof",
75     env="MOZ_JPROF",
76     help="Enable jprof profiling tool (needs mozilla/tools/jprof)",
80 @depends("--enable-jprof")
81 def jprof(value):
82     if value:
83         return True
86 set_config("MOZ_JPROF", jprof)
87 set_define("MOZ_JPROF", jprof)
88 imply_option("--enable-profiling", jprof)
90 option("--disable-gecko-profiler", help="Disable the Gecko profiler")
93 @depends("--disable-gecko-profiler", target)
94 def gecko_profiler(enable_gecko_profiler, target):
95     if not enable_gecko_profiler:
96         return False
98     if target.os == "Android":
99         return target.cpu in ("aarch64", "arm", "x86", "x86_64")
100     elif target.kernel == "Linux":
101         return target.cpu in ("aarch64", "arm", "x86", "x86_64", "mips64")
102     elif target.kernel == "FreeBSD":
103         return target.cpu in ("aarch64", "x86_64")
104     return target.kernel in ("Darwin", "WINNT")
107 @depends(gecko_profiler)
108 def gecko_profiler_define(value):
109     if value:
110         return True
113 set_config("MOZ_GECKO_PROFILER", gecko_profiler_define)
114 set_define("MOZ_GECKO_PROFILER", gecko_profiler_define)
117 # Whether code to parse ELF binaries should be compiled for the Gecko profiler
118 # (for symbol table dumping).
119 @depends(gecko_profiler, target)
120 def gecko_profiler_parse_elf(value, target):
121     # Currently we only want to build this code on Linux (including Android) and BSD.
122     # For Android, this is in order to dump symbols from Android system, where
123     # on other platforms there exist alternatives that don't require bloating
124     # up our binary size. For Linux more generally, we use this in profile
125     # pre-symbolication support, since MozDescribeCodeAddress doesn't do
126     # anything useful on that platform. (Ideally, we would update
127     # MozDescribeCodeAddress to call into some Rust crates that parse ELF and
128     # DWARF data, but build system issues currently prevent Rust from being
129     # used in mozglue.)
130     if value and (target.kernel == "Linux" or target.kernel == "FreeBSD"):
131         return True
134 set_config("MOZ_GECKO_PROFILER_PARSE_ELF", gecko_profiler_parse_elf)
135 set_define("MOZ_GECKO_PROFILER_PARSE_ELF", gecko_profiler_parse_elf)
137 # enable this by default if the profiler is enabled
138 # Note: also requires jemalloc
139 set_config("MOZ_PROFILER_MEMORY", gecko_profiler_define)
140 set_define("MOZ_PROFILER_MEMORY", gecko_profiler_define)
143 @depends(
144     "--enable-debug",
145     milestone,
146     build_project,
147     # Artifact builds are included because the downloaded artifacts can
148     # have DMD enabled.
149     when=artifact_builds | depends(when="--enable-replace-malloc")(lambda: True),
151 def dmd_default(debug, milestone, build_project):
152     return bool(build_project == "browser" and (debug or milestone.is_nightly))
155 option(
156     "--enable-dmd",
157     env="MOZ_DMD",
158     default=dmd_default,
159     help="{Enable|Disable} Dark Matter Detector (heap profiler). "
160     "Also enables jemalloc, replace-malloc and profiling",
164 @depends("--enable-dmd")
165 def dmd(value):
166     if value:
167         return True
170 set_config("MOZ_DMD", dmd)
171 set_define("MOZ_DMD", dmd)
172 imply_option("--enable-profiling", dmd)
173 imply_option("--enable-jemalloc", dmd, when=compile_environment)
174 imply_option("--enable-replace-malloc", dmd, when=compile_environment)
177 # midir-based Web MIDI support
178 # ==============================================================
179 @depends(target)
180 def midir_linux_support(target):
181     return (
182         target.kernel == "Linux" and target.os != "Android" and target.cpu != "riscv64"
183     )
186 @depends(target, midir_linux_support)
187 def midir_support(target, midir_linux_support):
188     if target.os in ("WINNT", "OSX") or midir_linux_support:
189         return True
192 set_config("MOZ_WEBMIDI_MIDIR_IMPL", midir_support)
195 # Enable various cubeb backends
196 # ==============================================================
197 @depends(target)
198 def audio_backends_default(target):
199     if target.os == "Android":
200         return (
201             "aaudio",
202             "opensl",
203         )
204     elif target.os in ("DragonFly", "FreeBSD", "SunOS"):
205         return ("oss",)
206     elif target.os == "OpenBSD":
207         return ("sndio",)
208     elif target.kernel == "Darwin":
209         return ("audiounit",)
210     elif target.os == "NetBSD":
211         return ("sunaudio",)
212     elif target.os == "SunOS":
213         return ("sunaudio",)
214     elif target.os == "WINNT":
215         return ("wasapi",)
216     else:
217         return ("pulseaudio",)
220 option(
221     "--enable-audio-backends",
222     nargs="+",
223     choices=(
224         "aaudio",
225         "alsa",
226         "audiounit",
227         "jack",
228         "opensl",
229         "oss",
230         "pulseaudio",
231         "sndio",
232         "sunaudio",
233         "wasapi",
234     ),
235     default=audio_backends_default,
236     help="{Enable|Disable} various cubeb backends",
240 @depends("--enable-audio-backends", target)
241 def imply_aaudio(values, target):
242     if any("aaudio" in value for value in values) and target.os != "Android":
243         die("Cannot enable AAudio on %s", target.os)
244     return any("aaudio" in value for value in values) or None
247 @depends("--enable-audio-backends", target)
248 def imply_alsa(values, target):
249     if (
250         any("alsa" in value for value in values)
251         and target.kernel != "Linux"
252         and target.os != "FreeBSD"
253     ):
254         die("Cannot enable ALSA on %s", target.os)
255     return any("alsa" in value for value in values) or None
258 @depends("--enable-audio-backends", target)
259 def imply_audiounit(values, target):
260     if any("audiounit" in value for value in values) and target.kernel != "Darwin":
261         die("Cannot enable AudioUnit on %s", target.os)
262     return any("audiounit" in value for value in values) or None
265 @depends("--enable-audio-backends")
266 def imply_jack(values):
267     return any("jack" in value for value in values) or None
270 @depends("--enable-audio-backends", target)
271 def imply_opensl(values, target):
272     if any("opensl" in value for value in values) and target.os != "Android":
273         die("Cannot enable OpenSL on %s", target.os)
274     return any("opensl" in value for value in values) or None
277 @depends("--enable-audio-backends", target)
278 def imply_oss(values, target):
279     if any("oss" in value for value in values) and (
280         target.os in ("Android", "OSX", "iOS", "WINNT")
281     ):
282         die("Cannot enable OSS on %s", target.os)
283     return any("oss" in value for value in values) or None
286 @depends("--enable-audio-backends", target)
287 def imply_pulseaudio(values, target):
288     if any("pulseaudio" in value for value in values) and (
289         target.os in ("Android", "OSX", "iOS", "WINNT")
290     ):
291         die("Cannot enable PulseAudio on %s", target.os)
292     return any("pulseaudio" in value for value in values) or None
295 @depends("--enable-audio-backends", target)
296 def imply_sndio(values, target):
297     if any("sndio" in value for value in values) and (
298         target.os in ("Android", "OSX", "iOS", "WINNT")
299     ):
300         die("Cannot enable sndio on %s", target.os)
301     return any("sndio" in value for value in values) or None
304 @depends("--enable-audio-backends", target)
305 def imply_sunaudio(values, target):
306     if any("sunaudio" in value for value in values) and (
307         target.os != "NetBSD" and target.os != "SunOS"
308     ):
309         die("Cannot enable sunaudio on %s", target.os)
310     return any("sunaudio" in value for value in values) or None
313 @depends("--enable-audio-backends", target)
314 def imply_wasapi(values, target):
315     if any("wasapi" in value for value in values) and target.os != "WINNT":
316         die("Cannot enable WASAPI on %s", target.os)
317     return any("wasapi" in value for value in values) or None
320 set_config("MOZ_AAUDIO", imply_aaudio, when="--enable-audio-backends")
322 imply_option("--enable-alsa", imply_alsa, reason="--enable-audio-backends")
324 set_config("MOZ_AUDIOUNIT_RUST", imply_audiounit, when="--enable-audio-backends")
326 imply_option("--enable-jack", imply_jack, reason="--enable-audio-backends")
328 set_config("MOZ_OPENSL", imply_opensl, when="--enable-audio-backends")
330 set_config("MOZ_OSS", imply_oss, when="--enable-audio-backends")
332 imply_option("--enable-pulseaudio", imply_pulseaudio, reason="--enable-audio-backends")
334 imply_option("--enable-sndio", imply_sndio, reason="--enable-audio-backends")
336 set_config("MOZ_SUNAUDIO", imply_sunaudio, when="--enable-audio-backends")
338 set_config("MOZ_WASAPI", imply_wasapi, when="--enable-audio-backends")
340 # ALSA cubeb backend
341 # ==============================================================
342 option("--enable-alsa", env="MOZ_ALSA", help="Enable ALSA audio backend.")
345 @depends("--enable-alsa", midir_linux_support)
346 def enable_alsa_or_midir_linux_support(alsa_enabled, midir_linux_support):
347     return alsa_enabled or midir_linux_support
350 pkg_check_modules("MOZ_ALSA", "alsa", when=enable_alsa_or_midir_linux_support)
352 set_config("MOZ_ALSA", True, when="--enable-alsa")
353 set_define("MOZ_ALSA", True, when="--enable-alsa")
355 # JACK cubeb backend
356 # ==============================================================
357 system_lib_option("--enable-jack", env="MOZ_JACK", help="Enable JACK audio backend.")
359 jack = pkg_check_modules("MOZ_JACK", "jack", when="--enable-jack")
361 set_config("MOZ_JACK", depends_if(jack)(lambda _: True))
363 # PulseAudio cubeb backend
364 # ==============================================================
365 option(
366     "--enable-pulseaudio",
367     env="MOZ_PULSEAUDIO",
368     help="{Enable|Disable} PulseAudio audio backend.",
371 pulseaudio = pkg_check_modules("MOZ_PULSEAUDIO", "libpulse", when="--enable-pulseaudio")
373 set_config("MOZ_PULSEAUDIO", depends_if(pulseaudio)(lambda _: True))
374 set_define("MOZ_PULSEAUDIO", depends_if(pulseaudio)(lambda _: True))
376 # sndio cubeb backend
377 # ==============================================================
378 system_lib_option("--enable-sndio", env="MOZ_SNDIO", help="Enable sndio audio backend.")
380 sndio = pkg_check_modules("MOZ_SNDIO", "sndio", when="--enable-sndio")
382 set_config("MOZ_SNDIO", depends_if(sndio)(lambda _: True))
384 # Javascript engine
385 # ==============================================================
386 include("../js/moz.configure")
389 # NodeJS
390 # ==============================================================
391 include("../build/moz.configure/node.configure")
393 # JsonCpp
394 # ==============================================================
395 set_define("JSON_USE_EXCEPTION", 0)
397 # L10N
398 # ==============================================================
399 option("--with-l10n-base", nargs=1, env="L10NBASEDIR", help="Path to l10n repositories")
402 @depends("--with-l10n-base", "MOZ_AUTOMATION", build_environment)
403 @imports(_from="os.path", _import="isdir")
404 @imports(_from="os.path", _import="expanduser")
405 @imports(_from="os", _import="environ")
406 def l10n_base(value, automation, build_env):
407     if value:
408         path = value[0]
409         if not isdir(path):
410             die("Invalid value --with-l10n-base, %s doesn't exist", path)
411     elif automation:
412         path = os.path.join(build_env.topsrcdir, "../l10n-central")
413     else:
414         path = os.path.join(
415             environ.get(
416                 "MOZBUILD_STATE_PATH", expanduser(os.path.join("~", ".mozbuild"))
417             ),
418             "l10n-central",
419         )
420     return os.path.realpath(os.path.abspath(path))
423 set_config("L10NBASEDIR", l10n_base)
426 # Default toolkit
427 # ==============================================================
428 @depends(target)
429 def toolkit_choices(target):
430     if target.os == "WINNT":
431         return ("cairo-windows",)
432     elif target.os == "OSX":
433         return ("cairo-cocoa",)
434     elif target.os == "iOS":
435         return ("cairo-uikit",)
436     elif target.os == "Android":
437         return ("cairo-android",)
438     else:
439         # cairo-gtk3 - X11 backend with optional Wayland backend (auto detected)
440         # cairo-gtk3-wayland - Wayland backend with optional X11 backend (auto detected)
441         # cairo-gtk3-x11-wayland - builds explicitly with X11 & Wayland backends
442         return (
443             "cairo-gtk3",
444             "cairo-gtk3-wayland",
445             "cairo-gtk3-x11-wayland",
446             "cairo-gtk3-wayland-only",
447             "cairo-gtk3-x11-only",
448         )
451 @depends(toolkit_choices)
452 def toolkit_default(choices):
453     return choices[0]
456 option(
457     "--enable-default-toolkit",
458     nargs=1,
459     choices=toolkit_choices,
460     default=toolkit_default,
461     help="Select default toolkit",
465 @depends("--enable-default-toolkit")
466 def full_toolkit(value):
467     if value:
468         return value[0]
471 @depends(full_toolkit)
472 def toolkit(toolkit):
473     if toolkit.startswith("cairo-gtk3"):
474         widget_toolkit = "gtk"
475     else:
476         widget_toolkit = toolkit.replace("cairo-", "")
477     return widget_toolkit
480 set_config("MOZ_WIDGET_TOOLKIT", toolkit)
481 add_old_configure_assignment("MOZ_WIDGET_TOOLKIT", toolkit)
484 @depends(toolkit)
485 def toolkit_define(toolkit):
486     if toolkit != "windows":
487         return "MOZ_WIDGET_%s" % toolkit.upper()
490 set_define(toolkit_define, True)
493 @depends(toolkit)
494 def toolkit_gtk(toolkit):
495     return toolkit == "gtk"
498 @depends(toolkit_gtk, full_toolkit)
499 def toolkit_gtk_x11(toolkit_gtk, full_toolkit):
500     return toolkit_gtk and full_toolkit != "cairo-gtk3-wayland-only"
503 @depends(full_toolkit)
504 def toolkit_gtk_x11_optional(full_toolkit):
505     return full_toolkit == "cairo-gtk3-wayland"
508 @depends(toolkit_gtk, full_toolkit)
509 def toolkit_gtk_wayland(toolkit_gtk, full_toolkit):
510     return toolkit_gtk and full_toolkit != "cairo-gtk3-x11-only"
513 @depends(full_toolkit)
514 def toolkit_gtk_wayland_optional(full_toolkit):
515     return full_toolkit == "cairo-gtk3"
518 # Wayland support
519 # ==============================================================
520 wayland_headers = pkg_check_modules(
521     "MOZ_WAYLAND",
522     "gtk+-wayland-3.0 >= 3.14 xkbcommon >= 0.4.1",
523     allow_missing=toolkit_gtk_wayland_optional,
524     when=toolkit_gtk_wayland,
528 @depends(wayland_headers, toolkit_gtk, artifact_builds, toolkit_gtk_wayland)
529 def wayland_headers(wayland, toolkit_gtk, artifacts, toolkit_gtk_wayland):
530     if not toolkit_gtk_wayland:
531         return False
532     if toolkit_gtk and artifacts:
533         return True
534     return wayland
537 set_config("MOZ_WAYLAND", depends_if(wayland_headers)(lambda _: True))
538 set_define("MOZ_WAYLAND", depends_if(wayland_headers)(lambda _: True))
541 # Hardware-accelerated video decode with VAAPI and V4L2 on Linux
542 # ==============================================================
543 set_config("MOZ_ENABLE_VAAPI", True, when=toolkit_gtk)
544 set_define("MOZ_ENABLE_VAAPI", True, when=toolkit_gtk)
547 @depends(target, toolkit_gtk)
548 def v4l2(target, toolkit_gtk):
549     # V4L2 decode is only used in GTK/Linux and generally only appears on
550     # embedded SOCs.
551     if target.cpu in ("arm", "aarch64", "riscv64") and toolkit_gtk:
552         return True
555 set_config("MOZ_ENABLE_V4L2", True, when=v4l2)
556 set_define("MOZ_ENABLE_V4L2", True, when=v4l2)
558 # GL Provider
559 # ==============================================================
560 option("--with-gl-provider", nargs=1, help="Set GL provider backend type")
563 @depends("--with-gl-provider")
564 def gl_provider(value):
565     if value:
566         return value[0]
569 @depends(gl_provider)
570 def gl_provider_define(provider):
571     if provider:
572         return "GLContextProvider%s" % provider
575 set_define("MOZ_GL_PROVIDER", gl_provider_define)
578 @depends(gl_provider, toolkit_gtk)
579 def gl_default_provider(value, toolkit_gtk):
580     if value:
581         return value
582     elif toolkit_gtk:
583         return "EGL"
586 set_config("MOZ_GL_PROVIDER", gl_provider)
587 set_config("MOZ_GL_DEFAULT_PROVIDER", gl_default_provider)
590 @depends(gl_default_provider)
591 def gl_provider_define(provider):
592     if provider:
593         return "GL_PROVIDER_%s" % provider
596 set_define(gl_provider_define, True)
599 # PDF printing
600 # ==============================================================
601 @depends(toolkit)
602 def pdf_printing(toolkit):
603     if toolkit in ("windows", "gtk", "android"):
604         return True
607 set_config("MOZ_PDF_PRINTING", pdf_printing)
608 set_define("MOZ_PDF_PRINTING", pdf_printing)
611 # Event loop instrumentation
612 # ==============================================================
613 option(env="MOZ_INSTRUMENT_EVENT_LOOP", help="Force-enable event loop instrumentation")
616 @depends("MOZ_INSTRUMENT_EVENT_LOOP", toolkit)
617 def instrument_event_loop(value, toolkit):
618     if value or (
619         toolkit in ("windows", "gtk", "cocoa", "android") and value.origin == "default"
620     ):
621         return True
624 set_config("MOZ_INSTRUMENT_EVENT_LOOP", instrument_event_loop)
625 set_define("MOZ_INSTRUMENT_EVENT_LOOP", instrument_event_loop)
628 # Fontconfig Freetype
629 # ==============================================================
630 option(env="USE_FC_FREETYPE", help="Force-enable the use of fontconfig freetype")
633 @depends("USE_FC_FREETYPE", toolkit)
634 def fc_freetype(value, toolkit):
635     if value or (toolkit == "gtk" and value.origin == "default"):
636         return True
639 set_define("USE_FC_FREETYPE", fc_freetype)
641 # Pango
642 # ==============================================================
643 pkg_check_modules("MOZ_PANGO", "pango >= 1.22.0", when=toolkit_gtk)
645 # Fontconfig
646 # ==============================================================
647 fontconfig_info = pkg_check_modules(
648     "_FONTCONFIG", "fontconfig >= 2.7.0", when=fc_freetype
652 @depends(fc_freetype)
653 def check_for_freetype2(fc_freetype):
654     if fc_freetype:
655         return True
658 # Check for freetype2. Flags are combined with fontconfig flags.
659 freetype2_info = pkg_check_modules(
660     "_FT2", "freetype2 >= 9.10.3", when=check_for_freetype2
664 @depends(fontconfig_info, freetype2_info)
665 def freetype2_combined_info(fontconfig_info, freetype2_info):
666     if not freetype2_info:
667         return
668     if not fontconfig_info:
669         return freetype2_info
670     return namespace(
671         cflags=freetype2_info.cflags + fontconfig_info.cflags,
672         libs=freetype2_info.libs + fontconfig_info.libs,
673     )
676 set_define("MOZ_HAVE_FREETYPE2", depends_if(freetype2_info)(lambda _: True))
679 # Apple platform decoder support
680 # ==============================================================
681 @depends(toolkit)
682 def applemedia(toolkit):
683     if toolkit in ("cocoa", "uikit"):
684         return True
687 set_config("MOZ_APPLEMEDIA", applemedia)
688 set_define("MOZ_APPLEMEDIA", applemedia)
690 # Windows Media Foundation support
691 # ==============================================================
692 option("--disable-wmf", help="Disable support for Windows Media Foundation")
695 @depends("--disable-wmf", target, "--help")
696 def wmf(value, target, _):
697     enabled = bool(value)
698     if value.origin == "default":
699         # Enable Windows Media Foundation support by default.
700         # Note our minimum SDK version is Windows 7 SDK, so we are (currently)
701         # guaranteed to have a recent-enough SDK to build WMF.
702         enabled = target.os == "WINNT"
703     if enabled and target.os != "WINNT":
704         die("Cannot enable Windows Media Foundation support on %s", target.os)
705     if enabled:
706         return True
709 @depends(artifact_builds, c_compiler, when=wmf)
710 def wmfmediaengine(artifact_builds, c_compiler):
711     if c_compiler:
712         return c_compiler.type == "clang-cl"
713     return bool(artifact_builds)
716 set_config("MOZ_WMF", wmf)
717 set_define("MOZ_WMF", wmf)
719 set_config("MOZ_WMF_MEDIA_ENGINE", True, when=wmfmediaengine)
720 set_define("MOZ_WMF_MEDIA_ENGINE", True, when=wmfmediaengine)
722 # FFmpeg H264/AAC Decoding Support
723 # ==============================================================
724 option("--disable-ffmpeg", help="Disable FFmpeg for fragmented H264/AAC decoding")
727 @depends("--disable-ffmpeg", target)
728 def ffmpeg(value, target):
729     enabled = bool(value)
730     if value.origin == "default":
731         enabled = target.os not in ("Android", "WINNT")
732     if enabled:
733         return True
736 set_config("MOZ_FFMPEG", ffmpeg)
737 set_define("MOZ_FFMPEG", ffmpeg)
739 # AV1 Video Codec Support
740 # ==============================================================
741 option("--disable-av1", help="Disable av1 video support")
744 @depends("--enable-av1")
745 def av1(value):
746     if value:
747         return True
750 @depends(target, when=av1 & compile_environment)
751 def dav1d_asm(target):
752     if target.cpu in ("aarch64", "x86", "x86_64"):
753         return True
756 @depends(target, when=av1 & compile_environment)
757 def dav1d_nasm(target):
758     if target.cpu in ("x86", "x86_64"):
759         return namespace(version="2.14", what="AV1")
762 set_config("MOZ_DAV1D_ASM", dav1d_asm)
763 set_define("MOZ_DAV1D_ASM", dav1d_asm)
764 set_config("MOZ_AV1", av1)
765 set_define("MOZ_AV1", av1)
767 # JXL Image Codec Support
768 # ==============================================================
769 option("--disable-jxl", help="Disable jxl image support")
772 @depends("--disable-jxl", milestone.is_nightly)
773 def jxl(value, is_nightly):
774     if is_nightly and value:
775         return True
778 set_config("MOZ_JXL", jxl)
779 set_define("MOZ_JXL", jxl)
781 set_config("MOZ_SAMPLE_TYPE_FLOAT32", True)
782 set_define("MOZ_SAMPLE_TYPE_FLOAT32", True)
784 set_define("MOZ_VORBIS", True)
785 set_config("MOZ_VORBIS", True)
787 option(
788     "--disable-real-time-tracing",
789     help="Disable tracing of real-time audio callbacks",
792 set_config("MOZ_REAL_TIME_TRACING", True, when="--enable-real-time-tracing")
793 set_define("MOZ_REAL_TIME_TRACING", True, when="--enable-real-time-tracing")
795 # OpenMAX IL Decoding Support
796 # ==============================================================
797 option("--enable-openmax", help="Enable OpenMAX IL for video/audio decoding")
800 @depends("--enable-openmax")
801 def openmax(value):
802     enabled = bool(value)
803     if enabled:
804         return True
807 set_config("MOZ_OMX", openmax)
808 set_define("MOZ_OMX", openmax)
811 # EME Support
812 # ==============================================================
813 @depends(target, wmf)
814 def eme_choices(target, wmf):
815     if (
816         target.kernel in ("WINNT", "Linux")
817         and target.os != "Android"
818         and target.cpu in ("x86", "x86_64")
819     ):
820         if wmf:
821             return ("widevine", "wmfcdm")
822         return ("widevine",)
823     if target.kernel == "WINNT" and target.cpu == "aarch64":
824         return ("widevine",)
825     if target.os in ("OSX"):
826         return ("widevine",)
829 # Widevine is enabled by default in desktop browser builds.
830 @depends(build_project, eme_choices)
831 def eme_default(build_project, choices):
832     if build_project == "browser":
833         return choices
836 option(
837     "--enable-eme",
838     nargs="+",
839     choices=eme_choices,
840     default=eme_default,
841     when=eme_choices,
842     help="{Enable|Disable} support for Encrypted Media Extensions",
846 @depends("--enable-eme", when=eme_choices)
847 def eme_modules(value):
848     return value
851 # Fallback to an empty list when eme_choices is empty, setting eme_modules to
852 # None.
853 set_config("MOZ_EME_MODULES", eme_modules | dependable([]))
856 # Media Foundation CDM support
857 # ==============================================================
858 @depends(eme_modules, when=wmfmediaengine)
859 def wmfcdm(modules):
860     if "wmfcdm" in modules:
861         return True
864 set_config("MOZ_WMF_CDM", True, when=wmfcdm)
865 set_define("MOZ_WMF_CDM", True, when=wmfcdm)
868 option(
869     name="--enable-chrome-format",
870     help="Select FORMAT of chrome files during packaging.",
871     nargs=1,
872     choices=("omni", "jar", "flat"),
873     default="omni",
877 @depends("--enable-chrome-format")
878 def packager_format(value):
879     return value[0]
882 set_config("MOZ_PACKAGER_FORMAT", packager_format)
884 # The packager minifies two different types of files: non-JS (mostly property
885 # files for l10n), and JS.  Setting MOZ_PACKAGER_MINIFY only minifies the
886 # former.  Firefox doesn't yet minify JS, due to concerns about debuggability.
888 # Also, the JS minification setup really only works correctly on Android:
889 # we need extra setup to use the newly-built shell for Linux and Windows,
890 # and cross-compilation for macOS requires some extra care.
893 @depends(target_is_android, "--enable-debug", milestone.is_nightly)
894 def enable_minify_default(is_android, debug, is_nightly):
895     if is_android and not debug and not is_nightly:
896         return ("properties", "js")
897     return ("properties",)
900 option(
901     name="--enable-minify",
902     help="Select types of files to minify during packaging.",
903     nargs="*",
904     choices=("properties", "js"),
905     default=enable_minify_default,
909 @depends("--enable-minify")
910 def enable_minify(value):
911     if "js" in value and "properties" not in value:
912         die("--enable-minify=js requires --enable-minify=properties.")
913     return namespace(
914         properties="properties" in value,
915         js="js" in value,
916     )
919 set_config("MOZ_PACKAGER_MINIFY", True, when=enable_minify.properties)
920 set_config("MOZ_PACKAGER_MINIFY_JS", True, when=enable_minify.js)
923 @depends(host, build_project)
924 def jar_maker_format(host, build_project):
925     # Multilocales for mobile/android use the same mergedirs for all locales,
926     # so we can't use symlinks for those builds.
927     if host.os == "WINNT" or build_project == "mobile/android":
928         return "flat"
929     return "symlink"
932 set_config("MOZ_JAR_MAKER_FILE_FORMAT", jar_maker_format)
935 @depends(toolkit)
936 def omnijar_name(toolkit):
937     # Fennec's static resources live in the assets/ folder of the
938     # APK.  Adding a path to the name here works because we only
939     # have one omnijar file in the final package (which is not the
940     # case on desktop).
941     return "assets/omni.ja" if toolkit == "android" else "omni.ja"
944 set_config("OMNIJAR_NAME", omnijar_name)
946 project_flag("MOZ_PLACES", help="Build Places if required", set_as_define=True)
948 project_flag(
949     "MOZ_SERVICES_HEALTHREPORT",
950     help="Build Firefox Health Reporter Service",
951     set_as_define=True,
954 project_flag(
955     "MOZ_NORMANDY",
956     help="Enable Normandy recipe runner",
957     set_as_define=True,
960 project_flag("MOZ_SERVICES_SYNC", help="Build Sync Services if required")
962 project_flag(
963     "MOZ_ANDROID_HISTORY",
964     help="Enable Android History instead of Places",
965     set_as_define=True,
968 project_flag(
969     "MOZ_DEDICATED_PROFILES",
970     help="Enable dedicated profiles per install",
971     set_as_define=True,
974 project_flag(
975     "MOZ_BLOCK_PROFILE_DOWNGRADE",
976     help="Block users from starting profiles last used by a newer build",
977     set_as_define=True,
981 @depends("MOZ_PLACES", "MOZ_ANDROID_HISTORY")
982 def check_places_and_android_history(places, android_history):
983     if places and android_history:
984         die("Cannot use MOZ_ANDROID_HISTORY alongside MOZ_PLACES.")
985     if not places and not android_history:
986         die("One of MOZ_ANDROID_HISTORY or MOZ_PLACES must be set.")
989 option(
990     env="MOZ_TELEMETRY_REPORTING",
991     default=mozilla_official,
992     help="Enable telemetry reporting",
995 set_define("MOZ_TELEMETRY_REPORTING", True, when="MOZ_TELEMETRY_REPORTING")
998 @depends("MOZ_TELEMETRY_REPORTING", milestone.is_nightly)
999 def telemetry_on_by_default(reporting, is_nightly):
1000     return reporting and is_nightly
1003 set_define("MOZ_TELEMETRY_ON_BY_DEFAULT", True, when=telemetry_on_by_default)
1006 # gpsd support
1007 # ==============================================================
1008 system_lib_option("--enable-gpsd", env="MOZ_GPSD", help="Enable gpsd support")
1011 @depends("--enable-gpsd")
1012 def gpsd(value):
1013     return bool(value)
1016 system_gpsd = pkg_check_modules("MOZ_GPSD", "libgps >= 3.11", when=gpsd)
1018 set_config("MOZ_GPSD", depends_if(system_gpsd)(lambda _: True))
1020 # Miscellaneous programs
1021 # ==============================================================
1023 check_prog("TAR", ("gnutar", "gtar", "tar"))
1024 check_prog("UNZIP", ("unzip",))
1026 # Key files
1027 # ==============================================================
1028 include("../build/moz.configure/keyfiles.configure")
1030 simple_keyfile("Mozilla API")
1032 simple_keyfile("Google Location Service API")
1034 simple_keyfile("Google Safebrowsing API")
1036 id_and_secret_keyfile("Bing API")
1038 simple_keyfile("Adjust SDK")
1040 id_and_secret_keyfile("Leanplum SDK")
1042 simple_keyfile("Pocket API")
1045 # WebRender Debugger integration
1046 # ==============================================================
1048 option(
1049     "--enable-webrender-debugger", help="Build the websocket debug server in WebRender"
1052 set_config(
1053     "MOZ_WEBRENDER_DEBUGGER", depends_if("--enable-webrender-debugger")(lambda _: True)
1056 # Additional system headers defined at the application level
1057 # ==============================================================
1059 option(
1060     "--enable-app-system-headers",
1061     env="MOZ_APP_SYSTEM_HEADERS",
1062     help="Use additional system headers defined in $MOZ_BUILD_APP/app-system-headers.mozbuild",
1066 @depends("--enable-app-system-headers")
1067 def app_system_headers(value):
1068     if value:
1069         return True
1072 set_config("MOZ_APP_SYSTEM_HEADERS", app_system_headers)
1073 set_define("MOZ_APP_SYSTEM_HEADERS", app_system_headers)
1076 # Printing
1077 # ==============================================================
1078 @depends(target)
1079 def printing_default(target):
1080     return target.os != "iOS"
1083 option(
1084     "--disable-printing",
1085     default=printing_default,
1086     help="{Enable|Disable} printing support",
1090 @depends("--disable-printing")
1091 def printing(value):
1092     if value:
1093         return True
1096 set_config("NS_PRINTING", printing)
1097 set_define("NS_PRINTING", printing)
1098 set_define("NS_PRINT_PREVIEW", printing)
1101 # Speech-dispatcher support
1102 # ==============================================================
1103 @depends(toolkit)
1104 def no_speechd_on_non_gtk(toolkit):
1105     if toolkit != "gtk":
1106         return False
1109 imply_option(
1110     "--enable-synth-speechd", no_speechd_on_non_gtk, reason="--enable-default-toolkit"
1113 option("--disable-synth-speechd", help="Disable speech-dispatcher support")
1115 set_config("MOZ_SYNTH_SPEECHD", depends_if("--disable-synth-speechd")(lambda _: True))
1117 # Speech API
1118 # ==============================================================
1119 option("--disable-webspeech", help="Disable support for HTML Speech API")
1122 @depends("--disable-webspeech")
1123 def webspeech(value):
1124     if value:
1125         return True
1128 set_config("MOZ_WEBSPEECH", webspeech)
1129 set_define("MOZ_WEBSPEECH", webspeech)
1131 # Speech API test backend
1132 # ==============================================================
1133 option(
1134     "--enable-webspeechtestbackend",
1135     default=webspeech,
1136     help="{Enable|Disable} support for HTML Speech API Test Backend",
1140 @depends_if("--enable-webspeechtestbackend")
1141 def webspeech_test_backend(value):
1142     return True
1145 set_config("MOZ_WEBSPEECH_TEST_BACKEND", webspeech_test_backend)
1146 set_define("MOZ_WEBSPEECH_TEST_BACKEND", webspeech_test_backend)
1149 # Graphics
1150 # ==============================================================
1151 @depends(target, milestone)
1152 def skia_pdf_default(target, milestone):
1153     return milestone.is_nightly and target.os != "WINNT"
1156 option("--enable-skia-pdf", default=skia_pdf_default, help="{Enable|Disable} Skia PDF")
1158 set_config("MOZ_ENABLE_SKIA_PDF", True, when="--enable-skia-pdf")
1159 set_define("MOZ_ENABLE_SKIA_PDF", True, when="--enable-skia-pdf")
1161 set_config(
1162     "SKIA_INCLUDES",
1163     [
1164         "/gfx/skia",
1165         "/gfx/skia/skia",
1166     ],
1169 system_lib_option(
1170     "--with-system-webp", help="Use system libwebp (located with pkgconfig)"
1173 system_webp = pkg_check_modules(
1174     "MOZ_WEBP", "libwebp >= 1.0.2 libwebpdemux >= 1.0.2", when="--with-system-webp"
1177 set_config("MOZ_SYSTEM_WEBP", depends(when=system_webp)(lambda: True))
1180 # Build Freetype in the tree
1181 # ==============================================================
1182 @depends(target, "--enable-skia-pdf")
1183 def tree_freetype(target, skia_pdf):
1184     if target.os == "Android" or (skia_pdf and target.os == "WINNT"):
1185         return True
1188 set_define("MOZ_TREE_FREETYPE", tree_freetype)
1189 set_config("MOZ_TREE_FREETYPE", tree_freetype)
1191 set_define("HAVE_FT_BITMAP_SIZE_Y_PPEM", tree_freetype)
1192 set_define("HAVE_FT_GLYPHSLOT_EMBOLDEN", tree_freetype)
1193 set_define("HAVE_FT_LOAD_SFNT_TABLE", tree_freetype)
1196 @depends(freetype2_combined_info, tree_freetype, build_environment)
1197 def ft2_info(freetype2_combined_info, tree_freetype, build_env):
1198     if tree_freetype:
1199         return namespace(
1200             cflags=("-I%s/modules/freetype2/include" % build_env.topsrcdir,), libs=()
1201         )
1202     if freetype2_combined_info:
1203         return freetype2_combined_info
1206 set_config("FT2_LIBS", ft2_info.libs)
1209 @depends(target, tree_freetype, freetype2_info)
1210 def enable_cairo_ft(target, tree_freetype, freetype2_info):
1211     # Avoid defining MOZ_ENABLE_CAIRO_FT on Windows platforms because
1212     # "cairo-ft-font.c" includes <dlfcn.h>, which only exists on posix platforms
1213     return freetype2_info or (tree_freetype and target.os != "WINNT")
1216 set_config("MOZ_ENABLE_CAIRO_FT", True, when=enable_cairo_ft)
1217 set_config("CAIRO_FT_CFLAGS", ft2_info.cflags, when=enable_cairo_ft)
1220 # WebDriver (HTTP / BiDi)
1221 # ==============================================================
1223 # WebDriver is a remote control interface that enables introspection and
1224 # control of user agents. It provides a platform- and language-neutral wire
1225 # protocol as a way for out-of-process programs to remotely instruct the
1226 # behavior of web browsers.
1228 # The Gecko implementation is backed by Marionette and Remote Agent.
1229 # Both protocols are not really toolkit features, as much as Gecko engine
1230 # features. But they are enabled based on the toolkit, so here it lives.
1232 # Marionette remote protocol
1233 # -----------------------------------------------------------
1235 # Marionette is the Gecko remote protocol used for various remote control,
1236 # automation, and testing purposes throughout Gecko-based applications like
1237 # Firefox, Thunderbird, and any mobile browser built upon GeckoView.
1239 # It also backs ../testing/geckodriver, which is Mozilla's WebDriver
1240 # implementation.
1242 # The source of Marionette lives in ../remote/marionette.
1244 # For more information, see:
1245 # https://firefox-source-docs.mozilla.org/testing/marionette/index.html
1247 # Remote Agent (WebDriver BiDi / partial CDP)
1248 # -----------------------------------------------------------
1250 # The primary purpose is the implementation of the WebDriver BiDi specification.
1251 # But it also complements the existing Firefox Developer Tools Remote Debugging
1252 # Protocol (RDP) by implementing a subset of the Chrome DevTools Protocol (CDP).
1254 # The source of Remote Agent lives in ../remote.
1256 # For more information, see:
1257 # https://firefox-source-docs.mozilla.org/remote/index.html
1260 option(
1261     "--disable-webdriver",
1262     help="Disable support for WebDriver remote protocols",
1266 @depends("--disable-webdriver")
1267 def webdriver(enabled):
1268     if enabled:
1269         return True
1272 set_config("ENABLE_WEBDRIVER", webdriver)
1273 set_define("ENABLE_WEBDRIVER", webdriver)
1276 # geckodriver WebDriver implementation
1277 # ==============================================================
1279 # Turn off geckodriver for build configs we don't handle yet,
1280 # but allow --enable-geckodriver to override when compile environment is available.
1281 # --disable-tests implies disabling geckodriver.
1282 # Disable building in CI
1285 @depends(
1286     "--enable-tests", target, cross_compiling, hazard_analysis, asan, "MOZ_AUTOMATION"
1288 def geckodriver_default(enable_tests, target, cross_compile, hazard, asan, automation):
1289     if not enable_tests:
1290         return False
1291     if hazard or target.os == "Android" or (asan and cross_compile):
1292         return False
1293     if automation:
1294         return False
1295     return True
1298 option(
1299     "--enable-geckodriver",
1300     default=geckodriver_default,
1301     when="--enable-compile-environment",
1302     help="{Build|Do not build} geckodriver",
1306 @depends("--enable-geckodriver", when="--enable-compile-environment")
1307 def geckodriver(enabled):
1308     if enabled:
1309         return True
1312 set_config("MOZ_GECKODRIVER", geckodriver)
1315 # WebRTC
1316 # ========================================================
1317 @depends(target)
1318 def webrtc_default(target):
1319     # Turn off webrtc for OS's we don't handle yet, but allow
1320     # --enable-webrtc to override.
1321     os_match = target.kernel in (
1322         "Linux",
1323         "WINNT",
1324         "DragonFly",
1325         "FreeBSD",
1326         "kFreeBSD",
1327         "NetBSD",
1328         "OpenBSD",
1329     )
1331     if not os_match:
1332         os_match = target.os in ("OSX",)
1334     cpu_match = target.cpu in (
1335         "x86_64",
1336         "arm",
1337         "aarch64",
1338         "x86",
1339         "ia64",
1340         "mips32",
1341         "mips64",
1342         "ppc",
1343         "ppc64",
1344         "riscv64",
1345     )
1347     return os_match and cpu_match and target.endianness == "little"
1350 option(
1351     "--disable-webrtc",
1352     default=webrtc_default,
1353     help="{Enable|Disable} support for WebRTC",
1357 @depends("--disable-webrtc")
1358 def webrtc(enabled):
1359     if enabled:
1360         return True
1363 set_config("MOZ_WEBRTC", webrtc)
1364 set_define("MOZ_WEBRTC", webrtc)
1365 set_config("MOZ_SCTP", webrtc)
1366 set_define("MOZ_SCTP", webrtc)
1367 set_config("MOZ_SRTP", webrtc)
1368 set_define("MOZ_SRTP", webrtc)
1369 set_config("MOZ_WEBRTC_SIGNALING", webrtc)
1370 set_define("MOZ_WEBRTC_SIGNALING", webrtc)
1371 set_config("MOZ_PEERCONNECTION", webrtc)
1372 set_define("MOZ_PEERCONNECTION", webrtc)
1373 # MOZ_WEBRTC_ASSERT_ALWAYS turns on a number of safety asserts in
1374 # opt/production builds (via MOZ_CRASH())
1375 set_config("MOZ_WEBRTC_ASSERT_ALWAYS", webrtc)
1376 set_define("MOZ_WEBRTC_ASSERT_ALWAYS", webrtc)
1378 # RAW media
1379 # ==============================================================
1382 @depends(target, webrtc)
1383 def raw_media_default(target, webrtc):
1384     if target.os == "Android":
1385         return True
1386     if webrtc:
1387         return True
1390 option(
1391     "--enable-raw",
1392     default=raw_media_default,
1393     help="{Enable|Disable} support for RAW media",
1396 set_config("MOZ_RAW", depends_if("--enable-raw")(lambda _: True))
1397 set_define("MOZ_RAW", depends_if("--enable-raw")(lambda _: True))
1400 # X11
1401 # ==============================================================
1402 @depends(webrtc, when=toolkit_gtk)
1403 def x11_libs(webrtc):
1404     libs = [
1405         "x11",
1406         "xcb",
1407         "xcb-shm",
1408         "x11-xcb",
1409         "xext",
1410         "xrandr >= 1.4.0",
1411     ]
1412     if webrtc:
1413         # third_party/libwebrtc/webrtc/webrtc_gn/moz.build adds those
1414         # manually, ensure they're available.
1415         libs += [
1416             "xcomposite",
1417             "xcursor",
1418             "xdamage",
1419             "xfixes",
1420             "xi",
1421         ]
1422     return libs
1425 x11_headers = pkg_check_modules(
1426     "MOZ_X11",
1427     x11_libs,
1428     allow_missing=toolkit_gtk_x11_optional,
1429     when=toolkit_gtk_x11,
1433 set_config("MOZ_X11", True, when=x11_headers)
1434 set_define("MOZ_X11", True, when=x11_headers)
1436 pkg_check_modules(
1437     "MOZ_X11_SM",
1438     ["ice", "sm"],
1439     cflags_only=True,
1440     allow_missing=toolkit_gtk_x11_optional,
1441     when=toolkit_gtk_x11,
1445 # ASan Reporter Addon
1446 # ==============================================================
1447 option(
1448     "--enable-address-sanitizer-reporter",
1449     help="Enable Address Sanitizer Reporter Extension",
1453 @depends("--enable-address-sanitizer-reporter")
1454 def enable_asan_reporter(value):
1455     if value:
1456         return True
1459 set_config("MOZ_ASAN_REPORTER", enable_asan_reporter)
1460 set_define("MOZ_ASAN_REPORTER", enable_asan_reporter)
1462 # Checks for library functions
1463 # ==============================================================
1464 with only_when(compile_environment & depends(target.os)(lambda os: os != "WINNT")):
1465     set_define("HAVE_STAT64", check_symbol("stat64"))
1466     set_define("HAVE_LSTAT64", check_symbol("lstat64"))
1467     set_define("HAVE_TRUNCATE64", check_symbol("truncate64"))
1468     set_define("HAVE_STATVFS64", check_symbol("statvfs64"))
1469     set_define("HAVE_STATVFS", check_symbol("statvfs"))
1470     set_define("HAVE_STATFS64", check_symbol("statfs64"))
1471     set_define("HAVE_STATFS", check_symbol("statfs"))
1472     set_define("HAVE_LUTIMES", check_symbol("lutimes"))
1473     set_define("HAVE_POSIX_FADVISE", check_symbol("posix_fadvise"))
1474     set_define("HAVE_POSIX_FALLOCATE", check_symbol("posix_fallocate"))
1475     set_define("HAVE_EVENTFD", check_symbol("eventfd"))
1477     have_arc4random = check_symbol("arc4random")
1478     set_define("HAVE_ARC4RANDOM", have_arc4random)
1479     set_define("HAVE_ARC4RANDOM_BUF", check_symbol("arc4random_buf"))
1480     set_define("HAVE_MALLINFO", check_symbol("mallinfo"))
1482 # Checks for headers
1483 # ==============================================================
1484 with only_when(compile_environment & depends(target.os)(lambda os: os != "WINNT")):
1485     set_define("HAVE_SYSIOCCOM_H", check_header("sys/ioccom.h"))
1487 # Elfhack
1488 # ==============================================================
1489 with only_when("--enable-compile-environment"):
1491     @depends(host, target)
1492     def has_elfhack(host, target):
1493         return (
1494             target.kernel == "Linux"
1495             and host.kernel == "Linux"
1496             and target.cpu in ("arm", "aarch64", "x86", "x86_64")
1497         )
1499     option(
1500         "--disable-elf-hack",
1501         nargs="?",
1502         choices=("legacy", "relr"),
1503         help="{Enable|Disable} elf hacks",
1504         when=has_elfhack,
1505     )
1507     @depends("--enable-elf-hack", when=has_elfhack)
1508     def may_enable_legacy_elfhack(enable):
1509         if enable and enable != ("relr",):
1510             return enable
1512     @depends("--enable-elf-hack", when=has_elfhack)
1513     def may_enable_relrhack(enable):
1514         if enable and enable != ("legacy",):
1515             return enable
1517     @depends(
1518         have_arc4random,
1519         android_version,
1520         when=target_has_linux_kernel,
1521     )
1522     def may_use_pack_relative_relocs(have_arc4random, android_version):
1523         # Packed relative relocations are only supported on Android since
1524         # version 11 (API 30), and in glibc since version 2.36.
1525         # glibc 2.36 also added the arc4random function, which is our proxy
1526         # to detect this (or newer) version being used.
1527         # When targetting those newer versions, we allow ourselves to use
1528         # packed relative relocations rather than elfhack.
1529         if android_version:
1530             return android_version >= 30
1531         return have_arc4random
1533     @depends(
1534         c_compiler,
1535         extra_toolchain_flags,
1536         linker_ldflags,
1537         readelf,
1538         when=may_use_pack_relative_relocs | may_enable_relrhack,
1539     )
1540     @checking("for -z pack-relative-relocs option to ld", bool)
1541     @imports(_from="__builtin__", _import="FileNotFoundError")
1542     @imports("os")
1543     @imports(_from="tempfile", _import="mkstemp")
1544     @imports("textwrap")
1545     def has_pack_relative_relocs(
1546         c_compiler,
1547         extra_toolchain_flags,
1548         linker_ldflags,
1549         readelf,
1550     ):
1551         try:
1552             fd, path = mkstemp(prefix="conftest.")
1553             os.close(fd)
1555             pack_rel_relocs = ["-Wl,-z,pack-relative-relocs"]
1556             if (
1557                 try_invoke_compiler(
1558                     # No configure_cache because it would not create the
1559                     # expected output file.
1560                     None,
1561                     [c_compiler.compiler] + c_compiler.flags,
1562                     c_compiler.language,
1563                     # The resulting binary is expected to have relative
1564                     # relocations, the `ptr` variable attempts to ensure
1565                     # there is at least one. This requires the executable
1566                     # being built as position independent.
1567                     "int main() { return 0; }\nint (*ptr)() = main;",
1568                     pack_rel_relocs
1569                     + ["-pie", "-o", path]
1570                     + (extra_toolchain_flags or [])
1571                     + linker_ldflags,
1572                     wrapper=c_compiler.wrapper,
1573                     onerror=lambda: None,
1574                 )
1575                 is not None
1576             ):
1577                 # BFD ld ignores options it doesn't understand. So check
1578                 # that we did get packed relative relocations (DT_RELR).
1579                 env = os.environ.copy()
1580                 env["LANG"] = "C"
1581                 dyn = check_cmd_output(readelf, "-d", path, env=env).splitlines()
1582                 tags = [
1583                     int(l.split()[0], 16) for l in dyn if l.strip().startswith("0x")
1584                 ]
1585                 # Older versions of readelf don't know about DT_RELR but will
1586                 # still display the tag number.
1587                 if 0x23 in tags:
1588                     needed = [l for l in dyn if l.split()[1:2] == ["(NEEDED)"]]
1589                     is_glibc = any(l.endswith("[libc.so.6]") for l in needed)
1590                     # The mold linker doesn't add a GLIBC_ABI_DT_RELR version
1591                     # dependency, which ld.so doesn't like.
1592                     # https://github.com/rui314/mold/issues/653#issuecomment-1670274638
1593                     if is_glibc:
1594                         versions = check_cmd_output(readelf, "-V", path, env=env)
1595                         if "GLIBC_ABI_DT_RELR" in versions.split():
1596                             return pack_rel_relocs
1597                     else:
1598                         return pack_rel_relocs
1599         finally:
1600             try:
1601                 os.remove(path)
1602             except FileNotFoundError:
1603                 pass
1605     @depends(
1606         has_pack_relative_relocs,
1607         may_enable_legacy_elfhack,
1608         may_enable_relrhack,
1609         may_use_pack_relative_relocs,
1610         when=has_pack_relative_relocs,
1611     )
1612     def pack_relative_relocs_flags(
1613         flags,
1614         may_enable_legacy_elfhack,
1615         may_enable_relrhack,
1616         may_use_pack_relative_relocs,
1617     ):
1618         # When relrhack is enabled, we don't pass the flag to the linker because
1619         # relrhack will take care of it.
1620         if may_enable_relrhack and may_enable_relrhack.origin != "default":
1621             return None
1622         # if elfhack is explicitly enabled instead of relrhack, we prioritize it
1623         # over packed relative relocs.
1624         if may_enable_legacy_elfhack and may_enable_legacy_elfhack.origin != "default":
1625             return None
1626         if may_use_pack_relative_relocs:
1627             return flags
1629     add_old_configure_assignment("PACK_REL_RELOC_FLAGS", pack_relative_relocs_flags)
1631     @depends(
1632         select_linker,
1633         pack_relative_relocs_flags,
1634         has_pack_relative_relocs,
1635         may_enable_legacy_elfhack,
1636         may_enable_relrhack,
1637         when=has_elfhack,
1638     )
1639     def which_elf_hack(
1640         linker,
1641         pack_relative_relocs_flags,
1642         has_pack_relative_relocs,
1643         may_enable_legacy_elfhack,
1644         may_enable_relrhack,
1645     ):
1646         if pack_relative_relocs_flags:
1647             return
1648         if may_enable_relrhack:
1649             if has_pack_relative_relocs:
1650                 return "relr"
1651             elif (
1652                 may_enable_relrhack.origin != "default"
1653                 and not may_enable_legacy_elfhack
1654             ):
1655                 die(
1656                     "Cannot enable relrhack without linker support for -z pack-relative-relocs"
1657                 )
1658         if may_enable_legacy_elfhack:
1659             if linker and linker.KIND in ("lld", "mold"):
1660                 if may_enable_legacy_elfhack.origin != "default":
1661                     die(
1662                         f"Cannot enable elfhack with {linker.KIND}."
1663                         " Use --enable-linker=bfd, --enable-linker=gold, or --disable-elf-hack"
1664                     )
1665             else:
1666                 return "legacy"
1668     set_config(
1669         "USE_ELF_HACK", True, when=depends(which_elf_hack)(lambda x: x == "legacy")
1670     )
1672     use_relrhack = depends(which_elf_hack)(lambda x: x == "relr")
1673     set_config("RELRHACK", True, when=use_relrhack)
1675     @depends(c_compiler, linker_ldflags, when=use_relrhack)
1676     def relrhack_real_linker(c_compiler, linker_ldflags):
1677         ld = "ld"
1678         for flag in linker_ldflags:
1679             if flag.startswith("-fuse-ld="):
1680                 ld = "ld." + flag[len("-fuse-ld=") :]
1681         ld = check_cmd_output(
1682             c_compiler.compiler, f"--print-prog-name={ld}", *c_compiler.flags
1683         )
1684         return ld.rstrip()
1686     @depends(relrhack_real_linker, when=use_relrhack)
1687     def relrhack_linker(ld):
1688         return os.path.basename(ld)
1690     set_config("RELRHACK_LINKER", relrhack_linker)
1692     std_filesystem = host_cxx_compiler.try_run(
1693         header="#include <filesystem>",
1694         body='auto foo = std::filesystem::absolute("");',
1695         flags=host_linker_ldflags,
1696         when=use_relrhack,
1697         onerror=lambda: None,
1698     )
1700     stdcxxfs = host_cxx_compiler.try_run(
1701         header="#include <filesystem>",
1702         body='auto foo = std::filesystem::absolute("");',
1703         flags=depends(host_linker_ldflags)(
1704             lambda flags: (flags or []) + ["-lstdc++fs"]
1705         ),
1706         check_msg="whether std::filesystem requires -lstdc++fs",
1707         when=use_relrhack & depends(std_filesystem)(lambda x: not x),
1708         onerror=lambda: None,
1709     )
1711     set_config("RELRHACK_LIBS", ["stdc++fs"], when=stdcxxfs)
1713     @depends(build_environment, relrhack_real_linker, when=use_relrhack)
1714     def relrhack_ldflags(build_env, ld):
1715         flags = [
1716             "-B",
1717             os.path.join(build_env.topobjdir, "build", "unix", "elfhack"),
1718         ]
1719         if os.path.basename(ld) != ld:
1720             flags.append(f"-Wl,--real-linker,{ld}")
1721         return flags
1723     set_config("RELRHACK_LDFLAGS", relrhack_ldflags)
1726 @depends(build_environment)
1727 def idl_roots(build_env):
1728     return namespace(
1729         ipdl_root=os.path.join(build_env.topobjdir, "ipc", "ipdl"),
1730         webidl_root=os.path.join(build_env.topobjdir, "dom", "bindings"),
1731         xpcom_root=os.path.join(build_env.topobjdir, "xpcom", "components"),
1732     )
1735 set_config("WEBIDL_ROOT", idl_roots.webidl_root)
1736 set_config("IPDL_ROOT", idl_roots.ipdl_root)
1737 set_config("XPCOM_ROOT", idl_roots.xpcom_root)
1739 # Proxy bypass protection
1740 # ==============================================================
1742 option(
1743     "--enable-proxy-bypass-protection",
1744     help="Prevent suspected or confirmed proxy bypasses",
1748 @depends_if("--enable-proxy-bypass-protection")
1749 def proxy_bypass_protection(_):
1750     return True
1753 set_config("MOZ_PROXY_BYPASS_PROTECTION", proxy_bypass_protection)
1754 set_define("MOZ_PROXY_BYPASS_PROTECTION", proxy_bypass_protection)
1756 # Proxy direct failover
1757 # ==============================================================
1759 option(
1760     "--disable-proxy-direct-failover",
1761     help="Disable direct failover for system requests",
1765 @depends_if("--disable-proxy-direct-failover")
1766 def proxy_direct_failover(value):
1767     if value:
1768         return True
1771 set_config("MOZ_PROXY_DIRECT_FAILOVER", proxy_direct_failover)
1772 set_define("MOZ_PROXY_DIRECT_FAILOVER", proxy_direct_failover)
1774 # MIDL
1775 # ==============================================================
1778 @depends(c_compiler, toolchain_prefix)
1779 def midl_names(c_compiler, toolchain_prefix):
1780     if c_compiler and c_compiler.type in ["gcc", "clang"]:
1781         # mingw
1782         widl = ("widl",)
1783         if toolchain_prefix:
1784             prefixed = tuple("%s%s" % (p, "widl") for p in toolchain_prefix)
1785             widl = prefixed + widl
1786         return widl
1788     return ("midl.exe",)
1791 @depends(target, "--enable-compile-environment")
1792 def check_for_midl(target, compile_environment):
1793     if target.os != "WINNT":
1794         return
1796     if compile_environment:
1797         return True
1800 midl = check_prog(
1801     "MIDL",
1802     midl_names,
1803     when=check_for_midl,
1804     allow_missing=True,
1805     paths=sdk_bin_path,
1806     # MIDL being used from a python wrapper script, we can live with it
1807     # having spaces.
1808     allow_spaces=True,
1811 option(env="MIDL_FLAGS", nargs=1, help="Extra flags to pass to MIDL")
1814 @depends(
1815     "MIDL_FLAGS",
1816     target,
1817     midl,
1818     when=depends(midl, target)(lambda m, t: m and t.kernel == "WINNT"),
1820 def midl_flags(flags, target, midl):
1821     if flags:
1822         flags = flags[0].split()
1823     else:
1824         flags = []
1826     if not midl.endswith("widl"):
1827         env = {
1828             "x86": "win32",
1829             "x86_64": "x64",
1830             "aarch64": "arm64",
1831         }[target.cpu]
1832         return flags + ["-nologo", "-no_cpp", "-env", env]
1834     # widl
1835     return (
1836         flags
1837         + {
1838             "x86": ["--win32", "-m32"],
1839             "x86_64": ["--win64", "-m64"],
1840         }[target.cpu]
1841     )
1844 set_config("MIDL_FLAGS", midl_flags)
1846 # Accessibility
1847 # ==============================================================
1849 option("--disable-accessibility", help="Disable accessibility support")
1852 @depends("--enable-accessibility", check_for_midl, midl, c_compiler)
1853 def accessibility(value, check_for_midl, midl, c_compiler):
1854     enabled = bool(value)
1856     if not enabled:
1857         return
1859     if check_for_midl and not midl:
1860         if c_compiler and c_compiler.type in ("gcc", "clang"):
1861             die(
1862                 "You have accessibility enabled, but widl could not be found. "
1863                 "Add --disable-accessibility to your mozconfig or install widl. "
1864                 "See https://developer.mozilla.org/en-US/docs/Cross_Compile_Mozilla_for_Mingw32 for details."
1865             )
1866         else:
1867             die(
1868                 "MIDL could not be found. "
1869                 "Building accessibility without MIDL is not supported."
1870             )
1872     return enabled
1875 set_config("ACCESSIBILITY", accessibility)
1876 set_define("ACCESSIBILITY", accessibility)
1879 @depends(moz_debug, developer_options)
1880 def a11y_log(debug, developer_options):
1881     return debug or developer_options
1884 set_config("A11Y_LOG", True, when=a11y_log)
1885 set_define("A11Y_LOG", True, when=a11y_log)
1888 # Addon signing
1889 # ==============================================================
1890 @depends(milestone)
1891 def require_signing(milestone):
1892     return milestone.is_release_or_beta and not milestone.is_esr
1895 option(
1896     env="MOZ_REQUIRE_SIGNING",
1897     default=require_signing,
1898     help="Enforce that add-ons are signed by the trusted root",
1901 set_config("MOZ_REQUIRE_SIGNING", True, when="MOZ_REQUIRE_SIGNING")
1902 set_define("MOZ_REQUIRE_SIGNING", True, when="MOZ_REQUIRE_SIGNING")
1904 option(
1905     "--with-unsigned-addon-scopes",
1906     nargs="+",
1907     choices=("app", "system"),
1908     help="Addon scopes where signature is not required",
1912 @depends("--with-unsigned-addon-scopes")
1913 def unsigned_addon_scopes(scopes):
1914     return namespace(
1915         app="app" in scopes or None,
1916         system="system" in scopes or None,
1917     )
1920 set_config("MOZ_UNSIGNED_APP_SCOPE", unsigned_addon_scopes.app)
1921 set_config("MOZ_UNSIGNED_SYSTEM_SCOPE", unsigned_addon_scopes.system)
1924 # Addon sideloading
1925 # ==============================================================
1926 option(
1927     "--allow-addon-sideload",
1928     default=milestone.is_esr,
1929     help="Addon sideloading is allowed",
1933 set_config("MOZ_ALLOW_ADDON_SIDELOAD", True, when="--allow-addon-sideload")
1935 # WebExtensions API WebIDL bindings
1936 # ==============================================================
1939 @depends(milestone)
1940 def extensions_webidl_bindings_default(milestone):
1941     # Only enable the webidl bindings for the WebExtensions APIs
1942     # in Nightly.
1943     return milestone.is_nightly
1946 option(
1947     "--enable-extensions-webidl-bindings",
1948     default=extensions_webidl_bindings_default,
1949     help="{Enable|Disable} building experimental WebExtensions WebIDL bindings",
1953 @depends("--enable-extensions-webidl-bindings")
1954 def extensions_webidl_enabled(value):
1955     return bool(value)
1958 set_config("MOZ_WEBEXT_WEBIDL_ENABLED", extensions_webidl_enabled)
1960 # Launcher process (Windows only)
1961 # ==============================================================
1964 @depends(target)
1965 def launcher_process_default(target):
1966     return target.os == "WINNT"
1969 option(
1970     "--enable-launcher-process",
1971     default=launcher_process_default,
1972     help="{Enable|Disable} launcher process by default",
1976 @depends("--enable-launcher-process", target)
1977 def launcher(value, target):
1978     enabled = bool(value)
1979     if enabled and target.os != "WINNT":
1980         die("Cannot enable launcher process on %s", target.os)
1981     if enabled:
1982         return True
1985 set_config("MOZ_LAUNCHER_PROCESS", launcher)
1986 set_define("MOZ_LAUNCHER_PROCESS", launcher)
1988 # llvm-dlltool (Windows only)
1989 # ==============================================================
1992 @depends(build_project, target, "--enable-compile-environment")
1993 def check_for_llvm_dlltool(build_project, target, compile_environment):
1994     if build_project != "browser":
1995         return
1997     if target.os != "WINNT":
1998         return
2000     return compile_environment
2003 llvm_dlltool = check_prog(
2004     "LLVM_DLLTOOL",
2005     ("llvm-dlltool",),
2006     what="llvm-dlltool",
2007     when=check_for_llvm_dlltool,
2008     paths=clang_search_path,
2012 @depends(target, when=llvm_dlltool)
2013 def llvm_dlltool_flags(target):
2014     arch = {
2015         "x86": "i386",
2016         "x86_64": "i386:x86-64",
2017         "aarch64": "arm64",
2018     }[target.cpu]
2020     return ["-m", arch]
2023 set_config("LLVM_DLLTOOL_FLAGS", llvm_dlltool_flags)
2025 # BITS download (Windows only)
2026 # ==============================================================
2028 option(
2029     "--enable-bits-download",
2030     when=target_is_windows,
2031     default=target_is_windows,
2032     help="{Enable|Disable} building BITS download support",
2035 set_define(
2036     "MOZ_BITS_DOWNLOAD",
2037     depends_if("--enable-bits-download", when=target_is_windows)(lambda _: True),
2039 set_config(
2040     "MOZ_BITS_DOWNLOAD",
2041     depends_if("--enable-bits-download", when=target_is_windows)(lambda _: True),
2044 # Bundled fonts on desktop platform
2045 # ==============================================================
2048 @depends(target)
2049 def bundled_fonts_default(target):
2050     return target.os == "WINNT" or target.kernel == "Linux"
2053 @depends(build_project)
2054 def allow_bundled_fonts(project):
2055     return project == "browser" or project == "comm/mail"
2058 option(
2059     "--enable-bundled-fonts",
2060     default=bundled_fonts_default,
2061     when=allow_bundled_fonts,
2062     help="{Enable|Disable} support for bundled fonts on desktop platforms",
2065 set_define(
2066     "MOZ_BUNDLED_FONTS",
2067     depends_if("--enable-bundled-fonts", when=allow_bundled_fonts)(lambda _: True),
2070 # Reflow counting
2071 # ==============================================================
2074 @depends(moz_debug)
2075 def reflow_perf(debug):
2076     if debug:
2077         return True
2080 option(
2081     "--enable-reflow-perf",
2082     default=reflow_perf,
2083     help="{Enable|Disable} reflow performance tracing",
2086 # The difference in conditions here comes from the initial implementation
2087 # in old-configure, which was unexplained there as well.
2088 set_define("MOZ_REFLOW_PERF", depends_if("--enable-reflow-perf")(lambda _: True))
2089 set_define("MOZ_REFLOW_PERF_DSP", reflow_perf)
2091 # Layout debugger
2092 # ==============================================================
2095 @depends(moz_debug)
2096 def layout_debugger(debug):
2097     if debug:
2098         return True
2101 option(
2102     "--enable-layout-debugger",
2103     default=layout_debugger,
2104     help="{Enable|Disable} layout debugger",
2107 set_config("MOZ_LAYOUT_DEBUGGER", True, when="--enable-layout-debugger")
2108 set_define("MOZ_LAYOUT_DEBUGGER", True, when="--enable-layout-debugger")
2111 # Shader Compiler for Windows (and MinGW Cross Compile)
2112 # ==============================================================
2114 with only_when(compile_environment):
2115     fxc = check_prog(
2116         "FXC",
2117         ("fxc.exe", "fxc2.exe"),
2118         when=depends(target)(lambda t: t.kernel == "WINNT"),
2119         paths=sdk_bin_path,
2120         # FXC being used from a python wrapper script, we can live with it
2121         # having spaces.
2122         allow_spaces=True,
2123     )
2126 # VPX
2127 # ===
2129 with only_when(compile_environment):
2130     system_lib_option(
2131         "--with-system-libvpx", help="Use system libvpx (located with pkgconfig)"
2132     )
2134     with only_when("--with-system-libvpx"):
2135         vpx = pkg_check_modules("MOZ_LIBVPX", "vpx >= 1.10.0")
2137         check_header(
2138             "vpx/vpx_decoder.h",
2139             flags=vpx.cflags,
2140             onerror=lambda: die(
2141                 "Couldn't find vpx/vpx_decoder.h, which is required to build "
2142                 "with system libvpx. Use --without-system-libvpx to build "
2143                 "with in-tree libvpx."
2144             ),
2145         )
2147         check_symbol(
2148             "vpx_codec_dec_init_ver",
2149             flags=vpx.libs,
2150             onerror=lambda: die(
2151                 "--with-system-libvpx requested but symbol vpx_codec_dec_init_ver "
2152                 "not found"
2153             ),
2154         )
2156         set_config("MOZ_SYSTEM_LIBVPX", True)
2158     @depends("--with-system-libvpx", target)
2159     def in_tree_vpx(system_libvpx, target):
2160         if system_libvpx:
2161             return
2163         arm_asm = (target.cpu == "arm") or None
2164         return namespace(arm_asm=arm_asm)
2166     @depends(target, when=in_tree_vpx)
2167     def vpx_nasm(target):
2168         if target.cpu in ("x86", "x86_64"):
2169             if target.kernel == "WINNT":
2170                 # Version 2.03 is needed for automatic safeseh support.
2171                 return namespace(version="2.03", what="VPX")
2172             return namespace(what="VPX")
2174     @depends(in_tree_vpx, vpx_nasm, target, neon_flags)
2175     def vpx_as_flags(vpx, vpx_nasm, target, neon_flags):
2176         if vpx and vpx.arm_asm:
2177             # These flags are a lie; they're just used to enable the requisite
2178             # opcodes; actual arch detection is done at runtime.
2179             return neon_flags
2180         elif vpx and vpx_nasm and target.os != "WINNT" and target.cpu != "x86_64":
2181             return ("-DPIC",)
2183     set_config("VPX_USE_NASM", True, when=vpx_nasm)
2184     set_config("VPX_ASFLAGS", vpx_as_flags)
2187 # JPEG
2188 # ====
2190 with only_when(compile_environment):
2191     system_lib_option(
2192         "--with-system-jpeg",
2193         nargs="?",
2194         help="Use system libjpeg (installed at given prefix)",
2195     )
2197     @depends_if("--with-system-jpeg")
2198     def jpeg_flags(value):
2199         if len(value):
2200             return namespace(
2201                 cflags=("-I%s/include" % value[0],),
2202                 ldflags=("-L%s/lib" % value[0], "-ljpeg"),
2203             )
2204         return namespace(
2205             ldflags=("-ljpeg",),
2206         )
2208     with only_when("--with-system-jpeg"):
2209         check_symbol(
2210             "jpeg_destroy_compress",
2211             flags=jpeg_flags.ldflags,
2212             onerror=lambda: die(
2213                 "--with-system-jpeg requested but symbol "
2214                 "jpeg_destroy_compress not found."
2215             ),
2216         )
2218         c_compiler.try_compile(
2219             includes=[
2220                 "stdio.h",
2221                 "sys/types.h",
2222                 "jpeglib.h",
2223             ],
2224             body="""
2225                 #if JPEG_LIB_VERSION < 62
2226                 #error Insufficient JPEG library version
2227                 #endif
2228             """,
2229             flags=jpeg_flags.cflags,
2230             check_msg="for sufficient jpeg library version",
2231             onerror=lambda: die(
2232                 "Insufficient JPEG library version for "
2233                 "--with-system-jpeg (62 required)"
2234             ),
2235         )
2237         c_compiler.try_compile(
2238             includes=[
2239                 "stdio.h",
2240                 "sys/types.h",
2241                 "jpeglib.h",
2242             ],
2243             body="""
2244                 #ifndef JCS_EXTENSIONS
2245                 #error libjpeg-turbo JCS_EXTENSIONS required
2246                 #endif
2247             """,
2248             flags=jpeg_flags.cflags,
2249             check_msg="for sufficient libjpeg-turbo JCS_EXTENSIONS",
2250             onerror=lambda: die(
2251                 "libjpeg-turbo JCS_EXTENSIONS required for " "--with-system-jpeg"
2252             ),
2253         )
2255         set_config("MOZ_JPEG_CFLAGS", jpeg_flags.cflags)
2256         set_config("MOZ_JPEG_LIBS", jpeg_flags.ldflags)
2258     @depends("--with-system-jpeg", target, neon_flags)
2259     def in_tree_jpeg_arm(system_jpeg, target, neon_flags):
2260         if system_jpeg:
2261             return
2263         if target.cpu == "arm":
2264             return neon_flags
2265         elif target.cpu == "aarch64":
2266             return ("-march=armv8-a",)
2268     @depends("--with-system-jpeg", target)
2269     def in_tree_jpeg_mips64(system_jpeg, target):
2270         if system_jpeg:
2271             return
2273         if target.cpu == "mips64":
2274             return ("-Wa,-mloongson-mmi", "-mloongson-ext")
2276     # Compiler check from https://github.com/libjpeg-turbo/libjpeg-turbo/blob/57ba02a408a9a55ccff25aae8b164632a3a4f177/simd/CMakeLists.txt#L419
2277     jpeg_mips64_mmi = c_compiler.try_compile(
2278         body='int c = 0, a = 0, b = 0; asm("paddb %0, %1, %2" : "=f" (c) : "f" (a), "f" (b));',
2279         check_msg="for loongson mmi support",
2280         flags=in_tree_jpeg_mips64,
2281         when=in_tree_jpeg_mips64,
2282     )
2284     @depends(
2285         "--with-system-jpeg",
2286         target,
2287         in_tree_jpeg_arm,
2288         in_tree_jpeg_mips64,
2289         jpeg_mips64_mmi,
2290     )
2291     def in_tree_jpeg(
2292         system_jpeg, target, in_tree_jpeg_arm, in_tree_jpeg_mips64, jpeg_mips64_mmi
2293     ):
2294         if system_jpeg:
2295             return
2297         if target.cpu in ("arm", "aarch64"):
2298             return in_tree_jpeg_arm
2299         elif target.kernel == "Darwin":
2300             if target.cpu == "x86":
2301                 return ("-DPIC", "-DMACHO")
2302             elif target.cpu == "x86_64":
2303                 return ("-D__x86_64__", "-DPIC", "-DMACHO")
2304         elif target.kernel == "WINNT":
2305             if target.cpu == "x86":
2306                 return ("-DPIC", "-DWIN32")
2307             elif target.cpu == "x86_64":
2308                 return ("-D__x86_64__", "-DPIC", "-DWIN64", "-DMSVC")
2309         elif target.cpu == "mips32":
2310             return ("-mdspr2",)
2311         elif target.cpu == "mips64" and jpeg_mips64_mmi:
2312             return in_tree_jpeg_mips64
2313         elif target.cpu == "x86":
2314             return ("-DPIC", "-DELF")
2315         elif target.cpu == "x86_64":
2316             return ("-D__x86_64__", "-DPIC", "-DELF")
2318     @depends(target, when=depends("--with-system-jpeg")(lambda x: not x))
2319     def jpeg_nasm(target):
2320         if target.cpu in ("x86", "x86_64"):
2321             # libjpeg-turbo 2.0.6 requires nasm 2.10.
2322             return namespace(version="2.10", what="JPEG")
2324     # Compiler checks from https://github.com/libjpeg-turbo/libjpeg-turbo/blob/57ba02a408a9a55ccff25aae8b164632a3a4f177/simd/CMakeLists.txt#L258
2325     jpeg_arm_neon_vld1_s16_x3 = c_compiler.try_compile(
2326         includes=["arm_neon.h"],
2327         body="int16_t input[12] = {}; int16x4x3_t output = vld1_s16_x3(input);",
2328         check_msg="for vld1_s16_x3 in arm_neon.h",
2329         flags=in_tree_jpeg_arm,
2330         when=in_tree_jpeg_arm,
2331     )
2333     jpeg_arm_neon_vld1_u16_x2 = c_compiler.try_compile(
2334         includes=["arm_neon.h"],
2335         body="uint16_t input[8] = {}; uint16x4x2_t output = vld1_u16_x2(input);",
2336         check_msg="for vld1_u16_x2 in arm_neon.h",
2337         flags=in_tree_jpeg_arm,
2338         when=in_tree_jpeg_arm,
2339     )
2341     jpeg_arm_neon_vld1q_u8_x4 = c_compiler.try_compile(
2342         includes=["arm_neon.h"],
2343         body="uint8_t input[64] = {}; uint8x16x4_t output = vld1q_u8_x4(input);",
2344         check_msg="for vld1q_u8_x4 in arm_neon.h",
2345         flags=in_tree_jpeg_arm,
2346         when=in_tree_jpeg_arm,
2347     )
2349     set_config("LIBJPEG_TURBO_USE_NASM", True, when=jpeg_nasm)
2350     set_config("LIBJPEG_TURBO_SIMD_FLAGS", in_tree_jpeg)
2351     set_config("LIBJPEG_TURBO_HAVE_VLD1_S16_X3", jpeg_arm_neon_vld1_s16_x3)
2352     set_config("LIBJPEG_TURBO_HAVE_VLD1_U16_X2", jpeg_arm_neon_vld1_u16_x2)
2353     set_config("LIBJPEG_TURBO_HAVE_VLD1Q_U8_X4", jpeg_arm_neon_vld1q_u8_x4)
2354     set_config(
2355         "LIBJPEG_TURBO_NEON_INTRINSICS",
2356         jpeg_arm_neon_vld1_s16_x3
2357         & jpeg_arm_neon_vld1_u16_x2
2358         & jpeg_arm_neon_vld1q_u8_x4,
2359     )
2362 # PNG
2363 # ===
2364 with only_when(compile_environment):
2365     system_lib_option(
2366         "--with-system-png",
2367         nargs="?",
2368         help="Use system libpng",
2369     )
2371     @depends("--with-system-png")
2372     def deprecated_system_png_path(value):
2373         if len(value) == 1:
2374             die(
2375                 "--with-system-png=PATH is not supported anymore. Please use "
2376                 "--with-system-png and set any necessary pkg-config environment variable."
2377             )
2379     png = pkg_check_modules("MOZ_PNG", "libpng >= 1.6.35", when="--with-system-png")
2381     check_symbol(
2382         "png_get_acTL",
2383         flags=png.libs,
2384         onerror=lambda: die(
2385             "--with-system-png won't work because the system's libpng doesn't have APNG support"
2386         ),
2387         when="--with-system-png",
2388     )
2390     set_config("MOZ_SYSTEM_PNG", True, when="--with-system-png")
2393 # FFmpeg's ffvpx configuration
2394 # ==============================================================
2397 @depends(target)
2398 def ffvpx(target):
2399     use_nasm = True
2400     audio_only = False
2401     flags = []
2403     # This enables audio and video codecs paths on Windows  x86 and x86_64,
2404     # macOS (all arch), and Linux x86_64. On other arch / OS combinations,
2405     # only audio codecs are enabled.
2406     if target.kernel == "WINNT":
2407         if target.cpu == "x86":
2408             # 32-bit windows need to prefix symbols with an underscore.
2409             flags = ["-DPIC", "-DWIN32", "-DPREFIX", "-Pconfig_win32.asm"]
2410         elif target.cpu == "x86_64":
2411             flags = [
2412                 "-D__x86_64__",
2413                 "-DPIC",
2414                 "-DWIN64",
2415                 "-DMSVC",
2416                 "-Pconfig_win64.asm",
2417             ]
2418         elif target.cpu == "aarch64":
2419             flags = ["-DPIC", "-DWIN64"]
2420             use_nasm = False
2421     elif target.kernel == "Darwin":
2422         # 32/64-bit macosx assemblers need to prefix symbols with an
2423         # underscore.
2424         flags = ["-DPIC", "-DMACHO", "-DPREFIX"]
2425         if target.cpu == "x86_64":
2426             flags += [
2427                 "-D__x86_64__",
2428                 "-Pconfig_darwin64.asm",
2429             ]
2430         elif target.cpu == "aarch64":
2431             use_nasm = False
2432     elif target.cpu == "x86_64":
2433         flags = ["-D__x86_64__", "-DPIC", "-DELF", "-Pconfig_unix64.asm"]
2434     else:
2435         audio_only = True
2437     if audio_only:
2438         use_nasm = False
2440     return namespace(
2441         use_nasm=use_nasm,
2442         audio_only=audio_only,
2443         flags=flags,
2444     )
2447 @depends(when=ffvpx.use_nasm)
2448 def ffvpx_nasm():
2449     # nasm 2.10 for AVX-2 support.
2450     return namespace(version="2.10", what="FFVPX")
2453 # ffvpx_nasm can't indirectly depend on vpx_as_flags, because it depends
2454 # on a compiler test, so we have to do a little bit of dance here.
2455 @depends(ffvpx, vpx_as_flags, target)
2456 def ffvpx(ffvpx, vpx_as_flags, target):
2457     if ffvpx and vpx_as_flags and target.cpu in ("arm", "aarch64"):
2458         ffvpx.flags.extend(vpx_as_flags)
2459     return ffvpx
2462 set_config("MOZ_FFVPX_AUDIOONLY", True, when=ffvpx.audio_only)
2463 set_define("MOZ_FFVPX_AUDIOONLY", True, when=ffvpx.audio_only)
2464 set_config("FFVPX_ASFLAGS", ffvpx.flags)
2465 set_config("FFVPX_USE_NASM", True, when=ffvpx.use_nasm)
2468 # nasm detection
2469 # ==============================================================
2470 @depends(dav1d_nasm, vpx_nasm, jpeg_nasm, ffvpx_nasm, when=compile_environment)
2471 def need_nasm(*requirements):
2472     requires = {
2473         x.what: x.version if hasattr(x, "version") else True for x in requirements if x
2474     }
2475     if requires:
2476         items = sorted(requires.keys())
2477         if len(items) > 1:
2478             what = " and ".join((", ".join(items[:-1]), items[-1]))
2479         else:
2480             what = items[0]
2481         versioned = {k: v for (k, v) in requires.items() if v is not True}
2482         return namespace(what=what, versioned=versioned)
2485 nasm = check_prog(
2486     "NASM",
2487     ["nasm"],
2488     allow_missing=True,
2489     bootstrap="nasm",
2490     when=need_nasm,
2494 @depends(nasm, need_nasm.what)
2495 def check_nasm(nasm, what):
2496     if not nasm and what:
2497         die("Nasm is required to build with %s, but it was not found." % what)
2498     return nasm
2501 @depends_if(check_nasm)
2502 @checking("nasm version")
2503 def nasm_version(nasm):
2504     version = (
2505         check_cmd_output(nasm, "-v", onerror=lambda: die("Failed to get nasm version."))
2506         .splitlines()[0]
2507         .split()[2]
2508     )
2509     return Version(version)
2512 @depends(nasm_version, need_nasm.versioned, when=need_nasm.versioned)
2513 def check_nasm_version(nasm_version, versioned):
2514     by_version = sorted(versioned.items(), key=lambda x: x[1])
2515     what, version = by_version[-1]
2516     if nasm_version < version:
2517         die(
2518             "Nasm version %s or greater is required to build with %s." % (version, what)
2519         )
2520     return nasm_version
2523 @depends(target, when=check_nasm_version)
2524 def nasm_asflags(target):
2525     asflags = {
2526         ("Darwin", "x86"): ["-f", "macho32"],
2527         ("Darwin", "x86_64"): ["-f", "macho64"],
2528         ("WINNT", "x86"): ["-f", "win32"],
2529         ("WINNT", "x86_64"): ["-f", "win64"],
2530     }.get((target.kernel, target.cpu), None)
2531     if asflags is None:
2532         # We're assuming every x86 platform we support that's
2533         # not Windows or Mac is ELF.
2534         if target.cpu == "x86":
2535             asflags = ["-f", "elf32"]
2536         elif target.cpu == "x86_64":
2537             asflags = ["-f", "elf64"]
2538     return asflags
2541 set_config("NASM_ASFLAGS", nasm_asflags)
2544 # ANGLE OpenGL->D3D translator for WebGL
2545 # ==============================================================
2547 with only_when(compile_environment & target_is_windows):
2548     set_config("MOZ_ANGLE_RENDERER", True)
2550 # Remoting protocol support
2551 # ==============================================================
2554 @depends(toolkit)
2555 def has_remote(toolkit):
2556     if toolkit in ("gtk", "windows", "cocoa"):
2557         return True
2560 set_config("MOZ_HAS_REMOTE", has_remote)
2561 set_define("MOZ_HAS_REMOTE", has_remote)
2563 # RLBox Library Sandboxing wasm support
2564 # ==============================================================
2567 def wasm_sandboxing_libraries():
2568     return (
2569         "graphite",
2570         "ogg",
2571         "hunspell",
2572         "expat",
2573         "woff2",
2574         "soundtouch",
2575     )
2578 @depends(dependable(wasm_sandboxing_libraries), build_project)
2579 def default_wasm_sandboxing_libraries(libraries, build_project):
2580     if build_project != "tools/rusttests":
2581         non_default_libs = {}
2583         return tuple(l for l in libraries if l not in non_default_libs)
2586 option(
2587     "--with-wasm-sandboxed-libraries",
2588     env="WASM_SANDBOXED_LIBRARIES",
2589     help="{Enable wasm sandboxing for the selected libraries|Disable wasm sandboxing}",
2590     nargs="+",
2591     choices=dependable(wasm_sandboxing_libraries),
2592     default=default_wasm_sandboxing_libraries,
2596 @depends("--with-wasm-sandboxed-libraries")
2597 def requires_wasm_sandboxing(libraries):
2598     if libraries:
2599         return True
2602 set_config("MOZ_USING_WASM_SANDBOXING", requires_wasm_sandboxing)
2603 set_define("MOZ_USING_WASM_SANDBOXING", requires_wasm_sandboxing)
2605 with only_when(requires_wasm_sandboxing & compile_environment):
2606     option(
2607         "--with-wasi-sysroot",
2608         env="WASI_SYSROOT",
2609         nargs=1,
2610         help="Path to wasi sysroot for wasm sandboxing",
2611     )
2613     @depends("--with-wasi-sysroot", requires_wasm_sandboxing)
2614     def bootstrap_wasi_sysroot(wasi_sysroot, requires_wasm_sandboxing):
2615         return requires_wasm_sandboxing and not wasi_sysroot
2617     @depends(
2618         "--with-wasi-sysroot",
2619         bootstrap_path("sysroot-wasm32-wasi", when=bootstrap_wasi_sysroot),
2620     )
2621     @imports("os")
2622     def wasi_sysroot(wasi_sysroot, bootstrapped_sysroot):
2623         if not wasi_sysroot:
2624             return bootstrapped_sysroot
2626         wasi_sysroot = wasi_sysroot[0]
2627         if not os.path.isdir(wasi_sysroot):
2628             die("Argument to --with-wasi-sysroot must be a directory")
2629         if not os.path.isabs(wasi_sysroot):
2630             die("Argument to --with-wasi-sysroot must be an absolute path")
2632         return wasi_sysroot
2634     @depends(wasi_sysroot)
2635     def wasi_sysroot_flags(wasi_sysroot):
2636         if wasi_sysroot:
2637             log.info("Using wasi sysroot in %s", wasi_sysroot)
2638             return ["--sysroot=%s" % wasi_sysroot]
2639         return []
2641     set_config("WASI_SYSROOT", wasi_sysroot)
2643     def wasm_compiler_with_flags(compiler, sysroot_flags):
2644         if compiler:
2645             return (
2646                 compiler.wrapper + [compiler.compiler] + compiler.flags + sysroot_flags
2647             )
2649     @template
2650     def wasm_compiler_error(msg):
2651         @depends("--with-wasm-sandboxed-libraries")
2652         def wasm_compiler_error(sandboxed_libs):
2653             suggest_disable = ""
2654             if sandboxed_libs.origin == "default":
2655                 suggest_disable = " Or build with --without-wasm-sandboxed-libraries."
2656             return lambda: die(msg + suggest_disable)
2658         return wasm_compiler_error
2660     @template
2661     def check_wasm_compiler(compiler, language):
2662         compiler.try_compile(
2663             includes=["cstring" if language == "C++" else "string.h"],
2664             flags=wasi_sysroot_flags,
2665             check_msg="the wasm %s compiler can find wasi headers" % language,
2666             onerror=wasm_compiler_error(
2667                 "Cannot find wasi headers or problem with the wasm compiler. "
2668                 "Please fix the problem."
2669             ),
2670         )
2672         compiler.try_run(
2673             flags=wasi_sysroot_flags,
2674             check_msg="the wasm %s linker can find wasi libraries" % language,
2675             onerror=wasm_compiler_error(
2676                 "Cannot find wasi libraries or problem with the wasm linker. "
2677                 "Please fix the problem."
2678             ),
2679         )
2681     wasm_cc = compiler("C", wasm, other_compiler=c_compiler)
2682     check_wasm_compiler(wasm_cc, "C")
2684     @depends(wasm_cc, wasi_sysroot_flags)
2685     def wasm_cc_with_flags(wasm_cc, wasi_sysroot_flags):
2686         return wasm_compiler_with_flags(wasm_cc, wasi_sysroot_flags)
2688     set_config("WASM_CC", wasm_cc_with_flags)
2690     wasm_cxx = compiler(
2691         "C++",
2692         wasm,
2693         c_compiler=wasm_cc,
2694         other_compiler=cxx_compiler,
2695         other_c_compiler=c_compiler,
2696     )
2697     check_wasm_compiler(wasm_cxx, "C++")
2699     @depends(wasm_cxx, wasi_sysroot_flags)
2700     def wasm_cxx_with_flags(wasm_cxx, wasi_sysroot_flags):
2701         return wasm_compiler_with_flags(wasm_cxx, wasi_sysroot_flags)
2703     set_config("WASM_CXX", wasm_cxx_with_flags)
2705     wasm_compile_flags = dependable(["-fno-exceptions", "-fno-strict-aliasing"])
2706     option(env="WASM_CFLAGS", nargs=1, help="Options to pass to WASM_CC")
2708     @depends("WASM_CFLAGS", wasm_compile_flags)
2709     def wasm_cflags(value, wasm_compile_flags):
2710         if value:
2711             return wasm_compile_flags + value
2712         else:
2713             return wasm_compile_flags
2715     set_config("WASM_CFLAGS", wasm_cflags)
2717     option(env="WASM_CXXFLAGS", nargs=1, help="Options to pass to WASM_CXX")
2719     @depends("WASM_CXXFLAGS", wasm_compile_flags)
2720     def wasm_cxxflags(value, wasm_compile_flags):
2721         if value:
2722             return wasm_compile_flags + value
2723         else:
2724             return wasm_compile_flags
2726     set_config("WASM_CXXFLAGS", wasm_cxxflags)
2729 @depends("--with-wasm-sandboxed-libraries")
2730 def wasm_sandboxing(libraries):
2731     if not libraries:
2732         return
2734     return namespace(**{name: True for name in libraries})
2737 @template
2738 def wasm_sandboxing_config_defines():
2739     for lib in wasm_sandboxing_libraries():
2740         set_config(
2741             "MOZ_WASM_SANDBOXING_%s" % lib.upper(), getattr(wasm_sandboxing, lib)
2742         )
2743         set_define(
2744             "MOZ_WASM_SANDBOXING_%s" % lib.upper(), getattr(wasm_sandboxing, lib)
2745         )
2748 wasm_sandboxing_config_defines()
2751 with only_when(compile_environment & wasm_sandboxing.hunspell):
2752     clock_in_wasi_sysroot = wasm_cc.try_run(
2753         header="#include <time.h>",
2754         body="clock();",
2755         check_msg="for clock() in wasi sysroot",
2756         flags=depends(wasi_sysroot_flags)(
2757             lambda sysroot_flags: ["-Werror"] + sysroot_flags
2758         ),
2759     )
2761     wasi_emulated_clock = wasm_cc.try_run(
2762         header="#include <time.h>",
2763         body="clock();",
2764         check_msg="for emulated clock() in wasi sysroot",
2765         flags=depends(wasi_sysroot_flags)(
2766             lambda sysroot_flags: [
2767                 "-Werror",
2768                 "-D_WASI_EMULATED_PROCESS_CLOCKS",
2769                 "-lwasi-emulated-process-clocks",
2770             ]
2771             + sysroot_flags
2772         ),
2773         when=depends(clock_in_wasi_sysroot)(lambda x: not x),
2774         onerror=lambda: die("Can't find clock() in wasi sysroot."),
2775     )
2777     set_config("MOZ_WASI_EMULATED_CLOCK", True, when=wasi_emulated_clock)
2780 # new Notification Store implementation
2781 # ==============================================================
2784 @depends(milestone)
2785 def new_notification_store(milestone):
2786     if milestone.is_nightly:
2787         return True
2790 set_config("MOZ_NEW_NOTIFICATION_STORE", True, when=new_notification_store)
2791 set_define("MOZ_NEW_NOTIFICATION_STORE", True, when=new_notification_store)
2794 # Auxiliary files persistence on application close
2795 # ==============================================================
2797 option(
2798     "--enable-disk-remnant-avoidance",
2799     help="Prevent persistence of auxiliary files on application close",
2803 set_config(
2804     "MOZ_AVOID_DISK_REMNANT_ON_CLOSE",
2805     True,
2806     when="--enable-disk-remnant-avoidance",
2810 # Glean SDK Integration Crate
2811 # ==============================================================
2814 @depends(target)
2815 def glean_android(target):
2816     return target.os == "Android"
2819 set_config("MOZ_GLEAN_ANDROID", True, when=glean_android)
2820 set_define("MOZ_GLEAN_ANDROID", True, when=glean_android)
2823 # dump_syms
2824 # ==============================================================
2826 check_prog(
2827     "DUMP_SYMS",
2828     ["dump_syms"],
2829     allow_missing=True,
2830     bootstrap="dump_syms",
2831     when=compile_environment,
2835 @depends(valid_windows_sdk_dir, host)
2836 @imports(_from="os", _import="environ")
2837 def pdbstr_paths(valid_windows_sdk_dir, host):
2838     if not valid_windows_sdk_dir:
2839         return
2841     vc_host = {
2842         "x86": "x86",
2843         "x86_64": "x64",
2844     }.get(host.cpu)
2846     return [
2847         environ["PATH"],
2848         os.path.join(valid_windows_sdk_dir.path, "Debuggers", vc_host, "srcsrv"),
2849     ]
2852 @depends("MOZ_AUTOMATION", c_compiler)
2853 def allow_missing_wintools(automation, c_compiler):
2854     if not automation:
2855         return True
2856     if c_compiler and c_compiler.type != "clang-cl":
2857         return True
2860 check_prog(
2861     "PDBSTR",
2862     ["pdbstr.exe"],
2863     allow_missing=allow_missing_wintools,
2864     when=compile_environment & target_is_windows,
2865     paths=pdbstr_paths,
2866     allow_spaces=True,
2870 check_prog(
2871     "WINCHECKSEC",
2872     ["winchecksec.exe", "winchecksec"],
2873     bootstrap="winchecksec",
2874     allow_missing=allow_missing_wintools,
2875     when=compile_environment & target_is_windows,
2879 # Fork server
2880 @depends(target, build_project)
2881 def forkserver_default(target, build_project):
2882     return build_project == "browser" and (
2883         (target.os == "GNU" and target.kernel == "Linux")
2884         or target.os == "FreeBSD"
2885         or target.os == "OpenBSD"
2886     )
2889 option(
2890     "--enable-forkserver",
2891     default=forkserver_default,
2892     env="MOZ_ENABLE_FORKSERVER",
2893     help="{Enable|Disable} fork server",
2897 @depends("--enable-forkserver", target)
2898 def forkserver_flag(value, target):
2899     if (
2900         target.os == "Android"
2901         or (target.os == "GNU" and target.kernel == "Linux")
2902         or target.os == "FreeBSD"
2903         or target.os == "OpenBSD"
2904     ):
2905         return bool(value)
2906     pass
2909 set_config("MOZ_ENABLE_FORKSERVER", forkserver_flag)
2910 set_define("MOZ_ENABLE_FORKSERVER", forkserver_flag, forkserver_flag)
2912 # Crash Reporter
2913 # ==============================================================
2915 with only_when(compile_environment & target_has_linux_kernel):
2916     # Check if we need to use the breakpad_getcontext fallback.
2917     getcontext = check_symbol("getcontext")
2918     set_config("HAVE_GETCONTEXT", getcontext)
2919     set_define("HAVE_GETCONTEXT", getcontext)
2921 # NSS
2922 # ==============================================================
2923 include("../build/moz.configure/nss.configure")
2926 # Enable or disable running in background task mode: headless for
2927 # periodic, short-lived, maintenance tasks.
2928 # ==============================================================================
2929 option(
2930     "--disable-backgroundtasks",
2931     help="Disable running in background task mode",
2933 set_config("MOZ_BACKGROUNDTASKS", True, when="--enable-backgroundtasks")
2934 set_define("MOZ_BACKGROUNDTASKS", True, when="--enable-backgroundtasks")
2937 # Update-related programs: updater, maintenance service, update agent,
2938 # default browser agent.
2939 # ==============================================================
2940 include("../build/moz.configure/update-programs.configure")
2943 # Mobile optimizations
2944 # ==============================================================
2945 option(
2946     "--enable-mobile-optimize",
2947     default=target_is_android,
2948     help="{Enable|Disable} mobile optimizations",
2951 set_define("MOZ_GFX_OPTIMIZE_MOBILE", True, when="--enable-mobile-optimize")
2952 # We ignore "paint will resample" on mobile for performance.
2953 # We may want to revisit this later.
2954 set_define("MOZ_IGNORE_PAINT_WILL_RESAMPLE", True, when="--enable-mobile-optimize")
2956 # Pref extensions
2957 # ==============================================================
2958 option("--disable-pref-extensions", help="Disable pref extensions such as autoconfig")
2959 set_config("MOZ_PREF_EXTENSIONS", True, when="--enable-pref-extensions")
2961 # Offer a way to disable the startup cache
2962 # ==============================================================
2963 option("--disable-startupcache", help="Disable startup cache")
2966 @depends("--enable-startupcache")
2967 def enable_startupcache(value):
2968     if value:
2969         return True
2972 set_define(
2973     "MOZ_DISABLE_STARTUPCACHE", True, when=depends(enable_startupcache)(lambda x: not x)
2977 # Branding
2978 # ==============================================================
2979 option(
2980     env="MOZ_APP_REMOTINGNAME",
2981     nargs=1,
2982     help="Used for the internal program name, which affects profile name "
2983     "and remoting. If not set, defaults to MOZ_APP_NAME if the update channel "
2984     "is release, and MOZ_APP_NAME-MOZ_UPDATE_CHANNEL otherwise.",
2988 @depends("MOZ_APP_REMOTINGNAME", moz_app_name, update_channel)
2989 def moz_app_remotingname(value, moz_app_name, update_channel):
2990     if value:
2991         return value[0]
2992     if update_channel == "release":
2993         return moz_app_name
2994     return moz_app_name + "-" + update_channel
2997 set_config("MOZ_APP_REMOTINGNAME", moz_app_remotingname)
2999 option(
3000     env="ANDROID_PACKAGE_NAME",
3001     nargs=1,
3002     help="Name of the Android package (default org.mozilla.$MOZ_APP_NAME)",
3006 @depends("ANDROID_PACKAGE_NAME", moz_app_name)
3007 def android_package_name(value, moz_app_name):
3008     if value:
3009         return value[0]
3010     if moz_app_name == "fennec":
3011         return "org.mozilla.fennec_aurora"
3012     return "org.mozilla.%s" % moz_app_name
3015 set_config("ANDROID_PACKAGE_NAME", android_package_name)
3018 # Miscellaneous options
3019 # ==============================================================
3020 option(env="MOZ_WINCONSOLE", nargs="?", help="Whether we can create a console window.")
3021 set_define("MOZ_WINCONSOLE", True, when=depends("MOZ_WINCONSOLE")(lambda x: x))
3024 # Alternative Crashreporter setting
3025 option(
3026     "--with-crashreporter-url",
3027     env="MOZ_CRASHREPORTER_URL",
3028     default="https://crash-reports.mozilla.com/",
3029     nargs=1,
3030     help="Set an alternative crashreporter url",
3033 set_config(
3034     "MOZ_CRASHREPORTER_URL",
3035     depends("--with-crashreporter-url")(lambda x: x[0].rstrip("/")),
3039 # Crash reporter options
3040 # ==============================================================
3041 @depends(target)
3042 def oxidized_breakpad(target):
3043     if target.kernel == "Linux":
3044         return target.cpu in ("aarch64", "arm", "x86", "x86_64")
3045     return False
3048 set_config("MOZ_OXIDIZED_BREAKPAD", True, when=oxidized_breakpad)
3049 set_define("MOZ_OXIDIZED_BREAKPAD", True, when=oxidized_breakpad)
3051 # Environment variable to mock the crashreporter for testing
3052 option(env="MOZ_CRASHREPORTER_MOCK", help="Mock the crashreporter to test native GUIs")
3053 set_config("MOZ_CRASHREPORTER_MOCK", True, when="MOZ_CRASHREPORTER_MOCK")
3056 # Wine
3057 # ==============================================================
3058 @depends(target, host)
3059 def want_wine(target, host):
3060     return target.kernel == "WINNT" and host.kernel != "WINNT"
3063 wine = check_prog(
3064     "WINE",
3065     ["wine64", "wine"],
3066     when=want_wine,
3067     bootstrap="wine/bin",
3070 # DOM Streams
3071 # ==============================================================
3072 # Set this to true so the JS engine knows we're doing a browser build.
3073 set_config("MOZ_DOM_STREAMS", True)
3074 set_define("MOZ_DOM_STREAMS", True)
3076 # libevent
3077 # ==============================================================
3078 with only_when(compile_environment):
3079     system_lib_option(
3080         "--with-system-libevent",
3081         nargs="?",
3082         help="Use system libevent",
3083     )
3085     @depends("--with-system-libevent")
3086     def deprecated_system_libevent_path(value):
3087         if len(value) == 1:
3088             die(
3089                 "--with-system-libevent=PATH is not supported anymore. Please use "
3090                 "--with-system-libevent and set any necessary pkg-config environment variable."
3091             )
3093     pkg_check_modules("MOZ_LIBEVENT", "libevent", when="--with-system-libevent")
3095     set_config("MOZ_SYSTEM_LIBEVENT", True, when="--with-system-libevent")
3098 # Crash reporting
3099 # ==============================================================
3100 @depends(target, developer_options, artifact_builds)
3101 def crashreporter_default(target, developer_options, artifacts):
3102     if target.os in ("WINNT", "OSX"):
3103         return True
3104     if target.kernel == "Linux" and target.cpu in ("x86", "x86_64", "arm", "aarch64"):
3105         # The crash reporter prevents crash stacktraces to be logged in the
3106         # logs on Android, so we leave it out by default in developer builds.
3107         return target.os != "Android" or not developer_options or artifacts
3110 option(
3111     "--enable-crashreporter",
3112     default=crashreporter_default,
3113     help="{Enable|Disable} crash reporting",
3117 set_config("MOZ_CRASHREPORTER", True, when="--enable-crashreporter")
3118 set_define("MOZ_CRASHREPORTER", True, when="--enable-crashreporter")
3120 with only_when(compile_environment):
3121     with only_when("--enable-crashreporter"):
3122         pkg_check_modules(
3123             "MOZ_GTHREAD",
3124             "gthread-2.0",
3125             when=depends(target)(lambda t: t.os == "GNU" and t.kernel == "Linux"),
3126         )
3128         set_config(
3129             "MOZ_CRASHREPORTER_INJECTOR",
3130             True,
3131             when=depends(target)(lambda t: t.os == "WINNT" and t.bitness == 32),
3132         )
3133         set_define(
3134             "MOZ_CRASHREPORTER_INJECTOR",
3135             True,
3136             when=depends(target)(lambda t: t.os == "WINNT" and t.bitness == 32),
3137         )
3140 # If we have any service that uploads data (and requires data submission
3141 # policy alert), set MOZ_DATA_REPORTING.
3142 # ==============================================================
3143 @depends(
3144     "MOZ_TELEMETRY_REPORTING",
3145     "MOZ_SERVICES_HEALTHREPORT",
3146     "--enable-crashreporter",
3147     "MOZ_NORMANDY",
3149 def data_reporting(telemetry, healthreport, crashreporter, normandy):
3150     return telemetry or healthreport or crashreporter or normandy
3153 set_config("MOZ_DATA_REPORTING", True, when=data_reporting)
3154 set_define("MOZ_DATA_REPORTING", True, when=data_reporting)
3157 # Gtk+
3158 # ==============================================================
3159 with only_when(toolkit_gtk):
3160     pkg_check_modules(
3161         "MOZ_GTK3",
3162         "gtk+-3.0 >= 3.14.0 gtk+-unix-print-3.0 glib-2.0 gobject-2.0 gio-unix-2.0",
3163     )
3165     set_define("GDK_VERSION_MIN_REQUIRED", "GDK_VERSION_3_14")
3166     set_define("GDK_VERSION_MAX_ALLOWED", "GDK_VERSION_3_14")
3168     pkg_check_modules("GLIB", "glib-2.0 >= 2.42 gobject-2.0")
3170     set_define("GLIB_VERSION_MIN_REQUIRED", "GLIB_VERSION_2_42")
3171     set_define("GLIB_VERSION_MAX_ALLOWED", "GLIB_VERSION_2_42")
3173     set_define("MOZ_ACCESSIBILITY_ATK", True, when=accessibility)
3175 # DBus
3176 # ==============================================================
3177 with only_when(toolkit_gtk):
3178     option("--disable-dbus", help="Disable dbus support")
3180     with only_when("--enable-dbus"):
3181         pkg_check_modules("MOZ_DBUS", "dbus-1 >= 0.60")
3183         set_config("MOZ_ENABLE_DBUS", True)
3184         set_define("MOZ_ENABLE_DBUS", True)
3187 # Necko's wifi scanner
3188 # ==============================================================
3189 @depends(target)
3190 def necko_wifi_when(target):
3191     return target.os in ("WINNT", "OSX", "DragonFly", "FreeBSD") or (
3192         target.kernel == "Linux" and target.os == "GNU"
3193     )
3196 option("--disable-necko-wifi", help="Disable necko wifi scanner", when=necko_wifi_when)
3198 set_config("NECKO_WIFI", True, when="--enable-necko-wifi")
3199 set_define("NECKO_WIFI", True, when="--enable-necko-wifi")
3202 @depends(
3203     depends("--enable-necko-wifi", when=necko_wifi_when)(lambda x: x),
3204     depends("--enable-dbus", when=toolkit_gtk)(lambda x: x),
3205     when=depends(target)(lambda t: t.os == "GNU" and t.kernel == "Linux"),
3207 def necko_wifi_dbus(necko_wifi, dbus):
3208     if necko_wifi and not dbus:
3209         die(
3210             "Necko WiFi scanning needs DBus on your platform, remove --disable-dbus"
3211             " or use --disable-necko-wifi"
3212         )
3213     return necko_wifi and dbus
3216 set_config("NECKO_WIFI_DBUS", True, when=necko_wifi_dbus)
3217 set_define("NECKO_WIFI_DBUS", True, when=necko_wifi_dbus)
3220 # Frontend JS debug mode
3221 # ==============================================================
3222 option("--enable-debug-js-modules", help="Enable debug mode for frontend JS libraries")
3224 set_config("DEBUG_JS_MODULES", True, when="--enable-debug-js-modules")
3227 # moz_dump_painting
3228 # ==============================================================
3229 option("--enable-dump-painting", help="Enable paint debugging")
3231 set_define(
3232     "MOZ_DUMP_PAINTING",
3233     True,
3234     when=depends("--enable-dump-painting", "--enable-debug")(
3235         lambda painting, debug: painting or debug
3236     ),
3238 set_define("MOZ_LAYERS_HAVE_LOG", True, when="--enable-dump-painting")
3241 # libproxy support
3242 # ==============================================================
3243 with only_when(toolkit_gtk):
3244     system_lib_option("--enable-libproxy", help="Enable libproxy support")
3246     with only_when("--enable-libproxy"):
3247         pkg_check_modules("MOZ_LIBPROXY", "libproxy-1.0")
3249         set_config("MOZ_ENABLE_LIBPROXY", True)
3250         set_define("MOZ_ENABLE_LIBPROXY", True)
3253 # Enable runtime logging
3254 # ==============================================================
3255 set_define("MOZ_LOGGING", True)
3256 set_define("FORCE_PR_LOG", True)
3258 # This will enable logging of addref, release, ctor, dtor.
3259 # ==============================================================
3260 option(
3261     "--enable-logrefcnt",
3262     default=moz_debug,
3263     help="{Enable|Disable} logging of refcounts",
3266 set_define("NS_BUILD_REFCNT_LOGGING", True, when="--enable-logrefcnt")
3269 # NegotiateAuth
3270 # ==============================================================
3271 option("--disable-negotiateauth", help="Disable GSS-API negotiation")
3273 set_config("MOZ_AUTH_EXTENSION", True, when="--enable-negotiateauth")
3274 set_define("MOZ_AUTH_EXTENSION", True, when="--enable-negotiateauth")
3277 # Parental control
3278 # ==============================================================
3279 option("--disable-parental-controls", help="Do not build parental controls")
3281 set_config(
3282     "MOZ_DISABLE_PARENTAL_CONTROLS",
3283     True,
3284     when=depends("--enable-parental-controls")(lambda x: not x),
3286 set_define(
3287     "MOZ_DISABLE_PARENTAL_CONTROLS",
3288     True,
3289     when=depends("--enable-parental-controls")(lambda x: not x),
3293 # Sandboxing support
3294 # ==============================================================
3295 @depends(target, tsan, asan)
3296 def sandbox_default(target, tsan, asan):
3297     # Only enable the sandbox by default on Linux, OpenBSD, macOS, and Windows
3298     if target.kernel == "Linux" and target.os == "GNU":
3299         # Bug 1182565: TSan conflicts with sandboxing on Linux.
3300         # Bug 1287971: LSan also conflicts with sandboxing on Linux.
3301         if tsan or asan:
3302             return False
3303         # Linux sandbox is only available on x86{,_64} and arm{,64}.
3304         return target.cpu in ("x86", "x86_64", "arm", "aarch64")
3305     return target.kernel in ("WINNT", "Darwin", "OpenBSD")
3308 option(
3309     "--enable-sandbox",
3310     default=sandbox_default,
3311     help="{Enable|Disable} sandboxing support",
3314 set_config("MOZ_SANDBOX", True, when="--enable-sandbox")
3315 set_define("MOZ_SANDBOX", True, when="--enable-sandbox")
3317 with only_when(depends(target.kernel)(lambda k: k not in ("Darwin", "WINNT"))):
3318     set_define("MOZ_CONTENT_TEMP_DIR", True, when="--enable-sandbox")
3320 # Searching of system directories for extensions.
3321 # ==============================================================
3322 # Note: this switch is meant to be used for test builds whose behavior should
3323 # not depend on what happens to be installed on the local machine.
3324 option(
3325     "--disable-system-extension-dirs",
3326     help="Disable searching system- and account-global directories for extensions"
3327     " of any kind; use only profile-specific extension directories",
3330 set_define("ENABLE_SYSTEM_EXTENSION_DIRS", True, when="--enable-system-extension-dirs")
3333 # Pixman
3334 # ==============================================================
3335 with only_when(compile_environment):
3336     system_lib_option(
3337         "--enable-system-pixman", help="Use system pixman (located with pkgconfig)"
3338     )
3340     @depends("--enable-system-pixman")
3341     def in_tree_pixman(pixman):
3342         return not pixman
3344     set_config("MOZ_TREE_PIXMAN", True, when=in_tree_pixman)
3345     set_define("MOZ_TREE_PIXMAN", True, when=in_tree_pixman)
3347     pkg_check_modules("MOZ_PIXMAN", "pixman-1 >= 0.36.0", when="--enable-system-pixman")
3348     # Set MOZ_PIXMAN_CFLAGS to an explicit empty value when --enable-system-pixman is *not* used,
3349     # for layout/style/extra-bindgen-flags
3350     set_config("MOZ_PIXMAN_CFLAGS", [], when=in_tree_pixman)
3353 # Universalchardet
3354 # ==============================================================
3355 with only_when(compile_environment):
3356     option("--disable-universalchardet", help="Disable universal encoding detection")
3358     set_config("MOZ_UNIVERSALCHARDET", True, when="--enable-universalchardet")
3361 # Disable zipwriter
3362 # ==============================================================
3363 with only_when(compile_environment):
3364     option("--disable-zipwriter", help="Disable zipwriter component")
3366     set_config("MOZ_ZIPWRITER", True, when="--enable-zipwriter")
3369 # Location of the mozilla user directory
3370 # ==============================================================
3371 with only_when(compile_environment):
3373     @depends(target)
3374     def default_user_appdir(target):
3375         if target.kernel in ("WINNT", "Darwin"):
3376             return "Mozilla"
3377         return ".mozilla"
3379     option(
3380         "--with-user-appdir",
3381         nargs=1,
3382         default=default_user_appdir,
3383         help="Set user-specific appdir",
3384     )
3386     @depends("--with-user-appdir")
3387     def user_appdir(appdir):
3388         if not appdir:
3389             die("--without-user-appdir is not a valid option.")
3390         if "/" in appdir[0]:
3391             die("--with-user-appdir must be a single relative path.")
3392         return '"{}"'.format(appdir[0])
3394     set_define("MOZ_USER_DIR", user_appdir)
3397 # Check for sin_len and sin6_len - used by SCTP; only appears in Mac/*BSD generally
3398 # ==============================================================
3399 with only_when(compile_environment):
3400     have_sin_len = c_compiler.try_compile(
3401         includes=["netinet/in.h"],
3402         body="struct sockaddr_in x; void *foo = (void*) &x.sin_len;",
3403         check_msg="for sin_len in struct sockaddr_in",
3404     )
3405     have_sin6_len = c_compiler.try_compile(
3406         includes=["netinet/in.h"],
3407         body="struct sockaddr_in6 x; void *foo = (void*) &x.sin6_len;",
3408         check_msg="for sin_len6 in struct sockaddr_in6",
3409     )
3410     set_define("HAVE_SIN_LEN", have_sin_len)
3411     set_define("HAVE_SIN6_LEN", have_sin6_len)
3412     # HAVE_CONN_LEN must be the same as HAVE_SIN_LEN and HAVE_SIN6_LEN
3413     set_define("HAVE_SCONN_LEN", have_sin_len & have_sin6_len)
3414     set_define(
3415         "HAVE_SA_LEN",
3416         c_compiler.try_compile(
3417             includes=["netinet/in.h"],
3418             body="struct sockaddr x; void *foo = (void*) &x.sa_len;",
3419             check_msg="for sa_len in struct sockaddr",
3420         ),
3421     )
3424 # Check for pthread_cond_timedwait_monotonic_np
3425 # ==============================================================
3426 with only_when(compile_environment):
3427     set_define(
3428         "HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC",
3429         c_compiler.try_compile(
3430             includes=["pthread.h"],
3431             body="pthread_cond_timedwait_monotonic_np(0, 0, 0);",
3432             # -Werror to catch any "implicit declaration" warning that means the function
3433             # is not supported.
3434             flags=["-Werror=implicit-function-declaration"],
3435             check_msg="for pthread_cond_timedwait_monotonic_np",
3436         ),
3437     )
3440 # Custom dynamic linker for Android
3441 # ==============================================================
3442 with only_when(target_has_linux_kernel & compile_environment):
3443     option(
3444         env="MOZ_LINKER",
3445         default=depends(target.os, when="--enable-jemalloc")(
3446             lambda os: os == "Android"
3447         ),
3448         help="{Enable|Disable} custom dynamic linker",
3449     )
3451     set_config("MOZ_LINKER", True, when="MOZ_LINKER")
3452     set_define("MOZ_LINKER", True, when="MOZ_LINKER")
3453     add_old_configure_assignment("MOZ_LINKER", True, when="MOZ_LINKER")
3455     moz_linker = depends(when="MOZ_LINKER")(lambda: True)
3458 # 32-bits ethtool_cmd.speed
3459 # ==============================================================
3460 with only_when(target_has_linux_kernel & compile_environment):
3461     set_config(
3462         "MOZ_WEBRTC_HAVE_ETHTOOL_SPEED_HI",
3463         c_compiler.try_compile(
3464             includes=["linux/ethtool.h"],
3465             body="struct ethtool_cmd cmd; cmd.speed_hi = 0;",
3466             check_msg="for 32-bits ethtool_cmd.speed",
3467         ),
3468     )
3470 # Gamepad support
3471 # ==============================================================
3472 check_header(
3473     "linux/joystick.h",
3474     onerror=lambda: die(
3475         "Can't find header linux/joystick.h, needed for gamepad support."
3476         " Please install Linux kernel headers."
3477     ),
3478     when=target_has_linux_kernel & compile_environment,
3482 # Smart card support
3483 # ==============================================================
3484 @depends(build_project)
3485 def disable_smart_cards(build_project):
3486     return build_project == "mobile/android"
3489 set_config("MOZ_NO_SMART_CARDS", True, when=disable_smart_cards)
3490 set_define("MOZ_NO_SMART_CARDS", True, when=disable_smart_cards)
3492 # Enable UniFFI fixtures
3493 # ==============================================================
3494 # These are used to test the uniffi-bindgen-gecko-js code generation.  They
3495 # should not be enabled in release builds.
3497 option(
3498     "--enable-uniffi-fixtures",
3499     help="Enable UniFFI Fixtures/Examples",
3502 set_config("MOZ_UNIFFI_FIXTURES", True, when="--enable-uniffi-fixtures")
3504 # System policies
3505 # ==============================================================
3507 option(
3508     "--disable-system-policies",
3509     help="Disable reading policies from Windows registry, macOS's file system attributes, and /etc/firefox",
3512 set_config("MOZ_SYSTEM_POLICIES", True, when="--enable-system-policies")
3514 # Allow disabling the creation a legacy profile
3515 # ==============================================================
3517 option(
3518     "--disable-legacy-profile-creation",
3519     help="Disable the creation a legacy profile, to be used by old versions "
3520     "of Firefox, when no profiles exist.",
3523 set_config("MOZ_CREATE_LEGACY_PROFILE", True, when="--enable-legacy-profile-creation")
3526 # STL wrapping
3527 # ==============================================================
3528 set_config("WRAP_STL_INCLUDES", True)
3529 set_config(
3530     "STL_FLAGS",
3531     depends(build_environment.dist)(lambda dist: [f"-I{dist}/stl_wrappers"]),
3535 # Perl detection
3536 # ==============================================================
3537 @depends(target)
3538 def need_perl(target):
3539     # Ideally, we'd also depend on gnu_as here, but that adds complications.
3540     return target.cpu == "arm"
3543 perl = check_prog("PERL", ("perl5", "perl"), when=need_perl)
3546 @template
3547 def perl_version_check(min_version):
3548     @depends(perl)
3549     @checking("for minimum required perl version >= %s" % min_version)
3550     def get_perl_version(perl):
3551         return Version(
3552             check_cmd_output(
3553                 perl,
3554                 "-e",
3555                 "print $]",
3556                 onerror=lambda: die("Failed to get perl version."),
3557             )
3558         )
3560     @depends(get_perl_version)
3561     def check_perl_version(version):
3562         if version < min_version:
3563             die("Perl %s or higher is required.", min_version)
3565     @depends(perl)
3566     @checking("for full perl installation")
3567     @imports("subprocess")
3568     def has_full_perl_installation(perl):
3569         ret = subprocess.call([perl, "-e", "use Config; exit(!-d $Config{archlib})"])
3570         return ret == 0
3572     @depends(has_full_perl_installation)
3573     def require_full_perl_installation(has_full_perl_installation):
3574         if not has_full_perl_installation:
3575             die(
3576                 "Cannot find Config.pm or $Config{archlib}. "
3577                 "A full perl installation is required."
3578             )
3581 with only_when(need_perl):
3582     perl_version_check("5.006")
3585 # windows-rs as bootstrappable toolchain
3586 # ==============================================================
3587 # The in-tree windows crate's purpose is to avoid vendoring the
3588 # original windows crate, which is too large.
3589 # The ideal solution would be for cargo to allow exceptions to
3590 # vendoring, but it doesn't.
3591 # The adopted solution is to somehow use the crate contents from
3592 # a directory given via the mozbuild config, or bootstrapped.
3594 # Unfortunately, doing `include!(mozbuild::windows_rs_path!("src/lib.rs"))`
3595 # in the crate's lib.rs doesn't work because of
3596 # https://github.com/rust-lang/rust/issues/66920.
3598 # Previous versions of the windows crate had submodules declared
3599 # directly in lib.rs. Annotating each of them with
3600 # `#[path = concat!(mozbuild::windows_rs_path!("path/to/mod.rs"))]`
3601 # unfortunately also didn't work, because of
3602 # https://github.com/rust-lang/rust/issues/48250.
3604 # Thankfully, newer versions of the windows crate now only have an
3605 # `include!` at the end of lib.rs, so we can get away with simply
3606 # replacing it with an `include!` that uses `mozbuild::windows_rs_path!`.
3608 # We ensure that the in-tree contents match what we expect based on
3609 # the original crate.
3610 # The expectations are as such:
3611 # - Cargo.toml is identical to the original one with the addition of the
3612 #   following two lines at the end (after an empty line):
3613 #     [dependencies.mozbuild]
3614 #     version = "0.1"
3615 # - src/lib.rs is mostly identical to the original one, with two notable
3616 #   differences:
3617 #   - the addition of `#![allow(warnings)]` on the first line, because if
3618 #     the crate had been vendored normally, it would not be affected by
3619 #     `-D warnings`, and `#![allow(warnings)]` mimicks that.
3620 #   - the replacement of any
3621 #     `include!("path/file.rs")`
3622 #     with
3623 #     `include!(mozbuild::windows_rs_path!("src/path/file.rs"))`
3624 with only_when(target_is_windows & compile_environment):
3625     option(
3626         env="MOZ_WINDOWS_RS_DIR",
3627         nargs=1,
3628         help="Path to the source of the 'windows' Rust crate",
3629     )
3631     @depends(
3632         "MOZ_WINDOWS_RS_DIR",
3633         bootstrap_path(
3634             "windows-rs",
3635             when=depends("MOZ_WINDOWS_RS_DIR")(lambda x: not x),
3636         ),
3637         build_environment.topsrcdir,
3638     )
3639     @checking("for the windows rust crate source")
3640     @imports(_from="__builtin__", _import="open")
3641     @imports("re")
3642     @imports("toml")
3643     def windows_rs_dir(dir, bootstrapped, topsrcdir):
3644         if bootstrapped:
3645             dir = bootstrapped
3646         elif dir:
3647             dir = dir[0]
3649         raw_cargo_toml = open(
3650             os.path.join(topsrcdir, "build/rust/windows/Cargo.toml")
3651         ).read()
3652         cargo_toml = toml.loads(raw_cargo_toml)
3653         expected_version = cargo_toml["package"]["version"]
3655         if not dir:
3656             raise FatalCheckError(
3657                 "Cannot find the windows rust crate source.\n"
3658                 f"Try downloading it with `cargo download -x windows={expected_version}`\n"
3659                 "(you may need to `cargo install cargo-download` first)\n"
3660                 f"and set `MOZ_WINDOWS_RS_DIR` to location of the `windows-{expected_version}`"
3661                 " directory"
3662             )
3664         raw_cargo_toml_orig = open(os.path.join(dir, "Cargo.toml")).read()
3665         cargo_toml = toml.loads(raw_cargo_toml_orig)
3666         version = cargo_toml["package"]["version"]
3667         if version != expected_version:
3668             raise FatalCheckError(
3669                 f"The windows rust crate source in {dir} contains version "
3670                 f"{version}, but expected {expected_version}."
3671             )
3672         # Now that we've done the basic sanity check, let's go deeper.
3673         DEPENDENCIES = '\n[dependencies.mozbuild]\nversion = "0.1"\n'
3674         if not raw_cargo_toml.endswith(DEPENDENCIES):
3675             configure_error("In-tree windows crate is missing dependency on mozbuild")
3676         if raw_cargo_toml[: -len(DEPENDENCIES)] != raw_cargo_toml_orig:
3677             configure_error("In-tree windows crate Cargo.toml doesn't match original")
3679         lib_rs = open(os.path.join(topsrcdir, "build/rust/windows/src/lib.rs")).read()
3680         lib_rs_orig = open(os.path.join(dir, "src/lib.rs")).read()
3681         lib_rs_expected = "#![allow(warnings)]\n" + re.sub(
3682             r'include!\("([^"]*)"\)',
3683             r'include!(mozbuild::windows_rs_path!("src/\1"))',
3684             lib_rs_orig,
3685         )
3686         if lib_rs != lib_rs_expected:
3687             configure_error("In-tree windows crate lib.rs doesn't match original")
3689         return dir
3691     set_config("MOZ_WINDOWS_RS_DIR", windows_rs_dir)