author Ryan VanderMeulen <>
Wed, 05 Jul 2017 12:58:39 -0400
changeset 416074 11755fd63168581e194258d04bb6a7337779ec78
parent 415763 31e471d5b2896cbbfddb0025fb872532cf841bc4
child 416177 3c0fd2f12ad95ec4b453f917466c6f5e8d33c0cc
permissions -rw-r--r--
Backed out changeset 261d61f4eeec (bug 1356701) for causing bug 1378339.

# -*- 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

# Profiling
# ==============================================================
# Some of the options here imply an option from js/moz.configure,
# so, need to be declared before the include.

option('--enable-jprof', env='MOZ_JPROF',
       help='Enable jprof profiling tool (needs mozilla/tools/jprof)')

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')
    elif target.kernel == 'Linux':
        return target.cpu in ('x86', '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)

option('--enable-dmd', env='MOZ_DMD',
       help='Enable 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)
imply_option('--enable-replace-malloc', dmd)

# JACK cubeb backend
# ==============================================================
option('--enable-jack', env='MOZ_JACK',
       help='Enable JACK audio backend.')

def jack(value):
    if value:
        return True

set_config('MOZ_JACK', jack)
set_define('MOZ_JACK', jack)

# Javascript engine
# ==============================================================

# Rust
# ==============================================================

# L10N
# ==============================================================
option('--with-l10n-base', nargs=1, env='L10NBASEDIR',
       help='Path to l10n repositories')

@imports(_from='os.path', _import='isdir')
def l10n_base(value):
    if value:
        path = value[0]
        if not isdir(path):
            die("Invalid value --with-l10n-base, %s doesn't exist", path)
        return os.path.realpath(os.path.abspath(path))

set_config('L10NBASEDIR', l10n_base)

# Default toolkit
# ==============================================================
# Normally, we'd want to use the `default` field on the option, but that
# requires --target to be resolved at --help time, which requires to run
# config.guess, which we want to avoid. Even better, we could actually set
# `choices` depending on the target, but that doesn't pan out for the same
# reason.
option('--enable-default-toolkit', nargs=1,
       choices=('cairo-windows', 'cairo-gtk3', 'cairo-gtk3-wayland',
                'cairo-cocoa', 'cairo-uikit', 'cairo-android'),
       help='Select default toolkit')

@depends('--enable-default-toolkit', target, '--help')
def toolkit(value, target, _):
    # Define possible choices for each platform. The default is the first one
    # listed when there are several.
    os = target.os
    if target.os == 'WINNT':
        platform_choices = ('cairo-windows',)
    elif target.os == 'OSX':
        platform_choices = ('cairo-cocoa',)
    elif target.os == 'iOS':
        platform_choices = ('cairo-uikit',)
    elif target.os == 'Android':
        if value.origin == 'implied':
            # Trust values coming from imply_option() (used in
            # b2g/moz.configure).
            platform_choices = tuple(value)
            platform_choices = ('cairo-android',)
        platform_choices = ('cairo-gtk3', 'cairo-gtk3-wayland')

    if value:
        if value[0] not in platform_choices:
            die('`%s` is not a valid value for --enable-default-toolkit on %s\n'
                'Valid values: %s', value[0], os, ', '.join(platform_choices))
        return value[0]

    return platform_choices[0]

def wayland(toolkit):
    return toolkit == 'cairo-gtk3-wayland'

def toolkit(toolkit):
    if toolkit == 'cairo-gtk2-x11':
        widget_toolkit = 'gtk2'
    elif toolkit == 'cairo-gtk3-wayland' :
        widget_toolkit = 'gtk3'
        widget_toolkit = toolkit.replace('cairo-', '')
    return widget_toolkit

set_config('MOZ_WIDGET_TOOLKIT', toolkit)
add_old_configure_assignment('MOZ_WIDGET_TOOLKIT', toolkit)

def toolkit_gtk(toolkit):
    if toolkit == 'gtk2':
        return '2'
    elif toolkit == 'gtk3':
        return '3'

set_define('MOZ_WIDGET_GTK', toolkit_gtk)

def toolkit_define(toolkit):
    if toolkit not in ('gtk2', 'gtk3', 'windows'):
        return 'MOZ_WIDGET_%s' % toolkit.upper()

set_define(toolkit_define, True)

option('--without-x', env='WITHOUT_X', help='Disable X11 support')

@depends('--without-x', toolkit)
def x11(value, toolkit):
    if not value:
        die('--without-x is not supported')

    x11_toolkits = ('gtk2', 'gtk3')
    if value and value.origin != 'default' and toolkit not in x11_toolkits:
        die('--with-x is only valid with --enable-default-toolkit={%s}',

    return True if value and toolkit in x11_toolkits else None

set_config('MOZ_ENABLE_XREMOTE', x11)
set_define('MOZ_ENABLE_XREMOTE', x11)
set_config('MOZ_X11', x11)
set_define('MOZ_X11', x11)
add_old_configure_assignment('MOZ_X11', x11)

# Wayland support
# ==============================================================
wayland_headers = pkg_check_modules('MOZ_WAYLAND', 'gtk+-wayland-3.0 >= 3.22',

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, x11)
def gl_default_provider(value, x11):
    if value:
        return value
    elif x11:
        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', 'gtk2', 'gtk3', 'android'):
        return True

def pdf_surface_feature(pdf_printing):
    if pdf_printing:
        return '#define CAIRO_HAS_PDF_SURFACE 1'
        # CONFIGURE_SUBST_FILES need explicit empty values.
        return ''

set_config('MOZ_PDF_PRINTING', pdf_printing)
set_config('PDF_SURFACE_FEATURE', pdf_surface_feature)

# Event loop instrumentation
# ==============================================================
       help='Force-enable event loop instrumentation')

@depends('MOZ_INSTRUMENT_EVENT_LOOP', toolkit)
def instrument_event_loop(value, toolkit):
    if value or (toolkit in ('windows', 'gtk2', 'gtk3', '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
# ==============================================================
       help='Force-enable the use of fontconfig freetype')

@depends('USE_FC_FREETYPE', toolkit)
def fc_freetype(value, toolkit):
    if value or (toolkit in ('gtk2', 'gtk3') and
                 value.origin == 'default'):
        return True

add_old_configure_assignment('USE_FC_FREETYPE', fc_freetype)

# Pango
# ==============================================================
                  'pango >= 1.22.0 pangoft2 >= 1.22.0 pangocairo >= 1.22.0',

# Fontconfig
# ==============================================================
fontconfig_info = pkg_check_modules('_FONTCONFIG', 'fontconfig >= 2.7.0',

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',

@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,

                             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
# ==============================================================
       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
# ==============================================================
       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')

# Libaom AV1 Video Codec Support
# ==============================================================
        help='Enable libaom for av1 video support')

@depends('--enable-av1', target, milestone)
def av1(value, target, milestone):
    enabled = bool(value)
    if value.origin == 'default' and milestone.is_nightly:
        enabled = target.os != 'Android'
    if enabled:
        return True

set_config('MOZ_AV1', av1)
set_define('MOZ_AV1', av1)

# Built-in fragmented MP4 support.
# ==============================================================
option('--disable-fmp4', env='MOZ_FMP4',
       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)

# EME Support
# ==============================================================
# Widevine is enabled by default in desktop browser builds.
@depends(build_project, '--help')
def eme_default(build_project, help):
    if build_project == 'browser':
        return 'widevine'

       help='Enable support for Encrypted Media Extensions')

@depends('--enable-eme', target)
def enable_eme(value, target):
    # Widevine EME by default enabled on desktop Windows, MacOS and Linux,
    # x86 and x64 builds.
    if (target.kernel in ('Darwin', 'WINNT', 'Linux') and
        target.os not in ('Android', 'iOS') and
        target.cpu in ('x86', 'x86_64')):
        return value
    elif value and value.origin != 'default':
        die('%s is not supported on %s' % (value.format('--enable-eme'), target.alias))
    # Return the same type of OptionValue (Positive or Negative), with an empty tuple.
    return value.__class__(())

@depends(enable_eme, fmp4)
def eme(value, fmp4):
    enabled = bool(value)
    if value.origin == 'default':
        enabled = enabled or fmp4
    if enabled and not fmp4:
        die('Encrypted Media Extension support requires '
            'Fragmented MP4 support')
    if enabled:
        return True

def eme_modules(value):
    return value

set_config('MOZ_EME_MODULES', eme_modules)

       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), and necessitates some contortions during
    # packaging so that the resources in the omnijar are considered
    # as rooted at / and not as rooted at assets/ (which again is
    # not the case on desktop: there are omnijars rooted at webrtc/,
    # etc). handles changing the rooting of the single
    # omnijar.
    return 'assets/omni.ja' if toolkit == 'android' else 'omni.ja'

set_config('OMNIJAR_NAME', omnijar_name)

             help='Build Places if required',

             help='Build SocialAPI if required',

             help='Build Firefox Health Reporter Service',

             help='Build Sync Services if required')

             help='Enable Android History instead of Places',

             help='Allow legacy browser extensions',
             default=True, set_as_define=True)

       help='Enable Photon UI animations',

def photon_animations(value):
    if value:
        return bool(value)

set_config('MOZ_PHOTON_ANIMATIONS', photon_animations)
set_define('MOZ_PHOTON_ANIMATIONS', photon_animations)

       help='Enable Photon theme',

def photon_theme(value):
    if value:
        return bool(value)

set_config('MOZ_PHOTON_THEME', photon_theme)
set_define('MOZ_PHOTON_THEME', photon_theme)

def check_places_and_android_history(places, android_history):
    if places and android_history:
        die('Cannot use MOZ_ANDROID_HISTORY alongside MOZ_PLACES.')

# Permissions system
# ==============================================================
       help='Disable permissions (popup and cookie blocking)')

moz_permissions = depends_if('--disable-permissions')(lambda _: True)

set_config('MOZ_PERMISSIONS', moz_permissions)
set_define('MOZ_PERMISSIONS', moz_permissions)

# 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',

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',))

# Key files
# ==============================================================

simple_keyfile('Mozilla API')

simple_keyfile('Google API')

id_and_secret_keyfile('Bing API')

simple_keyfile('Adjust SDK')

id_and_secret_keyfile('Leanplum SDK')

# Servo integration
# ==============================================================
option('--enable-stylo', nargs='?', choices=('build',),
       help='Include Stylo in the build and/or enable it at runtime')

@depends('--enable-stylo', '--help')
def stylo_config(value, _):
    build_stylo = None
    enable_stylo = None

    # The default is to not build Stylo at all.
    if value.origin == 'default':
    elif len(value) and value[0] == 'build':
        build_stylo = True
    elif bool(value):
        build_stylo = True
        enable_stylo = True

    return namespace(
        build = build_stylo,
        enable = enable_stylo,

       help='Disable build-time bindgen for Stylo')

@depends(stylo_config, '--enable-stylo-build-bindgen', '--enable-compile-environment')
def building_stylo_bindgen(stylo_config, bindgen_enabled, compile_environment):
    if not compile_environment:
        return False
    if not bindgen_enabled:
        return False

# We support setting up the appropriate options for Stylo's build-time
# bindings generation via setting LLVM_CONFIG or by providing explicit
# configure options.  The Windows installer of LLVM/Clang doesn't provide
# llvm-config, so we need both methods to support all of our tier-1
# platforms.
def llvm_config_paths():
    llvm_config_progs = [

    # Also add in the location to which `mach bootstrap` installs clang.
    mozbuild_state_dir = os.environ.get('MOZBUILD_STATE_PATH',
                                        os.path.expanduser(os.path.join('~', '.mozbuild')))
    bootstrap_llvm_config = os.path.join(mozbuild_state_dir, 'clang', 'bin', 'llvm-config')


    return llvm_config_progs

llvm_config = check_prog('LLVM_CONFIG', llvm_config_paths,
                         what='llvm-config', allow_missing=True)

with only_when(building_stylo_bindgen):
    option('--with-libclang-path', nargs=1,
           help='Absolute path to a directory containing Clang/LLVM libraries for Stylo (version 3.9.x or above)')
    option('--with-clang-path', nargs=1,
           help='Absolute path to a Clang binary for Stylo bindgen (version 3.9.x or above)')

    def invoke_llvm_config(llvm_config, *options):
        '''Invoke llvm_config with the given options and return the first line of
        lines = check_cmd_output(llvm_config, *options).splitlines()
        return lines[0]

    @imports(_from='textwrap', _import='dedent')
    def check_minimum_llvm_config_version(llvm_config):
        version = Version(invoke_llvm_config(llvm_config, '--version'))
        min_version = Version('3.9.0')
        if version < min_version:
            llvm installation {} is incompatible with Stylo bindgen.

            To compile Stylo, please install version {} or greater of
            Clang + LLVM and ensure that the 'llvm-config' from that
            installation is first on your path.

            You can verify this by typing 'llvm-config --version'.
            '''.format(version, min_version)))

    @depends(llvm_config, '--with-libclang-path', '--with-clang-path',
             host_library_name_info, host)
    @imports(_from='textwrap', _import='dedent')
    def bindgen_config_paths(llvm_config, libclang_path, clang_path,
                             library_name_info, host):
        def search_for_libclang(path):
            # Try to ensure that the clang shared library that bindgen is going
            # to look for is actually present.  The files that we search for
            # mirror the logic in clang-sys/
            libclang_choices = []
            if host.os == 'WINNT':
            libclang_choices.append('%sclang%s' % (library_name_info.dll.prefix,
            if host.kernel == 'Linux':

            # At least one of the choices must be found.
            for choice in libclang_choices:
                libclang = os.path.join(path, choice)
                if os.path.exists(libclang):
                    return (True, None)
                return (False, list(set(libclang_choices)))

        if not libclang_path and not clang_path:
            # We must have LLVM_CONFIG in this case.
            if not llvm_config:
                Could not find LLVM/Clang installation for compiling stylo build-time
                bindgen.  Please specify the 'LLVM_CONFIG' environment variable
                (recommended), pass the '--with-libclang-path' and '--with-clang-path'
                options to configure, or put 'llvm-config' in your PATH.  Altering your
                PATH may expose 'clang' as well, potentially altering your compiler,
                which may not be what you intended.'''))

            libclang_arg = '--bindir' if host.os == 'WINNT' else '--libdir'
            libclang_path = invoke_llvm_config(llvm_config, libclang_arg)
            clang_path = os.path.join(invoke_llvm_config(llvm_config, '--bindir'),
            libclang_path = normsep(libclang_path)
            clang_path = normsep(clang_path)

            # Debian-based distros, at least, can have llvm-config installed
            # but not have other packages installed.  Since the user is trying
            # to use their system packages, we can't be more specific about what
            # they need.
            if not os.path.exists(libclang_path):
                The directory {} returned by `llvm-config {}` does not exist.
                Please check your system configuration.
                '''.format(libclang_path, libclang_arg)))

            (found, searched) = search_for_libclang(libclang_path)
            if not found:
                Could not find the clang shared library in the path {}
                returned by `llvm-config {}` (searched for files {}).
                Please check your system configuration.
                '''.format(libclang_path, libclang_arg, searched)))

            clang_resolved = find_program(clang_path)
            if not clang_resolved:
                The file {} returned by `llvm-config {}` does not exist.
                Please check your system configuration.
                '''.format(clang_path, '--bindir')))

            return namespace(

        if (not libclang_path and clang_path) or \
           (libclang_path and not clang_path):
            You must provide both of --with-libclang-path and --with-clang-path
            or neither of them.'''))

        libclang_path = libclang_path[0]
        clang_path = clang_path[0]

        if not os.path.exists(libclang_path) or \
           not os.path.isdir(libclang_path):
            The argument to --with-libclang-path is not a directory: {}

        (found, searched) = search_for_libclang(libclang_path)
        if not found:
            Could not find the clang shared library in the path {}
            specified by --with-libclang-path (searched for files {}).
            '''.format(libclang_path, searched)))

        clang_resolved = find_program(clang_path)
        if not clang_resolved:
            The argument to --with-clang-path is not a file: {}

        return namespace(

    set_config('MOZ_LIBCLANG_PATH', bindgen_config_paths.libclang_path)
    set_config('MOZ_CLANG_PATH', bindgen_config_paths.clang_path)
    set_config('MOZ_STYLO_BINDGEN', depends_if('--enable-stylo-build-bindgen')(lambda _: True))

set_config('MOZ_STYLO_ENABLE', stylo_config.enable)
set_define('MOZ_STYLO_ENABLE', stylo_config.enable)

option('--with-servo', env='SERVO_TARGET_DIR', nargs=1,
       help='Absolute path of the target directory where libgeckoservo can '
            'be found. This is generally servo_src_dir/target/release.')

def servo_target_dir(value):
    return value[0]

set_config('SERVO_TARGET_DIR', servo_target_dir)

# WebRender integration
option('--enable-webrender', nargs='?', choices=('build',),
       help='Include WebRender in the build and/or enable it at runtime')

@depends('--enable-webrender', milestone)
def webrender(value, milestone):
    build_webrender = None
    enable_webrender = None

    if value.origin == 'default':
        # if nothing is specified, default to just building on Nightly
        build_webrender = milestone.is_nightly
    elif value == 'build':
        # if explicitly set to 'build', then we build but don't enable
        build_webrender = True
    elif bool(value):
        # if set to true, then build and enable
        build_webrender = True
        enable_webrender = True

    # in all other cases, don't build it or enable it (defaults are fine)
    return namespace(
        build = build_webrender,
        enable = enable_webrender,

set_config('MOZ_ENABLE_WEBRENDER', webrender.enable)

# SIMD acceleration for Rust code (currently just encoding_rs)

option('--enable-rust-simd', env='MOZ_RUST_SIMD',
       help='Enable explicit SIMD in Rust code.')

@depends('--enable-rust-simd', target)
def rust_simd(value, target):
    # As of 2017-06-13, the simd crate only works on aarch64,
    # x86 and x86_64. It's meant to work on 32-bit ARM, too,
    # but currently does not.
    if target.cpu in ('aarch64', 'x86', 'x86_64') and value:
        return True

set_config('MOZ_RUST_SIMD', rust_simd)
set_define('MOZ_RUST_SIMD', rust_simd)

# Printing
# ==============================================================
def ios_disable_printing(target):
    if target.os == 'iOS':
        return False

imply_option('--enable-printing', ios_disable_printing, reason='--target')

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 not in ('gtk2', 'gtk3'):
        return False

imply_option('--enable-synth-speechd', no_speechd_on_non_gtk,

option('--disable-synth-speechd', help='Disable speech-dispatcher support')

           depends_if('--disable-synth-speechd')(lambda _: True))

# Speech API
# ==============================================================
option('--disable-webspeech', help='Disable support for HTML Speech API')

@depends('--disable-webspeech', '--help')
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 pocketsphinx backend
# ==============================================================
@depends(build_project, milestone, webspeech)
def webspeech_pocketsphinx(build_project, milestone, webspeech):
    if webspeech and milestone.is_nightly and build_project == 'b2g':
        return True

set_config('MOZ_WEBSPEECH_POCKETSPHINX', webspeech_pocketsphinx)
set_define('MOZ_WEBSPEECH_POCKETSPHINX', webspeech_pocketsphinx)

# Speech API models
# ==============================================================
@depends(build_project, milestone, webspeech)
def webspeech_models(build_project, milestone, webspeech):
    if webspeech and milestone.is_nightly and build_project == 'b2g':
        return True

set_config('MOZ_WEBSPEECH_MODELS', webspeech_models)
set_define('MOZ_WEBSPEECH_MODELS', webspeech_models)

# Speech API test backend
# ==============================================================
option('--enable-webspeechtestbackend', default=webspeech,
       help='Enable 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')

           depends_if('--enable-ipdl-tests')(lambda _: True))


# Network protocol support
# ==============================================================
@depends(check_build_environment, toolkit_gtk, '--help')
@imports(_from='__builtin__', _import='sorted')
def all_necko_protocols(build_env, toolkit_gtk, _):
    basedir = os.path.join(build_env.topsrcdir, 'netwerk', 'protocol')
    return tuple(sorted(p for p in os.listdir(basedir)
                        if (os.path.isdir(os.path.join(basedir, p)) and
                            (p != 'gio' or toolkit_gtk))))

default_necko_protocols = all_necko_protocols

@deprecated_option('--enable-necko-protocols', nargs='*')
def necko_protocols(protocols):
    return protocols

@depends(necko_protocols, default_necko_protocols)
def necko_protocols(protocols, default_protocols):
    if protocols is None or (protocols and len(protocols) == 0):
        return None
    if len(protocols) == 1 and protocols[0] == '':
        return False
    result = set()
    for p in protocols:
        if p in ('yes', 'all', 'default'):
            result |= set(default_protocols)
        if p in ('no', 'none'):
            result = set()
        if p.startswith('-'):
            if p[1:] in result:
    if result != set(default_protocols):
        return tuple(result)

imply_option('--enable-network-protocols', necko_protocols,

option('--enable-network-protocols', nargs='+', default=default_necko_protocols,
       help='Enable/disable specific protocol handlers')

def necko_protocol_defines(protocols):
    return tuple('NECKO_PROTOCOL_%s' % p for p in protocols)

add_old_configure_assignment('_NON_GLOBAL_ACDEFINES', necko_protocol_defines)

def set_necko_protocol_defines(protocols):
    for p in protocols:
        __sandbox__.set_define_impl(p, True)

@imports(_from='__builtin__', _import='sorted')
def necko_protocols(protocols):
    return tuple(sorted(protocols))

set_config('NECKO_PROTOCOLS', necko_protocols)
add_old_configure_assignment('NECKO_PROTOCOLS', necko_protocols)

# Graphics
# ==============================================================
option('--disable-skia', help='Disable use of Skia')

def skia(value):
    if not value:
        die('--disable-skia is not supported anymore')
        return True

set_config('MOZ_ENABLE_SKIA', skia)
set_define('MOZ_ENABLE_SKIA', skia)
set_define('USE_SKIA', skia)

@depends(skia, target)
def skia_android(skia, target):
    if skia and target.os == 'Android':
        return True

set_define('SK_BUILD_FOR_ANDROID_NDK', skia_android)

option('--disable-skia-gpu', help='Disable use of Skia-GPU')

@depends('--disable-skia-gpu', skia, target)
def skia_gpu(value, skia, target):
    if value.origin == 'default':
        if not skia:
            return None
        # Skia GPU support may not reliably build on certain *BSDs (see bug 1234494)
        if target.os in ('NetBSD', 'OpenBSD'):
            return None
    elif value and not skia:
        die('Cannot enable Skia-GPU without enabling Skia')
    if skia and value:
        return True

set_config('MOZ_ENABLE_SKIA_GPU', skia_gpu)
set_define('USE_SKIA_GPU', skia_gpu)

option('--enable-skia-pdf', help='Enable Skia PDF')

@depends('--enable-skia-pdf', skia, milestone)
def skia_pdf(value, skia, milestone):
    if value.origin == 'default':
        if not skia:
            return None
        if milestone.is_nightly:
            return True
    elif value and not skia:
        die('Cannot enable Skia PDF without enabling Skia')
    if skia and value:
        return True

set_config('MOZ_ENABLE_SKIA_PDF', skia_pdf)
set_define('MOZ_ENABLE_SKIA_PDF', skia_pdf)

option('--enable-skia-pdf-sfntly', help='Enable SFNTLY font subsetting in Skia PDF')

@depends('--enable-skia-pdf-sfntly', skia_pdf)
def skia_pdf_sfntly(value, skia_pdf):
    if value.origin == 'default':
        return skia_pdf
    if value and not skia_pdf:
        die('Cannot enable SFNTLY subsetting without enabling Skia PDF')
    if skia_pdf and value:
        return True

set_config('MOZ_ENABLE_SKIA_PDF_SFNTLY', skia_pdf_sfntly)
set_define('MOZ_ENABLE_SKIA_PDF_SFNTLY', skia_pdf_sfntly)

def sfntly_includes(skia_pdf_sfntly):
    includes = []
    if skia_pdf_sfntly:
        includes += [
    return includes

set_config('SFNTLY_INCLUDES', sfntly_includes)

@depends(skia, skia_gpu)
def skia_includes(skia, skia_gpu):
    includes = []
    if skia:
        includes += [

    if skia_gpu:
        includes += [

    return includes

set_config('SKIA_INCLUDES', skia_includes)

# Build Freetype in the tree
# ==============================================================
@depends(target, 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,),
    if freetype2_combined_info:
        return freetype2_combined_info

set_config('FT2_LIBS', ft2_info.libs)

# Mortar
# ==============================================================
option('--enable-mortar', help='Enable mortar extension')

set_config('MOZ_MORTAR', True, when='--enable-mortar')

# Marionette remote protocol
# ==============================================================
# Marionette is the Gecko remote protocol used for various remote control,
# automation, and testing purposes throughout Gecko, Firefox, and Fennec.
# Marionette lives in ../testing/marionette.
# Marionette is not really a toolkit feature, as much as a Gecko engine
# feature.  But it is enabled based on the toolkit (and target), so here
# it lives.
# It also backs ../testing/geckodriver, which is Mozilla's WebDriver
# implementation.
# For more information, see

def marionette(target):
    """Enable Marionette by default, except on Android."""
    if target.os != 'Android':
        return True

imply_option('--enable-marionette', marionette, reason='Not Android')

       help='Enable Marionette remote protocol')

def marionette(value):
    if value:
        return True

set_config('ENABLE_MARIONETTE', marionette)

# geckodriver WebDriver implementation
# ==============================================================
option('--enable-geckodriver', help='Enable WebDriver implementation')

def geckodriver(enable, automation, compile_env, cross_compile, hazard, target):
    geckodriver is implied on supported platforms when MOZ_AUTOMATION
    is set, but we also provide the --enable-geckodriver option for
    developers to use.

    At the present time, we want individual developers to be able to
    opt-in to building geckodriver locally, and for it to be enabled by
    default on supported CI build platforms.
    if enable:
        if not compile_env:
            die("--enable-geckodriver is not available without a compile "
                "environment. A geckodriver binary will be downloaded during "
                "an artifact build by default where available.")
        return True

    if enable.origin == 'default':
        linux32 = target.kernel == 'Linux' and target.cpu == 'x86'
        broken_platforms = cross_compile or linux32 or hazard

        if automation and compile_env and not broken_platforms:
            return True

set_config('ENABLE_GECKODRIVER', geckodriver)