diff options
Diffstat (limited to 'toolkit/moz.configure')
-rw-r--r-- | toolkit/moz.configure | 3684 |
1 files changed, 3684 insertions, 0 deletions
diff --git a/toolkit/moz.configure b/toolkit/moz.configure new file mode 100644 index 0000000000..b616109b1f --- /dev/null +++ b/toolkit/moz.configure @@ -0,0 +1,3684 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + +# Set the MOZ_CONFIGURE_OPTIONS variable with all the options that +# were passed somehow (environment, command line, mozconfig) +@dependable +@imports(_from="mozbuild.shellutil", _import="quote") +@imports(_from="mozbuild.util", _import="ensure_unicode") +@imports(_from="mozbuild.util", _import="system_encoding") +@imports("__sandbox__") +def all_configure_options(): + result = [] + previous = None + for option in __sandbox__._options.values(): + # __sandbox__._options contains items for both option.name and + # option.env. But it's also an OrderedDict, meaning both are + # consecutive. + # Also ignore OLD_CONFIGURE and MOZCONFIG because they're not + # interesting. + if option == previous or option.env in ("OLD_CONFIGURE", "MOZCONFIG"): + continue + previous = option + value = __sandbox__._value_for(option) + # We only want options that were explicitly given on the command + # line, the environment, or mozconfig, and that differ from the + # defaults. + if ( + value is not None + and value.origin not in ("default", "implied") + and value != option.default + ): + result.append( + ensure_unicode(__sandbox__._raw_options[option], system_encoding) + ) + # We however always include options that are sent to old configure + # because we don't know their actual defaults. (Keep the conditions + # separate for ease of understanding and ease of removal) + elif ( + option.help == "Help missing for old configure options" + and option in __sandbox__._raw_options + ): + result.append( + ensure_unicode(__sandbox__._raw_options[option], system_encoding) + ) + + # We shouldn't need this, but currently, quote will return a byte string + # if result is empty, and that's not wanted here. + if not result: + return "" + + return quote(*result) + + +set_config("MOZ_CONFIGURE_OPTIONS", all_configure_options) + + +@depends(target) +def fold_libs(target): + return target.os in ("WINNT", "OSX", "Android") + + +set_config("MOZ_FOLD_LIBS", fold_libs) + +# Profiling +# ============================================================== +# Some of the options here imply an option from js/moz.configure, +# so, need to be declared before the include. + +option( + "--enable-jprof", + env="MOZ_JPROF", + help="Enable jprof profiling tool (needs mozilla/tools/jprof)", +) + + +@depends("--enable-jprof") +def jprof(value): + if value: + return True + + +set_config("MOZ_JPROF", jprof) +set_define("MOZ_JPROF", jprof) +imply_option("--enable-profiling", jprof) + + +@depends(target) +def gecko_profiler(target): + if target.os == "Android": + return target.cpu in ("aarch64", "arm", "x86", "x86_64") + elif target.kernel == "Linux": + return target.cpu in ("aarch64", "arm", "x86", "x86_64", "mips64") + elif target.kernel == "FreeBSD": + return target.cpu in ("aarch64", "x86_64") + return target.os in ("OSX", "WINNT") + + +@depends(gecko_profiler) +def gecko_profiler_define(value): + if value: + return True + + +set_config("MOZ_GECKO_PROFILER", gecko_profiler_define) +set_define("MOZ_GECKO_PROFILER", gecko_profiler_define) + + +# Whether code to parse ELF binaries should be compiled for the Gecko profiler +# (for symbol table dumping). +@depends(gecko_profiler, target) +def gecko_profiler_parse_elf(value, target): + # Currently we only want to build this code on Linux (including Android) and BSD. + # For Android, this is in order to dump symbols from Android system, where + # on other platforms there exist alternatives that don't require bloating + # up our binary size. For Linux more generally, we use this in profile + # pre-symbolication support, since MozDescribeCodeAddress doesn't do + # anything useful on that platform. (Ideally, we would update + # MozDescribeCodeAddress to call into some Rust crates that parse ELF and + # DWARF data, but build system issues currently prevent Rust from being + # used in mozglue.) + if value and (target.kernel == "Linux" or target.kernel == "FreeBSD"): + return True + + +set_config("MOZ_GECKO_PROFILER_PARSE_ELF", gecko_profiler_parse_elf) +set_define("MOZ_GECKO_PROFILER_PARSE_ELF", gecko_profiler_parse_elf) + +# enable this by default if the profiler is enabled +# Note: also requires jemalloc +set_config("MOZ_PROFILER_MEMORY", gecko_profiler_define) +set_define("MOZ_PROFILER_MEMORY", gecko_profiler_define) + + +@depends( + "--enable-debug", + milestone, + build_project, + # Artifact builds are included because the downloaded artifacts can + # have DMD enabled. + when=artifact_builds | depends(when="--enable-replace-malloc")(lambda: True), +) +def dmd_default(debug, milestone, build_project): + return bool(build_project == "browser" and (debug or milestone.is_nightly)) + + +option( + "--enable-dmd", + env="MOZ_DMD", + default=dmd_default, + help="{Enable|Disable} Dark Matter Detector (heap profiler). " + "Also enables jemalloc, replace-malloc and profiling", +) + + +@depends("--enable-dmd") +def dmd(value): + if value: + return True + + +set_config("MOZ_DMD", dmd) +set_define("MOZ_DMD", dmd) +imply_option("--enable-profiling", dmd) +imply_option("--enable-jemalloc", dmd, when=compile_environment) +imply_option("--enable-replace-malloc", dmd, when=compile_environment) + + +# midir-based Web MIDI support +# ============================================================== +@depends(target) +def midir_linux_support(target): + return ( + target.kernel == "Linux" and target.os != "Android" and target.cpu != "riscv64" + ) + + +@depends(target, midir_linux_support) +def midir_support(target, midir_linux_support): + if target.os in ("WINNT", "OSX") or midir_linux_support: + return True + + +set_config("MOZ_WEBMIDI_MIDIR_IMPL", midir_support) + + +# Enable various cubeb backends +# ============================================================== +@depends(target) +def audio_backends_default(target): + if target.os == "Android": + return ( + "aaudio", + "opensl", + ) + elif target.os in ("DragonFly", "FreeBSD", "SunOS"): + return ("oss",) + elif target.os == "OpenBSD": + return ("sndio",) + elif target.os == "OSX": + return ("audiounit",) + elif target.os == "NetBSD": + return ("sunaudio",) + elif target.os == "SunOS": + return ("sunaudio",) + elif target.os == "WINNT": + return ("wasapi",) + else: + return ("pulseaudio",) + + +option( + "--enable-audio-backends", + nargs="+", + choices=( + "aaudio", + "alsa", + "audiounit", + "jack", + "opensl", + "oss", + "pulseaudio", + "sndio", + "sunaudio", + "wasapi", + ), + default=audio_backends_default, + help="{Enable|Disable} various cubeb backends", +) + + +@depends("--enable-audio-backends", target) +def imply_aaudio(values, target): + if any("aaudio" in value for value in values) and target.os != "Android": + die("Cannot enable AAudio on %s", target.os) + return any("aaudio" in value for value in values) or None + + +@depends("--enable-audio-backends", target) +def imply_alsa(values, target): + if ( + any("alsa" in value for value in values) + and target.kernel != "Linux" + and target.os != "FreeBSD" + ): + die("Cannot enable ALSA on %s", target.os) + return any("alsa" in value for value in values) or None + + +@depends("--enable-audio-backends", target) +def imply_audiounit(values, target): + if ( + any("audiounit" in value for value in values) + and target.os != "OSX" + and target.kernel != "Darwin" + ): + die("Cannot enable AudioUnit on %s", target.os) + return any("audiounit" in value for value in values) or None + + +@depends("--enable-audio-backends") +def imply_jack(values): + return any("jack" in value for value in values) or None + + +@depends("--enable-audio-backends", target) +def imply_opensl(values, target): + if any("opensl" in value for value in values) and target.os != "Android": + die("Cannot enable OpenSL on %s", target.os) + return any("opensl" in value for value in values) or None + + +@depends("--enable-audio-backends", target) +def imply_oss(values, target): + if any("oss" in value for value in values) and ( + target.os == "Android" or target.os == "OSX" or target.os == "WINNT" + ): + die("Cannot enable OSS on %s", target.os) + return any("oss" in value for value in values) or None + + +@depends("--enable-audio-backends", target) +def imply_pulseaudio(values, target): + if any("pulseaudio" in value for value in values) and ( + target.os == "Android" or target.os == "OSX" or target.os == "WINNT" + ): + die("Cannot enable PulseAudio on %s", target.os) + return any("pulseaudio" in value for value in values) or None + + +@depends("--enable-audio-backends", target) +def imply_sndio(values, target): + if any("sndio" in value for value in values) and ( + target.os == "Android" or target.os == "OSX" or target.os == "WINNT" + ): + die("Cannot enable sndio on %s", target.os) + return any("sndio" in value for value in values) or None + + +@depends("--enable-audio-backends", target) +def imply_sunaudio(values, target): + if any("sunaudio" in value for value in values) and ( + target.os != "NetBSD" and target.os != "SunOS" + ): + die("Cannot enable sunaudio on %s", target.os) + return any("sunaudio" in value for value in values) or None + + +@depends("--enable-audio-backends", target) +def imply_wasapi(values, target): + if any("wasapi" in value for value in values) and target.os != "WINNT": + die("Cannot enable WASAPI on %s", target.os) + return any("wasapi" in value for value in values) or None + + +set_config("MOZ_AAUDIO", imply_aaudio, when="--enable-audio-backends") + +imply_option("--enable-alsa", imply_alsa, reason="--enable-audio-backends") + +set_config("MOZ_AUDIOUNIT_RUST", imply_audiounit, when="--enable-audio-backends") + +imply_option("--enable-jack", imply_jack, reason="--enable-audio-backends") + +set_config("MOZ_OPENSL", imply_opensl, when="--enable-audio-backends") + +set_config("MOZ_OSS", imply_oss, when="--enable-audio-backends") + +imply_option("--enable-pulseaudio", imply_pulseaudio, reason="--enable-audio-backends") + +imply_option("--enable-sndio", imply_sndio, reason="--enable-audio-backends") + +set_config("MOZ_SUNAUDIO", imply_sunaudio, when="--enable-audio-backends") + +set_config("MOZ_WASAPI", imply_wasapi, when="--enable-audio-backends") + +# ALSA cubeb backend +# ============================================================== +option("--enable-alsa", env="MOZ_ALSA", help="Enable ALSA audio backend.") + + +@depends("--enable-alsa", midir_linux_support) +def enable_alsa_or_midir_linux_support(alsa_enabled, midir_linux_support): + return alsa_enabled or midir_linux_support + + +pkg_check_modules("MOZ_ALSA", "alsa", when=enable_alsa_or_midir_linux_support) + +set_config("MOZ_ALSA", True, when="--enable-alsa") +set_define("MOZ_ALSA", True, when="--enable-alsa") + +# JACK cubeb backend +# ============================================================== +system_lib_option("--enable-jack", env="MOZ_JACK", help="Enable JACK audio backend.") + +jack = pkg_check_modules("MOZ_JACK", "jack", when="--enable-jack") + +set_config("MOZ_JACK", depends_if(jack)(lambda _: True)) + +# PulseAudio cubeb backend +# ============================================================== +option( + "--enable-pulseaudio", + env="MOZ_PULSEAUDIO", + help="{Enable|Disable} PulseAudio audio backend.", +) + +pulseaudio = pkg_check_modules("MOZ_PULSEAUDIO", "libpulse", when="--enable-pulseaudio") + +set_config("MOZ_PULSEAUDIO", depends_if(pulseaudio)(lambda _: True)) +set_define("MOZ_PULSEAUDIO", depends_if(pulseaudio)(lambda _: True)) + +# sndio cubeb backend +# ============================================================== +system_lib_option("--enable-sndio", env="MOZ_SNDIO", help="Enable sndio audio backend.") + +sndio = pkg_check_modules("MOZ_SNDIO", "sndio", when="--enable-sndio") + +set_config("MOZ_SNDIO", depends_if(sndio)(lambda _: True)) + +# Javascript engine +# ============================================================== +include("../js/moz.configure") + + +# NodeJS +# ============================================================== +include("../build/moz.configure/node.configure") + +# JsonCpp +# ============================================================== +set_define("JSON_USE_EXCEPTION", 0) + +# L10N +# ============================================================== +option("--with-l10n-base", nargs=1, env="L10NBASEDIR", help="Path to l10n repositories") + + +@depends("--with-l10n-base", "MOZ_AUTOMATION", build_environment) +@imports(_from="os.path", _import="isdir") +@imports(_from="os.path", _import="expanduser") +@imports(_from="os", _import="environ") +def l10n_base(value, automation, build_env): + if value: + path = value[0] + if not isdir(path): + die("Invalid value --with-l10n-base, %s doesn't exist", path) + elif automation: + path = os.path.join(build_env.topsrcdir, "../l10n-central") + else: + path = os.path.join( + environ.get( + "MOZBUILD_STATE_PATH", expanduser(os.path.join("~", ".mozbuild")) + ), + "l10n-central", + ) + return os.path.realpath(os.path.abspath(path)) + + +set_config("L10NBASEDIR", l10n_base) + + +# Default toolkit +# ============================================================== +@depends(target) +def toolkit_choices(target): + if target.os == "WINNT": + return ("cairo-windows",) + elif target.os == "OSX": + return ("cairo-cocoa",) + elif target.os == "Android": + return ("cairo-android",) + else: + # cairo-gtk3 - X11 backend with optional Wayland backend (auto detected) + # cairo-gtk3-wayland - Wayland backend with optional X11 backend (auto detected) + # cairo-gtk3-x11-wayland - builds explicitly with X11 & Wayland backends + return ( + "cairo-gtk3", + "cairo-gtk3-wayland", + "cairo-gtk3-x11-wayland", + "cairo-gtk3-wayland-only", + "cairo-gtk3-x11-only", + ) + + +@depends(toolkit_choices) +def toolkit_default(choices): + return choices[0] + + +option( + "--enable-default-toolkit", + nargs=1, + choices=toolkit_choices, + default=toolkit_default, + help="Select default toolkit", +) + + +@depends("--enable-default-toolkit") +def full_toolkit(value): + if value: + return value[0] + + +@depends(full_toolkit) +def toolkit(toolkit): + if toolkit.startswith("cairo-gtk3"): + widget_toolkit = "gtk" + else: + widget_toolkit = toolkit.replace("cairo-", "") + return widget_toolkit + + +set_config("MOZ_WIDGET_TOOLKIT", toolkit) +add_old_configure_assignment("MOZ_WIDGET_TOOLKIT", toolkit) + + +@depends(toolkit) +def toolkit_define(toolkit): + if toolkit != "windows": + return "MOZ_WIDGET_%s" % toolkit.upper() + + +set_define(toolkit_define, True) + + +@depends(toolkit) +def toolkit_gtk(toolkit): + return toolkit == "gtk" + + +@depends(toolkit_gtk, full_toolkit) +def toolkit_gtk_x11(toolkit_gtk, full_toolkit): + return toolkit_gtk and full_toolkit != "cairo-gtk3-wayland-only" + + +@depends(full_toolkit) +def toolkit_gtk_x11_optional(full_toolkit): + return full_toolkit == "cairo-gtk3-wayland" + + +@depends(toolkit_gtk, full_toolkit) +def toolkit_gtk_wayland(toolkit_gtk, full_toolkit): + return toolkit_gtk and full_toolkit != "cairo-gtk3-x11-only" + + +@depends(full_toolkit) +def toolkit_gtk_wayland_optional(full_toolkit): + return full_toolkit == "cairo-gtk3" + + +# Wayland support +# ============================================================== +wayland_headers = pkg_check_modules( + "MOZ_WAYLAND", + "gtk+-wayland-3.0 >= 3.14 xkbcommon >= 0.4.1", + allow_missing=toolkit_gtk_wayland_optional, + when=toolkit_gtk_wayland, +) + + +@depends(wayland_headers, toolkit_gtk, artifact_builds, toolkit_gtk_wayland) +def wayland_headers(wayland, toolkit_gtk, artifacts, toolkit_gtk_wayland): + if not toolkit_gtk_wayland: + return False + if toolkit_gtk and artifacts: + return True + return wayland + + +set_config("MOZ_WAYLAND", depends_if(wayland_headers)(lambda _: True)) +set_define("MOZ_WAYLAND", depends_if(wayland_headers)(lambda _: True)) + + +# Hardware-accelerated video decode with VAAPI and V4L2 on Linux +# ============================================================== +set_config("MOZ_ENABLE_VAAPI", True, when=toolkit_gtk) +set_define("MOZ_ENABLE_VAAPI", True, when=toolkit_gtk) + + +@depends(target, toolkit_gtk) +def v4l2(target, toolkit_gtk): + # V4L2 decode is only used in GTK/Linux and generally only appears on + # embedded SOCs. + if target.cpu in ("arm", "aarch64", "riscv64") and toolkit_gtk: + return True + + +set_config("MOZ_ENABLE_V4L2", True, when=v4l2) +set_define("MOZ_ENABLE_V4L2", True, when=v4l2) + +# GL Provider +# ============================================================== +option("--with-gl-provider", nargs=1, help="Set GL provider backend type") + + +@depends("--with-gl-provider") +def gl_provider(value): + if value: + return value[0] + + +@depends(gl_provider) +def gl_provider_define(provider): + if provider: + return "GLContextProvider%s" % provider + + +set_define("MOZ_GL_PROVIDER", gl_provider_define) + + +@depends(gl_provider, toolkit_gtk) +def gl_default_provider(value, toolkit_gtk): + if value: + return value + elif toolkit_gtk: + return "EGL" + + +set_config("MOZ_GL_PROVIDER", gl_provider) +set_config("MOZ_GL_DEFAULT_PROVIDER", gl_default_provider) + + +@depends(gl_default_provider) +def gl_provider_define(provider): + if provider: + return "GL_PROVIDER_%s" % provider + + +set_define(gl_provider_define, True) + + +# PDF printing +# ============================================================== +@depends(toolkit) +def pdf_printing(toolkit): + if toolkit in ("windows", "gtk", "android"): + return True + + +set_config("MOZ_PDF_PRINTING", pdf_printing) +set_define("MOZ_PDF_PRINTING", pdf_printing) + + +# Event loop instrumentation +# ============================================================== +option(env="MOZ_INSTRUMENT_EVENT_LOOP", help="Force-enable event loop instrumentation") + + +@depends("MOZ_INSTRUMENT_EVENT_LOOP", toolkit) +def instrument_event_loop(value, toolkit): + if value or ( + toolkit in ("windows", "gtk", "cocoa", "android") and value.origin == "default" + ): + return True + + +set_config("MOZ_INSTRUMENT_EVENT_LOOP", instrument_event_loop) +set_define("MOZ_INSTRUMENT_EVENT_LOOP", instrument_event_loop) + + +# Fontconfig Freetype +# ============================================================== +option(env="USE_FC_FREETYPE", help="Force-enable the use of fontconfig freetype") + + +@depends("USE_FC_FREETYPE", toolkit) +def fc_freetype(value, toolkit): + if value or (toolkit == "gtk" and value.origin == "default"): + return True + + +set_define("USE_FC_FREETYPE", fc_freetype) + +# Pango +# ============================================================== +pkg_check_modules("MOZ_PANGO", "pango >= 1.22.0", when=toolkit_gtk) + +# Fontconfig +# ============================================================== +fontconfig_info = pkg_check_modules( + "_FONTCONFIG", "fontconfig >= 2.7.0", when=fc_freetype +) + + +@depends(fc_freetype) +def check_for_freetype2(fc_freetype): + if fc_freetype: + return True + + +# Check for freetype2. Flags are combined with fontconfig flags. +freetype2_info = pkg_check_modules( + "_FT2", "freetype2 >= 9.10.3", when=check_for_freetype2 +) + + +@depends(fontconfig_info, freetype2_info) +def freetype2_combined_info(fontconfig_info, freetype2_info): + if not freetype2_info: + return + if not fontconfig_info: + return freetype2_info + return namespace( + cflags=freetype2_info.cflags + fontconfig_info.cflags, + libs=freetype2_info.libs + fontconfig_info.libs, + ) + + +set_define("MOZ_HAVE_FREETYPE2", depends_if(freetype2_info)(lambda _: True)) + + +# Apple platform decoder support +# ============================================================== +@depends(toolkit) +def applemedia(toolkit): + if toolkit in ("cocoa", "uikit"): + return True + + +set_config("MOZ_APPLEMEDIA", applemedia) +set_define("MOZ_APPLEMEDIA", applemedia) + +# Windows Media Foundation support +# ============================================================== +option("--disable-wmf", help="Disable support for Windows Media Foundation") + + +@depends("--disable-wmf", target, "--help") +def wmf(value, target, _): + enabled = bool(value) + if value.origin == "default": + # Enable Windows Media Foundation support by default. + # Note our minimum SDK version is Windows 7 SDK, so we are (currently) + # guaranteed to have a recent-enough SDK to build WMF. + enabled = target.os == "WINNT" + if enabled and target.os != "WINNT": + die("Cannot enable Windows Media Foundation support on %s", target.os) + if enabled: + return True + + +@depends(artifact_builds, c_compiler, when=wmf) +def wmfmediaengine(artifact_builds, c_compiler): + if c_compiler: + return c_compiler.type == "clang-cl" + return bool(artifact_builds) + + +set_config("MOZ_WMF", wmf) +set_define("MOZ_WMF", wmf) + +set_config("MOZ_WMF_MEDIA_ENGINE", True, when=wmfmediaengine) +set_define("MOZ_WMF_MEDIA_ENGINE", True, when=wmfmediaengine) + +# FFmpeg H264/AAC Decoding Support +# ============================================================== +option("--disable-ffmpeg", help="Disable FFmpeg for fragmented H264/AAC decoding") + + +@depends("--disable-ffmpeg", target) +def ffmpeg(value, target): + enabled = bool(value) + if value.origin == "default": + enabled = target.os not in ("Android", "WINNT") + if enabled: + return True + + +set_config("MOZ_FFMPEG", ffmpeg) +set_define("MOZ_FFMPEG", ffmpeg) + +# AV1 Video Codec Support +# ============================================================== +option("--disable-av1", help="Disable av1 video support") + + +@depends("--enable-av1") +def av1(value): + if value: + return True + + +@depends(target, when=av1 & compile_environment) +def dav1d_asm(target): + if target.cpu in ("aarch64", "x86", "x86_64"): + return True + + +@depends(target, when=av1 & compile_environment) +def dav1d_nasm(target): + if target.cpu in ("x86", "x86_64"): + return namespace(version="2.14", what="AV1") + + +set_config("MOZ_DAV1D_ASM", dav1d_asm) +set_define("MOZ_DAV1D_ASM", dav1d_asm) +set_config("MOZ_AV1", av1) +set_define("MOZ_AV1", av1) + +# JXL Image Codec Support +# ============================================================== +option("--disable-jxl", help="Disable jxl image support") + + +@depends("--disable-jxl", milestone.is_nightly) +def jxl(value, is_nightly): + if is_nightly and value: + return True + + +set_config("MOZ_JXL", jxl) +set_define("MOZ_JXL", jxl) + +set_config("MOZ_SAMPLE_TYPE_FLOAT32", True) +set_define("MOZ_SAMPLE_TYPE_FLOAT32", True) + +set_define("MOZ_VORBIS", True) +set_config("MOZ_VORBIS", True) + +option( + "--disable-real-time-tracing", + help="Disable tracing of real-time audio callbacks", +) + +set_config("MOZ_REAL_TIME_TRACING", True, when="--enable-real-time-tracing") +set_define("MOZ_REAL_TIME_TRACING", True, when="--enable-real-time-tracing") + +# OpenMAX IL Decoding Support +# ============================================================== +option("--enable-openmax", help="Enable OpenMAX IL for video/audio decoding") + + +@depends("--enable-openmax") +def openmax(value): + enabled = bool(value) + if enabled: + return True + + +set_config("MOZ_OMX", openmax) +set_define("MOZ_OMX", openmax) + + +# EME Support +# ============================================================== +@depends(target, wmf) +def eme_choices(target, wmf): + if ( + target.kernel in ("WINNT", "Linux") + and target.os != "Android" + and target.cpu in ("x86", "x86_64") + ): + if wmf: + return ("widevine", "wmfcdm") + return ("widevine",) + if target.kernel == "WINNT" and target.cpu == "aarch64": + return ("widevine",) + if target.os in ("OSX"): + return ("widevine",) + + +# Widevine is enabled by default in desktop browser builds. +@depends(build_project, eme_choices) +def eme_default(build_project, choices): + if build_project == "browser": + return choices + + +option( + "--enable-eme", + nargs="+", + choices=eme_choices, + default=eme_default, + when=eme_choices, + help="{Enable|Disable} support for Encrypted Media Extensions", +) + + +@depends("--enable-eme", when=eme_choices) +def eme_modules(value): + return value + + +# Fallback to an empty list when eme_choices is empty, setting eme_modules to +# None. +set_config("MOZ_EME_MODULES", eme_modules | dependable([])) + + +# Media Foundation CDM support +# ============================================================== +@depends(eme_modules, when=wmfmediaengine) +def wmfcdm(modules): + if "wmfcdm" in modules: + return True + + +set_config("MOZ_WMF_CDM", True, when=wmfcdm) +set_define("MOZ_WMF_CDM", True, when=wmfcdm) + + +option( + name="--enable-chrome-format", + help="Select FORMAT of chrome files during packaging.", + nargs=1, + choices=("omni", "jar", "flat"), + default="omni", +) + + +@depends("--enable-chrome-format") +def packager_format(value): + return value[0] + + +set_config("MOZ_PACKAGER_FORMAT", packager_format) + +# The packager minifies two different types of files: non-JS (mostly property +# files for l10n), and JS. Setting MOZ_PACKAGER_MINIFY only minifies the +# former. Firefox doesn't yet minify JS, due to concerns about debuggability. +# +# Also, the JS minification setup really only works correctly on Android: +# we need extra setup to use the newly-built shell for Linux and Windows, +# and cross-compilation for macOS requires some extra care. + + +@depends(target_is_android, "--enable-debug", milestone.is_nightly) +def enable_minify_default(is_android, debug, is_nightly): + if is_android and not debug and not is_nightly: + return ("properties", "js") + return ("properties",) + + +option( + name="--enable-minify", + help="Select types of files to minify during packaging.", + nargs="*", + choices=("properties", "js"), + default=enable_minify_default, +) + + +@depends("--enable-minify") +def enable_minify(value): + if "js" in value and "properties" not in value: + die("--enable-minify=js requires --enable-minify=properties.") + return namespace( + properties="properties" in value, + js="js" in value, + ) + + +set_config("MOZ_PACKAGER_MINIFY", True, when=enable_minify.properties) +set_config("MOZ_PACKAGER_MINIFY_JS", True, when=enable_minify.js) + + +@depends(host, build_project) +def jar_maker_format(host, build_project): + # Multilocales for mobile/android use the same mergedirs for all locales, + # so we can't use symlinks for those builds. + if host.os == "WINNT" or build_project == "mobile/android": + return "flat" + return "symlink" + + +set_config("MOZ_JAR_MAKER_FILE_FORMAT", jar_maker_format) + + +@depends(toolkit) +def omnijar_name(toolkit): + # Fennec's static resources live in the assets/ folder of the + # APK. Adding a path to the name here works because we only + # have one omnijar file in the final package (which is not the + # case on desktop). + return "assets/omni.ja" if toolkit == "android" else "omni.ja" + + +set_config("OMNIJAR_NAME", omnijar_name) + +project_flag("MOZ_PLACES", help="Build Places if required", set_as_define=True) + +project_flag( + "MOZ_SERVICES_HEALTHREPORT", + help="Build Firefox Health Reporter Service", + set_as_define=True, +) + +project_flag( + "MOZ_NORMANDY", + help="Enable Normandy recipe runner", + set_as_define=True, +) + +project_flag("MOZ_SERVICES_SYNC", help="Build Sync Services if required") + +project_flag( + "MOZ_ANDROID_HISTORY", + help="Enable Android History instead of Places", + set_as_define=True, +) + +project_flag( + "MOZ_DEDICATED_PROFILES", + help="Enable dedicated profiles per install", + set_as_define=True, +) + +project_flag( + "MOZ_BLOCK_PROFILE_DOWNGRADE", + help="Block users from starting profiles last used by a newer build", + set_as_define=True, +) + + +@depends("MOZ_PLACES", "MOZ_ANDROID_HISTORY") +def check_places_and_android_history(places, android_history): + if places and android_history: + die("Cannot use MOZ_ANDROID_HISTORY alongside MOZ_PLACES.") + + +option( + env="MOZ_TELEMETRY_REPORTING", + default=mozilla_official, + help="Enable telemetry reporting", +) + +set_define("MOZ_TELEMETRY_REPORTING", True, when="MOZ_TELEMETRY_REPORTING") + + +@depends("MOZ_TELEMETRY_REPORTING", milestone.is_nightly) +def telemetry_on_by_default(reporting, is_nightly): + return reporting and is_nightly + + +set_define("MOZ_TELEMETRY_ON_BY_DEFAULT", True, when=telemetry_on_by_default) + + +# gpsd support +# ============================================================== +system_lib_option("--enable-gpsd", env="MOZ_GPSD", help="Enable gpsd support") + + +@depends("--enable-gpsd") +def gpsd(value): + return bool(value) + + +system_gpsd = pkg_check_modules("MOZ_GPSD", "libgps >= 3.11", when=gpsd) + +set_config("MOZ_GPSD", depends_if(system_gpsd)(lambda _: True)) + +# Miscellaneous programs +# ============================================================== + +check_prog("TAR", ("gnutar", "gtar", "tar")) +check_prog("UNZIP", ("unzip",)) + +# Key files +# ============================================================== +include("../build/moz.configure/keyfiles.configure") + +simple_keyfile("Mozilla API") + +simple_keyfile("Google Location Service API") + +simple_keyfile("Google Safebrowsing API") + +id_and_secret_keyfile("Bing API") + +simple_keyfile("Adjust SDK") + +id_and_secret_keyfile("Leanplum SDK") + +simple_keyfile("Pocket API") + + +# WebRender Debugger integration +# ============================================================== + +option( + "--enable-webrender-debugger", help="Build the websocket debug server in WebRender" +) + +set_config( + "MOZ_WEBRENDER_DEBUGGER", depends_if("--enable-webrender-debugger")(lambda _: True) +) + +# Additional system headers defined at the application level +# ============================================================== + +option( + "--enable-app-system-headers", + env="MOZ_APP_SYSTEM_HEADERS", + help="Use additional system headers defined in $MOZ_BUILD_APP/app-system-headers.mozbuild", +) + + +@depends("--enable-app-system-headers") +def app_system_headers(value): + if value: + return True + + +set_config("MOZ_APP_SYSTEM_HEADERS", app_system_headers) +set_define("MOZ_APP_SYSTEM_HEADERS", app_system_headers) + +# Printing +# ============================================================== +option("--disable-printing", help="Disable printing support") + + +@depends("--disable-printing") +def printing(value): + if value: + return True + + +set_config("NS_PRINTING", printing) +set_define("NS_PRINTING", printing) +set_define("NS_PRINT_PREVIEW", printing) + + +# Speech-dispatcher support +# ============================================================== +@depends(toolkit) +def no_speechd_on_non_gtk(toolkit): + if toolkit != "gtk": + return False + + +imply_option( + "--enable-synth-speechd", no_speechd_on_non_gtk, reason="--enable-default-toolkit" +) + +option("--disable-synth-speechd", help="Disable speech-dispatcher support") + +set_config("MOZ_SYNTH_SPEECHD", depends_if("--disable-synth-speechd")(lambda _: True)) + +# Speech API +# ============================================================== +option("--disable-webspeech", help="Disable support for HTML Speech API") + + +@depends("--disable-webspeech") +def webspeech(value): + if value: + return True + + +set_config("MOZ_WEBSPEECH", webspeech) +set_define("MOZ_WEBSPEECH", webspeech) + +# Speech API test backend +# ============================================================== +option( + "--enable-webspeechtestbackend", + default=webspeech, + help="{Enable|Disable} support for HTML Speech API Test Backend", +) + + +@depends_if("--enable-webspeechtestbackend") +def webspeech_test_backend(value): + return True + + +set_config("MOZ_WEBSPEECH_TEST_BACKEND", webspeech_test_backend) +set_define("MOZ_WEBSPEECH_TEST_BACKEND", webspeech_test_backend) + + +# Graphics +# ============================================================== +@depends(target, milestone) +def skia_pdf_default(target, milestone): + return milestone.is_nightly and target.os != "WINNT" + + +option("--enable-skia-pdf", default=skia_pdf_default, help="{Enable|Disable} Skia PDF") + +set_config("MOZ_ENABLE_SKIA_PDF", True, when="--enable-skia-pdf") +set_define("MOZ_ENABLE_SKIA_PDF", True, when="--enable-skia-pdf") + +set_config( + "SKIA_INCLUDES", + [ + "/gfx/skia", + "/gfx/skia/skia", + ], +) + +system_lib_option( + "--with-system-webp", help="Use system libwebp (located with pkgconfig)" +) + +system_webp = pkg_check_modules( + "MOZ_WEBP", "libwebp >= 1.0.2 libwebpdemux >= 1.0.2", when="--with-system-webp" +) + +set_config("MOZ_SYSTEM_WEBP", depends(when=system_webp)(lambda: True)) + + +# Build Freetype in the tree +# ============================================================== +@depends(target, "--enable-skia-pdf") +def tree_freetype(target, skia_pdf): + if target.os == "Android" or (skia_pdf and target.os == "WINNT"): + return True + + +set_define("MOZ_TREE_FREETYPE", tree_freetype) +set_config("MOZ_TREE_FREETYPE", tree_freetype) + +set_define("HAVE_FT_BITMAP_SIZE_Y_PPEM", tree_freetype) +set_define("HAVE_FT_GLYPHSLOT_EMBOLDEN", tree_freetype) +set_define("HAVE_FT_LOAD_SFNT_TABLE", tree_freetype) + + +@depends(freetype2_combined_info, tree_freetype, build_environment) +def ft2_info(freetype2_combined_info, tree_freetype, build_env): + if tree_freetype: + return namespace( + cflags=("-I%s/modules/freetype2/include" % build_env.topsrcdir,), libs=() + ) + if freetype2_combined_info: + return freetype2_combined_info + + +set_config("FT2_LIBS", ft2_info.libs) + + +@depends(target, tree_freetype, freetype2_info) +def enable_cairo_ft(target, tree_freetype, freetype2_info): + # Avoid defining MOZ_ENABLE_CAIRO_FT on Windows platforms because + # "cairo-ft-font.c" includes <dlfcn.h>, which only exists on posix platforms + return freetype2_info or (tree_freetype and target.os != "WINNT") + + +set_config("MOZ_ENABLE_CAIRO_FT", True, when=enable_cairo_ft) +set_config("CAIRO_FT_CFLAGS", ft2_info.cflags, when=enable_cairo_ft) + + +# WebDriver (HTTP / BiDi) +# ============================================================== +# +# WebDriver is a remote control interface that enables introspection and +# control of user agents. It provides a platform- and language-neutral wire +# protocol as a way for out-of-process programs to remotely instruct the +# behavior of web browsers. +# +# The Gecko implementation is backed by Marionette and Remote Agent. +# Both protocols are not really toolkit features, as much as Gecko engine +# features. But they are enabled based on the toolkit, so here it lives. +# +# Marionette remote protocol +# ----------------------------------------------------------- +# +# Marionette is the Gecko remote protocol used for various remote control, +# automation, and testing purposes throughout Gecko-based applications like +# Firefox, Thunderbird, and any mobile browser built upon GeckoView. +# +# It also backs ../testing/geckodriver, which is Mozilla's WebDriver +# implementation. +# +# The source of Marionette lives in ../remote/marionette. +# +# For more information, see: +# https://firefox-source-docs.mozilla.org/testing/marionette/index.html +# +# Remote Agent (WebDriver BiDi / partial CDP) +# ----------------------------------------------------------- +# +# The primary purpose is the implementation of the WebDriver BiDi specification. +# But it also complements the existing Firefox Developer Tools Remote Debugging +# Protocol (RDP) by implementing a subset of the Chrome DevTools Protocol (CDP). +# +# The source of Remote Agent lives in ../remote. +# +# For more information, see: +# https://firefox-source-docs.mozilla.org/remote/index.html + + +option( + "--disable-webdriver", + help="Disable support for WebDriver remote protocols", +) + + +@depends("--disable-webdriver") +def webdriver(enabled): + if enabled: + return True + + +set_config("ENABLE_WEBDRIVER", webdriver) +set_define("ENABLE_WEBDRIVER", webdriver) + + +# geckodriver WebDriver implementation +# ============================================================== +# +# Turn off geckodriver for build configs we don't handle yet, +# but allow --enable-geckodriver to override when compile environment is available. +# --disable-tests implies disabling geckodriver. +# Disable building in CI + + +@depends( + "--enable-tests", target, cross_compiling, hazard_analysis, asan, "MOZ_AUTOMATION" +) +def geckodriver_default(enable_tests, target, cross_compile, hazard, asan, automation): + if not enable_tests: + return False + if hazard or target.os == "Android" or (asan and cross_compile): + return False + if automation: + return False + return True + + +option( + "--enable-geckodriver", + default=geckodriver_default, + when="--enable-compile-environment", + help="{Build|Do not build} geckodriver", +) + + +@depends("--enable-geckodriver", when="--enable-compile-environment") +def geckodriver(enabled): + if enabled: + return True + + +set_config("MOZ_GECKODRIVER", geckodriver) + + +# WebRTC +# ======================================================== +@depends(target) +def webrtc_default(target): + # Turn off webrtc for OS's we don't handle yet, but allow + # --enable-webrtc to override. + os_match = target.kernel in ( + "Linux", + "WINNT", + "DragonFly", + "FreeBSD", + "kFreeBSD", + "NetBSD", + "OpenBSD", + ) + + if not os_match: + os_match = target.os in ("OSX",) + + cpu_match = target.cpu in ( + "x86_64", + "arm", + "aarch64", + "x86", + "ia64", + "mips32", + "mips64", + "ppc", + "ppc64", + "riscv64", + ) + + return os_match and cpu_match and target.endianness == "little" + + +option( + "--disable-webrtc", + default=webrtc_default, + help="{Enable|Disable} support for WebRTC", +) + + +@depends("--disable-webrtc") +def webrtc(enabled): + if enabled: + return True + + +set_config("MOZ_WEBRTC", webrtc) +set_define("MOZ_WEBRTC", webrtc) +set_config("MOZ_SCTP", webrtc) +set_define("MOZ_SCTP", webrtc) +set_config("MOZ_SRTP", webrtc) +set_define("MOZ_SRTP", webrtc) +set_config("MOZ_WEBRTC_SIGNALING", webrtc) +set_define("MOZ_WEBRTC_SIGNALING", webrtc) +set_config("MOZ_PEERCONNECTION", webrtc) +set_define("MOZ_PEERCONNECTION", webrtc) +# MOZ_WEBRTC_ASSERT_ALWAYS turns on a number of safety asserts in +# opt/production builds (via MOZ_CRASH()) +set_config("MOZ_WEBRTC_ASSERT_ALWAYS", webrtc) +set_define("MOZ_WEBRTC_ASSERT_ALWAYS", webrtc) + +# RAW media +# ============================================================== + + +@depends(target, webrtc) +def raw_media_default(target, webrtc): + if target.os == "Android": + return True + if webrtc: + return True + + +option( + "--enable-raw", + default=raw_media_default, + help="{Enable|Disable} support for RAW media", +) + +set_config("MOZ_RAW", depends_if("--enable-raw")(lambda _: True)) +set_define("MOZ_RAW", depends_if("--enable-raw")(lambda _: True)) + + +# X11 +# ============================================================== +@depends(webrtc, when=toolkit_gtk) +def x11_libs(webrtc): + libs = [ + "x11", + "xcb", + "xcb-shm", + "x11-xcb", + "xext", + "xrandr >= 1.4.0", + ] + if webrtc: + # third_party/libwebrtc/webrtc/webrtc_gn/moz.build adds those + # manually, ensure they're available. + libs += [ + "xcomposite", + "xcursor", + "xdamage", + "xfixes", + "xi", + ] + return libs + + +x11_headers = pkg_check_modules( + "MOZ_X11", + x11_libs, + allow_missing=toolkit_gtk_x11_optional, + when=toolkit_gtk_x11, +) + + +set_config("MOZ_X11", True, when=x11_headers) +set_define("MOZ_X11", True, when=x11_headers) + +pkg_check_modules( + "MOZ_X11_SM", + ["ice", "sm"], + cflags_only=True, + allow_missing=toolkit_gtk_x11_optional, + when=toolkit_gtk_x11, +) + + +# ASan Reporter Addon +# ============================================================== +option( + "--enable-address-sanitizer-reporter", + help="Enable Address Sanitizer Reporter Extension", +) + + +@depends("--enable-address-sanitizer-reporter") +def enable_asan_reporter(value): + if value: + return True + + +set_config("MOZ_ASAN_REPORTER", enable_asan_reporter) +set_define("MOZ_ASAN_REPORTER", enable_asan_reporter) + +# Checks for library functions +# ============================================================== +with only_when(compile_environment & depends(target.os)(lambda os: os != "WINNT")): + set_define("HAVE_STAT64", check_symbol("stat64")) + set_define("HAVE_LSTAT64", check_symbol("lstat64")) + set_define("HAVE_TRUNCATE64", check_symbol("truncate64")) + set_define("HAVE_STATVFS64", check_symbol("statvfs64")) + set_define("HAVE_STATVFS", check_symbol("statvfs")) + set_define("HAVE_STATFS64", check_symbol("statfs64")) + set_define("HAVE_STATFS", check_symbol("statfs")) + set_define("HAVE_LUTIMES", check_symbol("lutimes")) + set_define("HAVE_POSIX_FADVISE", check_symbol("posix_fadvise")) + set_define("HAVE_POSIX_FALLOCATE", check_symbol("posix_fallocate")) + set_define("HAVE_EVENTFD", check_symbol("eventfd")) + + have_arc4random = check_symbol("arc4random") + set_define("HAVE_ARC4RANDOM", have_arc4random) + set_define("HAVE_ARC4RANDOM_BUF", check_symbol("arc4random_buf")) + set_define("HAVE_MALLINFO", check_symbol("mallinfo")) + +# Checks for headers +# ============================================================== +with only_when(compile_environment & depends(target.os)(lambda os: os != "WINNT")): + set_define("HAVE_SYSIOCCOM_H", check_header("sys/ioccom.h")) + +# Elfhack +# ============================================================== +with only_when("--enable-compile-environment"): + + @depends(host, target) + def has_elfhack(host, target): + return ( + target.kernel == "Linux" + and host.kernel == "Linux" + and target.cpu in ("arm", "aarch64", "x86", "x86_64") + ) + + option( + "--disable-elf-hack", + nargs="?", + choices=("legacy", "relr"), + help="{Enable|Disable} elf hacks", + when=has_elfhack, + ) + + @depends("--enable-elf-hack", when=has_elfhack) + def may_enable_legacy_elfhack(enable): + if enable and enable != ("relr",): + return enable + + @depends("--enable-elf-hack", when=has_elfhack) + def may_enable_relrhack(enable): + if enable and enable != ("legacy",): + return enable + + @depends( + have_arc4random, + android_version, + when=target_has_linux_kernel, + ) + def may_use_pack_relative_relocs(have_arc4random, android_version): + # Packed relative relocations are only supported on Android since + # version 11 (API 30), and in glibc since version 2.36. + # glibc 2.36 also added the arc4random function, which is our proxy + # to detect this (or newer) version being used. + # When targetting those newer versions, we allow ourselves to use + # packed relative relocations rather than elfhack. + if android_version: + return android_version >= 30 + return have_arc4random + + @depends( + c_compiler, + extra_toolchain_flags, + linker_ldflags, + readelf, + when=may_use_pack_relative_relocs | may_enable_relrhack, + ) + @checking("for -z pack-relative-relocs option to ld", bool) + @imports(_from="__builtin__", _import="FileNotFoundError") + @imports("os") + @imports(_from="tempfile", _import="mkstemp") + @imports("textwrap") + def has_pack_relative_relocs( + c_compiler, + extra_toolchain_flags, + linker_ldflags, + readelf, + ): + try: + fd, path = mkstemp(prefix="conftest.") + os.close(fd) + + pack_rel_relocs = ["-Wl,-z,pack-relative-relocs"] + if ( + try_invoke_compiler( + # No configure_cache because it would not create the + # expected output file. + None, + [c_compiler.compiler] + c_compiler.flags, + c_compiler.language, + # The resulting binary is expected to have relative + # relocations, the `ptr` variable attempts to ensure + # there is at least one. This requires the executable + # being built as position independent. + "int main() { return 0; }\nint (*ptr)() = main;", + pack_rel_relocs + + ["-pie", "-o", path] + + (extra_toolchain_flags or []) + + linker_ldflags, + wrapper=c_compiler.wrapper, + onerror=lambda: None, + ) + is not None + ): + # BFD ld ignores options it doesn't understand. So check + # that we did get packed relative relocations (DT_RELR). + env = os.environ.copy() + env["LANG"] = "C" + dyn = check_cmd_output(readelf, "-d", path, env=env).splitlines() + tags = [ + int(l.split()[0], 16) for l in dyn if l.strip().startswith("0x") + ] + # Older versions of readelf don't know about DT_RELR but will + # still display the tag number. + if 0x23 in tags: + needed = [l for l in dyn if l.split()[1:2] == ["(NEEDED)"]] + is_glibc = any(l.endswith("[libc.so.6]") for l in needed) + # The mold linker doesn't add a GLIBC_ABI_DT_RELR version + # dependency, which ld.so doesn't like. + # https://github.com/rui314/mold/issues/653#issuecomment-1670274638 + if is_glibc: + versions = check_cmd_output(readelf, "-V", path, env=env) + if "GLIBC_ABI_DT_RELR" in versions.split(): + return pack_rel_relocs + else: + return pack_rel_relocs + finally: + try: + os.remove(path) + except FileNotFoundError: + pass + + @depends( + has_pack_relative_relocs, + may_enable_legacy_elfhack, + may_enable_relrhack, + may_use_pack_relative_relocs, + when=has_pack_relative_relocs, + ) + def pack_relative_relocs_flags( + flags, + may_enable_legacy_elfhack, + may_enable_relrhack, + may_use_pack_relative_relocs, + ): + # When relrhack is enabled, we don't pass the flag to the linker because + # relrhack will take care of it. + if may_enable_relrhack and may_enable_relrhack.origin != "default": + return None + # if elfhack is explicitly enabled instead of relrhack, we prioritize it + # over packed relative relocs. + if may_enable_legacy_elfhack and may_enable_legacy_elfhack.origin != "default": + return None + if may_use_pack_relative_relocs: + return flags + + add_old_configure_assignment("PACK_REL_RELOC_FLAGS", pack_relative_relocs_flags) + + @depends( + select_linker, + pack_relative_relocs_flags, + has_pack_relative_relocs, + may_enable_legacy_elfhack, + may_enable_relrhack, + when=has_elfhack, + ) + def which_elf_hack( + linker, + pack_relative_relocs_flags, + has_pack_relative_relocs, + may_enable_legacy_elfhack, + may_enable_relrhack, + ): + if pack_relative_relocs_flags: + return + if may_enable_relrhack: + if has_pack_relative_relocs: + return "relr" + elif ( + may_enable_relrhack.origin != "default" + and not may_enable_legacy_elfhack + ): + die( + "Cannot enable relrhack without linker support for -z pack-relative-relocs" + ) + if may_enable_legacy_elfhack: + if linker and linker.KIND in ("lld", "mold"): + if may_enable_legacy_elfhack.origin != "default": + die( + f"Cannot enable elfhack with {linker.KIND}." + " Use --enable-linker=bfd, --enable-linker=gold, or --disable-elf-hack" + ) + else: + return "legacy" + + set_config( + "USE_ELF_HACK", True, when=depends(which_elf_hack)(lambda x: x == "legacy") + ) + + use_relrhack = depends(which_elf_hack)(lambda x: x == "relr") + set_config("RELRHACK", True, when=use_relrhack) + + @depends(c_compiler, linker_ldflags, when=use_relrhack) + def relrhack_real_linker(c_compiler, linker_ldflags): + ld = "ld" + for flag in linker_ldflags: + if flag.startswith("-fuse-ld="): + ld = "ld." + flag[len("-fuse-ld=") :] + ld = check_cmd_output( + c_compiler.compiler, f"--print-prog-name={ld}", *c_compiler.flags + ) + return ld.rstrip() + + @depends(relrhack_real_linker, when=use_relrhack) + def relrhack_linker(ld): + return os.path.basename(ld) + + set_config("RELRHACK_LINKER", relrhack_linker) + + std_filesystem = host_cxx_compiler.try_run( + header="#include <filesystem>", + body='auto foo = std::filesystem::absolute("");', + flags=host_linker_ldflags, + when=use_relrhack, + onerror=lambda: None, + ) + + stdcxxfs = host_cxx_compiler.try_run( + header="#include <filesystem>", + body='auto foo = std::filesystem::absolute("");', + flags=depends(host_linker_ldflags)( + lambda flags: (flags or []) + ["-lstdc++fs"] + ), + check_msg="whether std::filesystem requires -lstdc++fs", + when=use_relrhack & depends(std_filesystem)(lambda x: not x), + onerror=lambda: None, + ) + + set_config("RELRHACK_LIBS", ["stdc++fs"], when=stdcxxfs) + + @depends(build_environment, relrhack_real_linker, when=use_relrhack) + def relrhack_ldflags(build_env, ld): + flags = [ + "-B", + os.path.join(build_env.topobjdir, "build", "unix", "elfhack"), + ] + if os.path.basename(ld) != ld: + flags.append(f"-Wl,--real-linker,{ld}") + return flags + + set_config("RELRHACK_LDFLAGS", relrhack_ldflags) + + +@depends(build_environment) +def idl_roots(build_env): + return namespace( + ipdl_root=os.path.join(build_env.topobjdir, "ipc", "ipdl"), + webidl_root=os.path.join(build_env.topobjdir, "dom", "bindings"), + xpcom_root=os.path.join(build_env.topobjdir, "xpcom", "components"), + ) + + +set_config("WEBIDL_ROOT", idl_roots.webidl_root) +set_config("IPDL_ROOT", idl_roots.ipdl_root) +set_config("XPCOM_ROOT", idl_roots.xpcom_root) + +# Proxy bypass protection +# ============================================================== + +option( + "--enable-proxy-bypass-protection", + help="Prevent suspected or confirmed proxy bypasses", +) + + +@depends_if("--enable-proxy-bypass-protection") +def proxy_bypass_protection(_): + return True + + +set_config("MOZ_PROXY_BYPASS_PROTECTION", proxy_bypass_protection) +set_define("MOZ_PROXY_BYPASS_PROTECTION", proxy_bypass_protection) + +# Proxy direct failover +# ============================================================== + +option( + "--disable-proxy-direct-failover", + help="Disable direct failover for system requests", +) + + +@depends_if("--disable-proxy-direct-failover") +def proxy_direct_failover(value): + if value: + return True + + +set_config("MOZ_PROXY_DIRECT_FAILOVER", proxy_direct_failover) +set_define("MOZ_PROXY_DIRECT_FAILOVER", proxy_direct_failover) + +# MIDL +# ============================================================== + + +@depends(c_compiler, toolchain_prefix) +def midl_names(c_compiler, toolchain_prefix): + if c_compiler and c_compiler.type in ["gcc", "clang"]: + # mingw + widl = ("widl",) + if toolchain_prefix: + prefixed = tuple("%s%s" % (p, "widl") for p in toolchain_prefix) + widl = prefixed + widl + return widl + + return ("midl.exe",) + + +@depends(target, "--enable-compile-environment") +def check_for_midl(target, compile_environment): + if target.os != "WINNT": + return + + if compile_environment: + return True + + +midl = check_prog( + "MIDL", + midl_names, + when=check_for_midl, + allow_missing=True, + paths=sdk_bin_path, + # MIDL being used from a python wrapper script, we can live with it + # having spaces. + allow_spaces=True, +) + +option(env="MIDL_FLAGS", nargs=1, help="Extra flags to pass to MIDL") + + +@depends( + "MIDL_FLAGS", + target, + midl, + when=depends(midl, target)(lambda m, t: m and t.kernel == "WINNT"), +) +def midl_flags(flags, target, midl): + if flags: + flags = flags[0].split() + else: + flags = [] + + if not midl.endswith("widl"): + env = { + "x86": "win32", + "x86_64": "x64", + "aarch64": "arm64", + }[target.cpu] + return flags + ["-nologo", "-no_cpp", "-env", env] + + # widl + return ( + flags + + { + "x86": ["--win32", "-m32"], + "x86_64": ["--win64", "-m64"], + }[target.cpu] + ) + + +set_config("MIDL_FLAGS", midl_flags) + +# Accessibility +# ============================================================== + +option("--disable-accessibility", help="Disable accessibility support") + + +@depends("--enable-accessibility", check_for_midl, midl, c_compiler) +def accessibility(value, check_for_midl, midl, c_compiler): + enabled = bool(value) + + if not enabled: + return + + if check_for_midl and not midl: + if c_compiler and c_compiler.type in ("gcc", "clang"): + die( + "You have accessibility enabled, but widl could not be found. " + "Add --disable-accessibility to your mozconfig or install widl. " + "See https://developer.mozilla.org/en-US/docs/Cross_Compile_Mozilla_for_Mingw32 for details." + ) + else: + die( + "MIDL could not be found. " + "Building accessibility without MIDL is not supported." + ) + + return enabled + + +set_config("ACCESSIBILITY", accessibility) +set_define("ACCESSIBILITY", accessibility) + + +@depends(moz_debug, developer_options) +def a11y_log(debug, developer_options): + return debug or developer_options + + +set_config("A11Y_LOG", True, when=a11y_log) +set_define("A11Y_LOG", True, when=a11y_log) + + +# Addon signing +# ============================================================== +@depends(milestone) +def require_signing(milestone): + return milestone.is_release_or_beta and not milestone.is_esr + + +option( + env="MOZ_REQUIRE_SIGNING", + default=require_signing, + help="Enforce that add-ons are signed by the trusted root", +) + +set_config("MOZ_REQUIRE_SIGNING", True, when="MOZ_REQUIRE_SIGNING") +set_define("MOZ_REQUIRE_SIGNING", True, when="MOZ_REQUIRE_SIGNING") + +option( + "--with-unsigned-addon-scopes", + nargs="+", + choices=("app", "system"), + help="Addon scopes where signature is not required", +) + + +@depends("--with-unsigned-addon-scopes") +def unsigned_addon_scopes(scopes): + return namespace( + app="app" in scopes or None, + system="system" in scopes or None, + ) + + +set_config("MOZ_UNSIGNED_APP_SCOPE", unsigned_addon_scopes.app) +set_config("MOZ_UNSIGNED_SYSTEM_SCOPE", unsigned_addon_scopes.system) + + +# Addon sideloading +# ============================================================== +option( + "--allow-addon-sideload", + default=milestone.is_esr, + help="Addon sideloading is allowed", +) + + +set_config("MOZ_ALLOW_ADDON_SIDELOAD", True, when="--allow-addon-sideload") + +# WebExtensions API WebIDL bindings +# ============================================================== + + +@depends(milestone) +def extensions_webidl_bindings_default(milestone): + # Only enable the webidl bindings for the WebExtensions APIs + # in Nightly. + return milestone.is_nightly + + +option( + "--enable-extensions-webidl-bindings", + default=extensions_webidl_bindings_default, + help="{Enable|Disable} building experimental WebExtensions WebIDL bindings", +) + + +@depends("--enable-extensions-webidl-bindings") +def extensions_webidl_enabled(value): + return bool(value) + + +set_config("MOZ_WEBEXT_WEBIDL_ENABLED", extensions_webidl_enabled) + +# Launcher process (Windows only) +# ============================================================== + + +@depends(target) +def launcher_process_default(target): + return target.os == "WINNT" + + +option( + "--enable-launcher-process", + default=launcher_process_default, + help="{Enable|Disable} launcher process by default", +) + + +@depends("--enable-launcher-process", target) +def launcher(value, target): + enabled = bool(value) + if enabled and target.os != "WINNT": + die("Cannot enable launcher process on %s", target.os) + if enabled: + return True + + +set_config("MOZ_LAUNCHER_PROCESS", launcher) +set_define("MOZ_LAUNCHER_PROCESS", launcher) + +# llvm-dlltool (Windows only) +# ============================================================== + + +@depends(build_project, target, "--enable-compile-environment") +def check_for_llvm_dlltool(build_project, target, compile_environment): + if build_project != "browser": + return + + if target.os != "WINNT": + return + + return compile_environment + + +llvm_dlltool = check_prog( + "LLVM_DLLTOOL", + ("llvm-dlltool",), + what="llvm-dlltool", + when=check_for_llvm_dlltool, + paths=clang_search_path, +) + + +@depends(target, when=llvm_dlltool) +def llvm_dlltool_flags(target): + arch = { + "x86": "i386", + "x86_64": "i386:x86-64", + "aarch64": "arm64", + }[target.cpu] + + return ["-m", arch] + + +set_config("LLVM_DLLTOOL_FLAGS", llvm_dlltool_flags) + +# BITS download (Windows only) +# ============================================================== + +option( + "--enable-bits-download", + when=target_is_windows, + default=target_is_windows, + help="{Enable|Disable} building BITS download support", +) + +set_define( + "MOZ_BITS_DOWNLOAD", + depends_if("--enable-bits-download", when=target_is_windows)(lambda _: True), +) +set_config( + "MOZ_BITS_DOWNLOAD", + depends_if("--enable-bits-download", when=target_is_windows)(lambda _: True), +) + +# Bundled fonts on desktop platform +# ============================================================== + + +@depends(target) +def bundled_fonts_default(target): + return target.os == "WINNT" or target.kernel == "Linux" + + +@depends(build_project) +def allow_bundled_fonts(project): + return project == "browser" or project == "comm/mail" + + +option( + "--enable-bundled-fonts", + default=bundled_fonts_default, + when=allow_bundled_fonts, + help="{Enable|Disable} support for bundled fonts on desktop platforms", +) + +set_define( + "MOZ_BUNDLED_FONTS", + depends_if("--enable-bundled-fonts", when=allow_bundled_fonts)(lambda _: True), +) + +# Reflow counting +# ============================================================== + + +@depends(moz_debug) +def reflow_perf(debug): + if debug: + return True + + +option( + "--enable-reflow-perf", + default=reflow_perf, + help="{Enable|Disable} reflow performance tracing", +) + +# The difference in conditions here comes from the initial implementation +# in old-configure, which was unexplained there as well. +set_define("MOZ_REFLOW_PERF", depends_if("--enable-reflow-perf")(lambda _: True)) +set_define("MOZ_REFLOW_PERF_DSP", reflow_perf) + +# Layout debugger +# ============================================================== + + +@depends(moz_debug) +def layout_debugger(debug): + if debug: + return True + + +option( + "--enable-layout-debugger", + default=layout_debugger, + help="{Enable|Disable} layout debugger", +) + +set_config("MOZ_LAYOUT_DEBUGGER", True, when="--enable-layout-debugger") +set_define("MOZ_LAYOUT_DEBUGGER", True, when="--enable-layout-debugger") + + +# Shader Compiler for Windows (and MinGW Cross Compile) +# ============================================================== + +with only_when(compile_environment): + fxc = check_prog( + "FXC", + ("fxc.exe", "fxc2.exe"), + when=depends(target)(lambda t: t.kernel == "WINNT"), + paths=sdk_bin_path, + # FXC being used from a python wrapper script, we can live with it + # having spaces. + allow_spaces=True, + ) + + +# VPX +# === + +with only_when(compile_environment): + system_lib_option( + "--with-system-libvpx", help="Use system libvpx (located with pkgconfig)" + ) + + with only_when("--with-system-libvpx"): + vpx = pkg_check_modules("MOZ_LIBVPX", "vpx >= 1.10.0") + + check_header( + "vpx/vpx_decoder.h", + flags=vpx.cflags, + onerror=lambda: die( + "Couldn't find vpx/vpx_decoder.h, which is required to build " + "with system libvpx. Use --without-system-libvpx to build " + "with in-tree libvpx." + ), + ) + + check_symbol( + "vpx_codec_dec_init_ver", + flags=vpx.libs, + onerror=lambda: die( + "--with-system-libvpx requested but symbol vpx_codec_dec_init_ver " + "not found" + ), + ) + + set_config("MOZ_SYSTEM_LIBVPX", True) + + @depends("--with-system-libvpx", target) + def in_tree_vpx(system_libvpx, target): + if system_libvpx: + return + + arm_asm = (target.cpu == "arm") or None + return namespace(arm_asm=arm_asm) + + @depends(target, when=in_tree_vpx) + def vpx_nasm(target): + if target.cpu in ("x86", "x86_64"): + if target.kernel == "WINNT": + # Version 2.03 is needed for automatic safeseh support. + return namespace(version="2.03", what="VPX") + return namespace(what="VPX") + + @depends(in_tree_vpx, vpx_nasm, target, neon_flags) + def vpx_as_flags(vpx, vpx_nasm, target, neon_flags): + if vpx and vpx.arm_asm: + # These flags are a lie; they're just used to enable the requisite + # opcodes; actual arch detection is done at runtime. + return neon_flags + elif vpx and vpx_nasm and target.os != "WINNT" and target.cpu != "x86_64": + return ("-DPIC",) + + set_config("VPX_USE_NASM", True, when=vpx_nasm) + set_config("VPX_ASFLAGS", vpx_as_flags) + + +# JPEG +# ==== + +with only_when(compile_environment): + system_lib_option( + "--with-system-jpeg", + nargs="?", + help="Use system libjpeg (installed at given prefix)", + ) + + @depends_if("--with-system-jpeg") + def jpeg_flags(value): + if len(value): + return namespace( + cflags=("-I%s/include" % value[0],), + ldflags=("-L%s/lib" % value[0], "-ljpeg"), + ) + return namespace( + ldflags=("-ljpeg",), + ) + + with only_when("--with-system-jpeg"): + check_symbol( + "jpeg_destroy_compress", + flags=jpeg_flags.ldflags, + onerror=lambda: die( + "--with-system-jpeg requested but symbol " + "jpeg_destroy_compress not found." + ), + ) + + c_compiler.try_compile( + includes=[ + "stdio.h", + "sys/types.h", + "jpeglib.h", + ], + body=""" + #if JPEG_LIB_VERSION < 62 + #error Insufficient JPEG library version + #endif + """, + flags=jpeg_flags.cflags, + check_msg="for sufficient jpeg library version", + onerror=lambda: die( + "Insufficient JPEG library version for " + "--with-system-jpeg (62 required)" + ), + ) + + c_compiler.try_compile( + includes=[ + "stdio.h", + "sys/types.h", + "jpeglib.h", + ], + body=""" + #ifndef JCS_EXTENSIONS + #error libjpeg-turbo JCS_EXTENSIONS required + #endif + """, + flags=jpeg_flags.cflags, + check_msg="for sufficient libjpeg-turbo JCS_EXTENSIONS", + onerror=lambda: die( + "libjpeg-turbo JCS_EXTENSIONS required for " "--with-system-jpeg" + ), + ) + + set_config("MOZ_JPEG_CFLAGS", jpeg_flags.cflags) + set_config("MOZ_JPEG_LIBS", jpeg_flags.ldflags) + + @depends("--with-system-jpeg", target, neon_flags) + def in_tree_jpeg_arm(system_jpeg, target, neon_flags): + if system_jpeg: + return + + if target.cpu == "arm": + return neon_flags + elif target.cpu == "aarch64": + return ("-march=armv8-a",) + + @depends("--with-system-jpeg", target) + def in_tree_jpeg_mips64(system_jpeg, target): + if system_jpeg: + return + + if target.cpu == "mips64": + return ("-Wa,-mloongson-mmi", "-mloongson-ext") + + # Compiler check from https://github.com/libjpeg-turbo/libjpeg-turbo/blob/57ba02a408a9a55ccff25aae8b164632a3a4f177/simd/CMakeLists.txt#L419 + jpeg_mips64_mmi = c_compiler.try_compile( + body='int c = 0, a = 0, b = 0; asm("paddb %0, %1, %2" : "=f" (c) : "f" (a), "f" (b));', + check_msg="for loongson mmi support", + flags=in_tree_jpeg_mips64, + when=in_tree_jpeg_mips64, + ) + + @depends( + "--with-system-jpeg", + target, + in_tree_jpeg_arm, + in_tree_jpeg_mips64, + jpeg_mips64_mmi, + ) + def in_tree_jpeg( + system_jpeg, target, in_tree_jpeg_arm, in_tree_jpeg_mips64, jpeg_mips64_mmi + ): + if system_jpeg: + return + + if target.cpu in ("arm", "aarch64"): + return in_tree_jpeg_arm + elif target.kernel == "Darwin": + if target.cpu == "x86": + return ("-DPIC", "-DMACHO") + elif target.cpu == "x86_64": + return ("-D__x86_64__", "-DPIC", "-DMACHO") + elif target.kernel == "WINNT": + if target.cpu == "x86": + return ("-DPIC", "-DWIN32") + elif target.cpu == "x86_64": + return ("-D__x86_64__", "-DPIC", "-DWIN64", "-DMSVC") + elif target.cpu == "mips32": + return ("-mdspr2",) + elif target.cpu == "mips64" and jpeg_mips64_mmi: + return in_tree_jpeg_mips64 + elif target.cpu == "x86": + return ("-DPIC", "-DELF") + elif target.cpu == "x86_64": + return ("-D__x86_64__", "-DPIC", "-DELF") + + @depends(target, when=depends("--with-system-jpeg")(lambda x: not x)) + def jpeg_nasm(target): + if target.cpu in ("x86", "x86_64"): + # libjpeg-turbo 2.0.6 requires nasm 2.10. + return namespace(version="2.10", what="JPEG") + + # Compiler checks from https://github.com/libjpeg-turbo/libjpeg-turbo/blob/57ba02a408a9a55ccff25aae8b164632a3a4f177/simd/CMakeLists.txt#L258 + jpeg_arm_neon_vld1_s16_x3 = c_compiler.try_compile( + includes=["arm_neon.h"], + body="int16_t input[12] = {}; int16x4x3_t output = vld1_s16_x3(input);", + check_msg="for vld1_s16_x3 in arm_neon.h", + flags=in_tree_jpeg_arm, + when=in_tree_jpeg_arm, + ) + + jpeg_arm_neon_vld1_u16_x2 = c_compiler.try_compile( + includes=["arm_neon.h"], + body="uint16_t input[8] = {}; uint16x4x2_t output = vld1_u16_x2(input);", + check_msg="for vld1_u16_x2 in arm_neon.h", + flags=in_tree_jpeg_arm, + when=in_tree_jpeg_arm, + ) + + jpeg_arm_neon_vld1q_u8_x4 = c_compiler.try_compile( + includes=["arm_neon.h"], + body="uint8_t input[64] = {}; uint8x16x4_t output = vld1q_u8_x4(input);", + check_msg="for vld1q_u8_x4 in arm_neon.h", + flags=in_tree_jpeg_arm, + when=in_tree_jpeg_arm, + ) + + set_config("LIBJPEG_TURBO_USE_NASM", True, when=jpeg_nasm) + set_config("LIBJPEG_TURBO_SIMD_FLAGS", in_tree_jpeg) + set_config("LIBJPEG_TURBO_HAVE_VLD1_S16_X3", jpeg_arm_neon_vld1_s16_x3) + set_config("LIBJPEG_TURBO_HAVE_VLD1_U16_X2", jpeg_arm_neon_vld1_u16_x2) + set_config("LIBJPEG_TURBO_HAVE_VLD1Q_U8_X4", jpeg_arm_neon_vld1q_u8_x4) + set_config( + "LIBJPEG_TURBO_NEON_INTRINSICS", + jpeg_arm_neon_vld1_s16_x3 + & jpeg_arm_neon_vld1_u16_x2 + & jpeg_arm_neon_vld1q_u8_x4, + ) + + +# PNG +# === +with only_when(compile_environment): + system_lib_option( + "--with-system-png", + nargs="?", + help="Use system libpng", + ) + + @depends("--with-system-png") + def deprecated_system_png_path(value): + if len(value) == 1: + die( + "--with-system-png=PATH is not supported anymore. Please use " + "--with-system-png and set any necessary pkg-config environment variable." + ) + + png = pkg_check_modules("MOZ_PNG", "libpng >= 1.6.35", when="--with-system-png") + + check_symbol( + "png_get_acTL", + flags=png.libs, + onerror=lambda: die( + "--with-system-png won't work because the system's libpng doesn't have APNG support" + ), + when="--with-system-png", + ) + + set_config("MOZ_SYSTEM_PNG", True, when="--with-system-png") + + +# FFmpeg's ffvpx configuration +# ============================================================== +with only_when(compile_environment): + + @depends(target) + def libav_fft(target): + if target.os == "Android" and target.cpu != "arm": + return True + return target.kernel in ("WINNT", "Darwin") or target.cpu == "x86_64" + + set_config("MOZ_LIBAV_FFT", depends(when=libav_fft)(lambda: True)) + set_define("MOZ_LIBAV_FFT", depends(when=libav_fft)(lambda: True)) + + +# Artifact builds need MOZ_FFVPX defined as if compilation happened. +with only_when(compile_environment | artifact_builds): + + @depends(target) + def ffvpx(target): + enable = use_nasm = True + flac_only = False + flags = [] + + if target.kernel == "WINNT": + if target.cpu == "x86": + # 32-bit windows need to prefix symbols with an underscore. + flags = ["-DPIC", "-DWIN32", "-DPREFIX", "-Pconfig_win32.asm"] + elif target.cpu == "x86_64": + flags = [ + "-D__x86_64__", + "-DPIC", + "-DWIN64", + "-DMSVC", + "-Pconfig_win64.asm", + ] + elif target.cpu == "aarch64": + flags = ["-DPIC", "-DWIN64"] + use_nasm = False + elif target.kernel == "Darwin": + # 32/64-bit macosx assemblers need to prefix symbols with an + # underscore. + flags = ["-DPIC", "-DMACHO", "-DPREFIX"] + if target.cpu == "x86_64": + flags += [ + "-D__x86_64__", + "-Pconfig_darwin64.asm", + ] + elif target.cpu == "aarch64": + use_nasm = False + elif target.cpu == "x86_64": + flags = ["-D__x86_64__", "-DPIC", "-DELF", "-Pconfig_unix64.asm"] + elif target.cpu in ("x86", "arm", "aarch64"): + flac_only = True + else: + enable = False + + if flac_only or not enable: + use_nasm = False + + return namespace( + enable=enable, + use_nasm=use_nasm, + flac_only=flac_only, + flags=flags, + ) + + @depends(when=ffvpx.use_nasm) + def ffvpx_nasm(): + # nasm 2.10 for AVX-2 support. + return namespace(version="2.10", what="FFVPX") + + # ffvpx_nasm can't indirectly depend on vpx_as_flags, because it depends + # on a compiler test, so we have to do a little bit of dance here. + @depends(ffvpx, vpx_as_flags, target) + def ffvpx(ffvpx, vpx_as_flags, target): + if ffvpx and vpx_as_flags and target.cpu in ("arm", "aarch64"): + ffvpx.flags.extend(vpx_as_flags) + return ffvpx + + set_config("MOZ_FFVPX", True, when=ffvpx.enable) + set_define("MOZ_FFVPX", True, when=ffvpx.enable) + set_config("MOZ_FFVPX_AUDIOONLY", True, when=ffvpx.flac_only) + set_define("MOZ_FFVPX_AUDIOONLY", True, when=ffvpx.flac_only) + set_config("FFVPX_ASFLAGS", ffvpx.flags) + set_config("FFVPX_USE_NASM", True, when=ffvpx.use_nasm) + + +# nasm detection +# ============================================================== +@depends(dav1d_nasm, vpx_nasm, jpeg_nasm, ffvpx_nasm, when=compile_environment) +def need_nasm(*requirements): + requires = { + x.what: x.version if hasattr(x, "version") else True for x in requirements if x + } + if requires: + items = sorted(requires.keys()) + if len(items) > 1: + what = " and ".join((", ".join(items[:-1]), items[-1])) + else: + what = items[0] + versioned = {k: v for (k, v) in requires.items() if v is not True} + return namespace(what=what, versioned=versioned) + + +nasm = check_prog( + "NASM", + ["nasm"], + allow_missing=True, + bootstrap="nasm", + when=need_nasm, +) + + +@depends(nasm, need_nasm.what) +def check_nasm(nasm, what): + if not nasm and what: + die("Nasm is required to build with %s, but it was not found." % what) + return nasm + + +@depends_if(check_nasm) +@checking("nasm version") +def nasm_version(nasm): + version = ( + check_cmd_output(nasm, "-v", onerror=lambda: die("Failed to get nasm version.")) + .splitlines()[0] + .split()[2] + ) + return Version(version) + + +@depends(nasm_version, need_nasm.versioned, when=need_nasm.versioned) +def check_nasm_version(nasm_version, versioned): + by_version = sorted(versioned.items(), key=lambda x: x[1]) + what, version = by_version[-1] + if nasm_version < version: + die( + "Nasm version %s or greater is required to build with %s." % (version, what) + ) + return nasm_version + + +@depends(target, when=check_nasm_version) +def nasm_asflags(target): + asflags = { + ("OSX", "x86"): ["-f", "macho32"], + ("OSX", "x86_64"): ["-f", "macho64"], + ("WINNT", "x86"): ["-f", "win32"], + ("WINNT", "x86_64"): ["-f", "win64"], + }.get((target.os, target.cpu), None) + if asflags is None: + # We're assuming every x86 platform we support that's + # not Windows or Mac is ELF. + if target.cpu == "x86": + asflags = ["-f", "elf32"] + elif target.cpu == "x86_64": + asflags = ["-f", "elf64"] + return asflags + + +set_config("NASM_ASFLAGS", nasm_asflags) + + +# ANGLE OpenGL->D3D translator for WebGL +# ============================================================== + +with only_when(compile_environment & target_is_windows): + set_config("MOZ_ANGLE_RENDERER", True) + +# Remoting protocol support +# ============================================================== + + +@depends(toolkit) +def has_remote(toolkit): + if toolkit in ("gtk", "windows", "cocoa"): + return True + + +set_config("MOZ_HAS_REMOTE", has_remote) +set_define("MOZ_HAS_REMOTE", has_remote) + +# RLBox Library Sandboxing wasm support +# ============================================================== + + +def wasm_sandboxing_libraries(): + return ( + "graphite", + "ogg", + "hunspell", + "expat", + "woff2", + "soundtouch", + ) + + +@depends(dependable(wasm_sandboxing_libraries), build_project) +def default_wasm_sandboxing_libraries(libraries, build_project): + if build_project != "tools/rusttests": + non_default_libs = {} + + return tuple(l for l in libraries if l not in non_default_libs) + + +option( + "--with-wasm-sandboxed-libraries", + env="WASM_SANDBOXED_LIBRARIES", + help="{Enable wasm sandboxing for the selected libraries|Disable wasm sandboxing}", + nargs="+", + choices=dependable(wasm_sandboxing_libraries), + default=default_wasm_sandboxing_libraries, +) + + +@depends("--with-wasm-sandboxed-libraries") +def requires_wasm_sandboxing(libraries): + if libraries: + return True + + +set_config("MOZ_USING_WASM_SANDBOXING", requires_wasm_sandboxing) +set_define("MOZ_USING_WASM_SANDBOXING", requires_wasm_sandboxing) + +with only_when(requires_wasm_sandboxing & compile_environment): + option( + "--with-wasi-sysroot", + env="WASI_SYSROOT", + nargs=1, + help="Path to wasi sysroot for wasm sandboxing", + ) + + @depends("--with-wasi-sysroot", requires_wasm_sandboxing) + def bootstrap_wasi_sysroot(wasi_sysroot, requires_wasm_sandboxing): + return requires_wasm_sandboxing and not wasi_sysroot + + @depends( + "--with-wasi-sysroot", + bootstrap_path("sysroot-wasm32-wasi", when=bootstrap_wasi_sysroot), + ) + @imports("os") + def wasi_sysroot(wasi_sysroot, bootstrapped_sysroot): + if not wasi_sysroot: + return bootstrapped_sysroot + + wasi_sysroot = wasi_sysroot[0] + if not os.path.isdir(wasi_sysroot): + die("Argument to --with-wasi-sysroot must be a directory") + if not os.path.isabs(wasi_sysroot): + die("Argument to --with-wasi-sysroot must be an absolute path") + + return wasi_sysroot + + @depends(wasi_sysroot) + def wasi_sysroot_flags(wasi_sysroot): + if wasi_sysroot: + log.info("Using wasi sysroot in %s", wasi_sysroot) + return ["--sysroot=%s" % wasi_sysroot] + return [] + + set_config("WASI_SYSROOT", wasi_sysroot) + + def wasm_compiler_with_flags(compiler, sysroot_flags): + if compiler: + return ( + compiler.wrapper + [compiler.compiler] + compiler.flags + sysroot_flags + ) + + @template + def wasm_compiler_error(msg): + @depends("--with-wasm-sandboxed-libraries") + def wasm_compiler_error(sandboxed_libs): + suggest_disable = "" + if sandboxed_libs.origin == "default": + suggest_disable = " Or build with --without-wasm-sandboxed-libraries." + return lambda: die(msg + suggest_disable) + + return wasm_compiler_error + + @template + def check_wasm_compiler(compiler, language): + compiler.try_compile( + includes=["cstring" if language == "C++" else "string.h"], + flags=wasi_sysroot_flags, + check_msg="the wasm %s compiler can find wasi headers" % language, + onerror=wasm_compiler_error( + "Cannot find wasi headers or problem with the wasm compiler. " + "Please fix the problem." + ), + ) + + compiler.try_run( + flags=wasi_sysroot_flags, + check_msg="the wasm %s linker can find wasi libraries" % language, + onerror=wasm_compiler_error( + "Cannot find wasi libraries or problem with the wasm linker. " + "Please fix the problem." + ), + ) + + wasm_cc = compiler("C", wasm, other_compiler=c_compiler) + check_wasm_compiler(wasm_cc, "C") + + @depends(wasm_cc, wasi_sysroot_flags) + def wasm_cc_with_flags(wasm_cc, wasi_sysroot_flags): + return wasm_compiler_with_flags(wasm_cc, wasi_sysroot_flags) + + set_config("WASM_CC", wasm_cc_with_flags) + + wasm_cxx = compiler( + "C++", + wasm, + c_compiler=wasm_cc, + other_compiler=cxx_compiler, + other_c_compiler=c_compiler, + ) + check_wasm_compiler(wasm_cxx, "C++") + + @depends(wasm_cxx, wasi_sysroot_flags) + def wasm_cxx_with_flags(wasm_cxx, wasi_sysroot_flags): + return wasm_compiler_with_flags(wasm_cxx, wasi_sysroot_flags) + + set_config("WASM_CXX", wasm_cxx_with_flags) + + wasm_compile_flags = dependable(["-fno-exceptions", "-fno-strict-aliasing"]) + option(env="WASM_CFLAGS", nargs=1, help="Options to pass to WASM_CC") + + @depends("WASM_CFLAGS", wasm_compile_flags) + def wasm_cflags(value, wasm_compile_flags): + if value: + return wasm_compile_flags + value + else: + return wasm_compile_flags + + set_config("WASM_CFLAGS", wasm_cflags) + + option(env="WASM_CXXFLAGS", nargs=1, help="Options to pass to WASM_CXX") + + @depends("WASM_CXXFLAGS", wasm_compile_flags) + def wasm_cxxflags(value, wasm_compile_flags): + if value: + return wasm_compile_flags + value + else: + return wasm_compile_flags + + set_config("WASM_CXXFLAGS", wasm_cxxflags) + + +@depends("--with-wasm-sandboxed-libraries") +def wasm_sandboxing(libraries): + if not libraries: + return + + return namespace(**{name: True for name in libraries}) + + +@template +def wasm_sandboxing_config_defines(): + for lib in wasm_sandboxing_libraries(): + set_config( + "MOZ_WASM_SANDBOXING_%s" % lib.upper(), getattr(wasm_sandboxing, lib) + ) + set_define( + "MOZ_WASM_SANDBOXING_%s" % lib.upper(), getattr(wasm_sandboxing, lib) + ) + + +wasm_sandboxing_config_defines() + + +with only_when(compile_environment & wasm_sandboxing.hunspell): + clock_in_wasi_sysroot = wasm_cc.try_run( + header="#include <time.h>", + body="clock();", + check_msg="for clock() in wasi sysroot", + flags=depends(wasi_sysroot_flags)( + lambda sysroot_flags: ["-Werror"] + sysroot_flags + ), + ) + + wasi_emulated_clock = wasm_cc.try_run( + header="#include <time.h>", + body="clock();", + check_msg="for emulated clock() in wasi sysroot", + flags=depends(wasi_sysroot_flags)( + lambda sysroot_flags: [ + "-Werror", + "-D_WASI_EMULATED_PROCESS_CLOCKS", + "-lwasi-emulated-process-clocks", + ] + + sysroot_flags + ), + when=depends(clock_in_wasi_sysroot)(lambda x: not x), + onerror=lambda: die("Can't find clock() in wasi sysroot."), + ) + + set_config("MOZ_WASI_EMULATED_CLOCK", True, when=wasi_emulated_clock) + + +# new Notification Store implementation +# ============================================================== + + +@depends(milestone) +def new_notification_store(milestone): + if milestone.is_nightly: + return True + + +set_config("MOZ_NEW_NOTIFICATION_STORE", True, when=new_notification_store) +set_define("MOZ_NEW_NOTIFICATION_STORE", True, when=new_notification_store) + + +# Auxiliary files persistence on application close +# ============================================================== + +option( + "--enable-disk-remnant-avoidance", + help="Prevent persistence of auxiliary files on application close", +) + + +set_config( + "MOZ_AVOID_DISK_REMNANT_ON_CLOSE", + True, + when="--enable-disk-remnant-avoidance", +) + + +# Glean SDK Integration Crate +# ============================================================== + + +@depends(target) +def glean_android(target): + return target.os == "Android" + + +set_config("MOZ_GLEAN_ANDROID", True, when=glean_android) +set_define("MOZ_GLEAN_ANDROID", True, when=glean_android) + + +# dump_syms +# ============================================================== + +check_prog( + "DUMP_SYMS", + ["dump_syms"], + allow_missing=True, + bootstrap="dump_syms", + when=compile_environment, +) + + +@depends(valid_windows_sdk_dir, host) +@imports(_from="os", _import="environ") +def pdbstr_paths(valid_windows_sdk_dir, host): + if not valid_windows_sdk_dir: + return + + vc_host = { + "x86": "x86", + "x86_64": "x64", + }.get(host.cpu) + + return [ + environ["PATH"], + os.path.join(valid_windows_sdk_dir.path, "Debuggers", vc_host, "srcsrv"), + ] + + +check_prog( + "PDBSTR", + ["pdbstr.exe"], + allow_missing=True, + when=compile_environment & target_is_windows, + paths=pdbstr_paths, + allow_spaces=True, +) + + +@depends("MOZ_AUTOMATION", c_compiler) +def allow_missing_winchecksec(automation, c_compiler): + if not automation: + return True + if c_compiler and c_compiler.type != "clang-cl": + return True + + +check_prog( + "WINCHECKSEC", + ["winchecksec.exe", "winchecksec"], + bootstrap="winchecksec", + allow_missing=allow_missing_winchecksec, + when=compile_environment & target_is_windows, +) + + +# Fork server +@depends(target, build_project) +def forkserver_default(target, build_project): + return build_project == "browser" and ( + (target.os == "GNU" and target.kernel == "Linux") + or target.os == "FreeBSD" + or target.os == "OpenBSD" + ) + + +option( + "--enable-forkserver", + default=forkserver_default, + env="MOZ_ENABLE_FORKSERVER", + help="{Enable|Disable} fork server", +) + + +@depends("--enable-forkserver", target) +def forkserver_flag(value, target): + if ( + target.os == "Android" + or (target.os == "GNU" and target.kernel == "Linux") + or target.os == "FreeBSD" + or target.os == "OpenBSD" + ): + return bool(value) + pass + + +set_config("MOZ_ENABLE_FORKSERVER", forkserver_flag) +set_define("MOZ_ENABLE_FORKSERVER", forkserver_flag, forkserver_flag) + +# Crash Reporter +# ============================================================== + +with only_when(compile_environment & target_has_linux_kernel): + # Check if we need to use the breakpad_getcontext fallback. + getcontext = check_symbol("getcontext") + set_config("HAVE_GETCONTEXT", getcontext) + set_define("HAVE_GETCONTEXT", getcontext) + +# NSS +# ============================================================== +include("../build/moz.configure/nss.configure") + + +# Enable or disable running in background task mode: headless for +# periodic, short-lived, maintenance tasks. +# ============================================================================== +option( + "--disable-backgroundtasks", + help="Disable running in background task mode", +) +set_config("MOZ_BACKGROUNDTASKS", True, when="--enable-backgroundtasks") +set_define("MOZ_BACKGROUNDTASKS", True, when="--enable-backgroundtasks") + + +# Update-related programs: updater, maintenance service, update agent, +# default browser agent. +# ============================================================== +include("../build/moz.configure/update-programs.configure") + + +# Mobile optimizations +# ============================================================== +option( + "--enable-mobile-optimize", + default=target_is_android, + help="{Enable|Disable} mobile optimizations", +) + +set_define("MOZ_GFX_OPTIMIZE_MOBILE", True, when="--enable-mobile-optimize") +# We ignore "paint will resample" on mobile for performance. +# We may want to revisit this later. +set_define("MOZ_IGNORE_PAINT_WILL_RESAMPLE", True, when="--enable-mobile-optimize") + +# Pref extensions +# ============================================================== +option("--disable-pref-extensions", help="Disable pref extensions such as autoconfig") +set_config("MOZ_PREF_EXTENSIONS", True, when="--enable-pref-extensions") + +# Offer a way to disable the startup cache +# ============================================================== +option("--disable-startupcache", help="Disable startup cache") + + +@depends("--enable-startupcache") +def enable_startupcache(value): + if value: + return True + + +set_define( + "MOZ_DISABLE_STARTUPCACHE", True, when=depends(enable_startupcache)(lambda x: not x) +) + + +# Branding +# ============================================================== +option( + env="MOZ_APP_REMOTINGNAME", + nargs=1, + help="Used for the internal program name, which affects profile name " + "and remoting. If not set, defaults to MOZ_APP_NAME if the update channel " + "is release, and MOZ_APP_NAME-MOZ_UPDATE_CHANNEL otherwise.", +) + + +@depends("MOZ_APP_REMOTINGNAME", moz_app_name, update_channel) +def moz_app_remotingname(value, moz_app_name, update_channel): + if value: + return value[0] + if update_channel == "release": + return moz_app_name + return moz_app_name + "-" + update_channel + + +set_config("MOZ_APP_REMOTINGNAME", moz_app_remotingname) + +option( + env="ANDROID_PACKAGE_NAME", + nargs=1, + help="Name of the Android package (default org.mozilla.$MOZ_APP_NAME)", +) + + +@depends("ANDROID_PACKAGE_NAME", moz_app_name) +def android_package_name(value, moz_app_name): + if value: + return value[0] + if moz_app_name == "fennec": + return "org.mozilla.fennec_aurora" + return "org.mozilla.%s" % moz_app_name + + +set_config("ANDROID_PACKAGE_NAME", android_package_name) + + +# Miscellaneous options +# ============================================================== +option(env="MOZ_WINCONSOLE", nargs="?", help="Whether we can create a console window.") +set_define("MOZ_WINCONSOLE", True, when=depends("MOZ_WINCONSOLE")(lambda x: x)) + + +# Alternative Crashreporter setting +option( + "--with-crashreporter-url", + env="MOZ_CRASHREPORTER_URL", + default="https://crash-reports.mozilla.com/", + nargs=1, + help="Set an alternative crashreporter url", +) + +set_config( + "MOZ_CRASHREPORTER_URL", + depends("--with-crashreporter-url")(lambda x: x[0].rstrip("/")), +) + + +# Crash reporter options +# ============================================================== +@depends(target) +def oxidized_breakpad(target): + if target.kernel == "Linux": + return target.cpu in ("aarch64", "arm", "x86", "x86_64") + return False + + +set_config("MOZ_OXIDIZED_BREAKPAD", True, when=oxidized_breakpad) +set_define("MOZ_OXIDIZED_BREAKPAD", True, when=oxidized_breakpad) + + +# Wine +# ============================================================== +@depends(target, host) +def want_wine(target, host): + return target.kernel == "WINNT" and host.kernel != "WINNT" + + +wine = check_prog( + "WINE", + ["wine64", "wine"], + when=want_wine, + bootstrap="wine/bin", +) + +# DOM Streams +# ============================================================== +# Set this to true so the JS engine knows we're doing a browser build. +set_config("MOZ_DOM_STREAMS", True) +set_define("MOZ_DOM_STREAMS", True) + +# libevent +# ============================================================== +with only_when(compile_environment): + system_lib_option( + "--with-system-libevent", + nargs="?", + help="Use system libevent", + ) + + @depends("--with-system-libevent") + def deprecated_system_libevent_path(value): + if len(value) == 1: + die( + "--with-system-libevent=PATH is not supported anymore. Please use " + "--with-system-libevent and set any necessary pkg-config environment variable." + ) + + pkg_check_modules("MOZ_LIBEVENT", "libevent", when="--with-system-libevent") + + set_config("MOZ_SYSTEM_LIBEVENT", True, when="--with-system-libevent") + + +# Crash reporting +# ============================================================== +@depends(target, developer_options, artifact_builds) +def crashreporter_default(target, developer_options, artifacts): + if target.kernel in ("WINNT", "Darwin"): + return True + if target.kernel == "Linux" and target.cpu in ("x86", "x86_64", "arm", "aarch64"): + # The crash reporter prevents crash stacktraces to be logged in the + # logs on Android, so we leave it out by default in developer builds. + return target.os != "Android" or not developer_options or artifacts + + +option( + "--enable-crashreporter", + default=crashreporter_default, + help="{Enable|Disable} crash reporting", +) + + +set_config("MOZ_CRASHREPORTER", True, when="--enable-crashreporter") +set_define("MOZ_CRASHREPORTER", True, when="--enable-crashreporter") + +with only_when(compile_environment): + with only_when("--enable-crashreporter"): + pkg_check_modules( + "MOZ_GTHREAD", + "gthread-2.0", + when=depends(target)(lambda t: t.os == "GNU" and t.kernel == "Linux"), + ) + + set_config( + "MOZ_CRASHREPORTER_INJECTOR", + True, + when=depends(target)(lambda t: t.os == "WINNT" and t.bitness == 32), + ) + set_define( + "MOZ_CRASHREPORTER_INJECTOR", + True, + when=depends(target)(lambda t: t.os == "WINNT" and t.bitness == 32), + ) + + +# If we have any service that uploads data (and requires data submission +# policy alert), set MOZ_DATA_REPORTING. +# ============================================================== +@depends( + "MOZ_TELEMETRY_REPORTING", + "MOZ_SERVICES_HEALTHREPORT", + "--enable-crashreporter", + "MOZ_NORMANDY", +) +def data_reporting(telemetry, healthreport, crashreporter, normandy): + return telemetry or healthreport or crashreporter or normandy + + +set_config("MOZ_DATA_REPORTING", True, when=data_reporting) +set_define("MOZ_DATA_REPORTING", True, when=data_reporting) + + +# Gtk+ +# ============================================================== +with only_when(toolkit_gtk): + pkg_check_modules( + "MOZ_GTK3", + "gtk+-3.0 >= 3.14.0 gtk+-unix-print-3.0 glib-2.0 gobject-2.0 gio-unix-2.0", + ) + + set_define("GDK_VERSION_MIN_REQUIRED", "GDK_VERSION_3_14") + set_define("GDK_VERSION_MAX_ALLOWED", "GDK_VERSION_3_14") + + pkg_check_modules("GLIB", "glib-2.0 >= 2.42 gobject-2.0") + + set_define("GLIB_VERSION_MIN_REQUIRED", "GLIB_VERSION_2_42") + set_define("GLIB_VERSION_MAX_ALLOWED", "GLIB_VERSION_2_42") + + set_define("MOZ_ACCESSIBILITY_ATK", True, when=accessibility) + +# DBus +# ============================================================== +with only_when(toolkit_gtk): + option("--disable-dbus", help="Disable dbus support") + + with only_when("--enable-dbus"): + pkg_check_modules("MOZ_DBUS", "dbus-1 >= 0.60") + + set_config("MOZ_ENABLE_DBUS", True) + set_define("MOZ_ENABLE_DBUS", True) + + +# Necko's wifi scanner +# ============================================================== +@depends(target) +def necko_wifi_when(target): + return target.os in ("WINNT", "OSX", "DragonFly", "FreeBSD") or ( + target.kernel == "Linux" and target.os == "GNU" + ) + + +option("--disable-necko-wifi", help="Disable necko wifi scanner", when=necko_wifi_when) + +set_config("NECKO_WIFI", True, when="--enable-necko-wifi") +set_define("NECKO_WIFI", True, when="--enable-necko-wifi") + + +@depends( + depends("--enable-necko-wifi", when=necko_wifi_when)(lambda x: x), + depends("--enable-dbus", when=toolkit_gtk)(lambda x: x), + when=depends(target)(lambda t: t.os == "GNU" and t.kernel == "Linux"), +) +def necko_wifi_dbus(necko_wifi, dbus): + if necko_wifi and not dbus: + die( + "Necko WiFi scanning needs DBus on your platform, remove --disable-dbus" + " or use --disable-necko-wifi" + ) + return necko_wifi and dbus + + +set_config("NECKO_WIFI_DBUS", True, when=necko_wifi_dbus) +set_define("NECKO_WIFI_DBUS", True, when=necko_wifi_dbus) + + +# Frontend JS debug mode +# ============================================================== +option("--enable-debug-js-modules", help="Enable debug mode for frontend JS libraries") + +set_config("DEBUG_JS_MODULES", True, when="--enable-debug-js-modules") + + +# moz_dump_painting +# ============================================================== +option("--enable-dump-painting", help="Enable paint debugging") + +set_define( + "MOZ_DUMP_PAINTING", + True, + when=depends("--enable-dump-painting", "--enable-debug")( + lambda painting, debug: painting or debug + ), +) +set_define("MOZ_LAYERS_HAVE_LOG", True, when="--enable-dump-painting") + + +# libproxy support +# ============================================================== +with only_when(toolkit_gtk): + system_lib_option("--enable-libproxy", help="Enable libproxy support") + + with only_when("--enable-libproxy"): + pkg_check_modules("MOZ_LIBPROXY", "libproxy-1.0") + + set_config("MOZ_ENABLE_LIBPROXY", True) + set_define("MOZ_ENABLE_LIBPROXY", True) + + +# Enable runtime logging +# ============================================================== +set_define("MOZ_LOGGING", True) +set_define("FORCE_PR_LOG", True) + +# This will enable logging of addref, release, ctor, dtor. +# ============================================================== +option( + "--enable-logrefcnt", + default=moz_debug, + help="{Enable|Disable} logging of refcounts", +) + +set_define("NS_BUILD_REFCNT_LOGGING", True, when="--enable-logrefcnt") + + +# NegotiateAuth +# ============================================================== +option("--disable-negotiateauth", help="Disable GSS-API negotiation") + +set_config("MOZ_AUTH_EXTENSION", True, when="--enable-negotiateauth") +set_define("MOZ_AUTH_EXTENSION", True, when="--enable-negotiateauth") + + +# Parental control +# ============================================================== +option("--disable-parental-controls", help="Do not build parental controls") + +set_config( + "MOZ_DISABLE_PARENTAL_CONTROLS", + True, + when=depends("--enable-parental-controls")(lambda x: not x), +) +set_define( + "MOZ_DISABLE_PARENTAL_CONTROLS", + True, + when=depends("--enable-parental-controls")(lambda x: not x), +) + + +# Sandboxing support +# ============================================================== +@depends(target, tsan, asan) +def sandbox_default(target, tsan, asan): + # Only enable the sandbox by default on Linux, OpenBSD, macOS, and Windows + if target.kernel == "Linux" and target.os == "GNU": + # Bug 1182565: TSan conflicts with sandboxing on Linux. + # Bug 1287971: LSan also conflicts with sandboxing on Linux. + if tsan or asan: + return False + # Linux sandbox is only available on x86{,_64} and arm{,64}. + return target.cpu in ("x86", "x86_64", "arm", "aarch64") + return target.kernel in ("WINNT", "Darwin", "OpenBSD") + + +option( + "--enable-sandbox", + default=sandbox_default, + help="{Enable|Disable} sandboxing support", +) + +set_config("MOZ_SANDBOX", True, when="--enable-sandbox") +set_define("MOZ_SANDBOX", True, when="--enable-sandbox") + +with only_when(depends(target.kernel)(lambda k: k not in ("Darwin", "WINNT"))): + set_define("MOZ_CONTENT_TEMP_DIR", True, when="--enable-sandbox") + +# Searching of system directories for extensions. +# ============================================================== +# Note: this switch is meant to be used for test builds whose behavior should +# not depend on what happens to be installed on the local machine. +option( + "--disable-system-extension-dirs", + help="Disable searching system- and account-global directories for extensions" + " of any kind; use only profile-specific extension directories", +) + +set_define("ENABLE_SYSTEM_EXTENSION_DIRS", True, when="--enable-system-extension-dirs") + + +# Pixman +# ============================================================== +with only_when(compile_environment): + system_lib_option( + "--enable-system-pixman", help="Use system pixman (located with pkgconfig)" + ) + + @depends("--enable-system-pixman") + def in_tree_pixman(pixman): + return not pixman + + set_config("MOZ_TREE_PIXMAN", True, when=in_tree_pixman) + set_define("MOZ_TREE_PIXMAN", True, when=in_tree_pixman) + + pkg_check_modules("MOZ_PIXMAN", "pixman-1 >= 0.36.0", when="--enable-system-pixman") + # Set MOZ_PIXMAN_CFLAGS to an explicit empty value when --enable-system-pixman is *not* used, + # for layout/style/extra-bindgen-flags + set_config("MOZ_PIXMAN_CFLAGS", [], when=in_tree_pixman) + + +# Universalchardet +# ============================================================== +with only_when(compile_environment): + option("--disable-universalchardet", help="Disable universal encoding detection") + + set_config("MOZ_UNIVERSALCHARDET", True, when="--enable-universalchardet") + + +# Disable zipwriter +# ============================================================== +with only_when(compile_environment): + option("--disable-zipwriter", help="Disable zipwriter component") + + set_config("MOZ_ZIPWRITER", True, when="--enable-zipwriter") + + +# Location of the mozilla user directory +# ============================================================== +with only_when(compile_environment): + + @depends(target) + def default_user_appdir(target): + if target.kernel in ("WINNT", "Darwin"): + return "Mozilla" + return ".mozilla" + + option( + "--with-user-appdir", + nargs=1, + default=default_user_appdir, + help="Set user-specific appdir", + ) + + @depends("--with-user-appdir") + def user_appdir(appdir): + if not appdir: + die("--without-user-appdir is not a valid option.") + if "/" in appdir[0]: + die("--with-user-appdir must be a single relative path.") + return '"{}"'.format(appdir[0]) + + set_define("MOZ_USER_DIR", user_appdir) + + +# Check for sin_len and sin6_len - used by SCTP; only appears in Mac/*BSD generally +# ============================================================== +with only_when(compile_environment): + have_sin_len = c_compiler.try_compile( + includes=["netinet/in.h"], + body="struct sockaddr_in x; void *foo = (void*) &x.sin_len;", + check_msg="for sin_len in struct sockaddr_in", + ) + have_sin6_len = c_compiler.try_compile( + includes=["netinet/in.h"], + body="struct sockaddr_in6 x; void *foo = (void*) &x.sin6_len;", + check_msg="for sin_len6 in struct sockaddr_in6", + ) + set_define("HAVE_SIN_LEN", have_sin_len) + set_define("HAVE_SIN6_LEN", have_sin6_len) + # HAVE_CONN_LEN must be the same as HAVE_SIN_LEN and HAVE_SIN6_LEN + set_define("HAVE_SCONN_LEN", have_sin_len & have_sin6_len) + set_define( + "HAVE_SA_LEN", + c_compiler.try_compile( + includes=["netinet/in.h"], + body="struct sockaddr x; void *foo = (void*) &x.sa_len;", + check_msg="for sa_len in struct sockaddr", + ), + ) + + +# Check for pthread_cond_timedwait_monotonic_np +# ============================================================== +with only_when(compile_environment): + set_define( + "HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC", + c_compiler.try_compile( + includes=["pthread.h"], + body="pthread_cond_timedwait_monotonic_np(0, 0, 0);", + # -Werror to catch any "implicit declaration" warning that means the function + # is not supported. + flags=["-Werror=implicit-function-declaration"], + check_msg="for pthread_cond_timedwait_monotonic_np", + ), + ) + + +# Custom dynamic linker for Android +# ============================================================== +with only_when(target_has_linux_kernel & compile_environment): + option( + env="MOZ_LINKER", + default=depends(target.os, when="--enable-jemalloc")( + lambda os: os == "Android" + ), + help="{Enable|Disable} custom dynamic linker", + ) + + set_config("MOZ_LINKER", True, when="MOZ_LINKER") + set_define("MOZ_LINKER", True, when="MOZ_LINKER") + add_old_configure_assignment("MOZ_LINKER", True, when="MOZ_LINKER") + + moz_linker = depends(when="MOZ_LINKER")(lambda: True) + + +# 32-bits ethtool_cmd.speed +# ============================================================== +with only_when(target_has_linux_kernel & compile_environment): + set_config( + "MOZ_WEBRTC_HAVE_ETHTOOL_SPEED_HI", + c_compiler.try_compile( + includes=["linux/ethtool.h"], + body="struct ethtool_cmd cmd; cmd.speed_hi = 0;", + check_msg="for 32-bits ethtool_cmd.speed", + ), + ) + +# Gamepad support +# ============================================================== +check_header( + "linux/joystick.h", + onerror=lambda: die( + "Can't find header linux/joystick.h, needed for gamepad support." + " Please install Linux kernel headers." + ), + when=target_has_linux_kernel & compile_environment, +) + + +# Smart card support +# ============================================================== +@depends(build_project) +def disable_smart_cards(build_project): + return build_project == "mobile/android" + + +set_config("MOZ_NO_SMART_CARDS", True, when=disable_smart_cards) +set_define("MOZ_NO_SMART_CARDS", True, when=disable_smart_cards) + +# Enable UniFFI fixtures +# ============================================================== +# These are used to test the uniffi-bindgen-gecko-js code generation. They +# should not be enabled in release builds. + +option( + "--enable-uniffi-fixtures", + help="Enable UniFFI Fixtures/Examples", +) + +set_config("MOZ_UNIFFI_FIXTURES", True, when="--enable-uniffi-fixtures") + +# System policies +# ============================================================== + +option( + "--disable-system-policies", + help="Disable reading policies from Windows registry, macOS's file system attributes, and /etc/firefox", +) + +set_config("MOZ_SYSTEM_POLICIES", True, when="--enable-system-policies") + +# Allow disabling the creation a legacy profile +# ============================================================== + +option( + "--disable-legacy-profile-creation", + help="Disable the creation a legacy profile, to be used by old versions " + "of Firefox, when no profiles exist.", +) + +set_config("MOZ_CREATE_LEGACY_PROFILE", True, when="--enable-legacy-profile-creation") + + +# STL wrapping +# ============================================================== +set_config("WRAP_STL_INCLUDES", True) +set_config( + "STL_FLAGS", + depends(build_environment.dist)(lambda dist: [f"-I{dist}/stl_wrappers"]), +) + + +# Perl detection +# ============================================================== +@depends(target) +def need_perl(target): + # Ideally, we'd also depend on gnu_as here, but that adds complications. + return target.cpu == "arm" + + +perl = check_prog("PERL", ("perl5", "perl"), when=need_perl) + + +@template +def perl_version_check(min_version): + @depends(perl) + @checking("for minimum required perl version >= %s" % min_version) + def get_perl_version(perl): + return Version( + check_cmd_output( + perl, + "-e", + "print $]", + onerror=lambda: die("Failed to get perl version."), + ) + ) + + @depends(get_perl_version) + def check_perl_version(version): + if version < min_version: + die("Perl %s or higher is required.", min_version) + + @depends(perl) + @checking("for full perl installation") + @imports("subprocess") + def has_full_perl_installation(perl): + ret = subprocess.call([perl, "-e", "use Config; exit(!-d $Config{archlib})"]) + return ret == 0 + + @depends(has_full_perl_installation) + def require_full_perl_installation(has_full_perl_installation): + if not has_full_perl_installation: + die( + "Cannot find Config.pm or $Config{archlib}. " + "A full perl installation is required." + ) + + +with only_when(need_perl): + perl_version_check("5.006") + + +# windows-rs as bootstrappable toolchain +# ============================================================== +# The in-tree windows crate's purpose is to avoid vendoring the +# original windows crate, which is too large. +# The ideal solution would be for cargo to allow exceptions to +# vendoring, but it doesn't. +# The adopted solution is to somehow use the crate contents from +# a directory given via the mozbuild config, or bootstrapped. +# +# Unfortunately, doing `include!(mozbuild::windows_rs_path!("src/lib.rs"))` +# in the crate's lib.rs doesn't work because of +# https://github.com/rust-lang/rust/issues/66920. +# +# Previous versions of the windows crate had submodules declared +# directly in lib.rs. Annotating each of them with +# `#[path = concat!(mozbuild::windows_rs_path!("path/to/mod.rs"))]` +# unfortunately also didn't work, because of +# https://github.com/rust-lang/rust/issues/48250. +# +# Thankfully, newer versions of the windows crate now only have an +# `include!` at the end of lib.rs, so we can get away with simply +# replacing it with an `include!` that uses `mozbuild::windows_rs_path!`. +# +# We ensure that the in-tree contents match what we expect based on +# the original crate. +# The expectations are as such: +# - Cargo.toml is identical to the original one with the addition of the +# following two lines at the end (after an empty line): +# [dependencies.mozbuild] +# version = "0.1" +# - src/lib.rs is mostly identical to the original one, with two notable +# differences: +# - the addition of `#![allow(warnings)]` on the first line, because if +# the crate had been vendored normally, it would not be affected by +# `-D warnings`, and `#![allow(warnings)]` mimicks that. +# - the replacement of any +# `include!("path/file.rs")` +# with +# `include!(mozbuild::windows_rs_path!("src/path/file.rs"))` +with only_when(target_is_windows & compile_environment): + option( + env="MOZ_WINDOWS_RS_DIR", + nargs=1, + help="Path to the source of the 'windows' Rust crate", + ) + + @depends( + "MOZ_WINDOWS_RS_DIR", + bootstrap_path( + "windows-rs", + when=depends("MOZ_WINDOWS_RS_DIR")(lambda x: not x), + ), + build_environment.topsrcdir, + ) + @checking("for the windows rust crate source") + @imports(_from="__builtin__", _import="open") + @imports("re") + @imports("toml") + def windows_rs_dir(dir, bootstrapped, topsrcdir): + if bootstrapped: + dir = bootstrapped + elif dir: + dir = dir[0] + + raw_cargo_toml = open( + os.path.join(topsrcdir, "build/rust/windows/Cargo.toml") + ).read() + cargo_toml = toml.loads(raw_cargo_toml) + expected_version = cargo_toml["package"]["version"] + + if not dir: + raise FatalCheckError( + "Cannot find the windows rust crate source.\n" + f"Try downloading it with `cargo download -x windows={expected_version}`\n" + "(you may need to `cargo install cargo-download` first)\n" + f"and set `MOZ_WINDOWS_RS_DIR` to location of the `windows-{expected_version}`" + " directory" + ) + + raw_cargo_toml_orig = open(os.path.join(dir, "Cargo.toml")).read() + cargo_toml = toml.loads(raw_cargo_toml_orig) + version = cargo_toml["package"]["version"] + if version != expected_version: + raise FatalCheckError( + f"The windows rust crate source in {dir} contains version " + f"{version}, but expected {expected_version}." + ) + # Now that we've done the basic sanity check, let's go deeper. + DEPENDENCIES = '\n[dependencies.mozbuild]\nversion = "0.1"\n' + if not raw_cargo_toml.endswith(DEPENDENCIES): + configure_error("In-tree windows crate is missing dependency on mozbuild") + if raw_cargo_toml[: -len(DEPENDENCIES)] != raw_cargo_toml_orig: + configure_error("In-tree windows crate Cargo.toml doesn't match original") + + lib_rs = open(os.path.join(topsrcdir, "build/rust/windows/src/lib.rs")).read() + lib_rs_orig = open(os.path.join(dir, "src/lib.rs")).read() + lib_rs_expected = "#![allow(warnings)]\n" + re.sub( + r'include!\("([^"]*)"\)', + r'include!(mozbuild::windows_rs_path!("src/\1"))', + lib_rs_orig, + ) + if lib_rs != lib_rs_expected: + configure_error("In-tree windows crate lib.rs doesn't match original") + + return dir + + set_config("MOZ_WINDOWS_RS_DIR", windows_rs_dir) |