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')
144 # rust.configure is included by js/moz.configure.
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_PREFIX', depends(library_name_info.dll.prefix)(lambda s: '"%s"' % s))
241 set_define('MOZ_DLL_SUFFIX', depends(library_name_info.dll.suffix)(lambda s: '"%s"' % s))
243 # Depends on host_library_name_info, so needs to go here.
244 include('build/moz.configure/bindgen.configure',
245 when='--enable-compile-environment')
246 include(include_project_configure)
249 @imports(_from='mozbuild.backend', _import='backends')
250 def build_backends_choices(_):
251 return tuple(backends)
254 @deprecated_option('--enable-build-backend', nargs='+',
255 choices=build_backends_choices)
256 def build_backend(backends):
258 return tuple('+%s' % b for b in backends)
260 imply_option('--build-backends', build_backend)
263 @depends('--enable-artifact-builds', '--disable-compile-environment',
264 '--enable-build-backend', '--help')
266 def build_backend_defaults(artifact_builds, compile_environment, requested_backends,
268 if 'Tup' in requested_backends:
269 # As a special case, if Tup was requested, do not combine it with any
270 # Make based backend by default.
272 elif artifact_builds:
273 all_backends = ['FasterMake+RecursiveMake']
275 all_backends = ['RecursiveMake', 'FasterMake']
276 # Normally, we'd use target.os == 'WINNT', but a dependency on target
277 # would require target to depend on --help, as well as host and shell,
278 # and this is not a can of worms we can open at the moment.
279 if sys.platform == 'win32' and compile_environment:
280 all_backends.append('VisualStudio')
281 return tuple(all_backends) or None
283 option('--build-backends', nargs='+', default=build_backend_defaults,
284 choices=build_backends_choices, help='Build backends to generate')
286 @depends('--build-backends')
287 def build_backends(backends):
290 set_config('BUILD_BACKENDS', build_backends)
292 option('--disable-gtest-in-build',
293 help='Force disable building the gtest libxul during the build.',
294 when='--enable-compile-environment')
296 # Determine whether to build the gtest xul. This happens in automation
297 # on Desktop platforms with the exception of Windows PGO, where linking
298 # xul-gtest.dll takes too long.
299 @depends('MOZ_PGO', build_project, target, 'MOZ_AUTOMATION', '--disable-gtest-in-build',
300 enable_tests, when='--enable-compile-environment')
301 def build_gtest(pgo, build_project, target, automation, enabled, enable_tests):
302 if not enable_tests or not enabled:
304 if (automation and build_project == 'browser' and
305 not (pgo and target.os == 'WINNT')):
308 set_config('LINK_GTEST_DURING_COMPILE', build_gtest)
311 # ==============================================================
312 option('--enable-ui-locale', default='en-US',
313 help='Select the user interface locale (default: en-US)')
315 set_config('MOZ_UI_LOCALE', depends('--enable-ui-locale')(lambda x: x))
317 # clang-plugin location
318 # ==============================================================
319 @depends(host_library_name_info, check_build_environment,
320 when='--enable-clang-plugin')
321 def clang_plugin_path(library_name_info, build_env):
322 topobjdir = build_env.topobjdir
323 if topobjdir.endswith('/js/src'):
324 topobjdir = topobjdir[:-7]
325 return os.path.abspath(
326 os.path.join(topobjdir, 'build', 'clang-plugin',
327 '%sclang-plugin%s' % (library_name_info.dll.prefix,
328 library_name_info.dll.suffix))
331 add_old_configure_assignment('CLANG_PLUGIN', clang_plugin_path)
335 # ==============================================================
336 awk = check_prog('AWK', ('gawk', 'mawk', 'nawk', 'awk'))
338 # Until the AWK variable is not necessary in old-configure
340 def awk_for_old_configure(value):
343 add_old_configure_assignment('AWK', awk_for_old_configure)
347 # ==============================================================
348 perl = check_prog('PERL', ('perl5', 'perl'))
350 # Until the PERL variable is not necessary in old-configure
352 def perl_for_old_configure(value):
355 add_old_configure_assignment('PERL', perl_for_old_configure)
358 def perl_version_check(min_version):
360 @checking('for minimum required perl version >= %s' % min_version)
361 def get_perl_version(perl):
362 return Version(check_cmd_output(
363 perl, '-e', 'print $]',
364 onerror=lambda: die('Failed to get perl version.')
367 @depends(get_perl_version)
368 def check_perl_version(version):
369 if version < min_version:
370 die('Perl %s or higher is required.', min_version)
373 @checking('for full perl installation')
374 @imports('subprocess')
375 def has_full_perl_installation(perl):
376 ret = subprocess.call(
377 [perl, '-e', 'use Config; exit(!-d $Config{archlib})'])
380 @depends(has_full_perl_installation)
381 def require_full_perl_installation(has_full_perl_installation):
382 if not has_full_perl_installation:
383 die('Cannot find Config.pm or $Config{archlib}. '
384 'A full perl installation is required.')
386 perl_version_check('5.006')
390 # ==============================================================
391 option(env='MAKE', nargs=1, help='Path to GNU make')
393 @depends('MAKE', host)
394 def possible_makes(make, host):
396 if host.kernel == 'WINNT':
397 candidates.append('mingw32-make')
399 candidates.append(make[0])
400 if host.kernel == 'WINNT':
401 candidates.extend(('make', 'gmake'))
403 candidates.extend(('gmake', 'make'))
406 check_prog('GMAKE', possible_makes)
408 @depends(build_backends, build_project)
409 def tup_include(build_backends, build_project):
410 # We need to check the rustc version when building with tup, but
411 # rustc_info isn't available when configuring js (and build_backends isn't
412 # available from project-specific configure), so as a workaround we only
413 # include the file when we know we'll need it. This can be removed when
414 # we globally require a rustc recent enough to build with tup.
415 if build_project not in ('browser', 'mobile/android'):
417 for backend in build_backends:
419 return 'build/moz.configure/tup.configure'
424 # ==============================================================
426 option(env='WATCHMAN', nargs=1, help='Path to the watchman program')
429 @checking('for watchman', callback=lambda w: w.path if w else 'not found')
432 prog = find_program('watchman')
437 # `watchman version` will talk to the Watchman daemon service.
438 # This can hang due to permissions problems. e.g.
439 # https://github.com/facebook/watchman/issues/376. So use
440 # `watchman --version` to prevent a class of failures.
441 out = check_cmd_output(prog, '--version', onerror=lambda: None)
445 return namespace(path=prog, version=Version(out.strip()))
447 @depends_if(watchman)
448 @checking('for watchman version')
449 def watchman_version(w):
452 set_config('WATCHMAN', watchman.path)
454 @depends_all(hg_version, hg_config, watchman)
455 @checking('for watchman Mercurial integration')
457 def watchman_hg(hg_version, hg_config, watchman):
458 if hg_version < Version('3.8'):
459 return 'no (Mercurial 3.8+ required)'
462 mode_disabled = False
464 for k in ('extensions.fsmonitor', 'extensions.hgext.fsmonitor'):
465 if k in hg_config and hg_config[k] != '!':
468 mode_disabled = hg_config.get('fsmonitor.mode') == 'off'
471 return 'no (fsmonitor extension not enabled)'
473 return 'no (fsmonitor.mode=off disables fsmonitor)'
477 # Miscellaneous programs
478 # ==============================================================
479 check_prog('XARGS', ('xargs',))
482 def extra_programs(target):
483 if target.kernel == 'Darwin':
485 DSYMUTIL=('dsymutil', 'llvm-dsymutil'),
486 MKFSHFS=('newfs_hfs', 'mkfs.hfsplus'),
487 HFS_TOOL=('hfsplus',)
489 if target.os == 'GNU' and target.kernel == 'Linux':
490 return namespace(RPMBUILD=('rpmbuild',))
492 check_prog('DSYMUTIL', extra_programs.DSYMUTIL,
494 check_prog('MKFSHFS', extra_programs.MKFSHFS,
496 check_prog('HFS_TOOL', extra_programs.HFS_TOOL,
498 check_prog('RPMBUILD', extra_programs.RPMBUILD,
504 def makensis_progs(target):
505 if target.kernel != 'WINNT':
515 # Look for nsis installed by msys environment. But only the 32-bit version.
516 # We use an absolute path and insert as the first entry so it is preferred
517 # over a 64-bit exe that may be in PATH.
518 if 'MSYSTEM_PREFIX' in os.environ:
519 prefix = os.path.dirname(os.environ['MSYSTEM_PREFIX'])
520 candidates.insert(0, os.path.join(prefix, 'mingw32', 'bin', 'makensis.exe'))
522 return tuple(candidates)
524 nsis = check_prog('MAKENSISU', makensis_progs, allow_missing=True)
526 # Make sure the version of makensis is up to date.
528 @checking('for NSIS version')
530 def nsis_version(nsis):
531 nsis_min_version = '3.0b1'
532 out = check_cmd_output(nsis, '-version',
533 onerror=lambda: die('Failed to get nsis version.'))
534 m = re.search(r'(?<=v)[0-9]+\.[0-9]+((a|b|rc)[0-9]+)?', out)
537 raise FatalCheckError('Unknown version of makensis')
538 ver = Version(m.group(0))
540 # Versions comparisons don't quite work well with beta versions, so ensure
541 # it works for the non-beta version.
542 if ver < nsis_min_version and (ver >= '3.0a' or ver < '3'):
543 raise FatalCheckError('To build the installer you must have NSIS'
544 ' version %s or greater in your path'
549 # And that makensis is 32-bit (but only on Windows).
550 @depends_if(nsis, when=depends(host)(lambda h: h.kernel == 'WINNT'))
551 @checking('for 32-bit NSIS')
552 def nsis_binary_type(nsis):
553 bin_type = windows_binary_type(nsis)
554 if bin_type != 'win32':
555 raise FatalCheckError('%s is not a 32-bit Windows application' % nsis)
559 # And any flags we have to give to makensis
561 def nsis_flags(host):
562 if host.kernel != 'WINNT':
566 set_config('MAKENSISU_FLAGS', nsis_flags)
568 check_prog('7Z', ('7z', '7za'), allow_missing=True, when=target_is_windows)
570 # Fallthrough to autoconf-based configure
571 include('build/moz.configure/old.configure')
573 @depends(check_build_environment, build_project)
574 @imports('__sandbox__')
576 def config_status_deps(build_env, build_project):
578 topsrcdir = build_env.topsrcdir
579 topobjdir = build_env.topobjdir
581 if not build_env.topobjdir.endswith('js/src'):
583 os.path.join(topsrcdir, build_project, 'confvars.sh'),
584 os.path.join(topobjdir, '.mozconfig.json'),
587 # mozconfig changes may impact js configure.
588 extra_deps = [os.path.join(topobjdir[:-7], '.mozconfig.json')]
590 return list(__sandbox__._all_paths) + extra_deps + [
591 os.path.join(topsrcdir, 'CLOBBER'),
592 os.path.join(topsrcdir, 'configure'),
593 os.path.join(topsrcdir, 'js', 'src', 'configure'),
594 os.path.join(topsrcdir, 'configure.in'),
595 os.path.join(topsrcdir, 'js', 'src', 'configure.in'),
596 os.path.join(topsrcdir, 'nsprpub', 'configure'),
597 os.path.join(topsrcdir, 'config', 'milestone.txt'),
598 os.path.join(topsrcdir, 'browser', 'config', 'version.txt'),
599 os.path.join(topsrcdir, 'browser', 'config', 'version_display.txt'),
600 os.path.join(topsrcdir, 'build', 'virtualenv_packages.txt'),
601 os.path.join(topsrcdir, 'python', 'mozbuild', 'mozbuild', 'virtualenv.py'),
602 os.path.join(topsrcdir, 'testing', 'mozbase', 'packages.txt'),
603 os.path.join(topsrcdir, 'aclocal.m4'),
604 os.path.join(topsrcdir, 'old-configure.in'),
605 os.path.join(topsrcdir, 'js', 'src', 'aclocal.m4'),
606 os.path.join(topsrcdir, 'js', 'src', 'old-configure.in'),
607 ] + glob.glob(os.path.join(topsrcdir, 'build', 'autoconf', '*.m4'))
609 set_config('CONFIG_STATUS_DEPS', config_status_deps)
610 # Please do not add anything after setting config_dep_paths.