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/.
6
7# Set the MOZ_CONFIGURE_OPTIONS variable with all the options that
8# were passed somehow (environment, command line, mozconfig)
9@dependable
10@imports(_from="mozbuild.shellutil", _import="quote")
11@imports(_from="mozbuild.util", _import="ensure_unicode")
12@imports(_from="mozbuild.util", _import="system_encoding")
13@imports(_from="six", _import="itervalues")
14@imports("__sandbox__")
15def all_configure_options():
16    result = []
17    previous = None
18    for option in itervalues(__sandbox__._options):
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            )
49
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 ""
54
55    return quote(*result)
56
57
58set_config("MOZ_CONFIGURE_OPTIONS", all_configure_options)
59
60
61@depends(target)
62def fold_libs(target):
63    return target.os in ("WINNT", "OSX", "Android")
64
65
66set_config("MOZ_FOLD_LIBS", fold_libs)
67
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.
72
73option(
74    "--enable-jprof",
75    env="MOZ_JPROF",
76    help="Enable jprof profiling tool (needs mozilla/tools/jprof)",
77)
78
79
80@depends("--enable-jprof")
81def jprof(value):
82    if value:
83        return True
84
85
86set_config("MOZ_JPROF", jprof)
87set_define("MOZ_JPROF", jprof)
88imply_option("--enable-profiling", jprof)
89
90
91@depends(target)
92def gecko_profiler(target):
93    if target.os == "Android":
94        return target.cpu in ("aarch64", "arm", "x86", "x86_64")
95    elif target.kernel == "Linux":
96        return target.cpu in ("aarch64", "arm", "x86", "x86_64", "mips64")
97    elif target.kernel == "FreeBSD":
98        return target.cpu in ("aarch64", "x86_64")
99    return target.os in ("OSX", "WINNT")
100
101
102@depends(gecko_profiler)
103def gecko_profiler_define(value):
104    if value:
105        return True
106
107
108set_config("MOZ_GECKO_PROFILER", gecko_profiler_define)
109set_define("MOZ_GECKO_PROFILER", gecko_profiler_define)
110
111
112# Whether code to parse ELF binaries should be compiled for the Gecko profiler
113# (for symbol table dumping).
114@depends(gecko_profiler, target)
115def gecko_profiler_parse_elf(value, target):
116    # Currently we only want to build this code on Linux (including Android) and BSD.
117    # For Android, this is in order to dump symbols from Android system, where
118    # on other platforms there exist alternatives that don't require bloating
119    # up our binary size. For Linux more generally, we use this in profile
120    # pre-symbolication support, since MozDescribeCodeAddress doesn't do
121    # anything useful on that platform. (Ideally, we would update
122    # MozDescribeCodeAddress to call into some Rust crates that parse ELF and
123    # DWARF data, but build system issues currently prevent Rust from being
124    # used in mozglue.)
125    if value and (target.kernel == "Linux" or target.kernel == "FreeBSD"):
126        return True
127
128
129set_config("MOZ_GECKO_PROFILER_PARSE_ELF", gecko_profiler_parse_elf)
130set_define("MOZ_GECKO_PROFILER_PARSE_ELF", gecko_profiler_parse_elf)
131
132# enable this by default if the profiler is enabled
133# Note: also requires jemalloc
134set_config("MOZ_PROFILER_MEMORY", gecko_profiler_define)
135set_define("MOZ_PROFILER_MEMORY", gecko_profiler_define)
136
137
138@depends(
139    "--enable-debug",
140    milestone,
141    build_project,
142    # Artifact builds are included because the downloaded artifacts can
143    # have DMD enabled.
144    when=artifact_builds | depends(when="--enable-replace-malloc")(lambda: True),
145)
146def dmd_default(debug, milestone, build_project):
147    return bool(build_project == "browser" and (debug or milestone.is_nightly))
148
149
150option(
151    "--enable-dmd",
152    env="MOZ_DMD",
153    default=dmd_default,
154    help="{Enable|Disable} Dark Matter Detector (heap profiler). "
155    "Also enables jemalloc, replace-malloc and profiling",
156)
157
158
159@depends("--enable-dmd")
160def dmd(value):
161    if value:
162        return True
163
164
165set_config("MOZ_DMD", dmd)
166set_define("MOZ_DMD", dmd)
167add_old_configure_assignment("MOZ_DMD", dmd)
168imply_option("--enable-profiling", dmd)
169imply_option("--enable-jemalloc", dmd, when=compile_environment)
170imply_option("--enable-replace-malloc", dmd, when=compile_environment)
171
172# ALSA cubeb backend
173# ==============================================================
174option("--enable-alsa", env="MOZ_ALSA", help="Enable ALSA audio backend.")
175
176alsa = pkg_check_modules("MOZ_ALSA", "alsa", when="--enable-alsa")
177
178set_config("MOZ_ALSA", depends_if(alsa)(lambda _: True))
179set_define("MOZ_ALSA", depends_if(alsa)(lambda _: True))
180
181# JACK cubeb backend
182# ==============================================================
183option("--enable-jack", env="MOZ_JACK", help="Enable JACK audio backend.")
184
185jack = pkg_check_modules("MOZ_JACK", "jack", when="--enable-jack")
186
187set_config("MOZ_JACK", depends_if(jack)(lambda _: True))
188set_define("MOZ_JACK", depends_if(jack)(lambda _: True))
189
190# PulseAudio cubeb backend
191# ==============================================================
192@depends(target)
193def pulseaudio_default(target):
194    return target.os not in ("WINNT", "OSX", "Android", "OpenBSD")
195
196
197option(
198    "--enable-pulseaudio",
199    env="MOZ_PULSEAUDIO",
200    default=pulseaudio_default,
201    help="{Enable|Disable} PulseAudio audio backend.",
202)
203
204pulseaudio = pkg_check_modules("MOZ_PULSEAUDIO", "libpulse", when="--enable-pulseaudio")
205
206set_config("MOZ_PULSEAUDIO", depends_if(pulseaudio)(lambda _: True))
207set_define("MOZ_PULSEAUDIO", depends_if(pulseaudio)(lambda _: True))
208
209# AudioUnit cubeb Rust backend
210# ==============================================================
211@depends(target)
212def enable_audiounit_rust(target):
213    return target.os == "OSX" and target.kernel == "Darwin"
214
215
216set_config("MOZ_AUDIOUNIT_RUST", True, when=enable_audiounit_rust)
217set_define("MOZ_AUDIOUNIT_RUST", True, when=enable_audiounit_rust)
218
219# Javascript engine
220# ==============================================================
221include("../js/moz.configure")
222
223
224# NodeJS
225# ==============================================================
226include("../build/moz.configure/node.configure")
227
228# L10N
229# ==============================================================
230option("--with-l10n-base", nargs=1, env="L10NBASEDIR", help="Path to l10n repositories")
231
232
233@depends("--with-l10n-base", "MOZ_AUTOMATION", check_build_environment)
234@imports(_from="os.path", _import="isdir")
235@imports(_from="os.path", _import="expanduser")
236@imports(_from="os", _import="environ")
237def l10n_base(value, automation, build_env):
238    if value:
239        path = value[0]
240        if not isdir(path):
241            die("Invalid value --with-l10n-base, %s doesn't exist", path)
242    elif automation:
243        path = os.path.join(build_env.topsrcdir, "../l10n-central")
244    else:
245        path = os.path.join(
246            environ.get(
247                "MOZBUILD_STATE_PATH", expanduser(os.path.join("~", ".mozbuild"))
248            ),
249            "l10n-central",
250        )
251    return os.path.realpath(os.path.abspath(path))
252
253
254set_config("L10NBASEDIR", l10n_base)
255
256
257# Default toolkit
258# ==============================================================
259@depends(target)
260def toolkit_choices(target):
261    if target.os == "WINNT":
262        return ("cairo-windows",)
263    elif target.os == "OSX":
264        return ("cairo-cocoa",)
265    elif target.os == "Android":
266        return ("cairo-android",)
267    else:
268        return ("cairo-gtk3", "cairo-gtk3-wayland")
269
270
271@depends(toolkit_choices)
272def toolkit_default(choices):
273    return choices[0]
274
275
276option(
277    "--enable-default-toolkit",
278    nargs=1,
279    choices=toolkit_choices,
280    default=toolkit_default,
281    help="Select default toolkit",
282)
283
284
285@depends_if("--enable-default-toolkit")
286def full_toolkit(value):
287    return value[0]
288
289
290@depends(full_toolkit)
291def toolkit(toolkit):
292    if toolkit.startswith("cairo-gtk3"):
293        widget_toolkit = "gtk"
294    else:
295        widget_toolkit = toolkit.replace("cairo-", "")
296    return widget_toolkit
297
298
299set_config("MOZ_WIDGET_TOOLKIT", toolkit)
300add_old_configure_assignment("MOZ_WIDGET_TOOLKIT", toolkit)
301
302
303@depends(toolkit)
304def toolkit_define(toolkit):
305    if toolkit != "windows":
306        return "MOZ_WIDGET_%s" % toolkit.upper()
307
308
309set_define(toolkit_define, True)
310
311
312@depends(toolkit)
313def toolkit_gtk(toolkit):
314    return toolkit == "gtk"
315
316
317set_config("MOZ_X11", True, when=toolkit_gtk)
318set_define("MOZ_X11", True, when=toolkit_gtk)
319add_old_configure_assignment("MOZ_X11", True, when=toolkit_gtk)
320
321# Wayland support
322# ==============================================================
323wayland_headers = pkg_check_modules(
324    "MOZ_WAYLAND",
325    "gtk+-waylandz-3.0 >= 3.14 xkbcommon >= 0.4.1 libdrm >= 2.4",
326    allow_missing=depends(full_toolkit)(lambda t: t == "cairo-gtk3"),
327    when=depends(full_toolkit)(lambda t: t in ("cairo-gtk3", "cairo-gtk3-wayland")),
328)
329
330
331@depends(wayland_headers, toolkit_gtk, artifact_builds)
332def wayland_headers(wayland, toolkit_gtk, artifacts):
333    if toolkit_gtk and artifacts:
334        return True
335    return wayland
336
337
338set_config("MOZ_WAYLAND", depends_if(wayland_headers)(lambda _: True))
339set_define("MOZ_WAYLAND", depends_if(wayland_headers)(lambda _: True))
340
341# GL Provider
342# ==============================================================
343option("--with-gl-provider", nargs=1, help="Set GL provider backend type")
344
345
346@depends("--with-gl-provider")
347def gl_provider(value):
348    if value:
349        return value[0]
350
351
352@depends(gl_provider)
353def gl_provider_define(provider):
354    if provider:
355        return "GLContextProvider%s" % provider
356
357
358set_define("MOZ_GL_PROVIDER", gl_provider_define)
359
360
361@depends(gl_provider, wayland_headers, toolkit_gtk)
362def gl_default_provider(value, wayland, toolkit_gtk):
363    if value:
364        return value
365    elif wayland:
366        return "EGL"
367    elif toolkit_gtk:
368        return "GLX"
369
370
371set_config("MOZ_GL_PROVIDER", gl_provider)
372set_config("MOZ_GL_DEFAULT_PROVIDER", gl_default_provider)
373
374
375@depends(gl_default_provider)
376def gl_provider_define(provider):
377    if provider:
378        return "GL_PROVIDER_%s" % provider
379
380
381set_define(gl_provider_define, True)
382
383
384# PDF printing
385# ==============================================================
386@depends(toolkit)
387def pdf_printing(toolkit):
388    if toolkit in ("windows", "gtk", "android"):
389        return True
390
391
392@depends(pdf_printing)
393def pdf_surface_feature(pdf_printing):
394    if pdf_printing:
395        return "#define CAIRO_HAS_PDF_SURFACE 1"
396    else:
397        # CONFIGURE_SUBST_FILES need explicit empty values.
398        return ""
399
400
401set_config("MOZ_PDF_PRINTING", pdf_printing)
402set_config("PDF_SURFACE_FEATURE", pdf_surface_feature)
403
404
405# Event loop instrumentation
406# ==============================================================
407option(env="MOZ_INSTRUMENT_EVENT_LOOP", help="Force-enable event loop instrumentation")
408
409
410@depends("MOZ_INSTRUMENT_EVENT_LOOP", toolkit)
411def instrument_event_loop(value, toolkit):
412    if value or (
413        toolkit in ("windows", "gtk", "cocoa", "android") and value.origin == "default"
414    ):
415        return True
416
417
418set_config("MOZ_INSTRUMENT_EVENT_LOOP", instrument_event_loop)
419set_define("MOZ_INSTRUMENT_EVENT_LOOP", instrument_event_loop)
420
421
422# Fontconfig Freetype
423# ==============================================================
424option(env="USE_FC_FREETYPE", help="Force-enable the use of fontconfig freetype")
425
426
427@depends("USE_FC_FREETYPE", toolkit)
428def fc_freetype(value, toolkit):
429    if value or (toolkit == "gtk" and value.origin == "default"):
430        return True
431
432
433add_old_configure_assignment("USE_FC_FREETYPE", fc_freetype)
434
435# Pango
436# ==============================================================
437pkg_check_modules(
438    "MOZ_PANGO",
439    "pango >= 1.22.0 pangoft2 >= 1.22.0 pangocairo >= 1.22.0",
440    when=toolkit_gtk,
441)
442
443# Fontconfig
444# ==============================================================
445fontconfig_info = pkg_check_modules(
446    "_FONTCONFIG", "fontconfig >= 2.7.0", when=fc_freetype
447)
448
449
450@depends(fc_freetype)
451def check_for_freetype2(fc_freetype):
452    if fc_freetype:
453        return True
454
455
456# Check for freetype2. Flags are combined with fontconfig flags.
457freetype2_info = pkg_check_modules(
458    "_FT2", "freetype2 >= 6.1.0", when=check_for_freetype2
459)
460
461
462@depends(fontconfig_info, freetype2_info)
463def freetype2_combined_info(fontconfig_info, freetype2_info):
464    if not freetype2_info:
465        return
466    if not fontconfig_info:
467        return freetype2_info
468    return namespace(
469        cflags=freetype2_info.cflags + fontconfig_info.cflags,
470        libs=freetype2_info.libs + fontconfig_info.libs,
471    )
472
473
474add_old_configure_assignment(
475    "_HAVE_FREETYPE2", depends_if(freetype2_info)(lambda _: True)
476)
477
478# Apple platform decoder support
479# ==============================================================
480@depends(toolkit)
481def applemedia(toolkit):
482    if toolkit in ("cocoa", "uikit"):
483        return True
484
485
486set_config("MOZ_APPLEMEDIA", applemedia)
487set_define("MOZ_APPLEMEDIA", applemedia)
488add_old_configure_assignment("MOZ_APPLEMEDIA", applemedia)
489
490# Windows Media Foundation support
491# ==============================================================
492option("--disable-wmf", help="Disable support for Windows Media Foundation")
493
494
495@depends("--disable-wmf", target)
496def wmf(value, target):
497    enabled = bool(value)
498    if value.origin == "default":
499        # Enable Windows Media Foundation support by default.
500        # Note our minimum SDK version is Windows 7 SDK, so we are (currently)
501        # guaranteed to have a recent-enough SDK to build WMF.
502        enabled = target.os == "WINNT"
503    if enabled and target.os != "WINNT":
504        die("Cannot enable Windows Media Foundation support on %s", target.os)
505    if enabled:
506        return True
507
508
509set_config("MOZ_WMF", wmf)
510set_define("MOZ_WMF", wmf)
511
512# FFmpeg H264/AAC Decoding Support
513# ==============================================================
514option("--disable-ffmpeg", help="Disable FFmpeg for fragmented H264/AAC decoding")
515
516
517@depends("--disable-ffmpeg", target)
518def ffmpeg(value, target):
519    enabled = bool(value)
520    if value.origin == "default":
521        enabled = target.os not in ("Android", "WINNT")
522    if enabled:
523        return True
524
525
526set_config("MOZ_FFMPEG", ffmpeg)
527set_define("MOZ_FFMPEG", ffmpeg)
528imply_option("--enable-fmp4", ffmpeg, "--enable-ffmpeg")
529
530# AV1 Video Codec Support
531# ==============================================================
532option("--disable-av1", help="Disable av1 video support")
533
534
535@depends("--enable-av1")
536def av1(value):
537    if value:
538        return True
539
540
541option("--with-system-av1",
542       help="Use system av1 (located with pkgconfig)")
543
544system_libaom_info = pkg_check_modules("MOZ_SYSTEM_LIBAOM", "aom >= 1.0.0",
545                                       when="--with-system-av1")
546
547system_libdav1d_info = pkg_check_modules("MOZ_SYSTEM_LIBDAV1D", "dav1d >= 0.1.1",
548                                         when="--with-system-av1")
549
550@depends(system_libaom_info, system_libdav1d_info)
551def system_av1(system_libaom_info, system_libdav1d_info):
552    has_av1_libs = False
553    if system_libaom_info and system_libdav1d_info:
554        has_av1_libs = True
555    return has_av1_libs
556
557@depends(target, when=av1 & depends(system_av1)(lambda v: not v) & compile_environment)
558def dav1d_asm(target):
559    if target.cpu in ("aarch64", "x86", "x86_64"):
560        return True
561
562
563@depends(target, when=av1 & compile_environment)
564def dav1d_nasm(target):
565    if target.cpu in ("x86", "x86_64"):
566        return namespace(version="2.14", what="AV1")
567
568
569set_config("MOZ_DAV1D_ASM", dav1d_asm)
570set_define("MOZ_DAV1D_ASM", dav1d_asm)
571set_config("MOZ_AV1", av1)
572set_define("MOZ_AV1", av1)
573set_config("MOZ_SYSTEM_AV1", depends_if(system_av1)(lambda _: True))
574
575# JXL Image Codec Support
576# ==============================================================
577option("--disable-jxl", help="Disable jxl image support")
578
579
580@depends("--disable-jxl", milestone.is_nightly)
581def jxl(value, is_nightly):
582    if is_nightly and value:
583        return True
584
585
586set_config("MOZ_JXL", jxl)
587set_define("MOZ_JXL", jxl)
588
589# Built-in fragmented MP4 support.
590# ==============================================================
591option(
592    "--disable-fmp4",
593    env="MOZ_FMP4",
594    help="Disable support for in built Fragmented MP4 parsing",
595)
596
597
598@depends("--disable-fmp4", target, wmf, applemedia)
599def fmp4(value, target, wmf, applemedia):
600    enabled = bool(value)
601    if value.origin == "default":
602        # target.os == 'Android' includes all B2G versions
603        enabled = wmf or applemedia or target.os == "Android"
604    if enabled:
605        return True
606
607
608set_config("MOZ_FMP4", fmp4)
609set_define("MOZ_FMP4", fmp4)
610add_old_configure_assignment("MOZ_FMP4", fmp4)
611
612
613@depends(target)
614def sample_type_is_s16(target):
615    # Use integers over floats for audio on Android regardless of the CPU
616    # architecture, because audio backends for Android don't support floats.
617    # We also use integers on ARM because it's more efficient.
618    if target.os == "Android" or target.cpu == "arm":
619        return True
620
621
622@depends(sample_type_is_s16)
623def sample_type_is_float(t):
624    if not t:
625        return True
626
627
628set_config("MOZ_SAMPLE_TYPE_S16", sample_type_is_s16)
629set_define("MOZ_SAMPLE_TYPE_S16", sample_type_is_s16)
630set_config("MOZ_SAMPLE_TYPE_FLOAT32", sample_type_is_float)
631set_define("MOZ_SAMPLE_TYPE_FLOAT32", sample_type_is_float)
632
633set_define("MOZ_VORBIS", sample_type_is_float)
634set_config("MOZ_VORBIS", sample_type_is_float)
635set_define("MOZ_TREMOR", sample_type_is_s16)
636set_config("MOZ_TREMOR", sample_type_is_s16)
637
638# OpenMAX IL Decoding Support
639# ==============================================================
640option("--enable-openmax", help="Enable OpenMAX IL for video/audio decoding")
641
642
643@depends("--enable-openmax")
644def openmax(value):
645    enabled = bool(value)
646    if enabled:
647        return True
648
649
650set_config("MOZ_OMX", openmax)
651set_define("MOZ_OMX", openmax)
652
653# EME Support
654# ==============================================================
655@depends(target)
656def eme_choices(target):
657    if (
658        target.kernel in ("WINNT", "Linux")
659        and target.os != "Android"
660        and target.cpu in ("x86", "x86_64")
661    ):
662        return ("widevine",)
663    if target.kernel == "WINNT" and target.cpu == "aarch64":
664        return ("widevine",)
665    if target.os in ("OSX"):
666        return ("widevine",)
667
668
669# Widevine is enabled by default in desktop browser builds, except
670# on aarch64 Windows.
671@depends(build_project, eme_choices, target)
672def eme_default(build_project, choices, target):
673    if build_project == "browser":
674        if target.kernel != "WINNT" or target.cpu != "aarch64":
675            return choices
676
677
678option(
679    "--enable-eme",
680    nargs="+",
681    choices=eme_choices,
682    default=eme_default,
683    when=eme_choices,
684    help="{Enable|Disable} support for Encrypted Media Extensions",
685)
686
687
688@depends("--enable-eme", fmp4, when=eme_choices)
689def eme(enabled, fmp4):
690    if enabled and enabled.origin != "default" and not fmp4:
691        die("Encrypted Media Extension support requires " "Fragmented MP4 support")
692
693
694@depends("--enable-eme", when=eme_choices)
695def eme_modules(value):
696    return value
697
698
699# Fallback to an empty list when eme_choices is empty, setting eme_modules to
700# None.
701set_config("MOZ_EME_MODULES", eme_modules | dependable([]))
702
703
704@depends(eme_modules, target, when=eme_modules)
705def eme_win32_artifact(modules, target):
706    if "widevine" in modules and target.kernel == "WINNT" and target.cpu == "aarch64":
707        return True
708
709
710set_config("MOZ_EME_WIN32_ARTIFACT", eme_win32_artifact)
711
712option(
713    name="--enable-chrome-format",
714    help="Select FORMAT of chrome files during packaging.",
715    nargs=1,
716    choices=("omni", "jar", "flat"),
717    default="omni",
718)
719
720
721@depends("--enable-chrome-format")
722def packager_format(value):
723    return value[0]
724
725
726set_config("MOZ_PACKAGER_FORMAT", packager_format)
727
728
729@depends(host, build_project)
730def jar_maker_format(host, build_project):
731    # Multilocales for mobile/android use the same mergedirs for all locales,
732    # so we can't use symlinks for those builds.
733    if host.os == "WINNT" or build_project == "mobile/android":
734        return "flat"
735    return "symlink"
736
737
738set_config("MOZ_JAR_MAKER_FILE_FORMAT", jar_maker_format)
739
740
741@depends(toolkit)
742def omnijar_name(toolkit):
743    # Fennec's static resources live in the assets/ folder of the
744    # APK.  Adding a path to the name here works because we only
745    # have one omnijar file in the final package (which is not the
746    # case on desktop).
747    return "assets/omni.ja" if toolkit == "android" else "omni.ja"
748
749
750set_config("OMNIJAR_NAME", omnijar_name)
751
752project_flag("MOZ_PLACES", help="Build Places if required", set_as_define=True)
753
754project_flag(
755    "MOZ_SERVICES_HEALTHREPORT",
756    help="Build Firefox Health Reporter Service",
757    set_for_old_configure=True,
758    set_as_define=True,
759)
760
761project_flag(
762    "MOZ_NORMANDY",
763    help="Enable Normandy recipe runner",
764    set_for_old_configure=True,
765    set_as_define=True,
766)
767
768project_flag("MOZ_SERVICES_SYNC", help="Build Sync Services if required")
769
770project_flag(
771    "MOZ_ANDROID_HISTORY",
772    help="Enable Android History instead of Places",
773    set_as_define=True,
774)
775
776project_flag(
777    "MOZ_DEDICATED_PROFILES",
778    help="Enable dedicated profiles per install",
779    set_as_define=True,
780)
781
782project_flag(
783    "MOZ_BLOCK_PROFILE_DOWNGRADE",
784    help="Block users from starting profiles last used by a newer build",
785    set_as_define=True,
786)
787
788
789@depends("MOZ_PLACES", "MOZ_ANDROID_HISTORY")
790def check_places_and_android_history(places, android_history):
791    if places and android_history:
792        die("Cannot use MOZ_ANDROID_HISTORY alongside MOZ_PLACES.")
793
794
795option(
796    env="MOZ_TELEMETRY_REPORTING",
797    default=mozilla_official,
798    help="Enable telemetry reporting",
799)
800
801set_define("MOZ_TELEMETRY_REPORTING", True, when="MOZ_TELEMETRY_REPORTING")
802add_old_configure_assignment(
803    "MOZ_TELEMETRY_REPORTING", True, when="MOZ_TELEMETRY_REPORTING"
804)
805
806
807@depends("MOZ_TELEMETRY_REPORTING", milestone.is_nightly)
808def telemetry_on_by_default(reporting, is_nightly):
809    return reporting and is_nightly
810
811
812set_define("MOZ_TELEMETRY_ON_BY_DEFAULT", True, when=telemetry_on_by_default)
813
814
815# gpsd support
816# ==============================================================
817option("--enable-gpsd", env="MOZ_GPSD", help="Enable gpsd support")
818
819
820@depends("--enable-gpsd")
821def gpsd(value):
822    return bool(value)
823
824
825system_gpsd = pkg_check_modules("MOZ_GPSD", "libgps >= 3.11", when=gpsd)
826
827set_config("MOZ_GPSD", depends_if(system_gpsd)(lambda _: True))
828
829# Miscellaneous programs
830# ==============================================================
831
832check_prog("TAR", ("gnutar", "gtar", "tar"))
833check_prog("UNZIP", ("unzip",))
834check_prog("ZIP", ("zip",))
835check_prog("GN", ("gn",), allow_missing=True)
836
837# Key files
838# ==============================================================
839include("../build/moz.configure/keyfiles.configure")
840
841simple_keyfile("Mozilla API")
842
843simple_keyfile("Google Location Service API")
844
845simple_keyfile("Google Safebrowsing API")
846
847id_and_secret_keyfile("Bing API")
848
849simple_keyfile("Adjust SDK")
850
851id_and_secret_keyfile("Leanplum SDK")
852
853simple_keyfile("Pocket API")
854
855
856# WebRender Debugger integration
857# ==============================================================
858
859option(
860    "--enable-webrender-debugger", help="Build the websocket debug server in WebRender"
861)
862
863set_config(
864    "MOZ_WEBRENDER_DEBUGGER", depends_if("--enable-webrender-debugger")(lambda _: True)
865)
866
867# Additional system headers defined at the application level
868# ==============================================================
869
870option(
871    "--enable-app-system-headers",
872    env="MOZ_APP_SYSTEM_HEADERS",
873    help="Use additional system headers defined in $MOZ_BUILD_APP/app-system-headers.mozbuild",
874)
875
876
877@depends("--enable-app-system-headers")
878def app_system_headers(value):
879    if value:
880        return True
881
882
883set_config("MOZ_APP_SYSTEM_HEADERS", app_system_headers)
884set_define("MOZ_APP_SYSTEM_HEADERS", app_system_headers)
885
886# Printing
887# ==============================================================
888option("--disable-printing", help="Disable printing support")
889
890
891@depends("--disable-printing")
892def printing(value):
893    if value:
894        return True
895
896
897set_config("NS_PRINTING", printing)
898set_define("NS_PRINTING", printing)
899set_define("NS_PRINT_PREVIEW", printing)
900
901# Speech-dispatcher support
902# ==============================================================
903@depends(toolkit)
904def no_speechd_on_non_gtk(toolkit):
905    if toolkit != "gtk":
906        return False
907
908
909imply_option(
910    "--enable-synth-speechd", no_speechd_on_non_gtk, reason="--enable-default-toolkit"
911)
912
913option("--disable-synth-speechd", help="Disable speech-dispatcher support")
914
915set_config("MOZ_SYNTH_SPEECHD", depends_if("--disable-synth-speechd")(lambda _: True))
916
917# Speech API
918# ==============================================================
919option("--disable-webspeech", help="Disable support for HTML Speech API")
920
921
922@depends("--disable-webspeech")
923def webspeech(value):
924    if value:
925        return True
926
927
928set_config("MOZ_WEBSPEECH", webspeech)
929set_define("MOZ_WEBSPEECH", webspeech)
930add_old_configure_assignment("MOZ_WEBSPEECH", webspeech)
931
932# Speech API test backend
933# ==============================================================
934option(
935    "--enable-webspeechtestbackend",
936    default=webspeech,
937    help="{Enable|Disable} support for HTML Speech API Test Backend",
938)
939
940
941@depends_if("--enable-webspeechtestbackend")
942def webspeech_test_backend(value):
943    return True
944
945
946set_config("MOZ_WEBSPEECH_TEST_BACKEND", webspeech_test_backend)
947set_define("MOZ_WEBSPEECH_TEST_BACKEND", webspeech_test_backend)
948
949# Enable IPDL's "expensive" unit tests
950# ==============================================================
951option("--enable-ipdl-tests", help="Enable expensive IPDL tests")
952
953set_config("MOZ_IPDL_TESTS", depends_if("--enable-ipdl-tests")(lambda _: True))
954
955# Graphics
956# ==============================================================
957option("--disable-skia", help="Disable use of Skia")
958
959
960@depends("--disable-skia")
961def skia(value):
962    if not value:
963        die("--disable-skia is not supported anymore")
964    else:
965        return True
966
967
968set_config("MOZ_ENABLE_SKIA", skia)
969set_define("MOZ_ENABLE_SKIA", skia)
970set_define("USE_SKIA", skia)
971
972option("--enable-skia-pdf", help="Enable Skia PDF")
973
974
975@depends("--enable-skia-pdf", skia, target, milestone)
976def skia_pdf(value, skia, target, milestone):
977    if value.origin == "default":
978        if not skia:
979            return None
980        if milestone.is_nightly and target.os != "WINNT":
981            return True
982    elif value and not skia:
983        die("Cannot enable Skia PDF without enabling Skia")
984    if skia and value:
985        return True
986
987
988set_config("MOZ_ENABLE_SKIA_PDF", skia_pdf)
989set_define("MOZ_ENABLE_SKIA_PDF", skia_pdf)
990
991
992@depends(skia)
993def skia_includes(skia):
994    includes = []
995    if skia:
996        includes += [
997            "/gfx/skia",
998            "/gfx/skia/skia",
999        ]
1000    return includes
1001
1002
1003set_config("SKIA_INCLUDES", skia_includes)
1004
1005option("--with-system-webp", help="Use system libwebp (located with pkgconfig)")
1006
1007system_webp = pkg_check_modules(
1008    "MOZ_WEBP", "libwebp >= 1.0.2 libwebpdemux >= 1.0.2", when="--with-system-webp"
1009)
1010
1011set_config("MOZ_SYSTEM_WEBP", depends(when=system_webp)(lambda: True))
1012
1013# Build Freetype in the tree
1014# ==============================================================
1015@depends(target, skia_pdf)
1016def tree_freetype(target, skia_pdf):
1017    if target.os == "Android" or (skia_pdf and target.os == "WINNT"):
1018        return True
1019
1020
1021set_define("MOZ_TREE_FREETYPE", tree_freetype)
1022set_config("MOZ_TREE_FREETYPE", tree_freetype)
1023add_old_configure_assignment("MOZ_TREE_FREETYPE", tree_freetype)
1024
1025set_define("HAVE_FT_BITMAP_SIZE_Y_PPEM", tree_freetype)
1026set_define("HAVE_FT_GLYPHSLOT_EMBOLDEN", tree_freetype)
1027set_define("HAVE_FT_LOAD_SFNT_TABLE", tree_freetype)
1028
1029
1030@depends(freetype2_combined_info, tree_freetype, check_build_environment)
1031def ft2_info(freetype2_combined_info, tree_freetype, build_env):
1032    if tree_freetype:
1033        return namespace(
1034            cflags=("-I%s/modules/freetype2/include" % build_env.topsrcdir,), libs=()
1035        )
1036    if freetype2_combined_info:
1037        return freetype2_combined_info
1038
1039# Graphite2
1040# ==============================================================
1041option("--with-system-graphite2",
1042       help="Use system graphite2 (located with pkgconfig)")
1043
1044system_graphite2 = pkg_check_modules("MOZ_GRAPHITE2", "graphite2",
1045                                     when="--with-system-graphite2")
1046
1047set_config("MOZ_SYSTEM_GRAPHITE2", depends_if(system_graphite2)(lambda _: True))
1048
1049# HarfBuzz
1050# ==============================================================
1051option("--with-system-harfbuzz",
1052       help="Use system harfbuzz (located with pkgconfig)")
1053
1054system_harfbuzz = pkg_check_modules("MOZ_HARFBUZZ", "harfbuzz >= 2.7.4",
1055                                    when="--with-system-harfbuzz")
1056
1057set_config("MOZ_SYSTEM_HARFBUZZ", depends_if(system_harfbuzz)(lambda _: True))
1058
1059set_config("FT2_LIBS", ft2_info.libs)
1060add_old_configure_assignment("FT2_LIBS", ft2_info.libs)
1061add_old_configure_assignment("FT2_CFLAGS", ft2_info.cflags)
1062
1063# WebDriver (HTTP / BiDi)
1064# ==============================================================
1065#
1066# WebDriver is a remote control interface that enables introspection and
1067# control of user agents. It provides a platform- and language-neutral wire
1068# protocol as a way for out-of-process programs to remotely instruct the
1069# behavior of web browsers.
1070#
1071# The Gecko implementation is backed by Marionette and Remote Agent.
1072# Both protocols are not really toolkit features, as much as Gecko engine
1073# features. But they are enabled based on the toolkit, so here it lives.
1074#
1075# Marionette remote protocol
1076# -----------------------------------------------------------
1077#
1078# Marionette is the Gecko remote protocol used for various remote control,
1079# automation, and testing purposes throughout Gecko-based applications like
1080# Firefox, Thunderbird, and any mobile browser built upon GeckoView.
1081#
1082# It also backs ../testing/geckodriver, which is Mozilla's WebDriver
1083# implementation.
1084#
1085# The source of Marionette lives in ../remote/marionette.
1086#
1087# For more information, see:
1088# https://firefox-source-docs.mozilla.org/testing/marionette/index.html
1089#
1090# Remote Agent (WebDriver BiDi / partial CDP)
1091# -----------------------------------------------------------
1092#
1093# The primary purpose is the implementation of the WebDriver BiDi specification.
1094# But it also complements the existing Firefox Developer Tools Remote Debugging
1095# Protocol (RDP) by implementing a subset of the Chrome DevTools Protocol (CDP).
1096#
1097# The source of Remote Agent lives in ../remote.
1098#
1099# For more information, see:
1100# https://firefox-source-docs.mozilla.org/remote/index.html
1101
1102
1103option(
1104    "--disable-webdriver",
1105    help="Disable support for WebDriver remote protocols",
1106)
1107
1108
1109@depends("--disable-webdriver")
1110def webdriver(enabled):
1111    if enabled:
1112        return True
1113
1114
1115set_config("ENABLE_WEBDRIVER", webdriver)
1116set_define("ENABLE_WEBDRIVER", webdriver)
1117
1118
1119# geckodriver WebDriver implementation
1120# ==============================================================
1121#
1122# Turn off geckodriver for build configs we don't handle yet,
1123# but allow --enable-geckodriver to override when compile environment is available.
1124# --disable-tests implies disabling geckodriver.
1125# Disable building in CI
1126
1127
1128@depends(
1129    "--enable-tests", target, cross_compiling, hazard_analysis, asan, "MOZ_AUTOMATION"
1130)
1131def geckodriver_default(enable_tests, target, cross_compile, hazard, asan, automation):
1132    if not enable_tests:
1133        return False
1134    if hazard or target.os == "Android" or (asan and cross_compile):
1135        return False
1136    if automation:
1137        return False
1138    return True
1139
1140
1141option(
1142    "--enable-geckodriver",
1143    default=geckodriver_default,
1144    when="--enable-compile-environment",
1145    help="{Build|Do not build} geckodriver",
1146)
1147
1148
1149@depends("--enable-geckodriver", when="--enable-compile-environment")
1150def geckodriver(enabled):
1151    if enabled:
1152        return True
1153
1154
1155set_config("MOZ_GECKODRIVER", geckodriver)
1156
1157
1158# WebRTC
1159# ========================================================
1160@depends(target)
1161def webrtc_default(target):
1162    # Turn off webrtc for OS's we don't handle yet, but allow
1163    # --enable-webrtc to override.
1164    os_match = False
1165    for os_fragment in (
1166        "linux",
1167        "mingw",
1168        "android",
1169        "linuxandroid",
1170        "dragonfly",
1171        "freebsd",
1172        "netbsd",
1173        "openbsd",
1174        "darwin",
1175    ):
1176        if target.raw_os.startswith(os_fragment):
1177            os_match = True
1178
1179    cpu_match = False
1180    if (
1181        target.cpu
1182        in (
1183            "x86_64",
1184            "arm",
1185            "aarch64",
1186            "x86",
1187            "ia64",
1188            "mips32",
1189            "mips64",
1190        )
1191        or target.cpu.startswith("ppc")
1192    ):
1193        cpu_match = True
1194
1195    if os_match and cpu_match:
1196        return True
1197    return False
1198
1199
1200option(
1201    "--disable-webrtc",
1202    default=webrtc_default,
1203    help="{Enable|Disable} support for WebRTC",
1204)
1205
1206
1207@depends("--disable-webrtc")
1208def webrtc(enabled):
1209    if enabled:
1210        return True
1211
1212
1213set_config("MOZ_WEBRTC", webrtc)
1214set_define("MOZ_WEBRTC", webrtc)
1215add_old_configure_assignment("MOZ_WEBRTC", webrtc)
1216set_config("MOZ_SCTP", webrtc)
1217set_define("MOZ_SCTP", webrtc)
1218set_config("MOZ_SRTP", webrtc)
1219set_define("MOZ_SRTP", webrtc)
1220set_config("MOZ_WEBRTC_SIGNALING", webrtc)
1221set_define("MOZ_WEBRTC_SIGNALING", webrtc)
1222set_config("MOZ_PEERCONNECTION", webrtc)
1223set_define("MOZ_PEERCONNECTION", webrtc)
1224# MOZ_WEBRTC_ASSERT_ALWAYS turns on a number of safety asserts in
1225# opt/production builds (via MOZ_CRASH())
1226set_config("MOZ_WEBRTC_ASSERT_ALWAYS", webrtc)
1227set_define("MOZ_WEBRTC_ASSERT_ALWAYS", webrtc)
1228
1229# RAW media
1230# ==============================================================
1231
1232
1233@depends(target, webrtc)
1234def raw_media_default(target, webrtc):
1235    if target.os == "Android":
1236        return True
1237    if webrtc:
1238        return True
1239
1240
1241option(
1242    "--enable-raw",
1243    default=raw_media_default,
1244    help="{Enable|Disable} support for RAW media",
1245)
1246
1247set_config("MOZ_RAW", depends_if("--enable-raw")(lambda _: True))
1248set_define("MOZ_RAW", depends_if("--enable-raw")(lambda _: True))
1249
1250# ASan Reporter Addon
1251# ==============================================================
1252option(
1253    "--enable-address-sanitizer-reporter",
1254    help="Enable Address Sanitizer Reporter Extension",
1255)
1256
1257
1258@depends("--enable-address-sanitizer-reporter")
1259def enable_asan_reporter(value):
1260    if value:
1261        return True
1262
1263
1264set_config("MOZ_ASAN_REPORTER", enable_asan_reporter)
1265set_define("MOZ_ASAN_REPORTER", enable_asan_reporter)
1266add_old_configure_assignment("MOZ_ASAN_REPORTER", enable_asan_reporter)
1267
1268# Elfhack
1269# ==============================================================
1270with only_when("--enable-compile-environment"):
1271
1272    @depends(host, target)
1273    def has_elfhack(host, target):
1274        return (
1275            target.kernel == "Linux"
1276            and host.kernel == "Linux"
1277            and target.cpu in ("arm", "x86", "x86_64")
1278        )
1279
1280    @depends("--enable-release", enable_linker)
1281    def default_elfhack(release, linker):
1282        # Disable elfhack when explicitly building with --enable-linker=lld
1283        if linker and linker.origin != "default" and linker[0] == "lld":
1284            return False
1285        return bool(release)
1286
1287    with only_when(has_elfhack):
1288        option(
1289            "--disable-elf-hack",
1290            default=default_elfhack,
1291            help="{Enable|Disable} elf hacks",
1292        )
1293
1294        set_config("USE_ELF_HACK", depends_if("--enable-elf-hack")(lambda _: True))
1295
1296
1297@depends(check_build_environment)
1298def idl_roots(build_env):
1299    return namespace(
1300        ipdl_root=os.path.join(build_env.topobjdir, "ipc", "ipdl"),
1301        webidl_root=os.path.join(build_env.topobjdir, "dom", "bindings"),
1302        xpcom_root=os.path.join(build_env.topobjdir, "xpcom", "components"),
1303    )
1304
1305
1306set_config("WEBIDL_ROOT", idl_roots.webidl_root)
1307set_config("IPDL_ROOT", idl_roots.ipdl_root)
1308set_config("XPCOM_ROOT", idl_roots.xpcom_root)
1309
1310# Proxy bypass protection
1311# ==============================================================
1312
1313option(
1314    "--enable-proxy-bypass-protection",
1315    help="Prevent suspected or confirmed proxy bypasses",
1316)
1317
1318
1319@depends_if("--enable-proxy-bypass-protection")
1320def proxy_bypass_protection(_):
1321    return True
1322
1323
1324set_config("MOZ_PROXY_BYPASS_PROTECTION", proxy_bypass_protection)
1325set_define("MOZ_PROXY_BYPASS_PROTECTION", proxy_bypass_protection)
1326
1327# Proxy direct failover
1328# ==============================================================
1329
1330option(
1331    "--disable-proxy-direct-failover",
1332    help="Disable direct failover for system requests",
1333)
1334
1335
1336@depends_if("--disable-proxy-direct-failover")
1337def proxy_direct_failover(value):
1338    if value:
1339        return True
1340
1341
1342set_config("MOZ_PROXY_DIRECT_FAILOVER", proxy_direct_failover)
1343set_define("MOZ_PROXY_DIRECT_FAILOVER", proxy_direct_failover)
1344
1345# MIDL
1346# ==============================================================
1347
1348
1349@depends(c_compiler, toolchain_prefix)
1350def midl_names(c_compiler, toolchain_prefix):
1351    if c_compiler and c_compiler.type in ["gcc", "clang"]:
1352        # mingw
1353        widl = ("widl",)
1354        if toolchain_prefix:
1355            prefixed = tuple("%s%s" % (p, "widl") for p in toolchain_prefix)
1356            widl = prefixed + widl
1357        return widl
1358
1359    return ("midl.exe",)
1360
1361
1362@depends(target, "--enable-compile-environment")
1363def check_for_midl(target, compile_environment):
1364    if target.os != "WINNT":
1365        return
1366
1367    if compile_environment:
1368        return True
1369
1370
1371midl = check_prog(
1372    "MIDL", midl_names, when=check_for_midl, allow_missing=True, paths=sdk_bin_path
1373)
1374
1375option(env="MIDL_FLAGS", nargs=1, help="Extra flags to pass to MIDL")
1376
1377
1378@depends(
1379    "MIDL_FLAGS",
1380    c_compiler,
1381    target,
1382    host,
1383    midl,
1384    when=depends(midl, target)(lambda m, t: m and t.kernel == "WINNT"),
1385)
1386def midl_flags(flags, c_compiler, target, host, midl):
1387    if flags:
1388        flags = flags[0].split()
1389    else:
1390        flags = []
1391
1392    if not midl.endswith("widl"):
1393        env = {
1394            "x86": "win32",
1395            "x86_64": "x64",
1396            "aarch64": "arm64",
1397        }[target.cpu]
1398        flags += ["-env", env]
1399
1400        if host.os == "WINNT":
1401            return flags + ["-cpp_cmd", c_compiler.compiler]
1402
1403        # If cross-compiling and using midl instead of widl, for now, we'll
1404        # assume we can find the Windows version of clang-cl in the PATH.
1405        # It is required because while Wine is able to spawn Linux
1406        # processes from Windows programs(!), the calling program doesn't
1407        # have access to the process output and can't wait for it to
1408        # finish. Midl runs clang-cl as a preprocessor and expects to read
1409        # its output...
1410        clang_cl_exe = find_program("clang-cl.exe")
1411        if not clang_cl_exe:
1412            die("Cannot find clang-cl.exe")
1413        return flags + ["-cpp_cmd", clang_cl_exe]
1414
1415    # widl
1416    return flags + {
1417        "x86": ["--win32", "-m32"],
1418        "x86_64": ["--win64", "-m64"],
1419    }[target.cpu]
1420
1421
1422set_config("MIDL_FLAGS", midl_flags)
1423
1424# Accessibility
1425# ==============================================================
1426
1427option("--disable-accessibility", help="Disable accessibility support")
1428
1429
1430@depends("--enable-accessibility", check_for_midl, midl, c_compiler)
1431def accessibility(value, check_for_midl, midl, c_compiler):
1432    enabled = bool(value)
1433
1434    if not enabled:
1435        return
1436
1437    if check_for_midl and not midl:
1438        if c_compiler and c_compiler.type in ("gcc", "clang"):
1439            die(
1440                "You have accessibility enabled, but widl could not be found. "
1441                "Add --disable-accessibility to your mozconfig or install widl. "
1442                "See https://developer.mozilla.org/en-US/docs/Cross_Compile_Mozilla_for_Mingw32 for details."
1443            )
1444        else:
1445            die(
1446                "MIDL could not be found. "
1447                "Building accessibility without MIDL is not supported."
1448            )
1449
1450    return enabled
1451
1452
1453set_config("ACCESSIBILITY", accessibility)
1454set_define("ACCESSIBILITY", accessibility)
1455add_old_configure_assignment("ACCESSIBILITY", accessibility)
1456
1457
1458# Addon signing
1459# ==============================================================
1460@depends(milestone)
1461def require_signing(milestone):
1462    return milestone.is_release_or_beta and not milestone.is_esr
1463
1464
1465option(
1466    env="MOZ_REQUIRE_SIGNING",
1467    default=require_signing,
1468    help="Enforce that add-ons are signed by the trusted root",
1469)
1470
1471set_config("MOZ_REQUIRE_SIGNING", True, when="MOZ_REQUIRE_SIGNING")
1472set_define("MOZ_REQUIRE_SIGNING", True, when="MOZ_REQUIRE_SIGNING")
1473
1474option(
1475    "--with-unsigned-addon-scopes",
1476    nargs="+",
1477    choices=("app", "system"),
1478    help="Addon scopes where signature is not required",
1479)
1480
1481
1482@depends("--with-unsigned-addon-scopes")
1483def unsigned_addon_scopes(scopes):
1484    return namespace(
1485        app="app" in scopes or None,
1486        system="system" in scopes or None,
1487    )
1488
1489
1490set_config("MOZ_UNSIGNED_APP_SCOPE", unsigned_addon_scopes.app)
1491set_config("MOZ_UNSIGNED_SYSTEM_SCOPE", unsigned_addon_scopes.system)
1492
1493
1494# Addon sideloading
1495# ==============================================================
1496option(
1497    "--allow-addon-sideload",
1498    default=milestone.is_esr,
1499    help="Addon sideloading is allowed",
1500)
1501
1502
1503set_config("MOZ_ALLOW_ADDON_SIDELOAD", True, when="--allow-addon-sideload")
1504
1505# WebExtensions API WebIDL bindings
1506# ==============================================================
1507
1508
1509@depends(milestone)
1510def extensions_webidl_bindings_default(milestone):
1511    # Only enable the webidl bindings for the WebExtensions APIs
1512    # in Nightly.
1513    return milestone.is_nightly
1514
1515
1516option(
1517    "--enable-extensions-webidl-bindings",
1518    default=extensions_webidl_bindings_default,
1519    help="{Enable|Disable} building experimental WebExtensions WebIDL bindings",
1520)
1521
1522
1523@depends("--enable-extensions-webidl-bindings")
1524def extensions_webidl_enabled(value):
1525    return bool(value)
1526
1527
1528set_config("MOZ_WEBEXT_WEBIDL_ENABLED", extensions_webidl_enabled)
1529
1530# Launcher process (Windows only)
1531# ==============================================================
1532
1533
1534@depends(target)
1535def launcher_process_default(target):
1536    return target.os == "WINNT"
1537
1538
1539option(
1540    "--enable-launcher-process",
1541    default=launcher_process_default,
1542    help="{Enable|Disable} launcher process by default",
1543)
1544
1545
1546@depends("--enable-launcher-process", target)
1547def launcher(value, target):
1548    enabled = bool(value)
1549    if enabled and target.os != "WINNT":
1550        die("Cannot enable launcher process on %s", target.os)
1551    if enabled:
1552        return True
1553
1554
1555set_config("MOZ_LAUNCHER_PROCESS", launcher)
1556set_define("MOZ_LAUNCHER_PROCESS", launcher)
1557
1558# llvm-dlltool (Windows only)
1559# ==============================================================
1560
1561
1562@depends(build_project, target, "--enable-compile-environment")
1563def check_for_llvm_dlltool(build_project, target, compile_environment):
1564    if build_project != "browser":
1565        return
1566
1567    if target.os != "WINNT":
1568        return
1569
1570    return compile_environment
1571
1572
1573llvm_dlltool = check_prog(
1574    "LLVM_DLLTOOL",
1575    ("llvm-dlltool",),
1576    what="llvm-dlltool",
1577    when=check_for_llvm_dlltool,
1578    paths=clang_search_path,
1579)
1580
1581
1582@depends(target, when=llvm_dlltool)
1583def llvm_dlltool_flags(target):
1584    arch = {
1585        "x86": "i386",
1586        "x86_64": "i386:x86-64",
1587        "aarch64": "arm64",
1588    }[target.cpu]
1589
1590    return ["-m", arch]
1591
1592
1593set_config("LLVM_DLLTOOL_FLAGS", llvm_dlltool_flags)
1594
1595# BITS download (Windows only)
1596# ==============================================================
1597
1598option(
1599    "--enable-bits-download",
1600    when=target_is_windows,
1601    default=target_is_windows,
1602    help="{Enable|Disable} building BITS download support",
1603)
1604
1605set_define(
1606    "MOZ_BITS_DOWNLOAD",
1607    depends_if("--enable-bits-download", when=target_is_windows)(lambda _: True),
1608)
1609set_config(
1610    "MOZ_BITS_DOWNLOAD",
1611    depends_if("--enable-bits-download", when=target_is_windows)(lambda _: True),
1612)
1613
1614# Bundled fonts on desktop platform
1615# ==============================================================
1616
1617
1618@depends(target)
1619def bundled_fonts_default(target):
1620    return target.os == "WINNT" or target.kernel == "Linux"
1621
1622
1623@depends(build_project)
1624def allow_bundled_fonts(project):
1625    return project == "browser" or project == "comm/mail"
1626
1627
1628option(
1629    "--enable-bundled-fonts",
1630    default=bundled_fonts_default,
1631    when=allow_bundled_fonts,
1632    help="{Enable|Disable} support for bundled fonts on desktop platforms",
1633)
1634
1635set_define(
1636    "MOZ_BUNDLED_FONTS",
1637    depends_if("--enable-bundled-fonts", when=allow_bundled_fonts)(lambda _: True),
1638)
1639
1640# Reflow counting
1641# ==============================================================
1642
1643
1644@depends(moz_debug)
1645def reflow_perf(debug):
1646    if debug:
1647        return True
1648
1649
1650option(
1651    "--enable-reflow-perf",
1652    default=reflow_perf,
1653    help="{Enable|Disable} reflow performance tracing",
1654)
1655
1656# The difference in conditions here comes from the initial implementation
1657# in old-configure, which was unexplained there as well.
1658set_define("MOZ_REFLOW_PERF", depends_if("--enable-reflow-perf")(lambda _: True))
1659set_define("MOZ_REFLOW_PERF_DSP", reflow_perf)
1660
1661# Layout debugger
1662# ==============================================================
1663
1664
1665@depends(moz_debug)
1666def layout_debugger(debug):
1667    if debug:
1668        return True
1669
1670
1671option(
1672    "--enable-layout-debugger",
1673    default=layout_debugger,
1674    help="{Enable|Disable} layout debugger",
1675)
1676
1677set_config("MOZ_LAYOUT_DEBUGGER", True, when="--enable-layout-debugger")
1678set_define("MOZ_LAYOUT_DEBUGGER", True, when="--enable-layout-debugger")
1679
1680
1681# Shader Compiler for Windows (and MinGW Cross Compile)
1682# ==============================================================
1683
1684with only_when(compile_environment):
1685    fxc = check_prog(
1686        "FXC",
1687        ("fxc.exe", "fxc2.exe"),
1688        when=depends(target)(lambda t: t.kernel == "WINNT"),
1689        paths=sdk_bin_path,
1690    )
1691
1692
1693# VPX
1694# ===
1695
1696with only_when(compile_environment):
1697    option("--with-system-libvpx", help="Use system libvpx (located with pkgconfig)")
1698
1699    with only_when("--with-system-libvpx"):
1700        vpx = pkg_check_modules("MOZ_LIBVPX", "vpx >= 1.8.0")
1701
1702        check_header(
1703            "vpx/vpx_decoder.h",
1704            flags=vpx.cflags,
1705            onerror=lambda: die(
1706                "Couldn't find vpx/vpx_decoder.h, which is required to build "
1707                "with system libvpx. Use --without-system-libvpx to build "
1708                "with in-tree libvpx."
1709            ),
1710        )
1711
1712        check_symbol(
1713            "vpx_codec_dec_init_ver",
1714            flags=vpx.libs,
1715            onerror=lambda: die(
1716                "--with-system-libvpx requested but symbol vpx_codec_dec_init_ver "
1717                "not found"
1718            ),
1719        )
1720
1721        set_config("MOZ_SYSTEM_LIBVPX", True)
1722
1723    @depends("--with-system-libvpx", target)
1724    def in_tree_vpx(system_libvpx, target):
1725        if system_libvpx:
1726            return
1727
1728        arm_asm = (target.cpu == "arm") or None
1729        return namespace(arm_asm=arm_asm)
1730
1731    @depends(target, when=in_tree_vpx)
1732    def vpx_nasm(target):
1733        if target.cpu in ("x86", "x86_64"):
1734            if target.kernel == "WINNT":
1735                # Version 2.03 is needed for automatic safeseh support.
1736                return namespace(version="2.03", what="VPX")
1737            return namespace(what="VPX")
1738
1739    # Building with -mfpu=neon requires either the "softfp" or the
1740    # "hardfp" ABI. Depending on the compiler's default target, and the
1741    # CFLAGS, the default ABI might be neither, in which case it is the
1742    # "softfloat" ABI.
1743    # The "softfloat" ABI is binary-compatible with the "softfp" ABI, so
1744    # we can safely mix code built with both ABIs. So, if we detect
1745    # that compiling uses the "softfloat" ABI, force the use of the
1746    # "softfp" ABI instead.
1747    # Confusingly, the __SOFTFP__ preprocessor variable indicates the
1748    # "softfloat" ABI, not the "softfp" ABI.
1749    # Note: VPX_ASFLAGS is also used in CFLAGS.
1750    softfp = cxx_compiler.try_compile(
1751        body="""
1752        #ifndef __SOFTFP__
1753        #error "compiler target supports -mfpu=neon, so we don't have to add extra flags"
1754        #endif""",
1755        when=in_tree_vpx.arm_asm,
1756    )
1757
1758    @depends(in_tree_vpx, vpx_nasm, softfp, target)
1759    def vpx_as_flags(vpx, vpx_nasm, softfp, target):
1760        flags = []
1761        if vpx and vpx.arm_asm:
1762            # These flags are a lie; they're just used to enable the requisite
1763            # opcodes; actual arch detection is done at runtime.
1764            flags = ["-march=armv7-a", "-mfpu=neon"]
1765            if softfp:
1766                flags.append("-mfloat-abi=softfp")
1767        elif vpx and vpx_nasm and target.os != "WINNT" and target.cpu != "x86_64":
1768            flags = ["-DPIC"]
1769        return flags
1770
1771    set_config("VPX_USE_NASM", True, when=vpx_nasm)
1772    set_config("VPX_ASFLAGS", vpx_as_flags)
1773
1774
1775# JPEG
1776# ====
1777
1778with only_when(compile_environment):
1779    option(
1780        "--with-system-jpeg",
1781        nargs="?",
1782        help="Use system libjpeg (installed at given prefix)",
1783    )
1784
1785    @depends_if("--with-system-jpeg")
1786    def jpeg_flags(value):
1787        if len(value):
1788            return namespace(
1789                cflags=("-I%s/include" % value[0],),
1790                ldflags=("-L%s/lib" % value[0], "-ljpeg"),
1791            )
1792        return namespace(
1793            ldflags=("-ljpeg",),
1794        )
1795
1796    with only_when("--with-system-jpeg"):
1797        check_symbol(
1798            "jpeg_destroy_compress",
1799            flags=jpeg_flags.ldflags,
1800            onerror=lambda: die(
1801                "--with-system-jpeg requested but symbol "
1802                "jpeg_destroy_compress not found."
1803            ),
1804        )
1805
1806        c_compiler.try_compile(
1807            includes=[
1808                "stdio.h",
1809                "sys/types.h",
1810                "jpeglib.h",
1811            ],
1812            body="""
1813                #if JPEG_LIB_VERSION < 62
1814                #error Insufficient JPEG library version
1815                #endif
1816            """,
1817            flags=jpeg_flags.cflags,
1818            check_msg="for sufficient jpeg library version",
1819            onerror=lambda: die(
1820                "Insufficient JPEG library version for "
1821                "--with-system-jpeg (62 required)"
1822            ),
1823        )
1824
1825        c_compiler.try_compile(
1826            includes=[
1827                "stdio.h",
1828                "sys/types.h",
1829                "jpeglib.h",
1830            ],
1831            body="""
1832                #ifndef JCS_EXTENSIONS
1833                #error libjpeg-turbo JCS_EXTENSIONS required
1834                #endif
1835            """,
1836            flags=jpeg_flags.cflags,
1837            check_msg="for sufficient libjpeg-turbo JCS_EXTENSIONS",
1838            onerror=lambda: die(
1839                "libjpeg-turbo JCS_EXTENSIONS required for " "--with-system-jpeg"
1840            ),
1841        )
1842
1843        set_config("MOZ_JPEG_CFLAGS", jpeg_flags.cflags)
1844        set_config("MOZ_JPEG_LIBS", jpeg_flags.ldflags)
1845
1846    @depends("--with-system-jpeg", target)
1847    def in_tree_jpeg(system_jpeg, target):
1848        if system_jpeg:
1849            return
1850
1851        if target.kernel == "Darwin":
1852            if target.cpu == "x86":
1853                return ("-DPIC", "-DMACHO")
1854            elif target.cpu == "x86_64":
1855                return ("-D__x86_64__", "-DPIC", "-DMACHO")
1856        elif target.kernel == "WINNT":
1857            if target.cpu == "x86":
1858                return ("-DPIC", "-DWIN32")
1859            elif target.cpu == "x86_64":
1860                return ("-D__x86_64__", "-DPIC", "-DWIN64", "-DMSVC")
1861        elif target.cpu == "arm":
1862            return ("-march=armv7-a", "-mfpu=neon")
1863        elif target.cpu == "aarch64":
1864            return ("-march=armv8-a",)
1865        elif target.cpu == "mips32":
1866            return ("-mdspr2",)
1867        elif target.cpu == "x86":
1868            return ("-DPIC", "-DELF")
1869        elif target.cpu == "x86_64":
1870            return ("-D__x86_64__", "-DPIC", "-DELF")
1871
1872    @depends(target, when=in_tree_jpeg)
1873    def jpeg_nasm(target):
1874        if target.cpu in ("x86", "x86_64"):
1875            # libjpeg-turbo 2.0.6 requires nasm 2.10.
1876            return namespace(version="2.10", what="JPEG")
1877
1878    set_config("LIBJPEG_TURBO_USE_NASM", True, when=jpeg_nasm)
1879    set_config("LIBJPEG_TURBO_ASFLAGS", in_tree_jpeg)
1880
1881
1882# FFmpeg's ffvpx configuration
1883# ==============================================================
1884with only_when(compile_environment):
1885
1886    @depends(target)
1887    def libav_fft(target):
1888        return target.kernel == "WINNT" or target.cpu == "x86_64"
1889
1890    set_config("MOZ_LIBAV_FFT", depends(when=libav_fft)(lambda: True))
1891    set_define("MOZ_LIBAV_FFT", depends(when=libav_fft)(lambda: True))
1892
1893
1894# Artifact builds need MOZ_FFVPX defined as if compilation happened.
1895with only_when(compile_environment | artifact_builds):
1896
1897    @depends(target)
1898    def ffvpx(target):
1899        enable = use_nasm = True
1900        flac_only = False
1901        flags = []
1902
1903        if target.kernel == "WINNT":
1904            if target.cpu == "x86":
1905                # 32-bit windows need to prefix symbols with an underscore.
1906                flags = ["-DPIC", "-DWIN32", "-DPREFIX", "-Pconfig_win32.asm"]
1907            elif target.cpu == "x86_64":
1908                flags = [
1909                    "-D__x86_64__",
1910                    "-DPIC",
1911                    "-DWIN64",
1912                    "-DMSVC",
1913                    "-Pconfig_win64.asm",
1914                ]
1915            elif target.cpu == "aarch64":
1916                flags = ["-DPIC", "-DWIN64"]
1917                use_nasm = False
1918        elif target.kernel == "Darwin":
1919            if target.cpu == "x86_64":
1920                # 32/64-bit macosx asemblers need to prefix symbols with an
1921                # underscore.
1922                flags = [
1923                    "-D__x86_64__",
1924                    "-DPIC",
1925                    "-DMACHO",
1926                    "-DPREFIX",
1927                    "-Pconfig_darwin64.asm",
1928                ]
1929            else:
1930                flac_only = True
1931        elif target.cpu == "x86_64":
1932            flags = ["-D__x86_64__", "-DPIC", "-DELF", "-Pconfig_unix64.asm"]
1933        elif target.cpu in ("x86", "arm", "aarch64"):
1934            flac_only = True
1935        else:
1936            enable = False
1937
1938        if flac_only or not enable:
1939            use_nasm = False
1940
1941        if use_nasm:
1942            # default disabled components
1943            flags.append("-Pdefaults_disabled.asm")
1944
1945        return namespace(
1946            enable=enable,
1947            use_nasm=use_nasm,
1948            flac_only=flac_only,
1949            flags=flags,
1950        )
1951
1952    @depends(when=ffvpx.use_nasm)
1953    def ffvpx_nasm():
1954        # nasm 2.10 for AVX-2 support.
1955        return namespace(version="2.10", what="FFVPX")
1956
1957    # ffvpx_nasm can't indirectly depend on vpx_as_flags, because it depends
1958    # on a compiler test, so we have to do a little bit of dance here.
1959    @depends(ffvpx, vpx_as_flags, target)
1960    def ffvpx(ffvpx, vpx_as_flags, target):
1961        if ffvpx and vpx_as_flags and target.cpu in ("arm", "aarch64"):
1962            ffvpx.flags.extend(vpx_as_flags)
1963        return ffvpx
1964
1965    set_config("MOZ_FFVPX", True, when=ffvpx.enable)
1966    set_define("MOZ_FFVPX", True, when=ffvpx.enable)
1967    set_config("MOZ_FFVPX_AUDIOONLY", True, when=ffvpx.flac_only)
1968    set_define("MOZ_FFVPX_AUDIOONLY", True, when=ffvpx.flac_only)
1969    set_config("FFVPX_ASFLAGS", ffvpx.flags)
1970    set_config("FFVPX_USE_NASM", True, when=ffvpx.use_nasm)
1971
1972
1973# nasm detection
1974# ==============================================================
1975@depends(dav1d_nasm, vpx_nasm, jpeg_nasm, ffvpx_nasm, when=compile_environment)
1976def need_nasm(*requirements):
1977    requires = {
1978        x.what: x.version if hasattr(x, "version") else True for x in requirements if x
1979    }
1980    if requires:
1981        items = sorted(requires.keys())
1982        if len(items) > 1:
1983            what = " and ".join((", ".join(items[:-1]), items[-1]))
1984        else:
1985            what = items[0]
1986        versioned = {k: v for (k, v) in requires.items() if v is not True}
1987        return namespace(what=what, versioned=versioned)
1988
1989
1990nasm = check_prog(
1991    "NASM",
1992    ["nasm"],
1993    allow_missing=True,
1994    bootstrap="nasm",
1995    when=need_nasm,
1996)
1997
1998
1999@depends(nasm, need_nasm.what)
2000def check_nasm(nasm, what):
2001    if not nasm and what:
2002        die("Nasm is required to build with %s, but it was not found." % what)
2003    return nasm
2004
2005
2006@depends_if(check_nasm)
2007@checking("nasm version")
2008def nasm_version(nasm):
2009    version = (
2010        check_cmd_output(nasm, "-v", onerror=lambda: die("Failed to get nasm version."))
2011        .splitlines()[0]
2012        .split()[2]
2013    )
2014    return Version(version)
2015
2016
2017@depends(nasm_version, need_nasm.versioned, when=need_nasm.versioned)
2018def check_nasm_version(nasm_version, versioned):
2019    by_version = sorted(versioned.items(), key=lambda x: x[1])
2020    what, version = by_version[-1]
2021    if nasm_version < version:
2022        die(
2023            "Nasm version %s or greater is required to build with %s." % (version, what)
2024        )
2025    return nasm_version
2026
2027
2028@depends(target, when=check_nasm_version)
2029def nasm_asflags(target):
2030    asflags = {
2031        ("OSX", "x86"): ["-f", "macho32"],
2032        ("OSX", "x86_64"): ["-f", "macho64"],
2033        ("WINNT", "x86"): ["-f", "win32"],
2034        ("WINNT", "x86_64"): ["-f", "win64"],
2035    }.get((target.os, target.cpu), None)
2036    if asflags is None:
2037        # We're assuming every x86 platform we support that's
2038        # not Windows or Mac is ELF.
2039        if target.cpu == "x86":
2040            asflags = ["-f", "elf32"]
2041        elif target.cpu == "x86_64":
2042            asflags = ["-f", "elf64"]
2043    return asflags
2044
2045
2046set_config("NASM_ASFLAGS", nasm_asflags)
2047
2048
2049# ANGLE OpenGL->D3D translator for WebGL
2050# ==============================================================
2051
2052with only_when(compile_environment & target_is_windows):
2053
2054    def d3d_compiler_dll_result(value):
2055        if not value.path:
2056            return "provided by the OS"
2057        return value.path
2058
2059    @depends(target, valid_windows_sdk_dir, fxc)
2060    @checking("for D3D compiler DLL", d3d_compiler_dll_result)
2061    @imports("os.path")
2062    def d3d_compiler_dll(target, windows_sdk_dir, fxc):
2063        suffix = {
2064            "x86_64": "x64",
2065        }.get(target.cpu, target.cpu)
2066
2067        name = "d3dcompiler_47.dll"
2068
2069        if target.cpu == "aarch64":
2070            # AArch64 Windows comes with d3dcompiler_47.dll installed
2071            return namespace(name=name, path=None)
2072
2073        if windows_sdk_dir:
2074            path = os.path.join(windows_sdk_dir.path, "Redist", "D3D", suffix, name)
2075            error_extra = "in Windows SDK at {}".format(windows_sdk_dir.path)
2076        else:
2077            path = os.path.join(os.path.dirname(fxc), name)
2078            error_extra = "alongside FXC at {}".format(fxc)
2079
2080        if os.path.exists(path):
2081            return namespace(name=name, path=path)
2082        die("Could not find {} {}".format(name, error_extra))
2083
2084    set_config("MOZ_ANGLE_RENDERER", True)
2085    set_config(
2086        "MOZ_D3DCOMPILER_VISTA_DLL", d3d_compiler_dll.name, when=d3d_compiler_dll.path
2087    )
2088    set_config("MOZ_D3DCOMPILER_VISTA_DLL_PATH", d3d_compiler_dll.path)
2089
2090# Remoting protocol support
2091# ==============================================================
2092
2093
2094@depends(toolkit)
2095def has_remote(toolkit):
2096    if toolkit in ("gtk", "windows", "cocoa"):
2097        return True
2098
2099
2100set_config("MOZ_HAS_REMOTE", has_remote)
2101set_define("MOZ_HAS_REMOTE", has_remote)
2102
2103# RLBox Library Sandboxing wasm support
2104# ==============================================================
2105
2106
2107def wasm_sandboxing_libraries():
2108    return (
2109        "graphite",
2110        "ogg",
2111        "hunspell",
2112    )
2113
2114
2115option(
2116    "--with-wasm-sandboxed-libraries",
2117    env="WASM_SANDBOXED_LIBRARIES",
2118    help="Enable wasm sandboxing for the selected libraries",
2119    nargs="+",
2120    choices=dependable(wasm_sandboxing_libraries),
2121)
2122
2123
2124@depends("--with-wasm-sandboxed-libraries")
2125def requires_wasm_sandboxing(libraries):
2126    if libraries:
2127        return True
2128
2129
2130set_config("MOZ_USING_WASM_SANDBOXING", requires_wasm_sandboxing)
2131set_define("MOZ_USING_WASM_SANDBOXING", requires_wasm_sandboxing)
2132
2133with only_when(requires_wasm_sandboxing & compile_environment):
2134    lucetc = check_prog("LUCETC", ["lucetc"], bootstrap="lucetc")
2135
2136    option(
2137        "--with-wasi-sysroot",
2138        env="WASI_SYSROOT",
2139        nargs=1,
2140        help="Path to wasi sysroot for wasm sandboxing",
2141    )
2142
2143    @depends("--with-wasi-sysroot", toolchains_base_dir)
2144    @imports("os")
2145    def wasi_sysroot(wasi_sysroot, toolchains_base_dir):
2146        if not wasi_sysroot:
2147            sysroot = os.path.join(
2148                toolchains_base_dir, "wasi-sysroot", "share", "wasi-sysroot"
2149            )
2150            if os.path.isdir(sysroot):
2151                return sysroot
2152            die(
2153                "Cannot find a wasi sysroot. Install the sysroot at %s or set "
2154                "--with-wasi-sysroot." % sysroot
2155            )
2156
2157        wasi_sysroot = wasi_sysroot[0]
2158        if not os.path.isdir(wasi_sysroot):
2159            die("Argument to --with-wasi-sysroot must be a directory")
2160        if not os.path.isabs(wasi_sysroot):
2161            die("Argument to --with-wasi-sysroot must be an absolute path")
2162
2163        return wasi_sysroot
2164
2165    set_config("WASI_SYSROOT", wasi_sysroot)
2166
2167    def wasm_compiler_with_flags(
2168        wasm_compiler, provided_wasm_compiler, sysroot, compiler_wrapper
2169    ):
2170        if not sysroot:
2171            return
2172        if provided_wasm_compiler:
2173            return " ".join(
2174                list(compiler_wrapper or [])
2175                + provided_wasm_compiler.wrapper
2176                + [provided_wasm_compiler.program]
2177                + provided_wasm_compiler.flags
2178                + ["--sysroot=%s" % sysroot]
2179            )
2180        elif wasm_compiler:
2181            return " ".join(
2182                list(compiler_wrapper or [])
2183                + [wasm_compiler]
2184                + ["--target=wasm32-wasi", "--sysroot=%s" % sysroot]
2185            )
2186
2187    option(env="WASM_CC", nargs=1, help="Path to the C->WASM compiler")
2188    provided_wasm_cc = provided_program("WASM_CC")
2189    wasm_cc = check_prog(
2190        "_WASM_CC",
2191        ["clang"],
2192        input=provided_wasm_cc.program,
2193        paths=clang_search_path,
2194        allow_missing=True,
2195        what="the C->WASM compiler",
2196    )
2197
2198    @depends(wasm_cc, provided_wasm_cc, wasi_sysroot, compiler_wrapper)
2199    def wasm_cc_with_flags(wasm_cc, provided_wasm_cc, wasi_sysroot, compiler_wrapper):
2200        return wasm_compiler_with_flags(
2201            wasm_cc, provided_wasm_cc, wasi_sysroot, compiler_wrapper
2202        )
2203
2204    set_config("WASM_CC", wasm_cc_with_flags)
2205
2206    option(env="WASM_CXX", nargs=1, help="Path to the C++->WASM compiler")
2207    provided_wasm_cxx = provided_program("WASM_CXX")
2208    wasm_cxx = check_prog(
2209        "_WASM_CXX",
2210        ["clang++"],
2211        input=provided_wasm_cxx.program,
2212        paths=clang_search_path,
2213        allow_missing=True,
2214        what="the C++->WASM compiler",
2215    )
2216
2217    @depends(wasm_cxx, provided_wasm_cxx, wasi_sysroot, compiler_wrapper)
2218    def wasm_cxx_with_flags(
2219        wasm_cxx, provided_wasm_cxx, wasi_sysroot, compiler_wrapper
2220    ):
2221        return wasm_compiler_with_flags(
2222            wasm_cxx, provided_wasm_cxx, wasi_sysroot, compiler_wrapper
2223        )
2224
2225    set_config("WASM_CXX", wasm_cxx_with_flags)
2226
2227    wasm_compile_flags = dependable(
2228        ["-fno-exceptions", "-fno-strict-aliasing", "-Qunused-arguments"]
2229    )
2230    option(env="WASM_CFLAGS", nargs=1, help="Options to pass to WASM_CC")
2231
2232    @depends("WASM_CFLAGS", wasm_compile_flags)
2233    def wasm_cflags(value, wasm_compile_flags):
2234        if value:
2235            return wasm_compile_flags + value
2236        else:
2237            return wasm_compile_flags
2238
2239    set_config("WASM_CFLAGS", wasm_cflags)
2240
2241    option(env="WASM_CXXFLAGS", nargs=1, help="Options to pass to WASM_CXX")
2242
2243    @depends("WASM_CXXFLAGS", wasm_compile_flags)
2244    def wasm_cxxflags(value, wasm_compile_flags):
2245        if value:
2246            return wasm_compile_flags + value
2247        else:
2248            return wasm_compile_flags
2249
2250    set_config("WASM_CXXFLAGS", wasm_cxxflags)
2251
2252    # This function is returning "ldflags" that lucetc will use when invoking
2253    # the linker, but really lucetc is going to be invoking the compiler, since
2254    # the compiler handles lots of details for us (like finding the linker in
2255    # cross-compilation scenarios).
2256    @depends(target)
2257    def lucetc_ldflags(target):
2258        if target.kernel == "Linux":
2259            return [
2260                "-Wl,-shared",
2261                "-nostdlib",
2262            ]
2263
2264        if target.kernel == "Darwin":
2265            return [
2266                "-Wl,-dylib",
2267                "-Wl,-dead_strip",
2268                "-Wl,-export_dynamic",
2269                "-Wl,-undefined,dynamic_lookup",
2270                "-nostdlib",
2271            ]
2272
2273    set_config("LUCETC_LDFLAGS", lucetc_ldflags)
2274
2275    # Re-using the Rust target triple here is not exactly correct, but it is an
2276    # excellent approximation for the platforms we currently support
2277    set_config("LUCETC_TARGET", rust_target_triple)
2278
2279
2280@depends("--with-wasm-sandboxed-libraries", target)
2281def wasm_sandboxing(libraries, target):
2282    if not libraries:
2283        return
2284
2285    # Wasm sandboxing is only enabled on specific targets.
2286    if not (
2287        target.cpu in ("x86_64",)
2288        and (target.kernel == "Linux" and target.os != "Android")
2289        or target.kernel == "Darwin"
2290    ):
2291        die("wasm sandboxing is only enabled on x86-64 Linux and Mac")
2292
2293    return namespace(**{name: True for name in libraries})
2294
2295
2296@template
2297def wasm_sandboxing_config_defines():
2298    for lib in wasm_sandboxing_libraries():
2299        set_config(
2300            "MOZ_WASM_SANDBOXING_%s" % lib.upper(), getattr(wasm_sandboxing, lib)
2301        )
2302        set_define(
2303            "MOZ_WASM_SANDBOXING_%s" % lib.upper(), getattr(wasm_sandboxing, lib)
2304        )
2305
2306
2307wasm_sandboxing_config_defines()
2308
2309
2310# new XULStore implementation
2311# ==============================================================
2312
2313
2314@depends(milestone)
2315def new_xulstore(milestone):
2316    if milestone.is_nightly:
2317        return True
2318
2319
2320set_config("MOZ_NEW_XULSTORE", True, when=new_xulstore)
2321set_define("MOZ_NEW_XULSTORE", True, when=new_xulstore)
2322
2323
2324# new Notification Store implementation
2325# ==============================================================
2326
2327
2328@depends(milestone)
2329def new_notification_store(milestone):
2330    if milestone.is_nightly:
2331        return True
2332
2333
2334set_config("MOZ_NEW_NOTIFICATION_STORE", True, when=new_notification_store)
2335set_define("MOZ_NEW_NOTIFICATION_STORE", True, when=new_notification_store)
2336
2337
2338# Glean SDK Integration Crate
2339# ==============================================================
2340
2341
2342@depends(target)
2343def glean_android(target):
2344    return target.os == "Android"
2345
2346
2347set_config("MOZ_GLEAN_ANDROID", True, when=glean_android)
2348set_define("MOZ_GLEAN_ANDROID", True, when=glean_android)
2349
2350
2351# dump_syms
2352# ==============================================================
2353
2354check_prog(
2355    "DUMP_SYMS",
2356    ["dump_syms"],
2357    allow_missing=True,
2358    bootstrap="dump_syms",
2359    when=compile_environment,
2360)
2361
2362
2363check_prog(
2364    "PDBSTR",
2365    ["pdbstr.exe"],
2366    allow_missing=True,
2367    bootstrap="pdbstr",
2368    when=compile_environment & target_is_windows,
2369)
2370
2371
2372@depends("MOZ_AUTOMATION", c_compiler)
2373def allow_missing_winchecksec(automation, c_compiler):
2374    if not automation:
2375        return True
2376    if c_compiler and c_compiler.type != "clang-cl":
2377        return True
2378
2379
2380check_prog(
2381    "WINCHECKSEC",
2382    ["winchecksec.exe", "winchecksec"],
2383    bootstrap="winchecksec",
2384    allow_missing=allow_missing_winchecksec,
2385    when=compile_environment & target_is_windows,
2386)
2387
2388# Fork server
2389@depends(target, build_project)
2390def forkserver_default(target, build_project):
2391    return build_project == "browser" and (
2392        (target.os == "GNU" and target.kernel == "Linux")
2393        or target.os == "FreeBSD"
2394        or target.os == "OpenBSD"
2395    )
2396
2397
2398option(
2399    "--enable-forkserver",
2400    default=forkserver_default,
2401    env="MOZ_ENABLE_FORKSERVER",
2402    help="{Enable|Disable} fork server",
2403)
2404
2405
2406@depends("--enable-forkserver", target)
2407def forkserver_flag(value, target):
2408    if (
2409        target.os == "Android"
2410        or (target.os == "GNU" and target.kernel == "Linux")
2411        or target.os == "FreeBSD"
2412        or target.os == "OpenBSD"
2413    ):
2414        return bool(value)
2415    pass
2416
2417
2418set_config("MOZ_ENABLE_FORKSERVER", forkserver_flag)
2419set_define("MOZ_ENABLE_FORKSERVER", forkserver_flag, forkserver_flag)
2420
2421# Crash Reporter
2422# ==============================================================
2423
2424with only_when(compile_environment & target_is_linux):
2425    # Check if we need to use the breakpad_getcontext fallback.
2426    getcontext = check_symbol("getcontext")
2427    set_config("HAVE_GETCONTEXT", getcontext)
2428    set_define("HAVE_GETCONTEXT", getcontext)
2429
2430# NSS
2431# ==============================================================
2432include("../build/moz.configure/nss.configure")
2433
2434
2435# Enable or disable running in background task mode: headless for
2436# periodic, short-lived, maintenance tasks.
2437# ==============================================================================
2438
2439
2440option(
2441    "--disable-backgroundtasks",
2442    help="Disable running in background task mode",
2443)
2444
2445
2446set_config(
2447    "MOZ_BACKGROUNDTASKS", depends_if("--enable-backgroundtasks")(lambda _: True)
2448)
2449
2450
2451# Update-related programs: updater, maintenance service, update agent,
2452# default browser agent.
2453# ==============================================================
2454include("../build/moz.configure/update-programs.configure")
2455
2456
2457# Mobile optimizations
2458# ==============================================================
2459option(
2460    "--enable-mobile-optimize",
2461    default=target_is_android,
2462    help="{Enable|Disable} mobile optimizations",
2463)
2464
2465set_define("MOZ_GFX_OPTIMIZE_MOBILE", True, when="--enable-mobile-optimize")
2466# We ignore "paint will resample" on mobile for performance.
2467# We may want to revisit this later.
2468set_define("MOZ_IGNORE_PAINT_WILL_RESAMPLE", True, when="--enable-mobile-optimize")
2469
2470# Pref extensions
2471# ==============================================================
2472option("--disable-pref-extensions", help="Disable pref extensions such as autoconfig")
2473set_config("MOZ_PREF_EXTENSIONS", True, when="--enable-pref-extensions")
2474
2475# Offer a way to disable the startup cache
2476# ==============================================================
2477option("--disable-startupcache", help="Disable startup cache")
2478
2479
2480@depends("--enable-startupcache")
2481def enable_startupcache(value):
2482    if value:
2483        return True
2484
2485
2486set_define(
2487    "MOZ_DISABLE_STARTUPCACHE", True, when=depends(enable_startupcache)(lambda x: not x)
2488)
2489
2490
2491# Branding
2492# ==============================================================
2493option(
2494    env="MOZ_APP_REMOTINGNAME",
2495    nargs=1,
2496    help="Used for the internal program name, which affects profile name "
2497    "and remoting. If not set, defaults to MOZ_APP_NAME.",
2498)
2499
2500
2501@depends("MOZ_APP_REMOTINGNAME", moz_app_name)
2502def moz_app_remotingname(value, moz_app_name):
2503    if value:
2504        return value[0]
2505    return moz_app_name
2506
2507
2508set_config("MOZ_APP_REMOTINGNAME", moz_app_remotingname)
2509
2510option(
2511    env="ANDROID_PACKAGE_NAME",
2512    nargs=1,
2513    help="Name of the Android package (default org.mozilla.$MOZ_APP_NAME)",
2514)
2515
2516
2517@depends("ANDROID_PACKAGE_NAME", moz_app_name)
2518def android_package_name(value, moz_app_name):
2519    if value:
2520        return value[0]
2521    if moz_app_name == "fennec":
2522        return "org.mozilla.fennec_aurora"
2523    return "org.mozilla.%s" % moz_app_name
2524
2525
2526set_config("ANDROID_PACKAGE_NAME", android_package_name)
2527
2528
2529# Miscellaneous options
2530# ==============================================================
2531option(env="MOZ_WINCONSOLE", nargs="?", help="Whether we can create a console window.")
2532set_define("MOZ_WINCONSOLE", True, when=depends("MOZ_WINCONSOLE")(lambda x: x))
2533
2534option(
2535    env="MOZ_USE_NATIVE_POPUP_WINDOWS",
2536    default=target_is_android,
2537    help="Whether to use native popup windows",
2538)
2539
2540set_define("MOZ_USE_NATIVE_POPUP_WINDOWS", True, when="MOZ_USE_NATIVE_POPUP_WINDOWS")
2541
2542
2543# Alternative Crashreporter setting
2544option(
2545    "--with-crashreporter-url",
2546    env="MOZ_CRASHREPORTER_URL",
2547    default="https://crash-reports.mozilla.com/",
2548    nargs=1,
2549    help="Set an alternative crashreporter url",
2550)
2551
2552set_config(
2553    "MOZ_CRASHREPORTER_URL",
2554    depends("--with-crashreporter-url")(lambda x: x[0].rstrip("/")),
2555)
2556
2557
2558# Crash reporter options
2559# ==============================================================
2560@depends(target)
2561def oxidized_breakpad(target):
2562    if target.kernel == "Linux" and target.os != "Android":
2563        return target.cpu in ("x86", "x86_64")
2564    return False
2565
2566
2567set_config("MOZ_OXIDIZED_BREAKPAD", True, when=oxidized_breakpad)
2568set_define("MOZ_OXIDIZED_BREAKPAD", True, when=oxidized_breakpad)
2569