Source code

Revision control

Other Tools

# -*- 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
# Set the MOZ_CONFIGURE_OPTIONS variable with all the options that
# were passed somehow (environment, command line, mozconfig)
@imports(_from="mozbuild.shellutil", _import="quote")
@imports(_from="mozbuild.util", _import="ensure_unicode")
@imports(_from="mozbuild.util", _import="system_encoding")
@imports(_from="six", _import="itervalues")
def all_configure_options():
result = []
previous = None
for option in itervalues(__sandbox__._options):
# __sandbox__._options contains items for both 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"):
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
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 ( == "Help missing for old configure options"
and option in __sandbox__._raw_options
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)
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.
help="Enable jprof profiling tool (needs mozilla/tools/jprof)",
def jprof(value):
if value:
return True
set_config("MOZ_JPROF", jprof)
set_define("MOZ_JPROF", jprof)
imply_option("--enable-profiling", jprof)
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")
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)
# 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))
help="{Enable|Disable} Dark Matter Detector (heap profiler). "
"Also enables jemalloc, replace-malloc and profiling",
def dmd(value):
if value:
return True
set_config("MOZ_DMD", dmd)
set_define("MOZ_DMD", dmd)
add_old_configure_assignment("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)
# ALSA cubeb backend
# ==============================================================
system_lib_option("--enable-alsa", env="MOZ_ALSA", help="Enable ALSA audio backend.")
alsa = pkg_check_modules("MOZ_ALSA", "alsa", when="--enable-alsa")
set_config("MOZ_ALSA", depends_if(alsa)(lambda _: True))
set_define("MOZ_ALSA", depends_if(alsa)(lambda _: True))
# 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))
set_define("MOZ_JACK", depends_if(jack)(lambda _: True))
# PulseAudio cubeb backend
# ==============================================================
def pulseaudio_default(target):
return target.os not in ("WINNT", "OSX", "Android", "OpenBSD")
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))
# AudioUnit cubeb Rust backend
# ==============================================================
def enable_audiounit_rust(target):
return target.os == "OSX" and target.kernel == "Darwin"
set_config("MOZ_AUDIOUNIT_RUST", True, when=enable_audiounit_rust)
set_define("MOZ_AUDIOUNIT_RUST", True, when=enable_audiounit_rust)
# Javascript engine
# ==============================================================
# NodeJS
# ==============================================================
# L10N
# ==============================================================
option("--with-l10n-base", nargs=1, env="L10NBASEDIR", help="Path to l10n repositories")
@depends("--with-l10n-base", "MOZ_AUTOMATION", check_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")
path = os.path.join(
"MOZBUILD_STATE_PATH", expanduser(os.path.join("~", ".mozbuild"))
return os.path.realpath(os.path.abspath(path))
set_config("L10NBASEDIR", l10n_base)
# Default toolkit
# ==============================================================
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",)
return ("cairo-gtk3", "cairo-gtk3-wayland")
def toolkit_default(choices):
return choices[0]
help="Select default toolkit",
def full_toolkit(value):
return value[0]
def toolkit(toolkit):
if toolkit.startswith("cairo-gtk3"):
widget_toolkit = "gtk"
widget_toolkit = toolkit.replace("cairo-", "")
return widget_toolkit
set_config("MOZ_WIDGET_TOOLKIT", toolkit)
add_old_configure_assignment("MOZ_WIDGET_TOOLKIT", toolkit)
def toolkit_define(toolkit):
if toolkit != "windows":
return "MOZ_WIDGET_%s" % toolkit.upper()
set_define(toolkit_define, True)
def toolkit_gtk(toolkit):
return toolkit == "gtk"
# Wayland support
# ==============================================================
wayland_headers = pkg_check_modules(
"gtk+-wayland-3.0 >= 3.14 xkbcommon >= 0.4.1 libdrm >= 2.4",
allow_missing=depends(full_toolkit)(lambda t: t == "cairo-gtk3"),
when=depends(full_toolkit)(lambda t: t in ("cairo-gtk3", "cairo-gtk3-wayland")),
@depends(wayland_headers, toolkit_gtk, artifact_builds)
def wayland_headers(wayland, toolkit_gtk, artifacts):
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))
# GL Provider
# ==============================================================
option("--with-gl-provider", nargs=1, help="Set GL provider backend type")
def gl_provider(value):
if value:
return value[0]
def gl_provider_define(provider):
if provider:
return "GLContextProvider%s" % provider
set_define("MOZ_GL_PROVIDER", gl_provider_define)
@depends(gl_provider, wayland_headers, toolkit_gtk)
def gl_default_provider(value, wayland, toolkit_gtk):
if value:
return value
elif wayland:
return "EGL"
elif toolkit_gtk:
return "GLX"
set_config("MOZ_GL_PROVIDER", gl_provider)
set_config("MOZ_GL_DEFAULT_PROVIDER", gl_default_provider)
def gl_provider_define(provider):
if provider:
return "GL_PROVIDER_%s" % provider
set_define(gl_provider_define, True)
# PDF printing
# ==============================================================
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
add_old_configure_assignment("USE_FC_FREETYPE", fc_freetype)
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
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 >= 6.1.0", when=check_for_freetype2
@depends(fontconfig_info, freetype2_info)
def freetype2_combined_info(fontconfig_info, freetype2_info):
if not freetype2_info:
if not fontconfig_info:
return freetype2_info
return namespace(
cflags=freetype2_info.cflags + fontconfig_info.cflags,
libs=freetype2_info.libs + fontconfig_info.libs,
"_HAVE_FREETYPE2", depends_if(freetype2_info)(lambda _: True)
set_define("MOZ_HAVE_FREETYPE2", depends_if(freetype2_info)(lambda _: True))
# Apple platform decoder support
# ==============================================================
def applemedia(toolkit):
if toolkit in ("cocoa", "uikit"):
return True
set_config("MOZ_APPLEMEDIA", applemedia)
set_define("MOZ_APPLEMEDIA", applemedia)
add_old_configure_assignment("MOZ_APPLEMEDIA", applemedia)
# Windows Media Foundation support
# ==============================================================
option("--disable-wmf", help="Disable support for Windows Media Foundation")
@depends("--disable-wmf", target)
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
set_config("MOZ_WMF", wmf)
set_define("MOZ_WMF", wmf)
# 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)
imply_option("--enable-fmp4", ffmpeg, "--enable-ffmpeg")
# AV1 Video Codec Support
# ==============================================================
option("--disable-av1", help="Disable av1 video support")
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)
# Built-in fragmented MP4 support.
# ==============================================================
help="Disable support for in built Fragmented MP4 parsing",
@depends("--disable-fmp4", target, wmf, applemedia)
def fmp4(value, target, wmf, applemedia):
enabled = bool(value)
if value.origin == "default":
# target.os == 'Android' includes all B2G versions
enabled = wmf or applemedia or target.os == "Android"
if enabled:
return True
set_config("MOZ_FMP4", fmp4)
set_define("MOZ_FMP4", fmp4)
add_old_configure_assignment("MOZ_FMP4", fmp4)
def sample_type_is_s16(target):
# Use integers over floats for audio on Android regardless of the CPU
# architecture, because audio backends for Android don't support floats.
# We also use integers on ARM because it's more efficient.
if target.os == "Android" or target.cpu == "arm":
return True
def sample_type_is_float(t):
if not t:
return True
set_config("MOZ_SAMPLE_TYPE_S16", sample_type_is_s16)
set_define("MOZ_SAMPLE_TYPE_S16", sample_type_is_s16)
set_config("MOZ_SAMPLE_TYPE_FLOAT32", sample_type_is_float)
set_define("MOZ_SAMPLE_TYPE_FLOAT32", sample_type_is_float)
set_define("MOZ_VORBIS", sample_type_is_float)
set_config("MOZ_VORBIS", sample_type_is_float)
set_define("MOZ_TREMOR", sample_type_is_s16)
set_config("MOZ_TREMOR", sample_type_is_s16)
# OpenMAX IL Decoding Support
# ==============================================================
option("--enable-openmax", help="Enable OpenMAX IL for video/audio decoding")
def openmax(value):
enabled = bool(value)
if enabled:
return True
set_config("MOZ_OMX", openmax)
set_define("MOZ_OMX", openmax)
# EME Support
# ==============================================================
def eme_choices(target):
if (
target.kernel in ("WINNT", "Linux")
and target.os != "Android"
and target.cpu in ("x86", "x86_64")
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, except
# on aarch64 Windows.
@depends(build_project, eme_choices, target)
def eme_default(build_project, choices, target):
if build_project == "browser":
if target.kernel != "WINNT" or target.cpu != "aarch64":
return choices
help="{Enable|Disable} support for Encrypted Media Extensions",
@depends("--enable-eme", fmp4, when=eme_choices)
def eme(enabled, fmp4):
if enabled and enabled.origin != "default" and not fmp4:
die("Encrypted Media Extension support requires " "Fragmented MP4 support")
@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([]))
@depends(eme_modules, target, when=eme_modules)
def eme_win32_artifact(modules, target):
if "widevine" in modules and target.kernel == "WINNT" and target.cpu == "aarch64":
return True
set_config("MOZ_EME_WIN32_ARTIFACT", eme_win32_artifact)
help="Select FORMAT of chrome files during packaging.",
choices=("omni", "jar", "flat"),
def packager_format(value):
return value[0]
set_config("MOZ_PACKAGER_FORMAT", packager_format)
@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)
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)
help="Build Firefox Health Reporter Service",
help="Enable Normandy recipe runner",
project_flag("MOZ_SERVICES_SYNC", help="Build Sync Services if required")
help="Enable Android History instead of Places",
help="Enable dedicated profiles per install",
help="Block users from starting profiles last used by a newer build",
def check_places_and_android_history(places, android_history):
if places and android_history:
die("Cannot use MOZ_ANDROID_HISTORY alongside MOZ_PLACES.")
help="Enable 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
# ==============================================================
option("--enable-gpsd", env="MOZ_GPSD", help="Enable gpsd support")
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",))
check_prog("ZIP", ("zip",))
check_prog("GN", ("gn",), allow_missing=True)
# Key files
# ==============================================================
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
# ==============================================================
"--enable-webrender-debugger", help="Build the websocket debug server in WebRender"
"MOZ_WEBRENDER_DEBUGGER", depends_if("--enable-webrender-debugger")(lambda _: True)
# Additional system headers defined at the application level
# ==============================================================
help="Use additional system headers defined in $MOZ_BUILD_APP/app-system-headers.mozbuild",
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")
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
# ==============================================================
def no_speechd_on_non_gtk(toolkit):
if toolkit != "gtk":
return False
"--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")
def webspeech(value):
if value:
return True
set_config("MOZ_WEBSPEECH", webspeech)
set_define("MOZ_WEBSPEECH", webspeech)
add_old_configure_assignment("MOZ_WEBSPEECH", webspeech)
# Speech API test backend
# ==============================================================
help="{Enable|Disable} support for HTML Speech API Test Backend",
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)
# Enable IPDL's "expensive" unit tests
# ==============================================================
option("--enable-ipdl-tests", help="Enable expensive IPDL tests")
set_config("MOZ_IPDL_TESTS", depends_if("--enable-ipdl-tests")(lambda _: True))
# 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")
"--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)
add_old_configure_assignment("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, check_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)
add_old_configure_assignment("FT2_LIBS", ft2_info.libs)
add_old_configure_assignment("FT2_CFLAGS", ft2_info.cflags)
# 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:
# 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:
help="Disable support for WebDriver remote protocols",
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
"--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
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
# ========================================================
def webrtc_default(target):
# Turn off webrtc for OS's we don't handle yet, but allow
# --enable-webrtc to override.
os_match = False
for os_fragment in (
if target.raw_os.startswith(os_fragment):
os_match = True
cpu_match = False
if (
in (
or target.cpu.startswith("ppc")
cpu_match = True
if os_match and cpu_match:
return True
return False
help="{Enable|Disable} support for 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
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
# ==============================================================
set_config("MOZ_X11", True, when=toolkit_gtk)
set_define("MOZ_X11", True, when=toolkit_gtk)
@depends(webrtc, when=toolkit_gtk)
def x11_libs(webrtc):
libs = [
if webrtc:
# third_party/libwebrtc/webrtc/webrtc_gn/ adds those
# manually, ensure they're available.
libs += [
return " ".join(libs)
pkg_check_modules("MOZ_X11", x11_libs, when=toolkit_gtk)
# ASan Reporter Addon
# ==============================================================
help="Enable Address Sanitizer Reporter Extension",
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)
add_old_configure_assignment("MOZ_ASAN_REPORTER", enable_asan_reporter)
# 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", "x86", "x86_64")
@depends("--enable-release", enable_linker)
def default_elfhack(release, linker):
# Disable elfhack when explicitly building with --enable-linker=lld
if linker and linker.origin != "default" and linker[0] == "lld":
return False
return bool(release)
with only_when(has_elfhack):
help="{Enable|Disable} elf hacks",
set_config("USE_ELF_HACK", depends_if("--enable-elf-hack")(lambda _: True))
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
# ==============================================================
help="Prevent suspected or confirmed proxy bypasses",
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
# ==============================================================
help="Disable direct failover for system requests",
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)
# ==============================================================
@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":
if compile_environment:
return True
midl = check_prog(
"MIDL", midl_names, when=check_for_midl, allow_missing=True, paths=sdk_bin_path
option(env="MIDL_FLAGS", nargs=1, help="Extra flags to pass to MIDL")
when=depends(midl, target)(lambda m, t: m and t.kernel == "WINNT"),
def midl_flags(flags, c_compiler, target, host, midl):
if flags:
flags = flags[0].split()
flags = []
if not midl.endswith("widl"):
env = {
"x86": "win32",
"x86_64": "x64",
"aarch64": "arm64",
flags += ["-env", env]
if host.os == "WINNT":
return flags + ["-cpp_cmd", c_compiler.compiler]
# If cross-compiling and using midl instead of widl, for now, we'll
# assume we can find the Windows version of clang-cl in the PATH.
# It is required because while Wine is able to spawn Linux
# processes from Windows programs(!), the calling program doesn't
# have access to the process output and can't wait for it to
# finish. Midl runs clang-cl as a preprocessor and expects to read
# its output...
clang_cl_exe = find_program("clang-cl.exe")
if not clang_cl_exe:
die("Cannot find clang-cl.exe")
return flags + ["-cpp_cmd", clang_cl_exe]
# widl
return flags + {
"x86": ["--win32", "-m32"],
"x86_64": ["--win64", "-m64"],
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:
if check_for_midl and not midl:
if c_compiler and c_compiler.type in ("gcc", "clang"):
"You have accessibility enabled, but widl could not be found. "
"Add --disable-accessibility to your mozconfig or install widl. "
"MIDL could not be found. "
"Building accessibility without MIDL is not supported."
return enabled
set_config("ACCESSIBILITY", accessibility)
set_define("ACCESSIBILITY", accessibility)
add_old_configure_assignment("ACCESSIBILITY", accessibility)
# Addon signing
# ==============================================================
def require_signing(milestone):
return milestone.is_release_or_beta and not milestone.is_esr
help="Enforce that add-ons are signed by the trusted root",
choices=("app", "system"),
help="Addon scopes where signature is not required",
def unsigned_addon_scopes(scopes):
return namespace(
app="app" in scopes or None,
system="system" in scopes or None,
set_config("MOZ_UNSIGNED_SYSTEM_SCOPE", unsigned_addon_scopes.system)
# Addon sideloading
# ==============================================================
help="Addon sideloading is allowed",
set_config("MOZ_ALLOW_ADDON_SIDELOAD", True, when="--allow-addon-sideload")
# WebExtensions API WebIDL bindings
# ==============================================================
def extensions_webidl_bindings_default(milestone):
# Only enable the webidl bindings for the WebExtensions APIs
# in Nightly.
return milestone.is_nightly
help="{Enable|Disable} building experimental WebExtensions WebIDL bindings",
def extensions_webidl_enabled(value):
return bool(value)
set_config("MOZ_WEBEXT_WEBIDL_ENABLED", extensions_webidl_enabled)
# Launcher process (Windows only)
# ==============================================================
def launcher_process_default(target):
return target.os == "WINNT"
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":
if target.os != "WINNT":
return compile_environment
llvm_dlltool = check_prog(
@depends(target, when=llvm_dlltool)
def llvm_dlltool_flags(target):
arch = {
"x86": "i386",
"x86_64": "i386:x86-64",
"aarch64": "arm64",
return ["-m", arch]
set_config("LLVM_DLLTOOL_FLAGS", llvm_dlltool_flags)
# BITS download (Windows only)
# ==============================================================
help="{Enable|Disable} building BITS download support",
depends_if("--enable-bits-download", when=target_is_windows)(lambda _: True),
depends_if("--enable-bits-download", when=target_is_windows)(lambda _: True),
# Bundled fonts on desktop platform
# ==============================================================
def bundled_fonts_default(target):
return target.os == "WINNT" or target.kernel == "Linux"
def allow_bundled_fonts(project):
return project == "browser" or project == "comm/mail"
help="{Enable|Disable} support for bundled fonts on desktop platforms",
depends_if("--enable-bundled-fonts", when=allow_bundled_fonts)(lambda _: True),
# Reflow counting
# ==============================================================
def reflow_perf(debug):
if debug:
return True
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
# ==============================================================
def layout_debugger(debug):
if debug:
return True
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.exe", "fxc2.exe"),
when=depends(target)(lambda t: t.kernel == "WINNT"),
# ===
with only_when(compile_environment):
"--with-system-libvpx", help="Use system libvpx (located with pkgconfig)"
with only_when("--with-system-libvpx"):
vpx = pkg_check_modules("MOZ_LIBVPX", "vpx >= 1.8.0")
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."
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:
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")
# Building with -mfpu=neon requires either the "softfp" or the
# "hardfp" ABI. Depending on the compiler's default target, and the
# CFLAGS, the default ABI might be neither, in which case it is the
# "softfloat" ABI.
# The "softfloat" ABI is binary-compatible with the "softfp" ABI, so
# we can safely mix code built with both ABIs. So, if we detect
# that compiling uses the "softfloat" ABI, force the use of the
# "softfp" ABI instead.
# Confusingly, the __SOFTFP__ preprocessor variable indicates the
# "softfloat" ABI, not the "softfp" ABI.
# Note: VPX_ASFLAGS is also used in CFLAGS.
softfp = cxx_compiler.try_compile(
#ifndef __SOFTFP__
#error "compiler target supports -mfpu=neon, so we don't have to add extra flags"
@depends(in_tree_vpx, vpx_nasm, softfp, target)
def vpx_as_flags(vpx, vpx_nasm, softfp, target):
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.
flags = ["-march=armv7-a", "-mfpu=neon"]
if softfp:
elif vpx and vpx_nasm and target.os != "WINNT" and target.cpu != "x86_64":
flags = ["-DPIC"]
return flags
set_config("VPX_USE_NASM", True, when=vpx_nasm)
set_config("VPX_ASFLAGS", vpx_as_flags)
# ====
with only_when(compile_environment):
help="Use system libjpeg (installed at given prefix)",
def jpeg_flags(value):
if len(value):
return namespace(
cflags=("-I%s/include" % value[0],),
ldflags=("-L%s/lib" % value[0], "-ljpeg"),
return namespace(
with only_when("--with-system-jpeg"):
onerror=lambda: die(
"--with-system-jpeg requested but symbol "
"jpeg_destroy_compress not found."