moz.configure
author Narcis Beleuzu <nbeleuzu@mozilla.com>
Tue, 11 Dec 2018 06:40:50 +0200
changeset 449919 fb94ec981a7d3d79a6ac55a2ad00a7b8a3be6149
parent 446945 83e6f0d47a8050ab1dc796dc0c795eac2f8cda4c
child 452969 29429b3bef3eda44f50a2efd8361987286c3276a
permissions -rwxr-xr-x
Backed out 131 changesets (bug 1483060, bug 1507325, bug 1509766, bug 1509173, bug 1447897, bug 1509859, bug 1510489, bug 1510196, bug 1507486, bug 1510315, bug 1510042, bug 1510645, bug 1508901, bug 1509857, bug 1509481, bug 1509201, bug 1509360, bug 1509204, bug 1503351, bug 1510303, bug 1510699, bug 1508488, bug 1510417, bug 1507258, bug 1507753, bug 1504428, bug 1509438, bug 1509436, bug 1509772, bug 1509773, bug 1509883, bug 1510638, bug 1508928, bug 1509526, bug 1510870, bug 1509506, bug 1509239, bug 1508871, bug 1487018, bug 1509130, bug 1509338, bug 1509611, bug 1509401, bug 1509335, bug 1509566, bug 1509243, bug 1510062, bug 1509419, bug 1510061, bug 1509612, bug 1511399, bug 1510373, bug 1509422, bug 1510170, bug 1510171, bug 1510172, bug 1507984, bug 1507775, bug 1509349, bug 1481585, bug 1507837, bug 1509343, bug 1509775, bug 1500160, bug 1509792, bug 1509790, bug 1509797, bug 1509602, bug 1509603, bug 1509517, bug 1510092, bug 1507797, bug 1510148, bug 1509564, bug 1510140, bug 1508914, bug 1509598, bug 1509312, bug 1509310, bug 1509351, bug 1509355, bug 1509463, bug 1509465, bug 1454984, bug 1509468, bug 1506701, bug 1509695, bug 1509694) for spidermokey bustages on bad-strategies.js Backed out changeset fcd0236d7afa (bug 1511399) Backed out changeset e57f1cff602f (bug 1509602) Backed out changeset 0b691a965306 (bug 1509602) Backed out changeset d615ea8e8dbe (bug 1510870) Backed out changeset bea20d1644f8 (bug 1510638) Backed out changeset 341d1454a719 (bug 1510645) Backed out changeset 7c40a661e06a (bug 1510417) Backed out changeset 55d7a32adf3e (bug 1510417) Backed out changeset 4b81c4c2722a (bug 1510699) Backed out changeset 885ff808ee3d (bug 1510489) Backed out changeset 0bb7f3d61db2 (bug 1510489) Backed out changeset 82a89d8cec98 (bug 1509401) Backed out changeset 53bd5ece31e6 (bug 1509401) Backed out changeset dabb54327a11 (bug 1509857) Backed out changeset 71deaa0942d3 (bug 1509857) Backed out changeset 453380fa9597 (bug 1507984) Backed out changeset 6d7f837ccbe1 (bug 1507984) Backed out changeset ed91c65bb17e (bug 1509517) Backed out changeset e61986873e76 (bug 1509517) Backed out changeset e17130d54efc (bug 1510148) Backed out changeset 4d2ca6c4816d (bug 1504428) Backed out changeset 737d0ec9198a (bug 1504428) Backed out changeset 8b2dd9baa2e0 (bug 1509694) Backed out changeset 763b81a477a9 (bug 1509694) Backed out changeset f6b9756d68b0 (bug 1510061) Backed out changeset 58b8d41e9b59 (bug 1510061) Backed out changeset e43407fb6f9d (bug 1510092) Backed out changeset 834b0fe4e318 (bug 1509173) Backed out changeset df6134e0788a (bug 1509173) Backed out changeset 76ee196e863f (bug 1510062) Backed out changeset a507c55880c7 (bug 1510062) Backed out changeset 4cf05d8ae51e (bug 1509338) Backed out changeset ec683b020846 (bug 1510315) Backed out changeset 22fc38b4cccb (bug 1510315) Backed out changeset 260d4216ebba (bug 1510042) Backed out changeset 197bb0764619 (bug 1510042) Backed out changeset 0fa6f935ad10 (bug 1508901) Backed out changeset 4fb8b50d7a66 (bug 1508901) Backed out changeset 5a996f748395 (bug 1510373) Backed out changeset 723db451649c (bug 1510373) Backed out changeset e6d78f16bd73 (bug 1509859) Backed out changeset af450646a969 (bug 1509859) Backed out changeset fcc10971a6e8 (bug 1509419) Backed out changeset 7721f268ee77 (bug 1510303) Backed out changeset 310e74f987c1 (bug 1510171) Backed out changeset bdd2149e1ba1 (bug 1510170) Backed out changeset 6c08117876e6 (bug 1510196) Backed out changeset 4cd63a9278f8 (bug 1509772) Backed out changeset 9d01c22bac93 (bug 1510172) Backed out changeset 74e263be28ce (bug 1510172) Backed out changeset eaada8efafca (bug 1509797) Backed out changeset a6ef4aa89f45 (bug 1454984) Backed out changeset f49a14324463 (bug 1454984) Backed out changeset 550d21e06e90 (bug 1510140) Backed out changeset dd707cfbeb0e (bug 1507258) Backed out changeset db69c8dd1e1b (bug 1507258) Backed out changeset 4ee76bcc47a1 (bug 1509792) Backed out changeset 050bf471d5cb (bug 1509792) Backed out changeset deed5aad26b3 (bug 1481585) Backed out changeset 7eea409daa8b (bug 1509201) Backed out changeset 57aedf21b9c5 (bug 1509201) Backed out changeset 39dc1e17f388 (bug 1509438) Backed out changeset 35ab42d3626e (bug 1509438) Backed out changeset 41e2805d6b57 (bug 1509790) Backed out changeset 15eb57180700 (bug 1509790) Backed out changeset a9a0fb79a2ca (bug 1509775) Backed out changeset 3cee5ee7e89d (bug 1509775) Backed out changeset bff634662787 (bug 1509766) Backed out changeset 67220e78c452 (bug 1509766) Backed out changeset cf1ab6cd9f83 (bug 1447897) Backed out changeset 9dcd0dc42e79 (bug 1447897) Backed out changeset 531f616d71b3 (bug 1508488) Backed out changeset 2e460352f253 (bug 1508488) Backed out changeset 051417f3d3f3 (bug 1509883) Backed out changeset 8f1dd7944d50 (bug 1509773) Backed out changeset 1261a407197b (bug 1509773) Backed out changeset 950188672908 (bug 1487018) Backed out changeset 3284125abf45 (bug 1487018) Backed out changeset 724c1eeb7910 (bug 1509463) Backed out changeset f9c3cf504b7a (bug 1509695) Backed out changeset f1d03b49d1d6 (bug 1509465) Backed out changeset b8c86bd9d68e (bug 1509612) Backed out changeset 2d0334e10ba1 (bug 1509611) Backed out changeset 155ddc13d7a0 (bug 1509468) Backed out changeset 11dbd2833e02 (bug 1509598) Backed out changeset ae1b488dbc16 (bug 1509130) Backed out changeset 978c4475bce2 (bug 1509130) Backed out changeset 77eab0952d9d (bug 1509603) Backed out changeset 5a5ec2897605 (bug 1483060) Backed out changeset c2f00da426ba (bug 1483060) Backed out changeset 82dc402e581c (bug 1509310) Backed out changeset 92c8c87dffcf (bug 1509422) Backed out changeset fce061989f24 (bug 1509566) Backed out changeset 70988c50685f (bug 1511399) Backed out changeset a393d292ef04 (bug 1509564) Backed out changeset 5f1fcc55c350 (bug 1503351) Backed out changeset 9b073aa19f6a (bug 1503351) Backed out changeset 9acf8f2e2e82 (bug 1507775) Backed out changeset 456273bb9289 (bug 1507837) Backed out changeset 9caf65060547 (bug 1509526) Backed out changeset b5b09b2d8445 (bug 1509506) Backed out changeset cde8bfd0dbc4 (bug 1509506) Backed out changeset d31b1d91a876 (bug 1509481) Backed out changeset b5a80f4677f2 (bug 1509436) Backed out changeset a6e95027e177 (bug 1509436) Backed out changeset 478bb0fcfa9a (bug 1507753) Backed out changeset 6dec8a00622a (bug 1508928) Backed out changeset a1cc7364d13d (bug 1508928) Backed out changeset 088b74eab160 (bug 1506701) Backed out changeset aef622ea3691 (bug 1507486) Backed out changeset 9f864e965fbd (bug 1508914) Backed out changeset b7f3db124039 (bug 1508914) Backed out changeset dc5b16243cbf (bug 1509239) Backed out changeset 1ae4e7035bb1 (bug 1509204) Backed out changeset 39bc05c1887a (bug 1509204) Backed out changeset 968beebda7f2 (bug 1507325) Backed out changeset 36b10e4454a8 (bug 1507325) Backed out changeset 5acde4c777eb (bug 1509343) Backed out changeset fb53794d49e7 (bug 1509360) Backed out changeset d75a74c29bb6 (bug 1509360) Backed out changeset 876d71e94aa4 (bug 1508871) Backed out changeset ec39d0b1ef49 (bug 1508871) Backed out changeset b724eeef1f5e (bug 1509335) Backed out changeset 7ac6bce2781d (bug 1507797) Backed out changeset aa960526fb2d (bug 1509355) Backed out changeset 4b33023c62f9 (bug 1500160) Backed out changeset dd64bd9c8000 (bug 1509349) Backed out changeset 8837efcf2f34 (bug 1509351) Backed out changeset d07ad4e1e5c5 (bug 1509312) Backed out changeset feff3cf9a249 (bug 1509312) Backed out changeset 634d87030e9c (bug 1509243)

# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

include('build/moz.configure/init.configure')

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

@depends('--enable-artifact-builds')
def artifact_builds(value):
    if value:
        return True

set_config('MOZ_ARTIFACT_BUILDS', artifact_builds)

imply_option('--enable-artifact-build-symbols',
             depends(artifact_builds)(lambda v: False if v is None else None),
             reason='--disable-artifact-builds')

option('--enable-artifact-build-symbols',
       help='Download symbols when artifact builds are enabled.')

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

@depends('--enable-artifact-builds')
def imply_disable_compile_environment(value):
    if value:
        return False

option(env='MOZ_COPY_PDBS',
    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)

option('--disable-compile-environment',
       help='Disable compiler/library checks')

@depends('--disable-compile-environment')
def compile_environment(compile_env):
    if compile_env:
        return True

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

js_option('--disable-tests',
          help='Do not build test libraries & programs')

@depends('--disable-tests')
def enable_tests(value):
    if value:
        return True

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

@depends(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,
                         use_own_tr1_tuple=True,
                         has_clone='0')

set_define('GTEST_OS_LINUX_ANDROID',
           linux_gtest_defines.os_linux_android)
set_define('GTEST_USE_OWN_TR1_TUPLE',
           linux_gtest_defines.use_own_tr1_tuple)
set_define('GTEST_HAS_CLONE',
           linux_gtest_defines.has_clone)

js_option('--enable-debug',
          nargs='?',
          help='Enable building with developer debug info '
               '(using the given compiler flags).')

@depends('--enable-debug')
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.
add_old_configure_assignment('MOZ_DEBUG',
                             depends('--enable-debug')(lambda x: bool(x)))

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

@depends(when='--enable-rust-debug')
def debug_rust():
    return True

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

include('build/moz.configure/pkg.configure')
# 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)

include('build/moz.configure/toolchain.configure',
        when='--enable-compile-environment')
include('build/moz.configure/memory.configure',
        when='--enable-compile-environment')
include('build/moz.configure/headers.configure',
        when='--enable-compile-environment')
include('build/moz.configure/warnings.configure',
        when='--enable-compile-environment')
include('build/moz.configure/flags.configure',
        when='--enable-compile-environment')
# rust.configure is included by js/moz.configure.

js_option('--enable-valgrind',
          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

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

    @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
        else:
            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))

# Depends on host_library_name_info, so needs to go here.
include('build/moz.configure/bindgen.configure',
        when='--enable-compile-environment')
include(include_project_configure)

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


@deprecated_option('--enable-build-backend', nargs='+',
                   choices=build_backends_choices)
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')
@imports('sys')
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']
    else:
        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:
        all_backends.append('VisualStudio')
    return tuple(all_backends) or None

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

@depends('--build-backends')
def build_backends(backends):
    return backends

set_config('BUILD_BACKENDS', build_backends)


@depends(check_build_environment, build_backends)
@imports('glob')
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,
                                                'backend.*Backend')):
        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)


option('--disable-gtest-in-build',
       help='Force disable building the gtest libxul during the build.',
       when='--enable-compile-environment')

# 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,
         when='--enable-clang-plugin')
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,
                                           library_name_info.dll.suffix))
    )

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
@depends(awk)
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
@depends(perl)
def perl_for_old_configure(value):
    return value

add_old_configure_assignment('PERL', perl_for_old_configure)

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

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

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

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

perl_version_check('5.006')


# 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':
        candidates.append('mingw32-make')
    if make:
        candidates.append(make[0])
    if host.kernel == 'WINNT':
        candidates.extend(('make', 'gmake'))
    else:
        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'

include(tup_include)

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

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

@depends('WATCHMAN')
@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:
        return

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

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

@depends_if(watchman)
@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')
@imports('os')
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',))

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

check_prog('DSYMUTIL', extra_programs.DSYMUTIL,
           allow_missing=True)
check_prog('MKFSHFS', extra_programs.MKFSHFS,
           allow_missing=True)
check_prog('HFS_TOOL', extra_programs.HFS_TOOL,
           allow_missing=True)
check_prog('RPMBUILD', extra_programs.RPMBUILD,
           allow_missing=True)


@depends(target)
@imports('os')
def makensis_progs(target):
    if target.kernel != 'WINNT':
        return

    candidates = [
        'makensis-3.01',
        'makensis-3.0b3',
        'makensis-3.0b1',
        'makensis',
    ]

    # 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.
@depends_if(nsis)
@checking('for NSIS version')
@imports('re')
def nsis_version(nsis):
    nsis_min_version = '3.0b1'
    out = check_cmd_output(nsis, '-version',
                           onerror=lambda: die('Failed to get nsis version.'))
    m = re.search(r'(?<=v)[0-9]+\.[0-9]+((a|b|rc)[0-9]+)?', out)

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

    # 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
@depends(host)
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)

# Fallthrough to autoconf-based configure
include('build/moz.configure/old.configure')

@depends(check_build_environment, build_project)
@imports('__sandbox__')
@imports('glob')
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, 'confvars.sh'),
            os.path.join(topobjdir, '.mozconfig.json'),
        ]
    else:
        # 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, 'configure.in'),
        os.path.join(topsrcdir, 'js', 'src', 'configure.in'),
        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', 'virtualenv.py'),
        os.path.join(topsrcdir, 'testing', 'mozbase', 'packages.txt'),
        os.path.join(topsrcdir, 'aclocal.m4'),
        os.path.join(topsrcdir, 'old-configure.in'),
        os.path.join(topsrcdir, 'js', 'src', 'aclocal.m4'),
        os.path.join(topsrcdir, 'js', 'src', 'old-configure.in'),
    ] + 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.