Bug 1431441 - Part 6 - Start middleman WebReplay process sandbox later r=Alex_Gaynor
[gecko.git] / moz.configure
blob750198c74218994dd588ef2ac03a38eee49dc602
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')
9 # Note:
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.
15 # - etc.
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):
22     if value:
23         return True
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):
39     if value:
40         return False
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):
49     if compile_env:
50         return True
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):
60     if value:
61         return True
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):
71     if official:
72         return True
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):
80     if value:
81         return '0'
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,
90                          has_clone='0')
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',
100           nargs='?',
101           help='Enable building with developer debug info '
102                '(using the given compiler flags).')
104 @depends('--enable-debug')
105 def moz_debug(debug):
106     if debug:
107         return bool(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')
121 def debug_rust():
122     return True
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):
151     if valgrind:
152         if not valgrind_h:
153             die('--enable-valgrind specified but Valgrind is not installed')
154         return True
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):
168     return value
170 @template
171 def library_name_info_template(host_or_target):
172     assert host_or_target in (host, target)
173     compiler = {
174         host: host_c_compiler,
175         target: c_compiler,
176     }[host_or_target]
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'):
184                 return namespace(
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'),
190                 )
192             return namespace(
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'),
198             )
200         elif host_or_target.kernel == 'Darwin':
201             return namespace(
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'),
207             )
208         elif so_version:
209             so = '.so.%s' % so_version
210         else:
211             so = '.so'
213         return namespace(
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'),
219         )
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)
246 @depends('--help')
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):
255     if 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')
263 @imports('sys')
264 def build_backend_defaults(artifact_builds, compile_environment, requested_backends,
265                            _):
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.
269         all_backends = []
270     elif artifact_builds:
271         all_backends = ['FasterMake+RecursiveMake']
272     else:
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):
286     return backends
288 set_config('BUILD_BACKENDS', build_backends)
291 @depends(check_build_environment, build_backends)
292 @imports('glob')
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 = (
297         ('Tup', 'Make'),
298         ('Make', 'Tup')
299     )
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:
322         return None
323     if (automation and build_project == 'browser' and
324         not (pgo and target.os == 'WINNT')):
325         return True
327 set_config('LINK_GTEST_DURING_COMPILE', build_gtest)
329 # Localization
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))
348     )
350 add_old_configure_assignment('CLANG_PLUGIN', clang_plugin_path)
353 # Awk detection
354 # ==============================================================
355 awk = check_prog('AWK', ('gawk', 'mawk', 'nawk', 'awk'))
357 # Until the AWK variable is not necessary in old-configure
358 @depends(awk)
359 def awk_for_old_configure(value):
360     return value
362 add_old_configure_assignment('AWK', awk_for_old_configure)
365 # Perl detection
366 # ==============================================================
367 perl = check_prog('PERL', ('perl5', 'perl'))
369 # Until the PERL variable is not necessary in old-configure
370 @depends(perl)
371 def perl_for_old_configure(value):
372     return value
374 add_old_configure_assignment('PERL', perl_for_old_configure)
376 @template
377 def perl_version_check(min_version):
378     @depends(perl)
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.')
384         ))
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)
391     @depends(perl)
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})'])
397         return ret == 0
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')
408 # GNU make detection
409 # ==============================================================
410 option(env='MAKE', nargs=1, help='Path to GNU make')
412 @depends('MAKE', host)
413 def possible_makes(make, host):
414     candidates = []
415     if host.kernel == 'WINNT':
416         candidates.append('mingw32-make')
417     if make:
418         candidates.append(make[0])
419     if host.kernel == 'WINNT':
420         candidates.extend(('make', 'gmake'))
421     else:
422         candidates.extend(('gmake', 'make'))
423     return candidates
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'):
435         return None
436     for backend in build_backends:
437         if 'Tup' in backend:
438             return 'build/moz.configure/tup.configure'
440 include(tup_include)
442 # watchman detection
443 # ==============================================================
445 option(env='WATCHMAN', nargs=1, help='Path to the watchman program')
447 @depends('WATCHMAN')
448 @checking('for watchman', callback=lambda w: w.path if w else 'not found')
449 def watchman(prog):
450     if not prog:
451         prog = find_program('watchman')
453     if not prog:
454         return
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)
461     if out is None:
462         return
464     return namespace(path=prog, version=Version(out.strip()))
466 @depends_if(watchman)
467 @checking('for watchman version')
468 def watchman_version(w):
469     return w.version
471 set_config('WATCHMAN', watchman.path)
473 @depends_all(hg_version, hg_config, watchman)
474 @checking('for watchman Mercurial integration')
475 @imports('os')
476 def watchman_hg(hg_version, hg_config, watchman):
477     if hg_version < Version('3.8'):
478         return 'no (Mercurial 3.8+ required)'
480     ext_enabled = False
481     mode_disabled = False
483     for k in ('extensions.fsmonitor', 'extensions.hgext.fsmonitor'):
484         if k in hg_config and hg_config[k] != '!':
485             ext_enabled = True
487     mode_disabled = hg_config.get('fsmonitor.mode') == 'off'
489     if not ext_enabled:
490         return 'no (fsmonitor extension not enabled)'
491     if mode_disabled:
492         return 'no (fsmonitor.mode=off disables fsmonitor)'
494     return True
496 # Miscellaneous programs
497 # ==============================================================
498 check_prog('XARGS', ('xargs',))
500 @depends(target)
501 def extra_programs(target):
502     if target.kernel == 'Darwin':
503         return namespace(
504             DSYMUTIL=('dsymutil', 'llvm-dsymutil'),
505             MKFSHFS=('newfs_hfs', 'mkfs.hfsplus'),
506             HFS_TOOL=('hfsplus',)
507         )
508     if target.os == 'GNU' and target.kernel == 'Linux':
509         return namespace(RPMBUILD=('rpmbuild',))
511 check_prog('DSYMUTIL', extra_programs.DSYMUTIL,
512            allow_missing=True)
513 check_prog('MKFSHFS', extra_programs.MKFSHFS,
514            allow_missing=True)
515 check_prog('HFS_TOOL', extra_programs.HFS_TOOL,
516            allow_missing=True)
517 check_prog('RPMBUILD', extra_programs.RPMBUILD,
518            allow_missing=True)
521 @depends(target)
522 @imports('os')
523 def makensis_progs(target):
524     if target.kernel != 'WINNT':
525         return
527     candidates = [
528         'makensis-3.01',
529         'makensis-3.0b3',
530         'makensis-3.0b1',
531         'makensis',
532     ]
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.
546 @depends_if(nsis)
547 @checking('for NSIS version')
548 @imports('re')
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)
555     if not m:
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'
564                               % nsis_min_version)
566     return ver
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)
576     return 'yes'
578 # And any flags we have to give to makensis
579 @depends(host)
580 def nsis_flags(host):
581     if host.kernel != 'WINNT':
582         return '-nocd'
583     return ''
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__')
594 @imports('glob')
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'):
601         extra_deps = [
602             os.path.join(topsrcdir, build_project, 'confvars.sh'),
603             os.path.join(topobjdir, '.mozconfig.json'),
604         ]
605     else:
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.