author Dão Gottwald <>
Wed, 20 Feb 2019 07:20:52 +0000
changeset 516104 b9fe883c6c1eb27d2e16aceba083b8081ec6f944
parent 515570 bb2895bfd1bc3d83c309e904dbe74e0c60c3fac9
child 516667 5f7e5c3ca87dcfdea30bfd83c968e656a0022d2f
permissions -rwxr-xr-x
Bug 1504766 - Let explicit Dark and Light themes ignore the Windows 10 setting for accent color in title bars. r=ntim,Gijs a=lizzard Differential Revision:

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


# Note:
# - Gecko-specific options and rules should go in toolkit/moz.configure.
# - Firefox-specific options and rules should go in browser/moz.configure.
# - Fennec-specific options and rules should go in
#   mobile/android/moz.configure.
# - Spidermonkey-specific options and rules should go in js/moz.configure.
# - etc.

option('--enable-artifact-builds', env='MOZ_ARTIFACT_BUILDS',
       help='Download and use prebuilt binary artifacts.')

def artifact_builds(value):
    if value:
        return True

set_config('MOZ_ARTIFACT_BUILDS', artifact_builds)

             depends(artifact_builds)(lambda v: False if v is None else None),

       help='Download symbols when artifact builds are enabled.')

           depends_if('--enable-artifact-build-symbols')(lambda _: True))

def imply_disable_compile_environment(value):
    if value:
        return False

    help='For builds that do not support symbols in the normal fashion,'
         ' generate and copy them into the resulting build archive.')

set_config('MOZ_COPY_PDBS', depends_if('MOZ_COPY_PDBS')(lambda _: True))

imply_option('--enable-compile-environment', imply_disable_compile_environment)

       help='Disable compiler/library checks')

def compile_environment(compile_env):
    if compile_env:
        return True

set_config('COMPILE_ENVIRONMENT', compile_environment)
add_old_configure_assignment('COMPILE_ENVIRONMENT', compile_environment)

          help='Do not build test libraries & programs')

def enable_tests(value):
    if value:
        return True

set_config('ENABLE_TESTS', enable_tests)
set_define('ENABLE_TESTS', enable_tests)

def gtest_has_rtti(value):
    if value:
        return '0'

set_define('GTEST_HAS_RTTI', gtest_has_rtti)

@depends(target, enable_tests)
def linux_gtest_defines(target, enable_tests):
    if enable_tests and target.os == 'Android':
        return namespace(os_linux_android=True,


          help='Enable building with developer debug info '
               '(using the given compiler flags).')

def moz_debug(debug):
    if debug:
        return bool(debug)

set_config('MOZ_DEBUG', moz_debug)
set_define('MOZ_DEBUG', moz_debug)
# Override any value MOZ_DEBUG may have from the environment when passing it
# down to old-configure.
                             depends('--enable-debug')(lambda x: bool(x)))

          default=depends(when='--enable-debug')(lambda: True),
          help='{Build|Do not build} Rust code with debug assertions turned '

def debug_rust():
    return True

set_config('MOZ_DEBUG_RUST', debug_rust)
set_define('MOZ_DEBUG_RUST', debug_rust)

js_option(env='MOZ_PGO', help='Build with profile guided optimizations')

set_config('MOZ_PGO', depends('MOZ_PGO')(lambda x: bool(x)))


# Make this assignment here rather than in pkg.configure to avoid
# requiring this file in unit tests.
add_old_configure_assignment('PKG_CONFIG', pkg_config)

# rust.configure is included by js/moz.configure.

          help='Enable Valgrind integration hooks')

valgrind_h = check_header('valgrind/valgrind.h', when='--enable-valgrind')

@depends('--enable-valgrind', valgrind_h)
def check_valgrind(valgrind, valgrind_h):
    if valgrind:
        if not valgrind_h:
            die('--enable-valgrind specified but Valgrind is not installed')
        return True

set_define('MOZ_VALGRIND', check_valgrind)
set_config('MOZ_VALGRIND', check_valgrind)

@depends(target, host)
def is_openbsd(target, host):
    return target.kernel == 'OpenBSD' or host.kernel == 'OpenBSD'

option(env='SO_VERSION', nargs=1, default='1.0', when=is_openbsd,
       help='Shared library version for OpenBSD systems')

@depends('SO_VERSION', when=is_openbsd)
def so_version(value):
    return value

def library_name_info_template(host_or_target):
    assert host_or_target in {host, target}
    compiler = {
        host: host_c_compiler,
        target: c_compiler,

    @depends(host_or_target, compiler, so_version)
    def library_name_info_impl(host_or_target, compiler, so_version):
        if host_or_target.kernel == 'WINNT':
            # There aren't artifacts for mingw builds, so it's OK that the
            # results are inaccurate in that case.
            if compiler and compiler.type not in ('msvc', 'clang-cl'):
                return namespace(
                    dll=namespace(prefix='', suffix='.dll'),
                    lib=namespace(prefix='lib', suffix='a'),
                    import_lib=namespace(prefix='lib', suffix='a'),
                    rust_lib=namespace(prefix='', suffix='lib'),
                    obj=namespace(prefix='', suffix='o'),

            return namespace(
                dll=namespace(prefix='', suffix='.dll'),
                lib=namespace(prefix='', suffix='lib'),
                import_lib=namespace(prefix='', suffix='lib'),
                rust_lib=namespace(prefix='', suffix='lib'),
                obj=namespace(prefix='', suffix='obj'),

        elif host_or_target.kernel == 'Darwin':
            return namespace(
                dll=namespace(prefix='lib', suffix='.dylib'),
                lib=namespace(prefix='lib', suffix='a'),
                import_lib=namespace(prefix=None, suffix=''),
                rust_lib=namespace(prefix='lib', suffix='a'),
                obj=namespace(prefix='', suffix='o'),
        elif so_version:
            so = '.so.%s' % so_version
            so = '.so'

        return namespace(
            dll=namespace(prefix='lib', suffix=so),
            lib=namespace(prefix='lib', suffix='a'),
            import_lib=namespace(prefix=None, suffix=''),
            rust_lib=namespace(prefix='lib', suffix='a'),
            obj=namespace(prefix='', suffix='o'),

    return library_name_info_impl

host_library_name_info = library_name_info_template(host)
library_name_info = library_name_info_template(target)

set_config('DLL_PREFIX', library_name_info.dll.prefix)
set_config('DLL_SUFFIX', library_name_info.dll.suffix)
set_config('HOST_DLL_PREFIX', host_library_name_info.dll.prefix)
set_config('HOST_DLL_SUFFIX', host_library_name_info.dll.suffix)
set_config('LIB_PREFIX', library_name_info.lib.prefix)
set_config('LIB_SUFFIX', library_name_info.lib.suffix)
set_config('RUST_LIB_PREFIX', library_name_info.rust_lib.prefix)
set_config('RUST_LIB_SUFFIX', library_name_info.rust_lib.suffix)
set_config('OBJ_SUFFIX', library_name_info.obj.suffix)
# Lots of compilation tests depend on this variable being present.
add_old_configure_assignment('OBJ_SUFFIX', library_name_info.obj.suffix)
set_config('IMPORT_LIB_SUFFIX', library_name_info.import_lib.suffix)
set_define('MOZ_DLL_PREFIX', depends(library_name_info.dll.prefix)(lambda s: '"%s"' % s))
set_define('MOZ_DLL_SUFFIX', depends(library_name_info.dll.suffix)(lambda s: '"%s"' % s))


@imports(_from='mozbuild.backend', _import='backends')
def build_backends_choices(_):
    return tuple(backends)

@deprecated_option('--enable-build-backend', nargs='+',
def build_backend(backends):
    if backends:
        return tuple('+%s' % b for b in backends)

imply_option('--build-backends', build_backend)

@depends('--enable-artifact-builds', '--disable-compile-environment',
         '--enable-build-backend', '--help')
def build_backend_defaults(artifact_builds, compile_environment, requested_backends,
    if 'Tup' in requested_backends:
        # As a special case, if Tup was requested, do not combine it with any
        # Make based backend by default.
        all_backends = []
    elif artifact_builds:
        all_backends = ['FasterMake+RecursiveMake']
        all_backends = ['RecursiveMake', 'FasterMake']
    # Normally, we'd use target.os == 'WINNT', but a dependency on target
    # would require target to depend on --help, as well as host and shell,
    # and this is not a can of worms we can open at the moment.
    if sys.platform == 'win32' and compile_environment:
    return tuple(all_backends) or None

option('--build-backends', nargs='+', default=build_backend_defaults,
       choices=build_backends_choices, help='Build backends to generate')

def build_backends(backends):
    return backends

set_config('BUILD_BACKENDS', build_backends)

@depends(check_build_environment, build_backends)
def check_objdir_backend_reuse(build_env, backends):
    # "Make based" might be RecursiveMake or a hybrid backend, so "Make" is
    # intentionally vague for use with the substring match below.
    incompatible_backends = (
        ('Tup', 'Make'),
        ('Make', 'Tup')
    for backend_file in glob.iglob(os.path.join(build_env.topobjdir,
        for prev, curr in incompatible_backends:
            if prev in backend_file and any(curr in b for b in backends):
                die("The active objdir, %s, was previously "
                    "used to build with a %s based backend. "
                    "Change objdirs (by setting MOZ_OBJDIR in "
                    "your mozconfig) or clobber to continue.\n",
                    build_env.topobjdir, prev)

       help='Force disable building the gtest libxul during the build.',

# Determine whether to build the gtest xul. This happens in automation
# on Desktop platforms with the exception of Windows PGO, where linking
# xul-gtest.dll takes too long.
@depends('MOZ_PGO', build_project, target, 'MOZ_AUTOMATION', '--disable-gtest-in-build',
         enable_tests, when='--enable-compile-environment')
def build_gtest(pgo, build_project, target, automation, enabled, enable_tests):
    if not enable_tests or not enabled:
        return None
    if (automation and build_project == 'browser' and
        not (pgo and target.os == 'WINNT')):
        return True

set_config('LINK_GTEST_DURING_COMPILE', build_gtest)

# Localization
# ==============================================================
option('--enable-ui-locale', default='en-US',
       help='Select the user interface locale (default: en-US)')

set_config('MOZ_UI_LOCALE', depends('--enable-ui-locale')(lambda x: x))

# clang-plugin location
# ==============================================================
@depends(host_library_name_info, check_build_environment,
def clang_plugin_path(library_name_info, build_env):
    topobjdir = build_env.topobjdir
    if topobjdir.endswith('/js/src'):
        topobjdir = topobjdir[:-7]
    return os.path.abspath(
        os.path.join(topobjdir, 'build', 'clang-plugin',
                     '%sclang-plugin%s' % (library_name_info.dll.prefix,

add_old_configure_assignment('CLANG_PLUGIN', clang_plugin_path)

# Awk detection
# ==============================================================
awk = check_prog('AWK', ('gawk', 'mawk', 'nawk', 'awk'))

# Until the AWK variable is not necessary in old-configure
def awk_for_old_configure(value):
    return value

add_old_configure_assignment('AWK', awk_for_old_configure)

# Perl detection
# ==============================================================
perl = check_prog('PERL', ('perl5', 'perl'))

# Until the PERL variable is not necessary in old-configure
def perl_for_old_configure(value):
    return value

add_old_configure_assignment('PERL', perl_for_old_configure)

def perl_version_check(min_version):
    @checking('for minimum required perl version >= %s' % min_version)
    def get_perl_version(perl):
        return Version(check_cmd_output(
            perl, '-e', 'print $]',
            onerror=lambda: die('Failed to get perl version.')

    def check_perl_version(version):
        if version < min_version:
            die('Perl %s or higher is required.', min_version)

    @checking('for full perl installation')
    def has_full_perl_installation(perl):
        ret =
            [perl, '-e', 'use Config; exit(!-d $Config{archlib})'])
        return ret == 0

    def require_full_perl_installation(has_full_perl_installation):
        if not has_full_perl_installation:
            die('Cannot find or $Config{archlib}. '
                'A full perl installation is required.')


# GNU make detection
# ==============================================================
option(env='MAKE', nargs=1, help='Path to GNU make')

@depends('MAKE', host)
def possible_makes(make, host):
    candidates = []
    if host.kernel == 'WINNT':
    if make:
    if host.kernel == 'WINNT':
        candidates.extend(('make', 'gmake'))
        candidates.extend(('gmake', 'make'))
    return candidates

check_prog('GMAKE', possible_makes)

@depends(build_backends, build_project)
def tup_include(build_backends, build_project):
    # We need to check the rustc version when building with tup, but
    # rustc_info isn't available when configuring js (and build_backends isn't
    # available from project-specific configure), so as a workaround we only
    # include the file when we know we'll need it. This can be removed when
    # we globally require a rustc recent enough to build with tup.
    if build_project not in ('browser', 'mobile/android'):
        return None
    for backend in build_backends:
        if 'Tup' in backend:
            return 'build/moz.configure/tup.configure'


# watchman detection
# ==============================================================

option(env='WATCHMAN', nargs=1, help='Path to the watchman program')

@checking('for watchman', callback=lambda w: w.path if w else 'not found')
def watchman(prog):
    if not prog:
        prog = find_program('watchman')

    if not prog:

    # `watchman version` will talk to the Watchman daemon service.
    # This can hang due to permissions problems. e.g.
    # So use
    # `watchman --version` to prevent a class of failures.
    out = check_cmd_output(prog, '--version', onerror=lambda: None)
    if out is None:

    return namespace(path=prog, version=Version(out.strip()))

@checking('for watchman version')
def watchman_version(w):
    return w.version

set_config('WATCHMAN', watchman.path)

@depends_all(hg_version, hg_config, watchman)
@checking('for watchman Mercurial integration')
def watchman_hg(hg_version, hg_config, watchman):
    if hg_version < Version('3.8'):
        return 'no (Mercurial 3.8+ required)'

    ext_enabled = False
    mode_disabled = False

    for k in ('extensions.fsmonitor', 'extensions.hgext.fsmonitor'):
        if k in hg_config and hg_config[k] != '!':
            ext_enabled = True

    mode_disabled = hg_config.get('fsmonitor.mode') == 'off'

    if not ext_enabled:
        return 'no (fsmonitor extension not enabled)'
    if mode_disabled:
        return 'no (fsmonitor.mode=off disables fsmonitor)'

    return True

# Miscellaneous programs
# ==============================================================
check_prog('XARGS', ('xargs',))

def extra_programs(target):
    if target.kernel == 'Darwin':
        return namespace(
            DSYMUTIL=('dsymutil', 'llvm-dsymutil'),
            MKFSHFS=('newfs_hfs', 'mkfs.hfsplus'),
    if target.os == 'GNU' and target.kernel == 'Linux':
        return namespace(RPMBUILD=('rpmbuild',))

check_prog('DSYMUTIL', extra_programs.DSYMUTIL,
check_prog('MKFSHFS', extra_programs.MKFSHFS,
check_prog('HFS_TOOL', extra_programs.HFS_TOOL,
check_prog('RPMBUILD', extra_programs.RPMBUILD,

def makensis_progs(target):
    if target.kernel != 'WINNT':

    candidates = [

    # Look for nsis installed by msys environment. But only the 32-bit version.
    # We use an absolute path and insert as the first entry so it is preferred
    # over a 64-bit exe that may be in PATH.
    if 'MSYSTEM_PREFIX' in os.environ:
        prefix = os.path.dirname(os.environ['MSYSTEM_PREFIX'])
        candidates.insert(0, os.path.join(prefix, 'mingw32', 'bin', 'makensis.exe'))

    return tuple(candidates)

nsis = check_prog('MAKENSISU', makensis_progs, allow_missing=True)

# Make sure the version of makensis is up to date.
@checking('for NSIS version')
def nsis_version(nsis):
    nsis_min_version = '3.0b1'
    out = check_cmd_output(nsis, '-version',
                           onerror=lambda: die('Failed to get nsis version.'))
    m ='(?<=v)[0-9]+\.[0-9]+((a|b|rc)[0-9]+)?', out)

    if not m:
        raise FatalCheckError('Unknown version of makensis')
    ver = Version(

    # Versions comparisons don't quite work well with beta versions, so ensure
    # it works for the non-beta version.
    if ver < nsis_min_version and (ver >= '3.0a' or ver < '3'):
        raise FatalCheckError('To build the installer you must have NSIS'
                              ' version %s or greater in your path'
                              % nsis_min_version)

    return ver

# And that makensis is 32-bit (but only on Windows).
@depends_if(nsis, when=depends(host)(lambda h: h.kernel == 'WINNT'))
@checking('for 32-bit NSIS')
def nsis_binary_type(nsis):
    bin_type = windows_binary_type(nsis)
    if bin_type != 'win32':
        raise FatalCheckError('%s is not a 32-bit Windows application' % nsis)

    return 'yes'

# And any flags we have to give to makensis
def nsis_flags(host):
    if host.kernel != 'WINNT':
        return '-nocd'
    return ''

set_config('MAKENSISU_FLAGS', nsis_flags)

check_prog('7Z', ('7z', '7za'), allow_missing=True, when=target_is_windows)

# Please do not add configure checks from here on.

# Fallthrough to autoconf-based configure

# JS Subconfigure.
include('js/sub.configure', when=compile_environment & toolkit)

@depends(check_build_environment, build_project)
def config_status_deps(build_env, build_project):

    topsrcdir = build_env.topsrcdir
    topobjdir = build_env.topobjdir

    if not build_env.topobjdir.endswith('js/src'):
        extra_deps = [
            os.path.join(topsrcdir, build_project, ''),
            os.path.join(topobjdir, '.mozconfig.json'),
        # mozconfig changes may impact js configure.
        extra_deps = [os.path.join(topobjdir[:-7], '.mozconfig.json')]

    return list(__sandbox__._all_paths) + extra_deps + [
        os.path.join(topsrcdir, 'CLOBBER'),
        os.path.join(topsrcdir, 'configure'),
        os.path.join(topsrcdir, 'js', 'src', 'configure'),
        os.path.join(topsrcdir, ''),
        os.path.join(topsrcdir, 'js', 'src', ''),
        os.path.join(topsrcdir, 'nsprpub', 'configure'),
        os.path.join(topsrcdir, 'config', 'milestone.txt'),
        os.path.join(topsrcdir, 'browser', 'config', 'version.txt'),
        os.path.join(topsrcdir, 'browser', 'config', 'version_display.txt'),
        os.path.join(topsrcdir, 'build', 'virtualenv_packages.txt'),
        os.path.join(topsrcdir, 'python', 'mozbuild', 'mozbuild', ''),
        os.path.join(topsrcdir, 'testing', 'mozbase', 'packages.txt'),
        os.path.join(topsrcdir, 'aclocal.m4'),
        os.path.join(topsrcdir, ''),
        os.path.join(topsrcdir, 'js', 'src', 'aclocal.m4'),
        os.path.join(topsrcdir, 'js', 'src', ''),
    ] + glob.glob(os.path.join(topsrcdir, 'build', 'autoconf', '*.m4'))

set_config('CONFIG_STATUS_DEPS', config_status_deps)
# Please do not add anything after setting config_dep_paths.