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_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',
263 '--enable-build-backend', '--help')
265 def build_backend_defaults(artifact_builds, compile_environment, requested_backends,
267 if 'Tup' in requested_backends:
268 # As a special case, if Tup was requested, do not combine it with any
269 # Make based backend by default.
271 elif artifact_builds:
272 all_backends = ['FasterMake+RecursiveMake']
274 all_backends = ['RecursiveMake', 'FasterMake']
275 # Normally, we'd use target.os == 'WINNT', but a dependency on target
276 # would require target to depend on --help, as well as host and shell,
277 # and this is not a can of worms we can open at the moment.
278 if sys.platform == 'win32' and compile_environment:
279 all_backends.append('VisualStudio')
280 return tuple(all_backends) or None
282 option('--build-backends', nargs='+', default=build_backend_defaults,
283 choices=build_backends_choices, help='Build backends to generate')
285 @depends('--build-backends')
286 def build_backends(backends):
289 set_config('BUILD_BACKENDS', build_backends)
291 option('--disable-gtest-in-build',
292 help='Force disable building the gtest libxul during the build.',
293 when='--enable-compile-environment')
295 # Determine whether to build the gtest xul. This happens in automation
296 # on Desktop platforms with the exception of Windows PGO, where linking
297 # xul-gtest.dll takes too long.
298 @depends('MOZ_PGO', build_project, target, 'MOZ_AUTOMATION', '--disable-gtest-in-build',
299 enable_tests, when='--enable-compile-environment')
300 def build_gtest(pgo, build_project, target, automation, enabled, enable_tests):
301 if not enable_tests or not enabled:
303 if (automation and build_project == 'browser' and
304 not (pgo and target.os == 'WINNT')):
307 set_config('LINK_GTEST_DURING_COMPILE', build_gtest)
310 # ==============================================================
311 option('--enable-ui-locale', default='en-US',
312 help='Select the user interface locale (default: en-US)')
314 set_config('MOZ_UI_LOCALE', depends('--enable-ui-locale')(lambda x: x))
316 # clang-plugin location
317 # ==============================================================
318 @depends(host_library_name_info, check_build_environment,
319 when='--enable-clang-plugin')
320 def clang_plugin_path(library_name_info, build_env):
321 topobjdir = build_env.topobjdir
322 if topobjdir.endswith('/js/src'):
323 topobjdir = topobjdir[:-7]
324 return os.path.abspath(
325 os.path.join(topobjdir, 'build', 'clang-plugin',
326 '%sclang-plugin%s' % (library_name_info.dll.prefix,
327 library_name_info.dll.suffix))
330 add_old_configure_assignment('CLANG_PLUGIN', clang_plugin_path)
334 # ==============================================================
335 awk = check_prog('AWK', ('gawk', 'mawk', 'nawk', 'awk'))
337 # Until the AWK variable is not necessary in old-configure
339 def awk_for_old_configure(value):
342 add_old_configure_assignment('AWK', awk_for_old_configure)
346 # ==============================================================
347 perl = check_prog('PERL', ('perl5', 'perl'))
349 # Until the PERL variable is not necessary in old-configure
351 def perl_for_old_configure(value):
354 add_old_configure_assignment('PERL', perl_for_old_configure)
357 def perl_version_check(min_version):
359 @checking('for minimum required perl version >= %s' % min_version)
360 def get_perl_version(perl):
361 return Version(check_cmd_output(
362 perl, '-e', 'print $]',
363 onerror=lambda: die('Failed to get perl version.')
366 @depends(get_perl_version)
367 def check_perl_version(version):
368 if version < min_version:
369 die('Perl %s or higher is required.', min_version)
372 @checking('for full perl installation')
373 @imports('subprocess')
374 def has_full_perl_installation(perl):
375 ret = subprocess.call(
376 [perl, '-e', 'use Config; exit(!-d $Config{archlib})'])
379 @depends(has_full_perl_installation)
380 def require_full_perl_installation(has_full_perl_installation):
381 if not has_full_perl_installation:
382 die('Cannot find Config.pm or $Config{archlib}. '
383 'A full perl installation is required.')
385 perl_version_check('5.006')
389 # ==============================================================
390 option(env='MAKE', nargs=1, help='Path to GNU make')
392 @depends('MAKE', host)
393 def possible_makes(make, host):
395 if host.kernel == 'WINNT':
396 candidates.append('mingw32-make')
398 candidates.append(make[0])
399 if host.kernel == 'WINNT':
400 candidates.extend(('make', 'gmake'))
402 candidates.extend(('gmake', 'make'))
405 check_prog('GMAKE', possible_makes)
407 @depends(build_backends, build_project)
408 def tup_include(build_backends, build_project):
409 # We need to check the rustc version when building with tup, but
410 # rustc_info isn't available when configuring js (and build_backends isn't
411 # available from project-specific configure), so as a workaround we only
412 # include the file when we know we'll need it. This can be removed when
413 # we globally require a rustc recent enough to build with tup.
414 if build_project not in ('browser', 'mobile/android'):
416 for backend in build_backends:
418 return 'build/moz.configure/tup.configure'
423 # ==============================================================
425 option(env='WATCHMAN', nargs=1, help='Path to the watchman program')
428 @checking('for watchman', callback=lambda w: w.path if w else 'not found')
431 prog = find_program('watchman')
436 # `watchman version` will talk to the Watchman daemon service.
437 # This can hang due to permissions problems. e.g.
438 # https://github.com/facebook/watchman/issues/376. So use
439 # `watchman --version` to prevent a class of failures.
440 out = check_cmd_output(prog, '--version', onerror=lambda: None)
444 return namespace(path=prog, version=Version(out.strip()))
446 @depends_if(watchman)
447 @checking('for watchman version')
448 def watchman_version(w):
451 set_config('WATCHMAN', watchman.path)
453 @depends_all(hg_version, hg_config, watchman)
454 @checking('for watchman Mercurial integration')
456 def watchman_hg(hg_version, hg_config, watchman):
457 if hg_version < Version('3.8'):
458 return 'no (Mercurial 3.8+ required)'
461 mode_disabled = False
463 for k in ('extensions.fsmonitor', 'extensions.hgext.fsmonitor'):
464 if k in hg_config and hg_config[k] != '!':
467 mode_disabled = hg_config.get('fsmonitor.mode') == 'off'
470 return 'no (fsmonitor extension not enabled)'
472 return 'no (fsmonitor.mode=off disables fsmonitor)'
476 # Miscellaneous programs
477 # ==============================================================
478 check_prog('XARGS', ('xargs',))
481 def extra_programs(target):
482 if target.kernel == 'Darwin':
484 DSYMUTIL=('dsymutil', 'llvm-dsymutil'),
485 MKFSHFS=('newfs_hfs', 'mkfs.hfsplus'),
486 HFS_TOOL=('hfsplus',)
488 if target.os == 'GNU' and target.kernel == 'Linux':
489 return namespace(RPMBUILD=('rpmbuild',))
491 check_prog('DSYMUTIL', extra_programs.DSYMUTIL,
493 check_prog('MKFSHFS', extra_programs.MKFSHFS,
495 check_prog('HFS_TOOL', extra_programs.HFS_TOOL,
497 check_prog('RPMBUILD', extra_programs.RPMBUILD,
503 def makensis_progs(target):
504 if target.kernel != 'WINNT':
514 # Look for nsis installed by msys environment. But only the 32-bit version.
515 # We use an absolute path and insert as the first entry so it is preferred
516 # over a 64-bit exe that may be in PATH.
517 if 'MSYSTEM_PREFIX' in os.environ:
518 prefix = os.path.dirname(os.environ['MSYSTEM_PREFIX'])
519 candidates.insert(0, os.path.join(prefix, 'mingw32', 'bin', 'makensis.exe'))
521 return tuple(candidates)
523 nsis = check_prog('MAKENSISU', makensis_progs, allow_missing=True)
525 # Make sure the version of makensis is up to date.
527 @checking('for NSIS version')
529 def nsis_version(nsis):
530 nsis_min_version = '3.0b1'
531 out = check_cmd_output(nsis, '-version',
532 onerror=lambda: die('Failed to get nsis version.'))
533 m = re.search(r'(?<=v)[0-9]+\.[0-9]+((a|b|rc)[0-9]+)?', out)
536 raise FatalCheckError('Unknown version of makensis')
537 ver = Version(m.group(0))
539 # Versions comparisons don't quite work well with beta versions, so ensure
540 # it works for the non-beta version.
541 if ver < nsis_min_version and (ver >= '3.0a' or ver < '3'):
542 raise FatalCheckError('To build the installer you must have NSIS'
543 ' version %s or greater in your path'
548 # And that makensis is 32-bit (but only on Windows).
549 @depends_if(nsis, when=depends(host)(lambda h: h.kernel == 'WINNT'))
550 @checking('for 32-bit NSIS')
551 def nsis_binary_type(nsis):
552 bin_type = windows_binary_type(nsis)
553 if bin_type != 'win32':
554 raise FatalCheckError('%s is not a 32-bit Windows application' % nsis)
558 # And any flags we have to give to makensis
560 def nsis_flags(host):
561 if host.kernel != 'WINNT':
565 set_config('MAKENSISU_FLAGS', nsis_flags)
567 check_prog('7Z', ('7z', '7za'), allow_missing=True, when=target_is_windows)
569 # Fallthrough to autoconf-based configure
570 include('build/moz.configure/old.configure')
572 @depends(check_build_environment, build_project)
573 @imports('__sandbox__')
575 def config_status_deps(build_env, build_project):
577 topsrcdir = build_env.topsrcdir
578 topobjdir = build_env.topobjdir
580 if not build_env.topobjdir.endswith('js/src'):
582 os.path.join(topsrcdir, build_project, 'confvars.sh'),
583 os.path.join(topobjdir, '.mozconfig.json'),
586 # mozconfig changes may impact js configure.
587 extra_deps = [os.path.join(topobjdir[:-7], '.mozconfig.json')]
589 return list(__sandbox__._all_paths) + extra_deps + [
590 os.path.join(topsrcdir, 'CLOBBER'),
591 os.path.join(topsrcdir, 'configure'),
592 os.path.join(topsrcdir, 'js', 'src', 'configure'),
593 os.path.join(topsrcdir, 'configure.in'),
594 os.path.join(topsrcdir, 'js', 'src', 'configure.in'),
595 os.path.join(topsrcdir, 'nsprpub', 'configure'),
596 os.path.join(topsrcdir, 'config', 'milestone.txt'),
597 os.path.join(topsrcdir, 'browser', 'config', 'version.txt'),
598 os.path.join(topsrcdir, 'browser', 'config', 'version_display.txt'),
599 os.path.join(topsrcdir, 'build', 'virtualenv_packages.txt'),
600 os.path.join(topsrcdir, 'python', 'mozbuild', 'mozbuild', 'virtualenv.py'),
601 os.path.join(topsrcdir, 'testing', 'mozbase', 'packages.txt'),
602 os.path.join(topsrcdir, 'aclocal.m4'),
603 os.path.join(topsrcdir, 'old-configure.in'),
604 os.path.join(topsrcdir, 'js', 'src', 'aclocal.m4'),
605 os.path.join(topsrcdir, 'js', 'src', 'old-configure.in'),
606 ] + glob.glob(os.path.join(topsrcdir, 'build', 'autoconf', '*.m4'))
608 set_config('CONFIG_STATUS_DEPS', config_status_deps)
609 # Please do not add anything after setting config_dep_paths.