Bug 1265584 [wpt PR 11167] - [Gecko Bug 1265584] Move wptrunner marionette usage...
[gecko.git] / moz.configure
blob7cec668aa7f18e7954b2d40752682ad9c2b23ad7
1 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
2 # vim: set filetype=python:
3 # This Source Code Form is subject to the terms of the Mozilla Public
4 # License, v. 2.0. If a copy of the MPL was not distributed with this
5 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 include('build/moz.configure/init.configure')
9 # Note:
10 # - Gecko-specific options and rules should go in toolkit/moz.configure.
11 # - Firefox-specific options and rules should go in browser/moz.configure.
12 # - Fennec-specific options and rules should go in
13 #   mobile/android/moz.configure.
14 # - Spidermonkey-specific options and rules should go in js/moz.configure.
15 # - etc.
17 option('--enable-artifact-builds', env='MOZ_ARTIFACT_BUILDS',
18        help='Download and use prebuilt binary artifacts.')
20 @depends('--enable-artifact-builds')
21 def artifact_builds(value):
22     if value:
23         return True
25 set_config('MOZ_ARTIFACT_BUILDS', artifact_builds)
27 imply_option('--enable-artifact-build-symbols',
28              depends(artifact_builds)(lambda v: False if v is None else None),
29              reason='--disable-artifact-builds')
31 option('--enable-artifact-build-symbols',
32        help='Download symbols when artifact builds are enabled.')
34 set_config('MOZ_ARTIFACT_BUILD_SYMBOLS',
35            depends_if('--enable-artifact-build-symbols')(lambda _: True))
37 @depends('--enable-artifact-builds')
38 def imply_disable_compile_environment(value):
39     if value:
40         return False
42 imply_option('--enable-compile-environment', imply_disable_compile_environment)
44 option('--disable-compile-environment',
45        help='Disable compiler/library checks')
47 @depends('--disable-compile-environment')
48 def compile_environment(compile_env):
49     if compile_env:
50         return True
52 set_config('COMPILE_ENVIRONMENT', compile_environment)
53 add_old_configure_assignment('COMPILE_ENVIRONMENT', compile_environment)
55 js_option('--disable-tests',
56           help='Do not build test libraries & programs')
58 @depends('--disable-tests')
59 def enable_tests(value):
60     if value:
61         return True
63 set_config('ENABLE_TESTS', enable_tests)
64 set_define('ENABLE_TESTS', enable_tests)
66 js_option(env='MOZILLA_OFFICIAL',
67           help='Build an official release')
69 @depends('MOZILLA_OFFICIAL')
70 def mozilla_official(official):
71     if official:
72         return True
74 set_config('MOZILLA_OFFICIAL', mozilla_official)
75 set_define('MOZILLA_OFFICIAL', mozilla_official)
76 add_old_configure_assignment('MOZILLA_OFFICIAL', mozilla_official)
78 @depends(enable_tests)
79 def gtest_has_rtti(value):
80     if value:
81         return '0'
83 set_define('GTEST_HAS_RTTI', gtest_has_rtti)
85 @depends(target, enable_tests)
86 def linux_gtest_defines(target, enable_tests):
87     if enable_tests and target.os == 'Android':
88         return namespace(os_linux_android=True,
89                          use_own_tr1_tuple=True,
90                          has_clone='0')
92 set_define('GTEST_OS_LINUX_ANDROID',
93            linux_gtest_defines.os_linux_android)
94 set_define('GTEST_USE_OWN_TR1_TUPLE',
95            linux_gtest_defines.use_own_tr1_tuple)
96 set_define('GTEST_HAS_CLONE',
97            linux_gtest_defines.has_clone)
99 js_option('--enable-debug',
100           nargs='?',
101           help='Enable building with developer debug info '
102                '(using the given compiler flags).')
104 @depends('--enable-debug')
105 def moz_debug(debug):
106     if debug:
107         return bool(debug)
109 set_config('MOZ_DEBUG', moz_debug)
110 set_define('MOZ_DEBUG', moz_debug)
111 # Override any value MOZ_DEBUG may have from the environment when passing it
112 # down to old-configure.
113 add_old_configure_assignment('MOZ_DEBUG',
114                              depends('--enable-debug')(lambda x: bool(x)))
116 js_option('--enable-rust-debug',
117           help='Build Rust code with debug assertions turned on.')
119 @depends('--enable-rust-debug', '--enable-debug')
120 def debug_rust(value, debug):
121     if value.origin == 'default':
122         return bool(debug) or None
123     elif bool(value):
124         return True
126 set_config('MOZ_DEBUG_RUST', debug_rust)
127 set_define('MOZ_DEBUG_RUST', debug_rust)
129 include('build/moz.configure/pkg.configure')
130 # Make this assignment here rather than in pkg.configure to avoid
131 # requiring this file in unit tests.
132 add_old_configure_assignment('PKG_CONFIG', pkg_config)
134 include('build/moz.configure/toolchain.configure',
135         when='--enable-compile-environment')
136 include('build/moz.configure/memory.configure',
137         when='--enable-compile-environment')
138 include('build/moz.configure/headers.configure',
139         when='--enable-compile-environment')
140 include('build/moz.configure/warnings.configure',
141         when='--enable-compile-environment')
142 include('build/moz.configure/flags.configure',
143         when='--enable-compile-environment')
146 js_option('--enable-valgrind',
147           help='Enable Valgrind integration hooks')
149 valgrind_h = check_header('valgrind/valgrind.h', when='--enable-valgrind')
151 @depends('--enable-valgrind', valgrind_h)
152 def check_valgrind(valgrind, valgrind_h):
153     if valgrind:
154         if not valgrind_h:
155             die('--enable-valgrind specified but Valgrind is not installed')
156         return True
158 set_define('MOZ_VALGRIND', check_valgrind)
159 set_config('MOZ_VALGRIND', check_valgrind)
161 @depends(target, host)
162 def is_openbsd(target, host):
163     return target.kernel == 'OpenBSD' or host.kernel == 'OpenBSD'
165 option(env='SO_VERSION', nargs=1, default='1.0', when=is_openbsd,
166        help='Shared library version for OpenBSD systems')
168 @depends('SO_VERSION', when=is_openbsd)
169 def so_version(value):
170     return value
172 @template
173 def library_name_info_template(host_or_target):
174     assert host_or_target in (host, target)
175     compiler = {
176         host: host_c_compiler,
177         target: c_compiler,
178     }[host_or_target]
180     @depends(host_or_target, compiler, so_version)
181     def library_name_info_impl(host_or_target, compiler, so_version):
182         if host_or_target.kernel == 'WINNT':
183             # There aren't artifacts for mingw builds, so it's OK that the
184             # results are inaccurate in that case.
185             if compiler and compiler.type not in ('msvc', 'clang-cl'):
186                 return namespace(
187                     dll=namespace(prefix='', suffix='.dll'),
188                     lib=namespace(prefix='lib', suffix='a'),
189                     import_lib=namespace(prefix='lib', suffix='a'),
190                     rust_lib=namespace(prefix='', suffix='lib'),
191                     obj=namespace(prefix='', suffix='o'),
192                 )
194             return namespace(
195                 dll=namespace(prefix='', suffix='.dll'),
196                 lib=namespace(prefix='', suffix='lib'),
197                 import_lib=namespace(prefix='', suffix='lib'),
198                 rust_lib=namespace(prefix='', suffix='lib'),
199                 obj=namespace(prefix='', suffix='obj'),
200             )
202         elif host_or_target.kernel == 'Darwin':
203             return namespace(
204                 dll=namespace(prefix='lib', suffix='.dylib'),
205                 lib=namespace(prefix='lib', suffix='a'),
206                 import_lib=namespace(prefix=None, suffix=''),
207                 rust_lib=namespace(prefix='lib', suffix='a'),
208                 obj=namespace(prefix='', suffix='o'),
209             )
210         elif so_version:
211             so = '.so.%s' % so_version
212         else:
213             so = '.so'
215         return namespace(
216             dll=namespace(prefix='lib', suffix=so),
217             lib=namespace(prefix='lib', suffix='a'),
218             import_lib=namespace(prefix=None, suffix=''),
219             rust_lib=namespace(prefix='lib', suffix='a'),
220             obj=namespace(prefix='', suffix='o'),
221         )
223     return library_name_info_impl
225 host_library_name_info = library_name_info_template(host)
226 library_name_info = library_name_info_template(target)
228 set_config('DLL_PREFIX', library_name_info.dll.prefix)
229 set_config('DLL_SUFFIX', library_name_info.dll.suffix)
230 set_config('HOST_DLL_PREFIX', host_library_name_info.dll.prefix)
231 set_config('HOST_DLL_SUFFIX', host_library_name_info.dll.suffix)
232 set_config('LIB_PREFIX', library_name_info.lib.prefix)
233 set_config('LIB_SUFFIX', library_name_info.lib.suffix)
234 set_config('RUST_LIB_PREFIX', library_name_info.rust_lib.prefix)
235 set_config('RUST_LIB_SUFFIX', library_name_info.rust_lib.suffix)
236 set_config('OBJ_SUFFIX', library_name_info.obj.suffix)
237 # Lots of compilation tests depend on this variable being present.
238 add_old_configure_assignment('OBJ_SUFFIX', library_name_info.obj.suffix)
239 set_config('IMPORT_LIB_SUFFIX', library_name_info.import_lib.suffix)
240 set_define('MOZ_DLL_SUFFIX', depends(library_name_info.dll.suffix)(lambda s: '"%s"' % s))
242 include(include_project_configure)
244 @depends('--help')
245 @imports(_from='mozbuild.backend', _import='backends')
246 def build_backends_choices(_):
247     return tuple(backends)
250 @deprecated_option('--enable-build-backend', nargs='+',
251                    choices=build_backends_choices)
252 def build_backend(backends):
253     if backends:
254         return tuple('+%s' % b for b in backends)
256 imply_option('--build-backends', build_backend)
259 @depends('--enable-artifact-builds', '--disable-compile-environment', '--help')
260 @imports('sys')
261 def build_backend_defaults(artifact_builds, compile_environment, _):
262     if artifact_builds:
263         all_backends = ['FasterMake+RecursiveMake']
264     else:
265         all_backends = ['RecursiveMake', 'FasterMake']
266     # Normally, we'd use target.os == 'WINNT', but a dependency on target
267     # would require target to depend on --help, as well as host and shell,
268     # and this is not a can of worms we can open at the moment.
269     if sys.platform == 'win32' and compile_environment:
270         all_backends.append('VisualStudio')
271     return tuple(all_backends)
273 option('--build-backends', nargs='+', default=build_backend_defaults,
274        choices=build_backends_choices, help='Build backends to generate')
276 @depends('--build-backends')
277 def build_backends(backends):
278     return backends
280 set_config('BUILD_BACKENDS', build_backends)
282 option('--disable-gtest-in-build',
283        help='Force disable building the gtest libxul during the build.',
284        when='--enable-compile-environment')
286 # Determine whether to build the gtest xul. This happens in automation
287 # on Desktop platforms with the exception of Windows PGO, where linking
288 # xul-gtest.dll takes too long.
289 @depends('MOZ_PGO', build_project, target, 'MOZ_AUTOMATION', '--disable-gtest-in-build',
290          enable_tests, when='--enable-compile-environment')
291 def build_gtest(pgo, build_project, target, automation, enabled, enable_tests):
292     if not enable_tests or not enabled:
293         return None
294     if (automation and build_project == 'browser' and
295         not (pgo and target.os == 'WINNT')):
296         return True
298 set_config('LINK_GTEST_DURING_COMPILE', build_gtest)
300 # Localization
301 # ==============================================================
302 option('--enable-ui-locale', default='en-US',
303        help='Select the user interface locale (default: en-US)')
305 set_config('MOZ_UI_LOCALE', depends('--enable-ui-locale')(lambda x: x))
307 # clang-plugin location
308 # ==============================================================
309 @depends(host_library_name_info, check_build_environment,
310          when='--enable-clang-plugin')
311 def clang_plugin_path(library_name_info, build_env):
312     topobjdir = build_env.topobjdir
313     if topobjdir.endswith('/js/src'):
314         topobjdir = topobjdir[:-7]
315     return os.path.abspath(
316         os.path.join(topobjdir, 'build', 'clang-plugin',
317                      '%sclang-plugin%s' % (library_name_info.dll.prefix,
318                                            library_name_info.dll.suffix))
319     )
321 add_old_configure_assignment('CLANG_PLUGIN', clang_plugin_path)
324 # Awk detection
325 # ==============================================================
326 awk = check_prog('AWK', ('gawk', 'mawk', 'nawk', 'awk'))
328 # Until the AWK variable is not necessary in old-configure
329 @depends(awk)
330 def awk_for_old_configure(value):
331     return value
333 add_old_configure_assignment('AWK', awk_for_old_configure)
336 # Perl detection
337 # ==============================================================
338 perl = check_prog('PERL', ('perl5', 'perl'))
340 # Until the PERL variable is not necessary in old-configure
341 @depends(perl)
342 def perl_for_old_configure(value):
343     return value
345 add_old_configure_assignment('PERL', perl_for_old_configure)
347 @template
348 def perl_version_check(min_version):
349     @depends(perl)
350     @checking('for minimum required perl version >= %s' % min_version)
351     def get_perl_version(perl):
352         return Version(check_cmd_output(
353             perl, '-e', 'print $]',
354             onerror=lambda: die('Failed to get perl version.')
355         ))
357     @depends(get_perl_version)
358     def check_perl_version(version):
359         if version < min_version:
360             die('Perl %s or higher is required.', min_version)
362     @depends(perl)
363     @checking('for full perl installation')
364     @imports('subprocess')
365     def has_full_perl_installation(perl):
366         ret = subprocess.call(
367             [perl, '-e', 'use Config; exit(!-d $Config{archlib})'])
368         return ret == 0
370     @depends(has_full_perl_installation)
371     def require_full_perl_installation(has_full_perl_installation):
372         if not has_full_perl_installation:
373             die('Cannot find Config.pm or $Config{archlib}. '
374                 'A full perl installation is required.')
376 perl_version_check('5.006')
379 # GNU make detection
380 # ==============================================================
381 option(env='MAKE', nargs=1, help='Path to GNU make')
383 @depends('MAKE', host)
384 def possible_makes(make, host):
385     candidates = []
386     if host.kernel == 'WINNT':
387         candidates.append('mingw32-make')
388     if make:
389         candidates.append(make[0])
390     if host.kernel == 'WINNT':
391         candidates.extend(('make', 'gmake'))
392     else:
393         candidates.extend(('gmake', 'make'))
394     return candidates
396 check_prog('GMAKE', possible_makes)
398 @depends(build_backends, build_project)
399 def tup_include(build_backends, build_project):
400     # We need to check the rustc version when building with tup, but
401     # rustc_info isn't available when configuring js (and build_backends isn't
402     # available from project-specific configure), so as a workaround we only
403     # include the file when we know we'll need it. This can be removed when
404     # we globally require a rustc recent enough to build with tup.
405     if build_project not in ('browser', 'mobile/android'):
406         return None
407     for backend in build_backends:
408         if 'Tup' in backend:
409             return 'build/moz.configure/tup.configure'
411 include(tup_include)
413 # watchman detection
414 # ==============================================================
416 option(env='WATCHMAN', nargs=1, help='Path to the watchman program')
418 @depends('WATCHMAN')
419 @checking('for watchman', callback=lambda w: w.path if w else 'not found')
420 def watchman(prog):
421     if not prog:
422         prog = find_program('watchman')
424     if not prog:
425         return
427     # `watchman version` will talk to the Watchman daemon service.
428     # This can hang due to permissions problems. e.g.
429     # https://github.com/facebook/watchman/issues/376. So use
430     # `watchman --version` to prevent a class of failures.
431     out = check_cmd_output(prog, '--version', onerror=lambda: None)
432     if out is None:
433         return
435     return namespace(path=prog, version=Version(out.strip()))
437 @depends_if(watchman)
438 @checking('for watchman version')
439 def watchman_version(w):
440     return w.version
442 set_config('WATCHMAN', watchman.path)
444 @depends_all(hg_version, hg_config, watchman)
445 @checking('for watchman Mercurial integration')
446 @imports('os')
447 def watchman_hg(hg_version, hg_config, watchman):
448     if hg_version < Version('3.8'):
449         return 'no (Mercurial 3.8+ required)'
451     ext_enabled = False
452     mode_disabled = False
454     for k in ('extensions.fsmonitor', 'extensions.hgext.fsmonitor'):
455         if k in hg_config and hg_config[k] != '!':
456             ext_enabled = True
458     mode_disabled = hg_config.get('fsmonitor.mode') == 'off'
460     if not ext_enabled:
461         return 'no (fsmonitor extension not enabled)'
462     if mode_disabled:
463         return 'no (fsmonitor.mode=off disables fsmonitor)'
465     return True
467 # Miscellaneous programs
468 # ==============================================================
469 check_prog('XARGS', ('xargs',))
471 @depends(target)
472 def extra_programs(target):
473     if target.kernel == 'Darwin':
474         return namespace(
475             DSYMUTIL=('dsymutil', 'llvm-dsymutil'),
476             MKFSHFS=('newfs_hfs', 'mkfs.hfsplus'),
477             HFS_TOOL=('hfsplus',)
478         )
479     if target.os == 'GNU' and target.kernel == 'Linux':
480         return namespace(RPMBUILD=('rpmbuild',))
482 check_prog('DSYMUTIL', extra_programs.DSYMUTIL,
483            allow_missing=True)
484 check_prog('MKFSHFS', extra_programs.MKFSHFS,
485            allow_missing=True)
486 check_prog('HFS_TOOL', extra_programs.HFS_TOOL,
487            allow_missing=True)
488 check_prog('RPMBUILD', extra_programs.RPMBUILD,
489            allow_missing=True)
492 @depends(target)
493 @imports('os')
494 def makensis_progs(target):
495     if target.kernel != 'WINNT':
496         return
498     candidates = [
499         'makensis-3.01',
500         'makensis-3.0b3',
501         'makensis-3.0b1',
502         'makensis',
503     ]
505     # Look for nsis installed by msys environment. But only the 32-bit version.
506     # We use an absolute path and insert as the first entry so it is preferred
507     # over a 64-bit exe that may be in PATH.
508     if 'MSYSTEM_PREFIX' in os.environ:
509         prefix = os.path.dirname(os.environ['MSYSTEM_PREFIX'])
510         candidates.insert(0, os.path.join(prefix, 'mingw32', 'bin', 'makensis.exe'))
512     return tuple(candidates)
514 nsis = check_prog('MAKENSISU', makensis_progs, allow_missing=True)
516 # Make sure the version of makensis is up to date.
517 @depends_if(nsis)
518 @checking('for NSIS version')
519 @imports('re')
520 def nsis_version(nsis):
521     nsis_min_version = '3.0b1'
522     out = check_cmd_output(nsis, '-version',
523                            onerror=lambda: die('Failed to get nsis version.'))
524     m = re.search(r'(?<=v)[0-9]+\.[0-9]+((a|b|rc)[0-9]+)?', out)
526     if not m:
527         raise FatalCheckError('Unknown version of makensis')
528     ver = Version(m.group(0))
530     # Versions comparisons don't quite work well with beta versions, so ensure
531     # it works for the non-beta version.
532     if ver < nsis_min_version and (ver >= '3.0a' or ver < '3'):
533         raise FatalCheckError('To build the installer you must have NSIS'
534                               ' version %s or greater in your path'
535                               % nsis_min_version)
537     return ver
539 # And that makensis is 32-bit (but only on Windows).
540 @depends_if(nsis, when=depends(host)(lambda h: h.kernel == 'WINNT'))
541 @checking('for 32-bit NSIS')
542 def nsis_binary_type(nsis):
543     bin_type = windows_binary_type(nsis)
544     if bin_type != 'win32':
545         raise FatalCheckError('%s is not a 32-bit Windows application' % nsis)
547     return 'yes'
549 # And any flags we have to give to makensis
550 @depends(host)
551 def nsis_flags(host):
552     if host.kernel != 'WINNT':
553         return '-nocd'
554     return ''
556 set_config('MAKENSISU_FLAGS', nsis_flags)
558 check_prog('7Z', ('7z', '7za'), allow_missing=True, when=target_is_windows)
560 # Fallthrough to autoconf-based configure
561 include('build/moz.configure/old.configure')
563 @depends(check_build_environment, build_project)
564 @imports('__sandbox__')
565 @imports('glob')
566 def config_status_deps(build_env, build_project):
568     topsrcdir = build_env.topsrcdir
569     topobjdir = build_env.topobjdir
571     if not build_env.topobjdir.endswith('js/src'):
572         extra_deps = [
573             os.path.join(topsrcdir, build_project, 'confvars.sh'),
574             os.path.join(topobjdir, '.mozconfig.json'),
575         ]
576     else:
577         # mozconfig changes may impact js configure.
578         extra_deps = [os.path.join(topobjdir[:-7], '.mozconfig.json')]
580     return list(__sandbox__._all_paths) + extra_deps + [
581         os.path.join(topsrcdir, 'configure'),
582         os.path.join(topsrcdir, 'js', 'src', 'configure'),
583         os.path.join(topsrcdir, 'configure.in'),
584         os.path.join(topsrcdir, 'js', 'src', 'configure.in'),
585         os.path.join(topsrcdir, 'nsprpub', 'configure'),
586         os.path.join(topsrcdir, 'config', 'milestone.txt'),
587         os.path.join(topsrcdir, 'browser', 'config', 'version.txt'),
588         os.path.join(topsrcdir, 'browser', 'config', 'version_display.txt'),
589         os.path.join(topsrcdir, 'build', 'virtualenv_packages.txt'),
590         os.path.join(topsrcdir, 'python', 'mozbuild', 'mozbuild', 'virtualenv.py'),
591         os.path.join(topsrcdir, 'testing', 'mozbase', 'packages.txt'),
592         os.path.join(topsrcdir, 'aclocal.m4'),
593         os.path.join(topsrcdir, 'old-configure.in'),
594         os.path.join(topsrcdir, 'js', 'src', 'aclocal.m4'),
595         os.path.join(topsrcdir, 'js', 'src', 'old-configure.in'),
596     ] + glob.glob(os.path.join(topsrcdir, 'build', 'autoconf', '*.m4'))
598 set_config('CONFIG_STATUS_DEPS', config_status_deps)
599 # Please do not add anything after setting config_dep_paths.