Bug 1486801 - Clicking on the [...] should expand the markup container. r=jdescottes
[gecko.git] / moz.configure
blob34badec4e4e3e2ec0dd88893be97a1c445271bbf
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           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
123     elif bool(value):
124         return True
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):
153     if valgrind:
154         if not valgrind_h:
155             die('--enable-valgrind specified but Valgrind is not installed')
156         return True
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):
170     return value
172 @template
173 def library_name_info_template(host_or_target):
174     assert host_or_target in (host, target)
175     compiler = {
176         host: host_c_compiler,
177         target: c_compiler,
178     }[host_or_target]
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'):
186                 return namespace(
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'),
192                 )
194             return namespace(
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'),
200             )
202         elif host_or_target.kernel == 'Darwin':
203             return namespace(
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'),
209             )
210         elif so_version:
211             so = '.so.%s' % so_version
212         else:
213             so = '.so'
215         return namespace(
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'),
221         )
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)
247 @depends('--help')
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):
256     if 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')
264 @imports('sys')
265 def build_backend_defaults(artifact_builds, compile_environment, requested_backends,
266                            _):
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.
270         all_backends = []
271     elif artifact_builds:
272         all_backends = ['FasterMake+RecursiveMake']
273     else:
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):
287     return 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:
302         return None
303     if (automation and build_project == 'browser' and
304         not (pgo and target.os == 'WINNT')):
305         return True
307 set_config('LINK_GTEST_DURING_COMPILE', build_gtest)
309 # Localization
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))
328     )
330 add_old_configure_assignment('CLANG_PLUGIN', clang_plugin_path)
333 # Awk detection
334 # ==============================================================
335 awk = check_prog('AWK', ('gawk', 'mawk', 'nawk', 'awk'))
337 # Until the AWK variable is not necessary in old-configure
338 @depends(awk)
339 def awk_for_old_configure(value):
340     return value
342 add_old_configure_assignment('AWK', awk_for_old_configure)
345 # Perl detection
346 # ==============================================================
347 perl = check_prog('PERL', ('perl5', 'perl'))
349 # Until the PERL variable is not necessary in old-configure
350 @depends(perl)
351 def perl_for_old_configure(value):
352     return value
354 add_old_configure_assignment('PERL', perl_for_old_configure)
356 @template
357 def perl_version_check(min_version):
358     @depends(perl)
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.')
364         ))
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)
371     @depends(perl)
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})'])
377         return ret == 0
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')
388 # GNU make detection
389 # ==============================================================
390 option(env='MAKE', nargs=1, help='Path to GNU make')
392 @depends('MAKE', host)
393 def possible_makes(make, host):
394     candidates = []
395     if host.kernel == 'WINNT':
396         candidates.append('mingw32-make')
397     if make:
398         candidates.append(make[0])
399     if host.kernel == 'WINNT':
400         candidates.extend(('make', 'gmake'))
401     else:
402         candidates.extend(('gmake', 'make'))
403     return candidates
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'):
415         return None
416     for backend in build_backends:
417         if 'Tup' in backend:
418             return 'build/moz.configure/tup.configure'
420 include(tup_include)
422 # watchman detection
423 # ==============================================================
425 option(env='WATCHMAN', nargs=1, help='Path to the watchman program')
427 @depends('WATCHMAN')
428 @checking('for watchman', callback=lambda w: w.path if w else 'not found')
429 def watchman(prog):
430     if not prog:
431         prog = find_program('watchman')
433     if not prog:
434         return
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)
441     if out is None:
442         return
444     return namespace(path=prog, version=Version(out.strip()))
446 @depends_if(watchman)
447 @checking('for watchman version')
448 def watchman_version(w):
449     return w.version
451 set_config('WATCHMAN', watchman.path)
453 @depends_all(hg_version, hg_config, watchman)
454 @checking('for watchman Mercurial integration')
455 @imports('os')
456 def watchman_hg(hg_version, hg_config, watchman):
457     if hg_version < Version('3.8'):
458         return 'no (Mercurial 3.8+ required)'
460     ext_enabled = False
461     mode_disabled = False
463     for k in ('extensions.fsmonitor', 'extensions.hgext.fsmonitor'):
464         if k in hg_config and hg_config[k] != '!':
465             ext_enabled = True
467     mode_disabled = hg_config.get('fsmonitor.mode') == 'off'
469     if not ext_enabled:
470         return 'no (fsmonitor extension not enabled)'
471     if mode_disabled:
472         return 'no (fsmonitor.mode=off disables fsmonitor)'
474     return True
476 # Miscellaneous programs
477 # ==============================================================
478 check_prog('XARGS', ('xargs',))
480 @depends(target)
481 def extra_programs(target):
482     if target.kernel == 'Darwin':
483         return namespace(
484             DSYMUTIL=('dsymutil', 'llvm-dsymutil'),
485             MKFSHFS=('newfs_hfs', 'mkfs.hfsplus'),
486             HFS_TOOL=('hfsplus',)
487         )
488     if target.os == 'GNU' and target.kernel == 'Linux':
489         return namespace(RPMBUILD=('rpmbuild',))
491 check_prog('DSYMUTIL', extra_programs.DSYMUTIL,
492            allow_missing=True)
493 check_prog('MKFSHFS', extra_programs.MKFSHFS,
494            allow_missing=True)
495 check_prog('HFS_TOOL', extra_programs.HFS_TOOL,
496            allow_missing=True)
497 check_prog('RPMBUILD', extra_programs.RPMBUILD,
498            allow_missing=True)
501 @depends(target)
502 @imports('os')
503 def makensis_progs(target):
504     if target.kernel != 'WINNT':
505         return
507     candidates = [
508         'makensis-3.01',
509         'makensis-3.0b3',
510         'makensis-3.0b1',
511         'makensis',
512     ]
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.
526 @depends_if(nsis)
527 @checking('for NSIS version')
528 @imports('re')
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)
535     if not m:
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'
544                               % nsis_min_version)
546     return ver
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)
556     return 'yes'
558 # And any flags we have to give to makensis
559 @depends(host)
560 def nsis_flags(host):
561     if host.kernel != 'WINNT':
562         return '-nocd'
563     return ''
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__')
574 @imports('glob')
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'):
581         extra_deps = [
582             os.path.join(topsrcdir, build_project, 'confvars.sh'),
583             os.path.join(topobjdir, '.mozconfig.json'),
584         ]
585     else:
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.