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')
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.
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):
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):
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):
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):
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):
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):
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,
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',
101 help='Enable building with developer debug info '
102 '(using the given compiler flags).')
104 @depends('--enable-debug')
105 def moz_debug(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
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):
155 die('--enable-valgrind specified but Valgrind is not installed')
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):
173 def library_name_info_template(host_or_target):
174 assert host_or_target in (host, target)
176 host: host_c_compiler,
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'):
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'),
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'),
202 elif host_or_target.kernel == 'Darwin':
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'),
211 so = '.so.%s' % so_version
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'),
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)
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):
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')
261 def build_backend_defaults(artifact_builds, compile_environment, _):
263 all_backends = ['FasterMake+RecursiveMake']
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):
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:
294 if (automation and build_project == 'browser' and
295 not (pgo and target.os == 'WINNT')):
298 set_config('LINK_GTEST_DURING_COMPILE', build_gtest)
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))
321 add_old_configure_assignment('CLANG_PLUGIN', clang_plugin_path)
325 # ==============================================================
326 awk = check_prog('AWK', ('gawk', 'mawk', 'nawk', 'awk'))
328 # Until the AWK variable is not necessary in old-configure
330 def awk_for_old_configure(value):
333 add_old_configure_assignment('AWK', awk_for_old_configure)
337 # ==============================================================
338 perl = check_prog('PERL', ('perl5', 'perl'))
340 # Until the PERL variable is not necessary in old-configure
342 def perl_for_old_configure(value):
345 add_old_configure_assignment('PERL', perl_for_old_configure)
348 def perl_version_check(min_version):
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.')
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)
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})'])
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')
380 # ==============================================================
381 option(env='MAKE', nargs=1, help='Path to GNU make')
383 @depends('MAKE', host)
384 def possible_makes(make, host):
386 if host.kernel == 'WINNT':
387 candidates.append('mingw32-make')
389 candidates.append(make[0])
390 if host.kernel == 'WINNT':
391 candidates.extend(('make', 'gmake'))
393 candidates.extend(('gmake', 'make'))
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'):
407 for backend in build_backends:
409 return 'build/moz.configure/tup.configure'
414 # ==============================================================
416 option(env='WATCHMAN', nargs=1, help='Path to the watchman program')
419 @checking('for watchman', callback=lambda w: w.path if w else 'not found')
422 prog = find_program('watchman')
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)
435 return namespace(path=prog, version=Version(out.strip()))
437 @depends_if(watchman)
438 @checking('for watchman version')
439 def watchman_version(w):
442 set_config('WATCHMAN', watchman.path)
444 @depends_all(hg_version, hg_config, watchman)
445 @checking('for watchman Mercurial integration')
447 def watchman_hg(hg_version, hg_config, watchman):
448 if hg_version < Version('3.8'):
449 return 'no (Mercurial 3.8+ required)'
452 mode_disabled = False
454 for k in ('extensions.fsmonitor', 'extensions.hgext.fsmonitor'):
455 if k in hg_config and hg_config[k] != '!':
458 mode_disabled = hg_config.get('fsmonitor.mode') == 'off'
461 return 'no (fsmonitor extension not enabled)'
463 return 'no (fsmonitor.mode=off disables fsmonitor)'
467 # Miscellaneous programs
468 # ==============================================================
469 check_prog('XARGS', ('xargs',))
472 def extra_programs(target):
473 if target.kernel == 'Darwin':
475 DSYMUTIL=('dsymutil', 'llvm-dsymutil'),
476 MKFSHFS=('newfs_hfs', 'mkfs.hfsplus'),
477 HFS_TOOL=('hfsplus',)
479 if target.os == 'GNU' and target.kernel == 'Linux':
480 return namespace(RPMBUILD=('rpmbuild',))
482 check_prog('DSYMUTIL', extra_programs.DSYMUTIL,
484 check_prog('MKFSHFS', extra_programs.MKFSHFS,
486 check_prog('HFS_TOOL', extra_programs.HFS_TOOL,
488 check_prog('RPMBUILD', extra_programs.RPMBUILD,
494 def makensis_progs(target):
495 if target.kernel != 'WINNT':
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.
518 @checking('for NSIS version')
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)
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'
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)
549 # And any flags we have to give to makensis
551 def nsis_flags(host):
552 if host.kernel != 'WINNT':
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__')
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'):
573 os.path.join(topsrcdir, build_project, 'confvars.sh'),
574 os.path.join(topobjdir, '.mozconfig.json'),
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.