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 # Depends on host_library_name_info, so needs to go here.
243 include('build/moz.configure/bindgen.configure',
244 when='--enable-compile-environment')
245 include(include_project_configure)
248 @imports(_from='mozbuild.backend', _import='backends')
249 def build_backends_choices(_):
250 return tuple(backends)
253 @deprecated_option('--enable-build-backend', nargs='+',
254 choices=build_backends_choices)
255 def build_backend(backends):
257 return tuple('+%s' % b for b in backends)
259 imply_option('--build-backends', build_backend)
262 @depends('--enable-artifact-builds', '--disable-compile-environment', '--help')
264 def build_backend_defaults(artifact_builds, compile_environment, _):
266 all_backends = ['FasterMake+RecursiveMake']
268 all_backends = ['RecursiveMake', 'FasterMake']
269 # Normally, we'd use target.os == 'WINNT', but a dependency on target
270 # would require target to depend on --help, as well as host and shell,
271 # and this is not a can of worms we can open at the moment.
272 if sys.platform == 'win32' and compile_environment:
273 all_backends.append('VisualStudio')
274 return tuple(all_backends)
276 option('--build-backends', nargs='+', default=build_backend_defaults,
277 choices=build_backends_choices, help='Build backends to generate')
279 @depends('--build-backends')
280 def build_backends(backends):
283 set_config('BUILD_BACKENDS', build_backends)
285 option('--disable-gtest-in-build',
286 help='Force disable building the gtest libxul during the build.',
287 when='--enable-compile-environment')
289 # Determine whether to build the gtest xul. This happens in automation
290 # on Desktop platforms with the exception of Windows PGO, where linking
291 # xul-gtest.dll takes too long.
292 @depends('MOZ_PGO', build_project, target, 'MOZ_AUTOMATION', '--disable-gtest-in-build',
293 enable_tests, when='--enable-compile-environment')
294 def build_gtest(pgo, build_project, target, automation, enabled, enable_tests):
295 if not enable_tests or not enabled:
297 if (automation and build_project == 'browser' and
298 not (pgo and target.os == 'WINNT')):
301 set_config('LINK_GTEST_DURING_COMPILE', build_gtest)
304 # ==============================================================
305 option('--enable-ui-locale', default='en-US',
306 help='Select the user interface locale (default: en-US)')
308 set_config('MOZ_UI_LOCALE', depends('--enable-ui-locale')(lambda x: x))
310 # clang-plugin location
311 # ==============================================================
312 @depends(host_library_name_info, check_build_environment,
313 when='--enable-clang-plugin')
314 def clang_plugin_path(library_name_info, build_env):
315 topobjdir = build_env.topobjdir
316 if topobjdir.endswith('/js/src'):
317 topobjdir = topobjdir[:-7]
318 return os.path.abspath(
319 os.path.join(topobjdir, 'build', 'clang-plugin',
320 '%sclang-plugin%s' % (library_name_info.dll.prefix,
321 library_name_info.dll.suffix))
324 add_old_configure_assignment('CLANG_PLUGIN', clang_plugin_path)
328 # ==============================================================
329 awk = check_prog('AWK', ('gawk', 'mawk', 'nawk', 'awk'))
331 # Until the AWK variable is not necessary in old-configure
333 def awk_for_old_configure(value):
336 add_old_configure_assignment('AWK', awk_for_old_configure)
340 # ==============================================================
341 perl = check_prog('PERL', ('perl5', 'perl'))
343 # Until the PERL variable is not necessary in old-configure
345 def perl_for_old_configure(value):
348 add_old_configure_assignment('PERL', perl_for_old_configure)
351 def perl_version_check(min_version):
353 @checking('for minimum required perl version >= %s' % min_version)
354 def get_perl_version(perl):
355 return Version(check_cmd_output(
356 perl, '-e', 'print $]',
357 onerror=lambda: die('Failed to get perl version.')
360 @depends(get_perl_version)
361 def check_perl_version(version):
362 if version < min_version:
363 die('Perl %s or higher is required.', min_version)
366 @checking('for full perl installation')
367 @imports('subprocess')
368 def has_full_perl_installation(perl):
369 ret = subprocess.call(
370 [perl, '-e', 'use Config; exit(!-d $Config{archlib})'])
373 @depends(has_full_perl_installation)
374 def require_full_perl_installation(has_full_perl_installation):
375 if not has_full_perl_installation:
376 die('Cannot find Config.pm or $Config{archlib}. '
377 'A full perl installation is required.')
379 perl_version_check('5.006')
383 # ==============================================================
384 option(env='MAKE', nargs=1, help='Path to GNU make')
386 @depends('MAKE', host)
387 def possible_makes(make, host):
389 if host.kernel == 'WINNT':
390 candidates.append('mingw32-make')
392 candidates.append(make[0])
393 if host.kernel == 'WINNT':
394 candidates.extend(('make', 'gmake'))
396 candidates.extend(('gmake', 'make'))
399 check_prog('GMAKE', possible_makes)
401 @depends(build_backends, build_project)
402 def tup_include(build_backends, build_project):
403 # We need to check the rustc version when building with tup, but
404 # rustc_info isn't available when configuring js (and build_backends isn't
405 # available from project-specific configure), so as a workaround we only
406 # include the file when we know we'll need it. This can be removed when
407 # we globally require a rustc recent enough to build with tup.
408 if build_project not in ('browser', 'mobile/android'):
410 for backend in build_backends:
412 return 'build/moz.configure/tup.configure'
417 # ==============================================================
419 option(env='WATCHMAN', nargs=1, help='Path to the watchman program')
422 @checking('for watchman', callback=lambda w: w.path if w else 'not found')
425 prog = find_program('watchman')
430 # `watchman version` will talk to the Watchman daemon service.
431 # This can hang due to permissions problems. e.g.
432 # https://github.com/facebook/watchman/issues/376. So use
433 # `watchman --version` to prevent a class of failures.
434 out = check_cmd_output(prog, '--version', onerror=lambda: None)
438 return namespace(path=prog, version=Version(out.strip()))
440 @depends_if(watchman)
441 @checking('for watchman version')
442 def watchman_version(w):
445 set_config('WATCHMAN', watchman.path)
447 @depends_all(hg_version, hg_config, watchman)
448 @checking('for watchman Mercurial integration')
450 def watchman_hg(hg_version, hg_config, watchman):
451 if hg_version < Version('3.8'):
452 return 'no (Mercurial 3.8+ required)'
455 mode_disabled = False
457 for k in ('extensions.fsmonitor', 'extensions.hgext.fsmonitor'):
458 if k in hg_config and hg_config[k] != '!':
461 mode_disabled = hg_config.get('fsmonitor.mode') == 'off'
464 return 'no (fsmonitor extension not enabled)'
466 return 'no (fsmonitor.mode=off disables fsmonitor)'
470 # Miscellaneous programs
471 # ==============================================================
472 check_prog('XARGS', ('xargs',))
475 def extra_programs(target):
476 if target.kernel == 'Darwin':
478 DSYMUTIL=('dsymutil', 'llvm-dsymutil'),
479 MKFSHFS=('newfs_hfs', 'mkfs.hfsplus'),
480 HFS_TOOL=('hfsplus',)
482 if target.os == 'GNU' and target.kernel == 'Linux':
483 return namespace(RPMBUILD=('rpmbuild',))
485 check_prog('DSYMUTIL', extra_programs.DSYMUTIL,
487 check_prog('MKFSHFS', extra_programs.MKFSHFS,
489 check_prog('HFS_TOOL', extra_programs.HFS_TOOL,
491 check_prog('RPMBUILD', extra_programs.RPMBUILD,
497 def makensis_progs(target):
498 if target.kernel != 'WINNT':
508 # Look for nsis installed by msys environment. But only the 32-bit version.
509 # We use an absolute path and insert as the first entry so it is preferred
510 # over a 64-bit exe that may be in PATH.
511 if 'MSYSTEM_PREFIX' in os.environ:
512 prefix = os.path.dirname(os.environ['MSYSTEM_PREFIX'])
513 candidates.insert(0, os.path.join(prefix, 'mingw32', 'bin', 'makensis.exe'))
515 return tuple(candidates)
517 nsis = check_prog('MAKENSISU', makensis_progs, allow_missing=True)
519 # Make sure the version of makensis is up to date.
521 @checking('for NSIS version')
523 def nsis_version(nsis):
524 nsis_min_version = '3.0b1'
525 out = check_cmd_output(nsis, '-version',
526 onerror=lambda: die('Failed to get nsis version.'))
527 m = re.search(r'(?<=v)[0-9]+\.[0-9]+((a|b|rc)[0-9]+)?', out)
530 raise FatalCheckError('Unknown version of makensis')
531 ver = Version(m.group(0))
533 # Versions comparisons don't quite work well with beta versions, so ensure
534 # it works for the non-beta version.
535 if ver < nsis_min_version and (ver >= '3.0a' or ver < '3'):
536 raise FatalCheckError('To build the installer you must have NSIS'
537 ' version %s or greater in your path'
542 # And that makensis is 32-bit (but only on Windows).
543 @depends_if(nsis, when=depends(host)(lambda h: h.kernel == 'WINNT'))
544 @checking('for 32-bit NSIS')
545 def nsis_binary_type(nsis):
546 bin_type = windows_binary_type(nsis)
547 if bin_type != 'win32':
548 raise FatalCheckError('%s is not a 32-bit Windows application' % nsis)
552 # And any flags we have to give to makensis
554 def nsis_flags(host):
555 if host.kernel != 'WINNT':
559 set_config('MAKENSISU_FLAGS', nsis_flags)
561 check_prog('7Z', ('7z', '7za'), allow_missing=True, when=target_is_windows)
563 # Fallthrough to autoconf-based configure
564 include('build/moz.configure/old.configure')
566 @depends(check_build_environment, build_project)
567 @imports('__sandbox__')
569 def config_status_deps(build_env, build_project):
571 topsrcdir = build_env.topsrcdir
572 topobjdir = build_env.topobjdir
574 if not build_env.topobjdir.endswith('js/src'):
576 os.path.join(topsrcdir, build_project, 'confvars.sh'),
577 os.path.join(topobjdir, '.mozconfig.json'),
580 # mozconfig changes may impact js configure.
581 extra_deps = [os.path.join(topobjdir[:-7], '.mozconfig.json')]
583 return list(__sandbox__._all_paths) + extra_deps + [
584 os.path.join(topsrcdir, 'configure'),
585 os.path.join(topsrcdir, 'js', 'src', 'configure'),
586 os.path.join(topsrcdir, 'configure.in'),
587 os.path.join(topsrcdir, 'js', 'src', 'configure.in'),
588 os.path.join(topsrcdir, 'nsprpub', 'configure'),
589 os.path.join(topsrcdir, 'config', 'milestone.txt'),
590 os.path.join(topsrcdir, 'browser', 'config', 'version.txt'),
591 os.path.join(topsrcdir, 'browser', 'config', 'version_display.txt'),
592 os.path.join(topsrcdir, 'build', 'virtualenv_packages.txt'),
593 os.path.join(topsrcdir, 'python', 'mozbuild', 'mozbuild', 'virtualenv.py'),
594 os.path.join(topsrcdir, 'testing', 'mozbase', 'packages.txt'),
595 os.path.join(topsrcdir, 'aclocal.m4'),
596 os.path.join(topsrcdir, 'old-configure.in'),
597 os.path.join(topsrcdir, 'js', 'src', 'aclocal.m4'),
598 os.path.join(topsrcdir, 'js', 'src', 'old-configure.in'),
599 ] + glob.glob(os.path.join(topsrcdir, 'build', 'autoconf', '*.m4'))
601 set_config('CONFIG_STATUS_DEPS', config_status_deps)
602 # Please do not add anything after setting config_dep_paths.