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 default=depends(when='--enable-debug')(lambda: True),
118 help='Build Rust code with debug assertions turned on.')
120 @depends(when='--enable-rust-debug')
124 set_config('MOZ_DEBUG_RUST', debug_rust)
125 set_define('MOZ_DEBUG_RUST', debug_rust)
127 include('build/moz.configure/pkg.configure')
128 # Make this assignment here rather than in pkg.configure to avoid
129 # requiring this file in unit tests.
130 add_old_configure_assignment('PKG_CONFIG', pkg_config)
132 include('build/moz.configure/toolchain.configure',
133 when='--enable-compile-environment')
134 include('build/moz.configure/memory.configure',
135 when='--enable-compile-environment')
136 include('build/moz.configure/headers.configure',
137 when='--enable-compile-environment')
138 include('build/moz.configure/warnings.configure',
139 when='--enable-compile-environment')
140 include('build/moz.configure/flags.configure',
141 when='--enable-compile-environment')
142 # rust.configure is included by js/moz.configure.
144 js_option('--enable-valgrind',
145 help='Enable Valgrind integration hooks')
147 valgrind_h = check_header('valgrind/valgrind.h', when='--enable-valgrind')
149 @depends('--enable-valgrind', valgrind_h)
150 def check_valgrind(valgrind, valgrind_h):
153 die('--enable-valgrind specified but Valgrind is not installed')
156 set_define('MOZ_VALGRIND', check_valgrind)
157 set_config('MOZ_VALGRIND', check_valgrind)
159 @depends(target, host)
160 def is_openbsd(target, host):
161 return target.kernel == 'OpenBSD' or host.kernel == 'OpenBSD'
163 option(env='SO_VERSION', nargs=1, default='1.0', when=is_openbsd,
164 help='Shared library version for OpenBSD systems')
166 @depends('SO_VERSION', when=is_openbsd)
167 def so_version(value):
171 def library_name_info_template(host_or_target):
172 assert host_or_target in (host, target)
174 host: host_c_compiler,
178 @depends(host_or_target, compiler, so_version)
179 def library_name_info_impl(host_or_target, compiler, so_version):
180 if host_or_target.kernel == 'WINNT':
181 # There aren't artifacts for mingw builds, so it's OK that the
182 # results are inaccurate in that case.
183 if compiler and compiler.type not in ('msvc', 'clang-cl'):
185 dll=namespace(prefix='', suffix='.dll'),
186 lib=namespace(prefix='lib', suffix='a'),
187 import_lib=namespace(prefix='lib', suffix='a'),
188 rust_lib=namespace(prefix='', suffix='lib'),
189 obj=namespace(prefix='', suffix='o'),
193 dll=namespace(prefix='', suffix='.dll'),
194 lib=namespace(prefix='', suffix='lib'),
195 import_lib=namespace(prefix='', suffix='lib'),
196 rust_lib=namespace(prefix='', suffix='lib'),
197 obj=namespace(prefix='', suffix='obj'),
200 elif host_or_target.kernel == 'Darwin':
202 dll=namespace(prefix='lib', suffix='.dylib'),
203 lib=namespace(prefix='lib', suffix='a'),
204 import_lib=namespace(prefix=None, suffix=''),
205 rust_lib=namespace(prefix='lib', suffix='a'),
206 obj=namespace(prefix='', suffix='o'),
209 so = '.so.%s' % so_version
214 dll=namespace(prefix='lib', suffix=so),
215 lib=namespace(prefix='lib', suffix='a'),
216 import_lib=namespace(prefix=None, suffix=''),
217 rust_lib=namespace(prefix='lib', suffix='a'),
218 obj=namespace(prefix='', suffix='o'),
221 return library_name_info_impl
223 host_library_name_info = library_name_info_template(host)
224 library_name_info = library_name_info_template(target)
226 set_config('DLL_PREFIX', library_name_info.dll.prefix)
227 set_config('DLL_SUFFIX', library_name_info.dll.suffix)
228 set_config('HOST_DLL_PREFIX', host_library_name_info.dll.prefix)
229 set_config('HOST_DLL_SUFFIX', host_library_name_info.dll.suffix)
230 set_config('LIB_PREFIX', library_name_info.lib.prefix)
231 set_config('LIB_SUFFIX', library_name_info.lib.suffix)
232 set_config('RUST_LIB_PREFIX', library_name_info.rust_lib.prefix)
233 set_config('RUST_LIB_SUFFIX', library_name_info.rust_lib.suffix)
234 set_config('OBJ_SUFFIX', library_name_info.obj.suffix)
235 # Lots of compilation tests depend on this variable being present.
236 add_old_configure_assignment('OBJ_SUFFIX', library_name_info.obj.suffix)
237 set_config('IMPORT_LIB_SUFFIX', library_name_info.import_lib.suffix)
238 set_define('MOZ_DLL_PREFIX', depends(library_name_info.dll.prefix)(lambda s: '"%s"' % s))
239 set_define('MOZ_DLL_SUFFIX', depends(library_name_info.dll.suffix)(lambda s: '"%s"' % s))
241 # Depends on host_library_name_info, so needs to go here.
242 include('build/moz.configure/bindgen.configure',
243 when='--enable-compile-environment')
244 include(include_project_configure)
247 @imports(_from='mozbuild.backend', _import='backends')
248 def build_backends_choices(_):
249 return tuple(backends)
252 @deprecated_option('--enable-build-backend', nargs='+',
253 choices=build_backends_choices)
254 def build_backend(backends):
256 return tuple('+%s' % b for b in backends)
258 imply_option('--build-backends', build_backend)
261 @depends('--enable-artifact-builds', '--disable-compile-environment',
262 '--enable-build-backend', '--help')
264 def build_backend_defaults(artifact_builds, compile_environment, requested_backends,
266 if 'Tup' in requested_backends:
267 # As a special case, if Tup was requested, do not combine it with any
268 # Make based backend by default.
270 elif artifact_builds:
271 all_backends = ['FasterMake+RecursiveMake']
273 all_backends = ['RecursiveMake', 'FasterMake']
274 # Normally, we'd use target.os == 'WINNT', but a dependency on target
275 # would require target to depend on --help, as well as host and shell,
276 # and this is not a can of worms we can open at the moment.
277 if sys.platform == 'win32' and compile_environment:
278 all_backends.append('VisualStudio')
279 return tuple(all_backends) or None
281 option('--build-backends', nargs='+', default=build_backend_defaults,
282 choices=build_backends_choices, help='Build backends to generate')
284 @depends('--build-backends')
285 def build_backends(backends):
288 set_config('BUILD_BACKENDS', build_backends)
291 @depends(check_build_environment, build_backends)
293 def check_objdir_backend_reuse(build_env, backends):
294 # "Make based" might be RecursiveMake or a hybrid backend, so "Make" is
295 # intentionally vague for use with the substring match below.
296 incompatible_backends = (
300 for backend_file in glob.iglob(os.path.join(build_env.topobjdir,
301 'backend.*Backend')):
302 for prev, curr in incompatible_backends:
303 if prev in backend_file and any(curr in b for b in backends):
304 die("The active objdir, %s, was previously "
305 "used to build with a %s based backend. "
306 "Change objdirs (by setting MOZ_OBJDIR in "
307 "your mozconfig) or clobber to continue.\n",
308 build_env.topobjdir, prev)
311 option('--disable-gtest-in-build',
312 help='Force disable building the gtest libxul during the build.',
313 when='--enable-compile-environment')
315 # Determine whether to build the gtest xul. This happens in automation
316 # on Desktop platforms with the exception of Windows PGO, where linking
317 # xul-gtest.dll takes too long.
318 @depends('MOZ_PGO', build_project, target, 'MOZ_AUTOMATION', '--disable-gtest-in-build',
319 enable_tests, when='--enable-compile-environment')
320 def build_gtest(pgo, build_project, target, automation, enabled, enable_tests):
321 if not enable_tests or not enabled:
323 if (automation and build_project == 'browser' and
324 not (pgo and target.os == 'WINNT')):
327 set_config('LINK_GTEST_DURING_COMPILE', build_gtest)
330 # ==============================================================
331 option('--enable-ui-locale', default='en-US',
332 help='Select the user interface locale (default: en-US)')
334 set_config('MOZ_UI_LOCALE', depends('--enable-ui-locale')(lambda x: x))
336 # clang-plugin location
337 # ==============================================================
338 @depends(host_library_name_info, check_build_environment,
339 when='--enable-clang-plugin')
340 def clang_plugin_path(library_name_info, build_env):
341 topobjdir = build_env.topobjdir
342 if topobjdir.endswith('/js/src'):
343 topobjdir = topobjdir[:-7]
344 return os.path.abspath(
345 os.path.join(topobjdir, 'build', 'clang-plugin',
346 '%sclang-plugin%s' % (library_name_info.dll.prefix,
347 library_name_info.dll.suffix))
350 add_old_configure_assignment('CLANG_PLUGIN', clang_plugin_path)
354 # ==============================================================
355 awk = check_prog('AWK', ('gawk', 'mawk', 'nawk', 'awk'))
357 # Until the AWK variable is not necessary in old-configure
359 def awk_for_old_configure(value):
362 add_old_configure_assignment('AWK', awk_for_old_configure)
366 # ==============================================================
367 perl = check_prog('PERL', ('perl5', 'perl'))
369 # Until the PERL variable is not necessary in old-configure
371 def perl_for_old_configure(value):
374 add_old_configure_assignment('PERL', perl_for_old_configure)
377 def perl_version_check(min_version):
379 @checking('for minimum required perl version >= %s' % min_version)
380 def get_perl_version(perl):
381 return Version(check_cmd_output(
382 perl, '-e', 'print $]',
383 onerror=lambda: die('Failed to get perl version.')
386 @depends(get_perl_version)
387 def check_perl_version(version):
388 if version < min_version:
389 die('Perl %s or higher is required.', min_version)
392 @checking('for full perl installation')
393 @imports('subprocess')
394 def has_full_perl_installation(perl):
395 ret = subprocess.call(
396 [perl, '-e', 'use Config; exit(!-d $Config{archlib})'])
399 @depends(has_full_perl_installation)
400 def require_full_perl_installation(has_full_perl_installation):
401 if not has_full_perl_installation:
402 die('Cannot find Config.pm or $Config{archlib}. '
403 'A full perl installation is required.')
405 perl_version_check('5.006')
409 # ==============================================================
410 option(env='MAKE', nargs=1, help='Path to GNU make')
412 @depends('MAKE', host)
413 def possible_makes(make, host):
415 if host.kernel == 'WINNT':
416 candidates.append('mingw32-make')
418 candidates.append(make[0])
419 if host.kernel == 'WINNT':
420 candidates.extend(('make', 'gmake'))
422 candidates.extend(('gmake', 'make'))
425 check_prog('GMAKE', possible_makes)
427 @depends(build_backends, build_project)
428 def tup_include(build_backends, build_project):
429 # We need to check the rustc version when building with tup, but
430 # rustc_info isn't available when configuring js (and build_backends isn't
431 # available from project-specific configure), so as a workaround we only
432 # include the file when we know we'll need it. This can be removed when
433 # we globally require a rustc recent enough to build with tup.
434 if build_project not in ('browser', 'mobile/android'):
436 for backend in build_backends:
438 return 'build/moz.configure/tup.configure'
443 # ==============================================================
445 option(env='WATCHMAN', nargs=1, help='Path to the watchman program')
448 @checking('for watchman', callback=lambda w: w.path if w else 'not found')
451 prog = find_program('watchman')
456 # `watchman version` will talk to the Watchman daemon service.
457 # This can hang due to permissions problems. e.g.
458 # https://github.com/facebook/watchman/issues/376. So use
459 # `watchman --version` to prevent a class of failures.
460 out = check_cmd_output(prog, '--version', onerror=lambda: None)
464 return namespace(path=prog, version=Version(out.strip()))
466 @depends_if(watchman)
467 @checking('for watchman version')
468 def watchman_version(w):
471 set_config('WATCHMAN', watchman.path)
473 @depends_all(hg_version, hg_config, watchman)
474 @checking('for watchman Mercurial integration')
476 def watchman_hg(hg_version, hg_config, watchman):
477 if hg_version < Version('3.8'):
478 return 'no (Mercurial 3.8+ required)'
481 mode_disabled = False
483 for k in ('extensions.fsmonitor', 'extensions.hgext.fsmonitor'):
484 if k in hg_config and hg_config[k] != '!':
487 mode_disabled = hg_config.get('fsmonitor.mode') == 'off'
490 return 'no (fsmonitor extension not enabled)'
492 return 'no (fsmonitor.mode=off disables fsmonitor)'
496 # Miscellaneous programs
497 # ==============================================================
498 check_prog('XARGS', ('xargs',))
501 def extra_programs(target):
502 if target.kernel == 'Darwin':
504 DSYMUTIL=('dsymutil', 'llvm-dsymutil'),
505 MKFSHFS=('newfs_hfs', 'mkfs.hfsplus'),
506 HFS_TOOL=('hfsplus',)
508 if target.os == 'GNU' and target.kernel == 'Linux':
509 return namespace(RPMBUILD=('rpmbuild',))
511 check_prog('DSYMUTIL', extra_programs.DSYMUTIL,
513 check_prog('MKFSHFS', extra_programs.MKFSHFS,
515 check_prog('HFS_TOOL', extra_programs.HFS_TOOL,
517 check_prog('RPMBUILD', extra_programs.RPMBUILD,
523 def makensis_progs(target):
524 if target.kernel != 'WINNT':
534 # Look for nsis installed by msys environment. But only the 32-bit version.
535 # We use an absolute path and insert as the first entry so it is preferred
536 # over a 64-bit exe that may be in PATH.
537 if 'MSYSTEM_PREFIX' in os.environ:
538 prefix = os.path.dirname(os.environ['MSYSTEM_PREFIX'])
539 candidates.insert(0, os.path.join(prefix, 'mingw32', 'bin', 'makensis.exe'))
541 return tuple(candidates)
543 nsis = check_prog('MAKENSISU', makensis_progs, allow_missing=True)
545 # Make sure the version of makensis is up to date.
547 @checking('for NSIS version')
549 def nsis_version(nsis):
550 nsis_min_version = '3.0b1'
551 out = check_cmd_output(nsis, '-version',
552 onerror=lambda: die('Failed to get nsis version.'))
553 m = re.search(r'(?<=v)[0-9]+\.[0-9]+((a|b|rc)[0-9]+)?', out)
556 raise FatalCheckError('Unknown version of makensis')
557 ver = Version(m.group(0))
559 # Versions comparisons don't quite work well with beta versions, so ensure
560 # it works for the non-beta version.
561 if ver < nsis_min_version and (ver >= '3.0a' or ver < '3'):
562 raise FatalCheckError('To build the installer you must have NSIS'
563 ' version %s or greater in your path'
568 # And that makensis is 32-bit (but only on Windows).
569 @depends_if(nsis, when=depends(host)(lambda h: h.kernel == 'WINNT'))
570 @checking('for 32-bit NSIS')
571 def nsis_binary_type(nsis):
572 bin_type = windows_binary_type(nsis)
573 if bin_type != 'win32':
574 raise FatalCheckError('%s is not a 32-bit Windows application' % nsis)
578 # And any flags we have to give to makensis
580 def nsis_flags(host):
581 if host.kernel != 'WINNT':
585 set_config('MAKENSISU_FLAGS', nsis_flags)
587 check_prog('7Z', ('7z', '7za'), allow_missing=True, when=target_is_windows)
589 # Fallthrough to autoconf-based configure
590 include('build/moz.configure/old.configure')
592 @depends(check_build_environment, build_project)
593 @imports('__sandbox__')
595 def config_status_deps(build_env, build_project):
597 topsrcdir = build_env.topsrcdir
598 topobjdir = build_env.topobjdir
600 if not build_env.topobjdir.endswith('js/src'):
602 os.path.join(topsrcdir, build_project, 'confvars.sh'),
603 os.path.join(topobjdir, '.mozconfig.json'),
606 # mozconfig changes may impact js configure.
607 extra_deps = [os.path.join(topobjdir[:-7], '.mozconfig.json')]
609 return list(__sandbox__._all_paths) + extra_deps + [
610 os.path.join(topsrcdir, 'CLOBBER'),
611 os.path.join(topsrcdir, 'configure'),
612 os.path.join(topsrcdir, 'js', 'src', 'configure'),
613 os.path.join(topsrcdir, 'configure.in'),
614 os.path.join(topsrcdir, 'js', 'src', 'configure.in'),
615 os.path.join(topsrcdir, 'nsprpub', 'configure'),
616 os.path.join(topsrcdir, 'config', 'milestone.txt'),
617 os.path.join(topsrcdir, 'browser', 'config', 'version.txt'),
618 os.path.join(topsrcdir, 'browser', 'config', 'version_display.txt'),
619 os.path.join(topsrcdir, 'build', 'virtualenv_packages.txt'),
620 os.path.join(topsrcdir, 'python', 'mozbuild', 'mozbuild', 'virtualenv.py'),
621 os.path.join(topsrcdir, 'testing', 'mozbase', 'packages.txt'),
622 os.path.join(topsrcdir, 'aclocal.m4'),
623 os.path.join(topsrcdir, 'old-configure.in'),
624 os.path.join(topsrcdir, 'js', 'src', 'aclocal.m4'),
625 os.path.join(topsrcdir, 'js', 'src', 'old-configure.in'),
626 ] + glob.glob(os.path.join(topsrcdir, 'build', 'autoconf', '*.m4'))
628 set_config('CONFIG_STATUS_DEPS', config_status_deps)
629 # Please do not add anything after setting config_dep_paths.