Bug 1477919 [wpt PR 12154] - url: DecodeURLEscapeSequences() should not apply UTF...
[gecko.git] / moz.configure
blob0bf96642120e52674d588ea5f0de0e7f944c7506
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')
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', '--help')
263 @imports('sys')
264 def build_backend_defaults(artifact_builds, compile_environment, _):
265     if artifact_builds:
266         all_backends = ['FasterMake+RecursiveMake']
267     else:
268         all_backends = ['RecursiveMake', 'FasterMake']
269     # Normally, we'd use target.os == 'WINNT', but a dependency on target
270     # would require target to depend on --help, as well as host and shell,
271     # and this is not a can of worms we can open at the moment.
272     if sys.platform == 'win32' and compile_environment:
273         all_backends.append('VisualStudio')
274     return tuple(all_backends)
276 option('--build-backends', nargs='+', default=build_backend_defaults,
277        choices=build_backends_choices, help='Build backends to generate')
279 @depends('--build-backends')
280 def build_backends(backends):
281     return backends
283 set_config('BUILD_BACKENDS', build_backends)
285 option('--disable-gtest-in-build',
286        help='Force disable building the gtest libxul during the build.',
287        when='--enable-compile-environment')
289 # Determine whether to build the gtest xul. This happens in automation
290 # on Desktop platforms with the exception of Windows PGO, where linking
291 # xul-gtest.dll takes too long.
292 @depends('MOZ_PGO', build_project, target, 'MOZ_AUTOMATION', '--disable-gtest-in-build',
293          enable_tests, when='--enable-compile-environment')
294 def build_gtest(pgo, build_project, target, automation, enabled, enable_tests):
295     if not enable_tests or not enabled:
296         return None
297     if (automation and build_project == 'browser' and
298         not (pgo and target.os == 'WINNT')):
299         return True
301 set_config('LINK_GTEST_DURING_COMPILE', build_gtest)
303 # Localization
304 # ==============================================================
305 option('--enable-ui-locale', default='en-US',
306        help='Select the user interface locale (default: en-US)')
308 set_config('MOZ_UI_LOCALE', depends('--enable-ui-locale')(lambda x: x))
310 # clang-plugin location
311 # ==============================================================
312 @depends(host_library_name_info, check_build_environment,
313          when='--enable-clang-plugin')
314 def clang_plugin_path(library_name_info, build_env):
315     topobjdir = build_env.topobjdir
316     if topobjdir.endswith('/js/src'):
317         topobjdir = topobjdir[:-7]
318     return os.path.abspath(
319         os.path.join(topobjdir, 'build', 'clang-plugin',
320                      '%sclang-plugin%s' % (library_name_info.dll.prefix,
321                                            library_name_info.dll.suffix))
322     )
324 add_old_configure_assignment('CLANG_PLUGIN', clang_plugin_path)
327 # Awk detection
328 # ==============================================================
329 awk = check_prog('AWK', ('gawk', 'mawk', 'nawk', 'awk'))
331 # Until the AWK variable is not necessary in old-configure
332 @depends(awk)
333 def awk_for_old_configure(value):
334     return value
336 add_old_configure_assignment('AWK', awk_for_old_configure)
339 # Perl detection
340 # ==============================================================
341 perl = check_prog('PERL', ('perl5', 'perl'))
343 # Until the PERL variable is not necessary in old-configure
344 @depends(perl)
345 def perl_for_old_configure(value):
346     return value
348 add_old_configure_assignment('PERL', perl_for_old_configure)
350 @template
351 def perl_version_check(min_version):
352     @depends(perl)
353     @checking('for minimum required perl version >= %s' % min_version)
354     def get_perl_version(perl):
355         return Version(check_cmd_output(
356             perl, '-e', 'print $]',
357             onerror=lambda: die('Failed to get perl version.')
358         ))
360     @depends(get_perl_version)
361     def check_perl_version(version):
362         if version < min_version:
363             die('Perl %s or higher is required.', min_version)
365     @depends(perl)
366     @checking('for full perl installation')
367     @imports('subprocess')
368     def has_full_perl_installation(perl):
369         ret = subprocess.call(
370             [perl, '-e', 'use Config; exit(!-d $Config{archlib})'])
371         return ret == 0
373     @depends(has_full_perl_installation)
374     def require_full_perl_installation(has_full_perl_installation):
375         if not has_full_perl_installation:
376             die('Cannot find Config.pm or $Config{archlib}. '
377                 'A full perl installation is required.')
379 perl_version_check('5.006')
382 # GNU make detection
383 # ==============================================================
384 option(env='MAKE', nargs=1, help='Path to GNU make')
386 @depends('MAKE', host)
387 def possible_makes(make, host):
388     candidates = []
389     if host.kernel == 'WINNT':
390         candidates.append('mingw32-make')
391     if make:
392         candidates.append(make[0])
393     if host.kernel == 'WINNT':
394         candidates.extend(('make', 'gmake'))
395     else:
396         candidates.extend(('gmake', 'make'))
397     return candidates
399 check_prog('GMAKE', possible_makes)
401 @depends(build_backends, build_project)
402 def tup_include(build_backends, build_project):
403     # We need to check the rustc version when building with tup, but
404     # rustc_info isn't available when configuring js (and build_backends isn't
405     # available from project-specific configure), so as a workaround we only
406     # include the file when we know we'll need it. This can be removed when
407     # we globally require a rustc recent enough to build with tup.
408     if build_project not in ('browser', 'mobile/android'):
409         return None
410     for backend in build_backends:
411         if 'Tup' in backend:
412             return 'build/moz.configure/tup.configure'
414 include(tup_include)
416 # watchman detection
417 # ==============================================================
419 option(env='WATCHMAN', nargs=1, help='Path to the watchman program')
421 @depends('WATCHMAN')
422 @checking('for watchman', callback=lambda w: w.path if w else 'not found')
423 def watchman(prog):
424     if not prog:
425         prog = find_program('watchman')
427     if not prog:
428         return
430     # `watchman version` will talk to the Watchman daemon service.
431     # This can hang due to permissions problems. e.g.
432     # https://github.com/facebook/watchman/issues/376. So use
433     # `watchman --version` to prevent a class of failures.
434     out = check_cmd_output(prog, '--version', onerror=lambda: None)
435     if out is None:
436         return
438     return namespace(path=prog, version=Version(out.strip()))
440 @depends_if(watchman)
441 @checking('for watchman version')
442 def watchman_version(w):
443     return w.version
445 set_config('WATCHMAN', watchman.path)
447 @depends_all(hg_version, hg_config, watchman)
448 @checking('for watchman Mercurial integration')
449 @imports('os')
450 def watchman_hg(hg_version, hg_config, watchman):
451     if hg_version < Version('3.8'):
452         return 'no (Mercurial 3.8+ required)'
454     ext_enabled = False
455     mode_disabled = False
457     for k in ('extensions.fsmonitor', 'extensions.hgext.fsmonitor'):
458         if k in hg_config and hg_config[k] != '!':
459             ext_enabled = True
461     mode_disabled = hg_config.get('fsmonitor.mode') == 'off'
463     if not ext_enabled:
464         return 'no (fsmonitor extension not enabled)'
465     if mode_disabled:
466         return 'no (fsmonitor.mode=off disables fsmonitor)'
468     return True
470 # Miscellaneous programs
471 # ==============================================================
472 check_prog('XARGS', ('xargs',))
474 @depends(target)
475 def extra_programs(target):
476     if target.kernel == 'Darwin':
477         return namespace(
478             DSYMUTIL=('dsymutil', 'llvm-dsymutil'),
479             MKFSHFS=('newfs_hfs', 'mkfs.hfsplus'),
480             HFS_TOOL=('hfsplus',)
481         )
482     if target.os == 'GNU' and target.kernel == 'Linux':
483         return namespace(RPMBUILD=('rpmbuild',))
485 check_prog('DSYMUTIL', extra_programs.DSYMUTIL,
486            allow_missing=True)
487 check_prog('MKFSHFS', extra_programs.MKFSHFS,
488            allow_missing=True)
489 check_prog('HFS_TOOL', extra_programs.HFS_TOOL,
490            allow_missing=True)
491 check_prog('RPMBUILD', extra_programs.RPMBUILD,
492            allow_missing=True)
495 @depends(target)
496 @imports('os')
497 def makensis_progs(target):
498     if target.kernel != 'WINNT':
499         return
501     candidates = [
502         'makensis-3.01',
503         'makensis-3.0b3',
504         'makensis-3.0b1',
505         'makensis',
506     ]
508     # Look for nsis installed by msys environment. But only the 32-bit version.
509     # We use an absolute path and insert as the first entry so it is preferred
510     # over a 64-bit exe that may be in PATH.
511     if 'MSYSTEM_PREFIX' in os.environ:
512         prefix = os.path.dirname(os.environ['MSYSTEM_PREFIX'])
513         candidates.insert(0, os.path.join(prefix, 'mingw32', 'bin', 'makensis.exe'))
515     return tuple(candidates)
517 nsis = check_prog('MAKENSISU', makensis_progs, allow_missing=True)
519 # Make sure the version of makensis is up to date.
520 @depends_if(nsis)
521 @checking('for NSIS version')
522 @imports('re')
523 def nsis_version(nsis):
524     nsis_min_version = '3.0b1'
525     out = check_cmd_output(nsis, '-version',
526                            onerror=lambda: die('Failed to get nsis version.'))
527     m = re.search(r'(?<=v)[0-9]+\.[0-9]+((a|b|rc)[0-9]+)?', out)
529     if not m:
530         raise FatalCheckError('Unknown version of makensis')
531     ver = Version(m.group(0))
533     # Versions comparisons don't quite work well with beta versions, so ensure
534     # it works for the non-beta version.
535     if ver < nsis_min_version and (ver >= '3.0a' or ver < '3'):
536         raise FatalCheckError('To build the installer you must have NSIS'
537                               ' version %s or greater in your path'
538                               % nsis_min_version)
540     return ver
542 # And that makensis is 32-bit (but only on Windows).
543 @depends_if(nsis, when=depends(host)(lambda h: h.kernel == 'WINNT'))
544 @checking('for 32-bit NSIS')
545 def nsis_binary_type(nsis):
546     bin_type = windows_binary_type(nsis)
547     if bin_type != 'win32':
548         raise FatalCheckError('%s is not a 32-bit Windows application' % nsis)
550     return 'yes'
552 # And any flags we have to give to makensis
553 @depends(host)
554 def nsis_flags(host):
555     if host.kernel != 'WINNT':
556         return '-nocd'
557     return ''
559 set_config('MAKENSISU_FLAGS', nsis_flags)
561 check_prog('7Z', ('7z', '7za'), allow_missing=True, when=target_is_windows)
563 # Fallthrough to autoconf-based configure
564 include('build/moz.configure/old.configure')
566 @depends(check_build_environment, build_project)
567 @imports('__sandbox__')
568 @imports('glob')
569 def config_status_deps(build_env, build_project):
571     topsrcdir = build_env.topsrcdir
572     topobjdir = build_env.topobjdir
574     if not build_env.topobjdir.endswith('js/src'):
575         extra_deps = [
576             os.path.join(topsrcdir, build_project, 'confvars.sh'),
577             os.path.join(topobjdir, '.mozconfig.json'),
578         ]
579     else:
580         # mozconfig changes may impact js configure.
581         extra_deps = [os.path.join(topobjdir[:-7], '.mozconfig.json')]
583     return list(__sandbox__._all_paths) + extra_deps + [
584         os.path.join(topsrcdir, 'configure'),
585         os.path.join(topsrcdir, 'js', 'src', 'configure'),
586         os.path.join(topsrcdir, 'configure.in'),
587         os.path.join(topsrcdir, 'js', 'src', 'configure.in'),
588         os.path.join(topsrcdir, 'nsprpub', 'configure'),
589         os.path.join(topsrcdir, 'config', 'milestone.txt'),
590         os.path.join(topsrcdir, 'browser', 'config', 'version.txt'),
591         os.path.join(topsrcdir, 'browser', 'config', 'version_display.txt'),
592         os.path.join(topsrcdir, 'build', 'virtualenv_packages.txt'),
593         os.path.join(topsrcdir, 'python', 'mozbuild', 'mozbuild', 'virtualenv.py'),
594         os.path.join(topsrcdir, 'testing', 'mozbase', 'packages.txt'),
595         os.path.join(topsrcdir, 'aclocal.m4'),
596         os.path.join(topsrcdir, 'old-configure.in'),
597         os.path.join(topsrcdir, 'js', 'src', 'aclocal.m4'),
598         os.path.join(topsrcdir, 'js', 'src', 'old-configure.in'),
599     ] + glob.glob(os.path.join(topsrcdir, 'build', 'autoconf', '*.m4'))
601 set_config('CONFIG_STATUS_DEPS', config_status_deps)
602 # Please do not add anything after setting config_dep_paths.