Bug 1454184 [wpt PR 10474] - [Resource Timing] Align TAO parsing to spec, a=testonly
[gecko.git] / toolkit / moz.configure
blob2b75d3e64f3b170c98982e3297a9b69f704e1865
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/.
8 # Profiling
9 # ==============================================================
10 # Some of the options here imply an option from js/moz.configure,
11 # so, need to be declared before the include.
13 option('--enable-jprof', env='MOZ_JPROF',
14        help='Enable jprof profiling tool (needs mozilla/tools/jprof)')
16 @depends('--enable-jprof')
17 def jprof(value):
18     if value:
19         return True
21 set_config('MOZ_JPROF', jprof)
22 set_define('MOZ_JPROF', jprof)
23 imply_option('--enable-profiling', jprof)
25 @depends(target)
26 def gecko_profiler(target):
27     if target.os == 'Android':
28         return target.cpu in ('aarch64', 'arm', 'x86')
29     elif target.kernel == 'Linux':
30         return target.cpu in ('x86', 'x86_64', 'mips64', 'arm')
31     return target.os in ('OSX', 'WINNT')
33 @depends(gecko_profiler)
34 def gecko_profiler_define(value):
35     if value:
36         return True
38 set_config('MOZ_GECKO_PROFILER', gecko_profiler_define)
39 set_define('MOZ_GECKO_PROFILER', gecko_profiler_define)
42 option('--enable-dmd', env='MOZ_DMD',
43        help='Enable Dark Matter Detector (heap profiler). '
44             'Also enables jemalloc, replace-malloc and profiling')
46 @depends('--enable-dmd')
47 def dmd(value):
48     if value:
49         return True
51 set_config('MOZ_DMD', dmd)
52 set_define('MOZ_DMD', dmd)
53 add_old_configure_assignment('MOZ_DMD', dmd)
54 imply_option('--enable-profiling', dmd)
55 imply_option('--enable-jemalloc', dmd)
56 imply_option('--enable-replace-malloc', dmd)
58 # ALSA cubeb backend
59 # ==============================================================
60 option('--enable-alsa', env='MOZ_ALSA',
61        help='Enable ALSA audio backend.')
63 alsa = pkg_check_modules('MOZ_ALSA', 'alsa', when='--enable-alsa')
65 set_config('MOZ_ALSA', depends_if(alsa)(lambda _: True))
66 set_define('MOZ_ALSA', depends_if(alsa)(lambda _: True))
68 # JACK cubeb backend
69 # ==============================================================
70 option('--enable-jack', env='MOZ_JACK',
71        help='Enable JACK audio backend.')
73 jack = pkg_check_modules('MOZ_JACK', 'jack', when='--enable-jack')
75 set_config('MOZ_JACK', depends_if(jack)(lambda _: True))
76 set_define('MOZ_JACK', depends_if(jack)(lambda _: True))
78 # PulseAudio cubeb backend
79 # ==============================================================
80 @depends(target)
81 def pulseaudio_default(target):
82     return target.os not in ('WINNT', 'OSX', 'iOS', 'Android', 'OpenBSD')
84 option('--enable-pulseaudio', env='MOZ_PULSEAUDIO', default=pulseaudio_default,
85        help='Enable PulseAudio audio backend.')
87 pulseaudio = pkg_check_modules('MOZ_PULSEAUDIO', 'libpulse', when='--enable-pulseaudio')
89 set_config('MOZ_PULSEAUDIO', depends_if(pulseaudio)(lambda _: True))
90 set_define('MOZ_PULSEAUDIO', depends_if(pulseaudio)(lambda _: True))
92 # Javascript engine
93 # ==============================================================
94 include('../js/moz.configure')
97 # Rust
98 # ==============================================================
99 include('../build/moz.configure/rust.configure',
100         when='--enable-compile-environment')
103 # L10N
104 # ==============================================================
105 option('--with-l10n-base', nargs=1, env='L10NBASEDIR',
106        help='Path to l10n repositories')
108 @depends('--with-l10n-base')
109 @imports(_from='os.path', _import='isdir')
110 @imports(_from='os.path', _import='expanduser')
111 @imports(_from='os', _import='environ')
112 def l10n_base(value):
113     if value:
114         path = value[0]
115         if not isdir(path):
116             die("Invalid value --with-l10n-base, %s doesn't exist", path)
117     else:
118         path = os.path.join(
119             environ.get(
120                 'MOZBUILD_STATE_PATH',
121                 expanduser(os.path.join('~', '.mozbuild'))),
122             'l10n-central')
123     return os.path.realpath(os.path.abspath(path))
125 set_config('L10NBASEDIR', l10n_base)
128 # Default toolkit
129 # ==============================================================
130 # Normally, we'd want to use the `default` field on the option, but that
131 # requires --target to be resolved at --help time, which requires to run
132 # config.guess, which we want to avoid. Even better, we could actually set
133 # `choices` depending on the target, but that doesn't pan out for the same
134 # reason.
135 option('--enable-default-toolkit', nargs=1,
136        choices=('cairo-windows', 'cairo-gtk3', 'cairo-gtk3-wayland',
137                 'cairo-cocoa', 'cairo-uikit', 'cairo-android'),
138        help='Select default toolkit')
140 @depends('--enable-default-toolkit', target, '--help')
141 def toolkit(value, target, _):
142     # Define possible choices for each platform. The default is the first one
143     # listed when there are several.
144     if target.os == 'WINNT':
145         platform_choices = ('cairo-windows',)
146     elif target.os == 'OSX':
147         platform_choices = ('cairo-cocoa',)
148     elif target.os == 'iOS':
149         platform_choices = ('cairo-uikit',)
150     elif target.os == 'Android':
151         platform_choices = ('cairo-android',)
152     else:
153         platform_choices = ('cairo-gtk3', 'cairo-gtk3-wayland')
155     if value:
156         if value[0] not in platform_choices:
157             die('`%s` is not a valid value for --enable-default-toolkit on %s\n'
158                 'Valid values: %s', value[0], target.os,
159                 ', '.join(platform_choices))
160         return value[0]
162     return platform_choices[0]
164 @depends(toolkit)
165 def wayland(toolkit):
166     return toolkit == 'cairo-gtk3-wayland'
168 @depends(toolkit)
169 def toolkit(toolkit):
170     if toolkit == 'cairo-gtk3-wayland':
171         widget_toolkit = 'gtk3'
172     else:
173         widget_toolkit = toolkit.replace('cairo-', '')
174     return widget_toolkit
176 set_config('MOZ_WIDGET_TOOLKIT', toolkit)
177 add_old_configure_assignment('MOZ_WIDGET_TOOLKIT', toolkit)
179 @depends(toolkit)
180 def toolkit_gtk(toolkit):
181     if toolkit == 'gtk3':
182         return '3'
184 set_define('MOZ_WIDGET_GTK', toolkit_gtk)
186 @depends(toolkit)
187 def toolkit_define(toolkit):
188     if toolkit not in ('gtk3', 'windows'):
189         return 'MOZ_WIDGET_%s' % toolkit.upper()
191 set_define(toolkit_define, True)
194 option('--without-x', env='WITHOUT_X', help='Disable X11 support')
196 @depends('--without-x', toolkit)
197 def x11(value, toolkit):
198     if not value:
199         die('--without-x is not supported')
201     x11_toolkits = ('gtk3',)
202     if value and value.origin != 'default' and toolkit not in x11_toolkits:
203         die('--with-x is only valid with --enable-default-toolkit={%s}',
204             ','.join(x11_toolkits))
206     return True if value and toolkit in x11_toolkits else None
208 set_config('MOZ_ENABLE_XREMOTE', x11)
209 set_define('MOZ_ENABLE_XREMOTE', x11)
210 set_config('MOZ_X11', x11)
211 set_define('MOZ_X11', x11)
212 add_old_configure_assignment('MOZ_X11', x11)
214 # Wayland support
215 # ==============================================================
216 wayland_headers = pkg_check_modules('MOZ_WAYLAND', 'gtk+-wayland-3.0 >= 3.22',
217                                     when=wayland)
219 set_config('MOZ_WAYLAND', depends_if(wayland_headers)(lambda _: True))
220 set_define('MOZ_WAYLAND', depends_if(wayland_headers)(lambda _: True))
222 # GL Provider
223 # ==============================================================
224 option('--with-gl-provider', nargs=1, help='Set GL provider backend type')
226 @depends('--with-gl-provider')
227 def gl_provider(value):
228     if value:
229         return value[0]
231 @depends(gl_provider)
232 def gl_provider_define(provider):
233     if provider:
234         return 'GLContextProvider%s' % provider
236 set_define('MOZ_GL_PROVIDER', gl_provider_define)
238 @depends(gl_provider, wayland, x11)
239 def gl_default_provider(value, wayland, x11):
240     if value:
241         return value
242     elif wayland:
243         return 'EGL'
244     elif x11:
245         return 'GLX'
247 set_config('MOZ_GL_PROVIDER', gl_provider)
248 set_config('MOZ_GL_DEFAULT_PROVIDER', gl_default_provider)
250 @depends(gl_default_provider)
251 def gl_provider_define(provider):
252     if provider:
253         return 'GL_PROVIDER_%s' % provider
255 set_define(gl_provider_define, True)
258 # PDF printing
259 # ==============================================================
260 @depends(toolkit)
261 def pdf_printing(toolkit):
262     if toolkit in ('windows', 'gtk3', 'android'):
263         return True
265 @depends(pdf_printing)
266 def pdf_surface_feature(pdf_printing):
267     if pdf_printing:
268         return '#define CAIRO_HAS_PDF_SURFACE 1'
269     else:
270         # CONFIGURE_SUBST_FILES need explicit empty values.
271         return ''
273 set_config('MOZ_PDF_PRINTING', pdf_printing)
274 set_config('PDF_SURFACE_FEATURE', pdf_surface_feature)
277 # Event loop instrumentation
278 # ==============================================================
279 option(env='MOZ_INSTRUMENT_EVENT_LOOP',
280        help='Force-enable event loop instrumentation')
282 @depends('MOZ_INSTRUMENT_EVENT_LOOP', toolkit)
283 def instrument_event_loop(value, toolkit):
284     if value or (toolkit in ('windows', 'gtk3', 'cocoa', 'android') and
285                  value.origin == 'default'):
286         return True
288 set_config('MOZ_INSTRUMENT_EVENT_LOOP', instrument_event_loop)
289 set_define('MOZ_INSTRUMENT_EVENT_LOOP', instrument_event_loop)
292 # Fontconfig Freetype
293 # ==============================================================
294 option(env='USE_FC_FREETYPE',
295        help='Force-enable the use of fontconfig freetype')
297 @depends('USE_FC_FREETYPE', toolkit)
298 def fc_freetype(value, toolkit):
299     if value or (toolkit == 'gtk3' and
300                  value.origin == 'default'):
301         return True
303 add_old_configure_assignment('USE_FC_FREETYPE', fc_freetype)
305 # Pango
306 # ==============================================================
307 pkg_check_modules('MOZ_PANGO',
308                   'pango >= 1.22.0 pangoft2 >= 1.22.0 pangocairo >= 1.22.0',
309                   when=toolkit_gtk)
311 # Fontconfig
312 # ==============================================================
313 fontconfig_info = pkg_check_modules('_FONTCONFIG', 'fontconfig >= 2.7.0',
314                                     when=fc_freetype)
316 @depends(fc_freetype)
317 def check_for_freetype2(fc_freetype):
318     if fc_freetype:
319         return True
321 # Check for freetype2. Flags are combined with fontconfig flags.
322 freetype2_info = pkg_check_modules('_FT2', 'freetype2 >= 6.1.0',
323                                    when=check_for_freetype2)
325 @depends(fontconfig_info, freetype2_info)
326 def freetype2_combined_info(fontconfig_info, freetype2_info):
327     if not freetype2_info:
328         return
329     if not fontconfig_info:
330         return freetype2_info
331     return namespace(
332         cflags=freetype2_info.cflags + fontconfig_info.cflags,
333         libs=freetype2_info.libs + fontconfig_info.libs,
334     )
336 add_old_configure_assignment('_HAVE_FREETYPE2',
337                              depends_if(freetype2_info)(lambda _: True))
339 # Apple platform decoder support
340 # ==============================================================
341 @depends(toolkit)
342 def applemedia(toolkit):
343     if toolkit in ('cocoa', 'uikit'):
344         return True
346 set_config('MOZ_APPLEMEDIA', applemedia)
347 set_define('MOZ_APPLEMEDIA', applemedia)
348 add_old_configure_assignment('MOZ_APPLEMEDIA', applemedia)
350 # Windows Media Foundation support
351 # ==============================================================
352 option('--disable-wmf',
353        help='Disable support for Windows Media Foundation')
355 @depends('--disable-wmf', target)
356 def wmf(value, target):
357     enabled = bool(value)
358     if value.origin == 'default':
359         # Enable Windows Media Foundation support by default.
360         # Note our minimum SDK version is Windows 7 SDK, so we are (currently)
361         # guaranteed to have a recent-enough SDK to build WMF.
362         enabled = target.os == 'WINNT'
363     if enabled and target.os != 'WINNT':
364         die('Cannot enable Windows Media Foundation support on %s', target.os)
365     if enabled:
366         return True
368 set_config('MOZ_WMF', wmf)
369 set_define('MOZ_WMF', wmf)
371 # FFmpeg H264/AAC Decoding Support
372 # ==============================================================
373 option('--disable-ffmpeg',
374        help='Disable FFmpeg for fragmented H264/AAC decoding')
376 @depends('--disable-ffmpeg', target)
377 def ffmpeg(value, target):
378     enabled = bool(value)
379     if value.origin == 'default':
380         enabled = target.os not in ('Android', 'WINNT')
381     if enabled:
382         return True
384 set_config('MOZ_FFMPEG', ffmpeg)
385 set_define('MOZ_FFMPEG', ffmpeg)
386 imply_option('--enable-fmp4', ffmpeg, '--enable-ffmpeg')
388 # Libaom AV1 Video Codec Support
389 # ==============================================================
390 option('--enable-av1',
391         help='Enable libaom for av1 video support')
393 @depends('--enable-av1', target, milestone)
394 def av1(value, target, milestone):
395     enabled = bool(value)
396     if value.origin == 'default' and milestone.is_nightly:
397         enabled = target.os != 'Android'
398     if enabled:
399         return True
401 set_config('MOZ_AV1', av1)
402 set_define('MOZ_AV1', av1)
404 # Built-in fragmented MP4 support.
405 # ==============================================================
406 option('--disable-fmp4', env='MOZ_FMP4',
407        help='Disable support for in built Fragmented MP4 parsing')
409 @depends('--disable-fmp4', target, wmf, applemedia)
410 def fmp4(value, target, wmf, applemedia):
411     enabled = bool(value)
412     if value.origin == 'default':
413         # target.os == 'Android' includes all B2G versions
414         enabled = wmf or applemedia or target.os == 'Android'
415     if enabled:
416         return True
418 set_config('MOZ_FMP4', fmp4)
419 set_define('MOZ_FMP4', fmp4)
420 add_old_configure_assignment('MOZ_FMP4', fmp4)
422 # OpenMAX IL Decoding Support
423 # ==============================================================
424 option('--enable-openmax',
425        help='Enable OpenMAX IL for video/audio decoding')
427 @depends('--enable-openmax')
428 def openmax(value):
429     enabled = bool(value)
430     if enabled:
431         return True
433 set_config('MOZ_OMX', openmax)
434 set_define('MOZ_OMX', openmax)
436 # EME Support
437 # ==============================================================
438 # Widevine is enabled by default in desktop browser builds.
439 @depends(build_project, '--help')
440 def eme_default(build_project, help):
441     if build_project == 'browser':
442         return 'widevine'
444 option('--enable-eme',
445        nargs='*',
446        choices=('widevine',),
447        default=eme_default,
448        help='Enable support for Encrypted Media Extensions')
450 @depends('--enable-eme', target)
451 def enable_eme(value, target):
452     # Widevine EME by default enabled on desktop Windows, MacOS and Linux,
453     # x86 and x64 builds.
454     if (target.kernel in ('Darwin', 'WINNT', 'Linux') and
455         target.os not in ('Android', 'iOS') and
456         target.cpu in ('x86', 'x86_64')):
457         return value
458     elif value and value.origin != 'default':
459         die('%s is not supported on %s' % (value.format('--enable-eme'), target.alias))
460     # Return the same type of OptionValue (Positive or Negative), with an empty tuple.
461     return value.__class__(())
463 @depends(enable_eme, fmp4)
464 def eme(value, fmp4):
465     enabled = bool(value)
466     if value.origin == 'default':
467         enabled = enabled or fmp4
468     if enabled and not fmp4:
469         die('Encrypted Media Extension support requires '
470             'Fragmented MP4 support')
471     if enabled:
472         return True
474 @depends(enable_eme)
475 def eme_modules(value):
476     return value
478 set_config('MOZ_EME_MODULES', eme_modules)
480 option(name='--enable-chrome-format',
481        help='Select FORMAT of chrome files during packaging.',
482        nargs=1,
483        choices=('omni', 'jar', 'flat'),
484        default='omni')
486 @depends('--enable-chrome-format')
487 def packager_format(value):
488     return value[0]
490 set_config('MOZ_PACKAGER_FORMAT', packager_format)
492 @depends(host, build_project)
493 def jar_maker_format(host, build_project):
494     # Multilocales for mobile/android use the same mergedirs for all locales,
495     # so we can't use symlinks for those builds.
496     if host.os == 'WINNT' or build_project == 'mobile/android':
497         return 'flat'
498     return 'symlink'
500 set_config('MOZ_JAR_MAKER_FILE_FORMAT', jar_maker_format)
502 @depends(toolkit)
503 def omnijar_name(toolkit):
504     # Fennec's static resources live in the assets/ folder of the
505     # APK.  Adding a path to the name here works because we only
506     # have one omnijar file in the final package (which is not the
507     # case on desktop), and necessitates some contortions during
508     # packaging so that the resources in the omnijar are considered
509     # as rooted at / and not as rooted at assets/ (which again is
510     # not the case on desktop: there are omnijars rooted at webrtc/,
511     # etc). packager.mk handles changing the rooting of the single
512     # omnijar.
513     return 'assets/omni.ja' if toolkit == 'android' else 'omni.ja'
515 set_config('OMNIJAR_NAME', omnijar_name)
517 project_flag('MOZ_PLACES',
518              help='Build Places if required',
519              set_as_define=True)
521 project_flag('MOZ_SERVICES_HEALTHREPORT',
522              help='Build Firefox Health Reporter Service',
523              set_for_old_configure=True,
524              set_as_define=True)
526 project_flag('MOZ_SERVICES_SYNC',
527              help='Build Sync Services if required')
529 project_flag('MOZ_ANDROID_HISTORY',
530              help='Enable Android History instead of Places',
531              set_as_define=True)
533 option(env='MOZ_ALLOW_LEGACY_EXTENSIONS',
534        default=milestone.is_nightly,
535        help='Allow legacy browser extensions')
537 @depends('MOZ_ALLOW_LEGACY_EXTENSIONS')
538 def legacy_extensions(value):
539     if bool(value):
540         return True
542 set_config('MOZ_ALLOW_LEGACY_EXTENSIONS', legacy_extensions)
543 set_define('MOZ_ALLOW_LEGACY_EXTENSIONS', legacy_extensions)
545 @depends('MOZ_PLACES', 'MOZ_ANDROID_HISTORY')
546 def check_places_and_android_history(places, android_history):
547     if places and android_history:
548         die('Cannot use MOZ_ANDROID_HISTORY alongside MOZ_PLACES.')
550 # gpsd support
551 # ==============================================================
552 option('--enable-gpsd', env='MOZ_GPSD',
553        help='Enable gpsd support')
555 @depends('--enable-gpsd')
556 def gpsd(value):
557     return bool(value)
559 system_gpsd = pkg_check_modules('MOZ_GPSD', 'libgps >= 3.11',
560                                 when=gpsd)
562 set_config('MOZ_GPSD', depends_if(system_gpsd)(lambda _: True))
564 # Miscellaneous programs
565 # ==============================================================
567 check_prog('TAR', ('gnutar', 'gtar', 'tar'))
568 check_prog('UNZIP', ('unzip',))
569 check_prog('ZIP', ('zip',))
570 check_prog('GN', ('gn',), allow_missing=True)
572 # Key files
573 # ==============================================================
574 include('../build/moz.configure/keyfiles.configure')
576 simple_keyfile('Mozilla API')
578 simple_keyfile('Google API')
580 id_and_secret_keyfile('Bing API')
582 simple_keyfile('Adjust SDK')
584 id_and_secret_keyfile('Leanplum SDK')
586 simple_keyfile('Pocket API')
588 # We support setting up the appropriate options for Stylo's build-time
589 # bindings generation via setting LLVM_CONFIG or by providing explicit
590 # configure options.  The Windows installer of LLVM/Clang doesn't provide
591 # llvm-config, so we need both methods to support all of our tier-1
592 # platforms.
593 @depends(host)
594 @imports('which')
595 @imports('os')
596 @imports('subprocess')
597 def llvm_config_paths(host):
598     llvm_supported_versions = ['6.0', '5.0', '4.0', '3.9']
599     llvm_config_progs = []
600     for version in llvm_supported_versions:
601         llvm_config_progs += [
602             'llvm-config-%s' % version,
603             'llvm-config-mp-%s' % version,    # MacPorts' chosen naming scheme.
604             'llvm-config%s' % version.replace('.', ''),
605         ]
606     llvm_config_progs.append('llvm-config')
608     # Homebrew on macOS doesn't make clang available on PATH, so we have to
609     # look for it in non-standard places.
610     if host.kernel == 'Darwin':
611         try:
612             brew = which.which('brew')
613             brew_config = subprocess.check_output([brew, 'config']).strip()
615             for line in brew_config.splitlines():
616                 if line.startswith('HOMEBREW_PREFIX'):
617                     fields = line.split(None, 2)
618                     prefix = fields[1] if len(fields) == 2 else ''
619                     path = ['opt', 'llvm', 'bin', 'llvm-config']
620                     llvm_config_progs.append(os.path.join(prefix, *path))
621                     break
622         except which.WhichError:
623             # Homebrew not installed, which is fine.
624             pass
626     # Also add in the location to which `mach bootstrap` or
627     # `mach artifact toolchain` installs clang.
628     mozbuild_state_dir = os.environ.get('MOZBUILD_STATE_PATH',
629                                         os.path.expanduser(os.path.join('~', '.mozbuild')))
630     bootstrap_llvm_config = os.path.join(mozbuild_state_dir, 'clang', 'bin', 'llvm-config')
632     llvm_config_progs.append(bootstrap_llvm_config)
634     return llvm_config_progs
636 llvm_config = check_prog('LLVM_CONFIG', llvm_config_paths,
637                          when='--enable-compile-environment',
638                          what='llvm-config', allow_missing=True)
640 with only_when('--enable-compile-environment'):
641     option('--with-libclang-path', nargs=1,
642            help='Absolute path to a directory containing Clang/LLVM libraries for Stylo (version 3.9.x or above)')
643     option('--with-clang-path', nargs=1,
644            help='Absolute path to a Clang binary for Stylo bindgen (version 3.9.x or above)')
646     def invoke_llvm_config(llvm_config, *options):
647         '''Invoke llvm_config with the given options and return the first line of
648         output.'''
649         lines = check_cmd_output(llvm_config, *options).splitlines()
650         return lines[0]
652     @imports(_from='textwrap', _import='dedent')
653     def check_minimum_llvm_config_version(llvm_config):
654         version = Version(invoke_llvm_config(llvm_config, '--version'))
655         min_version = Version('3.9.0')
656         if version < min_version:
657             die(dedent('''\
658             llvm installation {} is incompatible with Stylo bindgen.
660             To compile Stylo, please install version {} or greater of
661             Clang + LLVM and ensure that the 'llvm-config' from that
662             installation is first on your path.
664             You can verify this by typing 'llvm-config --version'.
665             '''.format(version, min_version)))
667     @depends(llvm_config, '--with-libclang-path', '--with-clang-path',
668              host_library_name_info, host)
669     @imports('os.path')
670     @imports('glob')
671     @imports(_from='textwrap', _import='dedent')
672     def bindgen_config_paths(llvm_config, libclang_path, clang_path,
673                              library_name_info, host):
674         def search_for_libclang(path):
675             # Try to ensure that the clang shared library that bindgen is going
676             # to look for is actually present.  The files that we search for
677             # mirror the logic in clang-sys/build.rs.
678             libclang_choices = []
679             if host.os == 'WINNT':
680                 libclang_choices.append('libclang.dll')
681             libclang_choices.append('%sclang%s' % (library_name_info.dll.prefix,
682                                                    library_name_info.dll.suffix))
683             if host.kernel == 'Linux':
684                 libclang_choices.append('libclang.so.1')
686             if host.os == 'OpenBSD':
687                 libclang_choices = glob.glob(path + '/libclang.so.*.*')
689             # At least one of the choices must be found.
690             for choice in libclang_choices:
691                 libclang = os.path.join(path, choice)
692                 if os.path.exists(libclang):
693                     return (True, None)
694             else:
695                 return (False, list(set(libclang_choices)))
697         if not libclang_path and not clang_path:
698             # We must have LLVM_CONFIG in this case.
699             if not llvm_config:
700                 die(dedent('''\
701                 Could not find LLVM/Clang installation for compiling stylo build-time
702                 bindgen.  Please specify the 'LLVM_CONFIG' environment variable
703                 (recommended), pass the '--with-libclang-path' and '--with-clang-path'
704                 options to configure, or put 'llvm-config' in your PATH.  Altering your
705                 PATH may expose 'clang' as well, potentially altering your compiler,
706                 which may not be what you intended.'''))
708             check_minimum_llvm_config_version(llvm_config)
709             libclang_arg = '--bindir' if host.os == 'WINNT' else '--libdir'
710             libclang_path = invoke_llvm_config(llvm_config, libclang_arg)
711             clang_path = os.path.join(invoke_llvm_config(llvm_config, '--bindir'),
712                                       'clang')
713             libclang_path = normsep(libclang_path)
714             clang_path = normsep(clang_path)
716             # Debian-based distros, at least, can have llvm-config installed
717             # but not have other packages installed.  Since the user is trying
718             # to use their system packages, we can't be more specific about what
719             # they need.
720             clang_resolved = find_program(clang_path)
721             if not clang_resolved:
722                 die(dedent('''\
723                 The file {} returned by `llvm-config {}` does not exist.
724                 clang is required to build Firefox.  Please install the
725                 necessary packages, or run `mach bootstrap`.
726                 '''.format(clang_path, '--bindir')))
728             if not os.path.exists(libclang_path):
729                 die(dedent('''\
730                 The directory {} returned by `llvm-config {}` does not exist.
731                 clang is required to build Firefox.  Please install the
732                 necessary packages, or run `mach bootstrap`.
733                 '''.format(libclang_path, libclang_arg)))
735             (found, searched) = search_for_libclang(libclang_path)
736             if not found:
737                 die(dedent('''\
738                 Could not find the clang shared library in the path {}
739                 returned by `llvm-config {}` (searched for files {}).
740                 clang is required to build Firefox.  Please install the
741                 necessary packages, or run `mach bootstrap`.
742                 '''.format(libclang_path, libclang_arg, searched)))
744             return namespace(
745                 libclang_path=libclang_path,
746                 clang_path=clang_resolved,
747             )
749         if (not libclang_path and clang_path) or \
750            (libclang_path and not clang_path):
751             die(dedent('''\
752             You must provide both of --with-libclang-path and --with-clang-path
753             or neither of them.'''))
755         libclang_path = libclang_path[0]
756         clang_path = clang_path[0]
758         if not os.path.exists(libclang_path) or \
759            not os.path.isdir(libclang_path):
760             die(dedent('''\
761             The argument to --with-libclang-path is not a directory: {}
762             '''.format(libclang_path)))
764         (found, searched) = search_for_libclang(libclang_path)
765         if not found:
766             die(dedent('''\
767             Could not find the clang shared library in the path {}
768             specified by --with-libclang-path (searched for files {}).
769             '''.format(libclang_path, searched)))
771         clang_resolved = find_program(clang_path)
772         if not clang_resolved:
773             die(dedent('''\
774             The argument to --with-clang-path is not a file: {}
775             '''.format(clang_path)))
777         return namespace(
778             libclang_path=libclang_path,
779             clang_path=clang_resolved,
780         )
782     set_config('MOZ_LIBCLANG_PATH', bindgen_config_paths.libclang_path)
783     set_config('MOZ_CLANG_PATH', bindgen_config_paths.clang_path)
785 option('--with-servo', env='SERVO_TARGET_DIR', nargs=1,
786        help='Absolute path of the target directory where libgeckoservo can '
787             'be found. This is generally servo_src_dir/target/release.')
789 @depends_if('--with-servo')
790 def servo_target_dir(value):
791     return value[0]
793 set_config('SERVO_TARGET_DIR', servo_target_dir)
795 # WebRender integration
796 option('--enable-webrender', nargs='?', choices=('build',),
797        help='Include WebRender in the build and/or enable it at runtime')
799 @depends('--enable-webrender', milestone)
800 def webrender(value, milestone):
801     build_webrender = None
802     enable_webrender = None
804     if value.origin == 'default':
805         # if nothing is specified, default to just building on Nightly
806         build_webrender = milestone.is_nightly
807     elif len(value) and value[0] == 'build':
808         # if explicitly set to 'build', then we build but don't enable
809         build_webrender = True
810     elif bool(value):
811         # if set to true, then build and enable
812         build_webrender = True
813         enable_webrender = True
815     # in all other cases, don't build it or enable it (defaults are fine)
816     return namespace(
817         build = build_webrender,
818         enable = enable_webrender,
819     )
821 set_config('MOZ_BUILD_WEBRENDER', webrender.build)
822 set_define('MOZ_BUILD_WEBRENDER', webrender.build)
823 set_config('MOZ_ENABLE_WEBRENDER', webrender.enable)
825 # SIMD acceleration for Rust code (currently just encoding_rs)
827 option('--enable-rust-simd', env='MOZ_RUST_SIMD',
828        help='Enable explicit SIMD in Rust code.')
830 @depends('--enable-rust-simd', target)
831 def rust_simd(value, target):
832     # As of 2017-06-13, the simd crate only works on aarch64,
833     # x86 and x86_64. It's meant to work on 32-bit ARM, too,
834     # but currently does not.
835     if target.cpu in ('aarch64', 'x86', 'x86_64') and value:
836         return True
838 set_config('MOZ_RUST_SIMD', rust_simd)
839 set_define('MOZ_RUST_SIMD', rust_simd)
841 # Printing
842 # ==============================================================
843 @depends(target)
844 def ios_disable_printing(target):
845     if target.os == 'iOS':
846         return False
848 imply_option('--enable-printing', ios_disable_printing, reason='--target')
850 option('--disable-printing', help='Disable printing support')
852 @depends('--disable-printing')
853 def printing(value):
854     if value:
855         return True
857 set_config('NS_PRINTING', printing)
858 set_define('NS_PRINTING', printing)
859 set_define('NS_PRINT_PREVIEW', printing)
861 # Speech-dispatcher support
862 # ==============================================================
863 @depends(toolkit)
864 def no_speechd_on_non_gtk(toolkit):
865     if toolkit != 'gtk3':
866         return False
868 imply_option('--enable-synth-speechd', no_speechd_on_non_gtk,
869              reason='--enable-default-toolkit')
871 option('--disable-synth-speechd', help='Disable speech-dispatcher support')
873 set_config('MOZ_SYNTH_SPEECHD',
874            depends_if('--disable-synth-speechd')(lambda _: True))
876 # Speech API
877 # ==============================================================
878 option('--disable-webspeech', help='Disable support for HTML Speech API')
880 @depends('--disable-webspeech', '--help')
881 def webspeech(value, _):
882     if value:
883         return True
885 set_config('MOZ_WEBSPEECH', webspeech)
886 set_define('MOZ_WEBSPEECH', webspeech)
887 add_old_configure_assignment('MOZ_WEBSPEECH', webspeech)
889 # Speech API test backend
890 # ==============================================================
891 option('--enable-webspeechtestbackend', default=webspeech,
892        help='Enable support for HTML Speech API Test Backend')
894 @depends_if('--enable-webspeechtestbackend')
895 def webspeech_test_backend(value):
896     return True
898 set_config('MOZ_WEBSPEECH_TEST_BACKEND', webspeech_test_backend)
899 set_define('MOZ_WEBSPEECH_TEST_BACKEND', webspeech_test_backend)
901 # Enable IPDL's "expensive" unit tests
902 # ==============================================================
903 option('--enable-ipdl-tests', help='Enable expensive IPDL tests')
905 set_config('MOZ_IPDL_TESTS',
906            depends_if('--enable-ipdl-tests')(lambda _: True))
908 include('nss.configure')
910 # Graphics
911 # ==============================================================
912 option('--disable-skia', help='Disable use of Skia')
914 @depends('--disable-skia')
915 def skia(value):
916     if not value:
917         die('--disable-skia is not supported anymore')
918     else:
919         return True
921 set_config('MOZ_ENABLE_SKIA', skia)
922 set_define('MOZ_ENABLE_SKIA', skia)
923 set_define('USE_SKIA', skia)
925 @depends(skia, target)
926 def skia_android(skia, target):
927     if skia and target.os == 'Android':
928         return True
930 set_define('SK_BUILD_FOR_ANDROID_NDK', skia_android)
932 option('--disable-skia-gpu', help='Disable use of Skia-GPU')
934 @depends('--disable-skia-gpu', skia)
935 def skia_gpu(value, skia):
936     if value.origin == 'default':
937         if not skia:
938             return None
939     elif value and not skia:
940         die('Cannot enable Skia-GPU without enabling Skia')
941     if skia and value:
942         return True
944 set_config('MOZ_ENABLE_SKIA_GPU', skia_gpu)
945 set_define('USE_SKIA_GPU', skia_gpu)
947 option('--enable-skia-pdf', help='Enable Skia PDF')
949 @depends('--enable-skia-pdf', skia, target, milestone)
950 def skia_pdf(value, skia, target, milestone):
951     if value.origin == 'default':
952         if not skia:
953             return None
954         if milestone.is_nightly and target.os != 'WINNT':
955             return True
956     elif value and not skia:
957         die('Cannot enable Skia PDF without enabling Skia')
958     if skia and value:
959         return True
961 set_config('MOZ_ENABLE_SKIA_PDF', skia_pdf)
962 set_define('MOZ_ENABLE_SKIA_PDF', skia_pdf)
964 option('--enable-skia-pdf-sfntly', help='Enable SFNTLY font subsetting in Skia PDF')
966 @depends('--enable-skia-pdf-sfntly', skia_pdf)
967 def skia_pdf_sfntly(value, skia_pdf):
968     if value.origin == 'default':
969         return skia_pdf
970     if value and not skia_pdf:
971         die('Cannot enable SFNTLY subsetting without enabling Skia PDF')
972     if skia_pdf and value:
973         return True
975 set_config('MOZ_ENABLE_SKIA_PDF_SFNTLY', skia_pdf_sfntly)
976 set_define('MOZ_ENABLE_SKIA_PDF_SFNTLY', skia_pdf_sfntly)
978 @depends(skia_pdf_sfntly)
979 def sfntly_includes(skia_pdf_sfntly):
980     includes = []
981     if skia_pdf_sfntly:
982         includes += [
983             '/gfx/sfntly/cpp/src',
984         ]
985     return includes
987 set_config('SFNTLY_INCLUDES', sfntly_includes)
989 @depends(skia)
990 def skia_includes(skia):
991     includes = []
992     if skia:
993         includes += [
994             '/gfx/skia',
995             '/gfx/skia/skia/include/config',
996             '/gfx/skia/skia/include/core',
997             '/gfx/skia/skia/include/gpu',
998             '/gfx/skia/skia/include/utils',
999         ]
1000     return includes
1002 set_config('SKIA_INCLUDES', skia_includes)
1004 # Build Freetype in the tree
1005 # ==============================================================
1006 @depends(target, skia_pdf)
1007 def tree_freetype(target, skia_pdf):
1008     if target.os == 'Android' or (skia_pdf and target.os == 'WINNT'):
1009         return True
1011 set_define('MOZ_TREE_FREETYPE', tree_freetype)
1012 set_config('MOZ_TREE_FREETYPE', tree_freetype)
1013 add_old_configure_assignment('MOZ_TREE_FREETYPE', tree_freetype)
1015 set_define('HAVE_FT_BITMAP_SIZE_Y_PPEM', tree_freetype)
1016 set_define('HAVE_FT_GLYPHSLOT_EMBOLDEN', tree_freetype)
1017 set_define('HAVE_FT_LOAD_SFNT_TABLE', tree_freetype)
1019 @depends(freetype2_combined_info, tree_freetype, check_build_environment)
1020 def ft2_info(freetype2_combined_info, tree_freetype, build_env):
1021     if tree_freetype:
1022         return namespace(cflags=('-I%s/modules/freetype2/include' % build_env.topsrcdir,),
1023                          libs=())
1024     if freetype2_combined_info:
1025         return freetype2_combined_info
1027 set_config('FT2_LIBS', ft2_info.libs)
1028 add_old_configure_assignment('FT2_LIBS',
1029                              ft2_info.libs)
1030 add_old_configure_assignment('FT2_CFLAGS',
1031                              ft2_info.cflags)
1033 # Mortar
1034 # ==============================================================
1035 option('--enable-mortar', help='Enable mortar extension')
1037 set_config('MOZ_MORTAR', True, when='--enable-mortar')
1039 # Marionette remote protocol
1040 # ==============================================================
1042 # Marionette is the Gecko remote protocol used for various remote control,
1043 # automation, and testing purposes throughout Gecko, Firefox, and Fennec.
1044 # Marionette lives in ../testing/marionette.
1046 # Marionette is not really a toolkit feature, as much as a Gecko engine
1047 # feature.  But it is enabled based on the toolkit (and target), so here
1048 # it lives.
1050 # It also backs ../testing/geckodriver, which is Mozilla's WebDriver
1051 # implementation.
1053 # For more information, see
1054 # https://developer.mozilla.org/en-US/docs/Mozilla/QA/Marionette.
1056 @depends(target)
1057 def marionette(target):
1058     """Enable Marionette by default, except on Android."""
1059     if target.os != 'Android':
1060         return True
1062 imply_option('--enable-marionette', marionette, reason='Not Android')
1064 option('--enable-marionette',
1065        help='Enable Marionette remote protocol')
1067 @depends('--enable-marionette')
1068 def marionette(value):
1069     if value:
1070         return True
1072 set_config('ENABLE_MARIONETTE', marionette)
1074 # geckodriver WebDriver implementation
1075 # ==============================================================
1076 option('--enable-geckodriver', help='Enable WebDriver implementation')
1078 @depends('--enable-geckodriver',
1079          'MOZ_AUTOMATION',
1080          compile_environment,
1081          cross_compiling,
1082          hazard_analysis)
1083 def geckodriver(enable, automation, compile_env, cross_compile, hazard):
1084     """
1085     geckodriver is implied on supported platforms when MOZ_AUTOMATION
1086     is set, but we also provide the --enable-geckodriver option for
1087     developers to use.
1089     At the present time, we want individual developers to be able to
1090     opt-in to building geckodriver locally, and for it to be enabled by
1091     default on supported CI build platforms.
1092     """
1093     if enable:
1094         if not compile_env:
1095             die("--enable-geckodriver is not available without a compile "
1096                 "environment. A geckodriver binary will be downloaded during "
1097                 "an artifact build by default where available.")
1098         return True
1100     if enable.origin == 'default':
1101         broken_platforms = cross_compile or hazard
1103         if automation and compile_env and not broken_platforms:
1104             return True
1106 set_config('ENABLE_GECKODRIVER', geckodriver)
1108 # WebRTC
1109 # ========================================================
1110 @depends(target)
1111 def webrtc_default(target):
1112     # Turn off webrtc for OS's we don't handle yet, but allow
1113     # --enable-webrtc to override.
1114     os_match = False
1115     for os_fragment in ('linux', 'mingw', 'android', 'linuxandroid',
1116                         'dragonfly', 'freebsd', 'netbsd', 'openbsd',
1117                         'darwin'):
1118         if target.raw_os.startswith(os_fragment):
1119             os_match = True
1121     cpu_match = False
1122     if (target.cpu in ('x86_64', 'arm', 'aarch64', 'x86', 'ia64', 'mips32', 'mips64') or
1123         target.cpu.startswith('ppc')):
1124         cpu_match = True
1126     if os_match and cpu_match:
1127         return True
1128     return False
1130 option('--disable-webrtc', default=webrtc_default,
1131        help='Disable support for WebRTC')
1133 @depends('--disable-webrtc')
1134 def webrtc(enabled):
1135     if enabled:
1136         return True
1138 set_config('MOZ_WEBRTC', webrtc)
1139 set_define('MOZ_WEBRTC', webrtc)
1140 add_old_configure_assignment('MOZ_WEBRTC', webrtc)
1141 set_config('MOZ_WEBRTC_SIGNALING', webrtc)
1142 set_define('MOZ_WEBRTC_SIGNALING', webrtc)
1143 set_config('MOZ_PEERCONNECTION', webrtc)
1144 set_define('MOZ_PEERCONNECTION', webrtc)
1145 # MOZ_WEBRTC_ASSERT_ALWAYS turns on a number of safety asserts in
1146 # opt/production builds (via MOZ_CRASH())
1147 set_config('MOZ_WEBRTC_ASSERT_ALWAYS', webrtc)
1148 set_define('MOZ_WEBRTC_ASSERT_ALWAYS', webrtc)
1150 # ASan Reporter Addon
1151 # ==============================================================
1152 option('--enable-address-sanitizer-reporter',
1153        help='Enable Address Sanitizer Reporter Extension')
1155 @depends('--enable-address-sanitizer-reporter')
1156 def enable_asan_reporter(value):
1157     if value:
1158         return True
1160 set_config('MOZ_ASAN_REPORTER', enable_asan_reporter)
1161 set_define('MOZ_ASAN_REPORTER', enable_asan_reporter)
1162 add_old_configure_assignment('MOZ_ASAN_REPORTER', enable_asan_reporter)
1164 # Elfhack
1165 # ==============================================================
1166 @depends(host, target)
1167 def has_elfhack(host, target):
1168     return target.kernel == 'Linux' and host.kernel == 'Linux' and \
1169            target.cpu in ('arm', 'x86', 'x86_64')
1171 with only_when(has_elfhack):
1172     option('--disable-elf-hack', help='Disable elf hacks')
1174     set_config('USE_ELF_HACK',
1175                depends_if('--enable-elf-hack')(lambda _: True))
1178 @depends(check_build_environment)
1179 def idl_roots(build_env):
1180     return namespace(ipdl_root=os.path.join(build_env.topobjdir, 'ipc', 'ipdl'),
1181                      webidl_root=os.path.join(build_env.topobjdir,
1182                                               'dom', 'bindings'))
1184 set_config('WEBIDL_ROOT', idl_roots.webidl_root)
1185 set_config('IPDL_ROOT', idl_roots.ipdl_root)
1187 # Proxy bypass protection
1188 # ==============================================================
1190 option('--enable-proxy-bypass-protection',
1191        help='Prevent suspected or confirmed proxy bypasses')
1193 @depends_if('--enable-proxy-bypass-protection')
1194 def proxy_bypass_protection(_):
1195     return True
1197 set_config('MOZ_PROXY_BYPASS_PROTECTION', proxy_bypass_protection)
1198 set_define('MOZ_PROXY_BYPASS_PROTECTION', proxy_bypass_protection)