Source code
Revision control
Copy as Markdown
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
# App-specific project settings
project_flag(
env="MOZ_APP_ID",
nargs=1,
help='used for application.ini\'s "ID" field, and crash reporter server url',
)
@depends("MOZ_APP_ID", build_project)
def check_moz_app_id(moz_app_id, build_project):
if not moz_app_id:
die(f"No value for MOZ_APP_ID in project '{build_project}'")
project_flag(
env="MOZ_APP_VENDOR",
nargs=1,
help='used for application.ini\'s "Vendor" field, which also impacts profile location and user-visible fields',
)
project_flag(
env="MOZ_APP_UA_NAME",
default="",
nargs=1,
help="application name in the User Agent string",
)
project_flag(
env="MOZ_DEVTOOLS",
default="server",
choices=("all", "server"),
nargs=1,
help="which devtools version should be built",
)
option(
env="MOZ_STUB_INSTALLER",
help="produce a stub installer",
)
set_config("MOZ_STUB_INSTALLER", True, when="MOZ_STUB_INSTALLER")
project_flag(
env="MOZ_PROFILE_MIGRATOR",
help="enable profile migrator",
)
project_flag(
env="BROWSER_CHROME_URL",
default="",
nargs=1,
set_as_define=True,
help="markup for a single browser window",
)
set_define(
"BROWSER_CHROME_URL_QUOTED",
depends("BROWSER_CHROME_URL")(lambda v: f'"{v[0]}"' if v else ""),
)
# External builds (specifically Ubuntu) may drop the hg repo information, so we allow to
# explicitly set the repository and changeset information in.
option(env="MOZ_SOURCE_REPO", nargs=1, help="project source repository")
set_config("MOZ_SOURCE_REPO", depends_if("MOZ_SOURCE_REPO")(lambda src: src[0]))
option(env="MOZ_SOURCE_CHANGESET", nargs=1, help="source changeset")
set_config("MOZ_SOURCE_CHANGESET", depends_if("MOZ_SOURCE_CHANGESET")(lambda v: v[0]))
option(
env="MOZ_INCLUDE_SOURCE_INFO",
# Build revisions should always be present in official builds
default=mozilla_official,
help="include build repository informations",
)
set_config("MOZ_INCLUDE_SOURCE_INFO", True, when="MOZ_INCLUDE_SOURCE_INFO")
option(
"--with-distribution-id",
nargs=1,
default="org.mozilla",
help="Set distribution-specific id",
)
set_config("MOZ_DISTRIBUTION_ID", depends("--with-distribution-id")(lambda v: v[0]))
add_old_configure_assignment(
"MOZ_DISTRIBUTION_ID", depends("--with-distribution-id")(lambda v: v[0])
)
@depends("MOZ_APP_VENDOR", build_project)
def check_moz_app_vendor(moz_app_vendor, build_project):
if not moz_app_vendor:
die(f"No value for MOZ_APP_VENDOR in project '{build_project}'")
# 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", "iOS", "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("--disable-gecko-profiler", help="Disable the Gecko profiler")
@depends("--disable-gecko-profiler", target)
def gecko_profiler(enable_gecko_profiler, target):
if not enable_gecko_profiler:
return False
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.kernel in ("Darwin", "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)
# Enable perfetto on Android if gecko profiling is enabled and only for
# nightly builds. Linux support requires at least linux-headers-3.18 for <linux/vm_sockets.h>
set_config(
"MOZ_PERFETTO", gecko_profiler_define, when=target_is_android & milestone.is_nightly
)
set_define(
"MOZ_PERFETTO", gecko_profiler_define, when=target_is_android & milestone.is_nightly
)
# 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.kernel == "Darwin":
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.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 in ("Android", "OSX", "iOS", "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 in ("Android", "OSX", "iOS", "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 in ("Android", "OSX", "iOS", "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", when=use_pkg_config
)
set_config("MOZ_AUDIOUNIT_RUST", imply_audiounit, when="--enable-audio-backends")
imply_option(
"--enable-jack", imply_jack, reason="--enable-audio-backends", when=use_pkg_config
)
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",
when=use_pkg_config,
)
imply_option(
"--enable-sndio", imply_sndio, reason="--enable-audio-backends", when=use_pkg_config
)
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.",
when=use_pkg_config,
)
@depends("--enable-alsa", when=use_pkg_config)
def enable_alsa_option(enable_alsa):
return enable_alsa
@depends(enable_alsa_option, 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.",
when=use_pkg_config,
)
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.",
when=use_pkg_config,
)
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.",
when=use_pkg_config,
)
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 == "iOS":
return ("cairo-uikit",)
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)
@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)
# 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 ("arm", "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_GECKOVIEW_HISTORY",
help="Enable Geckoview History instead of Places",
set_as_define=True,
)
# Child Process Name for IPC
# ==============================================================
@depends(toolkit, bin_suffix(target))
def moz_child_process_name(toolkit, bin_suffix):
if toolkit != "android":
return f"plugin-container{bin_suffix}"
else:
# We want to let Android unpack the file at install time, but it only
# does so if the file is named libsomething.so. The lib/ path is also
# required because the unpacked file will be under the lib/ subdirectory
# and will need to be executed from that path.
return "libplugin-container.so"
set_config("MOZ_CHILD_PROCESS_NAME", moz_child_process_name)
with only_when(target_is_osx):
set_config("MOZ_CHILD_PROCESS_BUNDLE", "plugin-container.app/Contents/MacOS/")
set_config(
"MOZ_CHILD_PROCESS_BUNDLEID",
depends("--with-distribution-id")(lambda v: f"{v[0]}.plugincontainer"),
)
set_config("MOZ_CHILD_PROCESS_BUNDLENAME", "plugin-container.app")
# Profile Management
# ==============================================================
# Selectable profiles are temporarily gated behind a build flag
option(
env="MOZ_SELECTABLE_PROFILES",
help="Enable experimental and unstable profile groups",
)
set_define("MOZ_SELECTABLE_PROFILES", True, when="MOZ_SELECTABLE_PROFILES")
set_config("MOZ_SELECTABLE_PROFILES", True, when="MOZ_SELECTABLE_PROFILES")
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_GECKOVIEW_HISTORY")
def check_places_and_geckoview_history(places, geckoview_history):
if places and geckoview_history:
die("Cannot use MOZ_GECKOVIEW_HISTORY alongside MOZ_PLACES.")
if not places and not geckoview_history:
die("One of MOZ_GECKOVIEW_HISTORY or MOZ_PLACES must be set.")
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)
# 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
# ==============================================================
@depends(target)
def printing_default(target):
return target.os != "iOS"
option(
"--disable-printing",
default=printing_default,
help="{Enable|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)",
when=use_pkg_config,
)
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:
#
# 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:
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_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 = pkg_check_modules(
"MOZ_X11",
x11_libs,
allow_missing=toolkit_gtk_x11_optional,
when=toolkit_gtk_x11,
config=False, # set after the OpenBSD hook below
)
@depends(x11, target_is_openbsd)
def moz_x11_libs(x11, target_is_openbsd):
if not x11:
return []
if target_is_openbsd:
rpath = tuple(
f"-Wl,-rpath-link,{flag[2:]}" for flag in x11.libs if flag.startswith("-L")
)
else:
rpath = ()
return x11.libs + rpath
set_config("MOZ_X11_CFLAGS", x11.cflags)
set_config("MOZ_X11_LIBS", moz_x11_libs)
set_config("MOZ_X11", True, when=x11)
set_define("MOZ_X11", True, when=x11)
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("textwrap")
def has_pack_relative_relocs(
c_compiler,
extra_toolchain_flags,
linker_ldflags,
readelf,
):
with create_temporary_file(suffix=".out") as path:
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.
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
@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
@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. "
)
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",
)