Bug 1523562 [wpt PR 14799] - [Animation Worklet] Upstream animation worklet inside...
[gecko.git] / toolkit / moz.configure
blob30b948758788886570e6744029f350f38ad1298c
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 # Set the MOZ_CONFIGURE_OPTIONS variable with all the options that
8 # were passed somehow (environment, command line, mozconfig)
9 @dependable
10 @imports(_from='mozbuild.shellutil', _import='quote')
11 @imports('__sandbox__')
12 def all_configure_options():
13     result = []
14     previous = None
15     for option in __sandbox__._options.itervalues():
16         # __sandbox__._options contains items for both option.name and
17         # option.env. But it's also an OrderedDict, meaning both are
18         # consecutive.
19         # Also ignore OLD_CONFIGURE and MOZCONFIG because they're not
20         # interesting.
21         if option == previous or option.env in ('OLD_CONFIGURE', 'MOZCONFIG'):
22             continue
23         previous = option
24         value = __sandbox__._value_for(option)
25         # We only want options that were explicitly given on the command
26         # line, the environment, or mozconfig, and that differ from the
27         # defaults.
28         if (value is not None and value.origin not in ('default', 'implied') and
29                 value != option.default):
30             result.append(__sandbox__._raw_options[option])
31         # We however always include options that are sent to old configure
32         # because we don't know their actual defaults. (Keep the conditions
33         # separate for ease of understanding and ease of removal)
34         elif (option.help == 'Help missing for old configure options' and
35                 option in __sandbox__._raw_options):
36             result.append(__sandbox__._raw_options[option])
38     return quote(*result)
41 set_config('MOZ_CONFIGURE_OPTIONS', all_configure_options)
43 # Profiling
44 # ==============================================================
45 # Some of the options here imply an option from js/moz.configure,
46 # so, need to be declared before the include.
48 option('--enable-jprof', env='MOZ_JPROF',
49        help='Enable jprof profiling tool (needs mozilla/tools/jprof)')
51 @depends('--enable-jprof')
52 def jprof(value):
53     if value:
54         return True
56 set_config('MOZ_JPROF', jprof)
57 set_define('MOZ_JPROF', jprof)
58 imply_option('--enable-profiling', jprof)
60 @depends(target)
61 def gecko_profiler(target):
62     if target.os == 'Android':
63         return target.cpu in ('aarch64', 'arm', 'x86', 'x86_64')
64     elif target.kernel == 'Linux':
65         return target.cpu in ('aarch64', 'arm', 'x86', 'x86_64', 'mips64')
66     return target.os in ('OSX', 'WINNT')
68 @depends(gecko_profiler)
69 def gecko_profiler_define(value):
70     if value:
71         return True
73 set_config('MOZ_GECKO_PROFILER', gecko_profiler_define)
74 set_define('MOZ_GECKO_PROFILER', gecko_profiler_define)
77 # Whether code to parse ELF binaries should be compiled for the Gecko profiler
78 # (for symbol table dumping).
79 @depends(gecko_profiler, target)
80 def gecko_profiler_parse_elf(value, target):
81     # Currently we only want to build this code on Android, in order to dump
82     # symbols from Android system libraries on the device. For other platforms
83     # there exist alternatives that don't require bloating up our binary size.
84     if value and target.os == 'Android':
85         return True
87 set_config('MOZ_GECKO_PROFILER_PARSE_ELF', gecko_profiler_parse_elf)
88 set_define('MOZ_GECKO_PROFILER_PARSE_ELF', gecko_profiler_parse_elf)
90 # enable this by default if the profiler is enabled
91 # Note: also requires jemalloc
92 set_config('MOZ_PROFILER_MEMORY', gecko_profiler_define)
93 set_define('MOZ_PROFILER_MEMORY', gecko_profiler_define)
95 option('--enable-dmd', env='MOZ_DMD',
96        help='Enable Dark Matter Detector (heap profiler). '
97             'Also enables jemalloc, replace-malloc and profiling')
99 @depends('--enable-dmd')
100 def dmd(value):
101     if value:
102         return True
104 set_config('MOZ_DMD', dmd)
105 set_define('MOZ_DMD', dmd)
106 add_old_configure_assignment('MOZ_DMD', dmd)
107 imply_option('--enable-profiling', dmd)
108 imply_option('--enable-jemalloc', dmd)
109 imply_option('--enable-replace-malloc', dmd)
111 # ALSA cubeb backend
112 # ==============================================================
113 option('--enable-alsa', env='MOZ_ALSA',
114        help='Enable ALSA audio backend.')
116 alsa = pkg_check_modules('MOZ_ALSA', 'alsa', when='--enable-alsa')
118 set_config('MOZ_ALSA', depends_if(alsa)(lambda _: True))
119 set_define('MOZ_ALSA', depends_if(alsa)(lambda _: True))
121 # JACK cubeb backend
122 # ==============================================================
123 option('--enable-jack', env='MOZ_JACK',
124        help='Enable JACK audio backend.')
126 jack = pkg_check_modules('MOZ_JACK', 'jack', when='--enable-jack')
128 set_config('MOZ_JACK', depends_if(jack)(lambda _: True))
129 set_define('MOZ_JACK', depends_if(jack)(lambda _: True))
131 # PulseAudio cubeb backend
132 # ==============================================================
133 @depends(target)
134 def pulseaudio_default(target):
135     return target.os not in ('WINNT', 'OSX', 'iOS', 'Android', 'OpenBSD')
137 option('--enable-pulseaudio', env='MOZ_PULSEAUDIO', default=pulseaudio_default,
138        help='{Enable|Disable} PulseAudio audio backend.')
140 pulseaudio = pkg_check_modules('MOZ_PULSEAUDIO', 'libpulse', when='--enable-pulseaudio')
142 set_config('MOZ_PULSEAUDIO', depends_if(pulseaudio)(lambda _: True))
143 set_define('MOZ_PULSEAUDIO', depends_if(pulseaudio)(lambda _: True))
145 # Javascript engine
146 # ==============================================================
147 include('../js/moz.configure')
150 # NodeJS
151 # ==============================================================
152 include('../build/moz.configure/node.configure')
154 # L10N
155 # ==============================================================
156 option('--with-l10n-base', nargs=1, env='L10NBASEDIR',
157        help='Path to l10n repositories')
159 @depends('--with-l10n-base', 'MOZ_AUTOMATION', target, check_build_environment)
160 @imports(_from='os.path', _import='isdir')
161 @imports(_from='os.path', _import='expanduser')
162 @imports(_from='os', _import='environ')
163 def l10n_base(value, automation, target, build_env):
164     if value:
165         path = value[0]
166         if not isdir(path):
167             die("Invalid value --with-l10n-base, %s doesn't exist", path)
168     elif automation:
169         if target.os == 'Android':
170             path = os.path.join(build_env.topobjdir, '..', '..', 'l10n-central')
171         else:
172             path = os.path.join(build_env.topobjdir, '..', '..', 'l10n')
173     else:
174         path = os.path.join(
175             environ.get(
176                 'MOZBUILD_STATE_PATH',
177                 expanduser(os.path.join('~', '.mozbuild'))),
178             'l10n-central')
179     return os.path.realpath(os.path.abspath(path))
181 set_config('L10NBASEDIR', l10n_base)
184 # Default toolkit
185 # ==============================================================
186 @depends(target)
187 def toolkit_choices(target):
188     if target.os == 'WINNT':
189         return ('cairo-windows',)
190     elif target.os == 'OSX':
191         return ('cairo-cocoa',)
192     elif target.os == 'iOS':
193         return ('cairo-uikit',)
194     elif target.os == 'Android':
195         return ('cairo-android',)
196     else:
197         return ('cairo-gtk3', 'cairo-gtk3-wayland')
199 @depends(toolkit_choices)
200 def toolkit_default(choices):
201     return choices[0]
203 option('--enable-default-toolkit', nargs=1,
204        choices=toolkit_choices, default=toolkit_default,
205        help='Select default toolkit')
207 @depends_if('--enable-default-toolkit')
208 def full_toolkit(value):
209     return value[0]
211 @depends(full_toolkit)
212 def toolkit(toolkit):
213     if toolkit == 'cairo-gtk3-wayland':
214         widget_toolkit = 'gtk3'
215     else:
216         widget_toolkit = toolkit.replace('cairo-', '')
217     return widget_toolkit
219 set_config('MOZ_WIDGET_TOOLKIT', toolkit)
220 add_old_configure_assignment('MOZ_WIDGET_TOOLKIT', toolkit)
222 @depends(toolkit)
223 def toolkit_define(toolkit):
224     if toolkit == 'gtk3':
225         toolkit = 'gtk'
226     if toolkit != 'windows':
227         return 'MOZ_WIDGET_%s' % toolkit.upper()
229 set_define(toolkit_define, True)
231 @depends(toolkit)
232 def toolkit_gtk(toolkit):
233     return toolkit == 'gtk3'
235 set_config('MOZ_X11', True, when=toolkit_gtk)
236 set_define('MOZ_X11', True, when=toolkit_gtk)
237 add_old_configure_assignment('MOZ_X11', True, when=toolkit_gtk)
239 # Wayland support
240 # ==============================================================
241 wayland_headers = pkg_check_modules(
242     'MOZ_WAYLAND', 'gtk+-wayland-3.0 >= 3.10 xkbcommon >= 0.4.1',
243     allow_missing=depends(full_toolkit)(lambda t: t == 'cairo-gtk3'),
244     when=depends(full_toolkit)(lambda t: t in ('cairo-gtk3', 'cairo-gtk3-wayland')))
247 @depends(wayland_headers, toolkit_gtk, artifact_builds)
248 def wayland_headers(wayland, toolkit_gtk, artifacts):
249     if toolkit_gtk and artifacts:
250         return True
251     return wayland
254 set_config('MOZ_WAYLAND', depends_if(wayland_headers)(lambda _: True))
255 set_define('MOZ_WAYLAND', depends_if(wayland_headers)(lambda _: True))
257 # GL Provider
258 # ==============================================================
259 option('--with-gl-provider', nargs=1, help='Set GL provider backend type')
261 @depends('--with-gl-provider')
262 def gl_provider(value):
263     if value:
264         return value[0]
266 @depends(gl_provider)
267 def gl_provider_define(provider):
268     if provider:
269         return 'GLContextProvider%s' % provider
271 set_define('MOZ_GL_PROVIDER', gl_provider_define)
273 @depends(gl_provider, wayland_headers, toolkit_gtk)
274 def gl_default_provider(value, wayland, toolkit_gtk):
275     if value:
276         return value
277     elif wayland:
278         return 'EGL'
279     elif toolkit_gtk:
280         return 'GLX'
282 set_config('MOZ_GL_PROVIDER', gl_provider)
283 set_config('MOZ_GL_DEFAULT_PROVIDER', gl_default_provider)
285 @depends(gl_default_provider)
286 def gl_provider_define(provider):
287     if provider:
288         return 'GL_PROVIDER_%s' % provider
290 set_define(gl_provider_define, True)
293 # PDF printing
294 # ==============================================================
295 @depends(toolkit)
296 def pdf_printing(toolkit):
297     if toolkit in ('windows', 'gtk3', 'android'):
298         return True
300 @depends(pdf_printing)
301 def pdf_surface_feature(pdf_printing):
302     if pdf_printing:
303         return '#define CAIRO_HAS_PDF_SURFACE 1'
304     else:
305         # CONFIGURE_SUBST_FILES need explicit empty values.
306         return ''
308 set_config('MOZ_PDF_PRINTING', pdf_printing)
309 set_config('PDF_SURFACE_FEATURE', pdf_surface_feature)
312 # Event loop instrumentation
313 # ==============================================================
314 option(env='MOZ_INSTRUMENT_EVENT_LOOP',
315        help='Force-enable event loop instrumentation')
317 @depends('MOZ_INSTRUMENT_EVENT_LOOP', toolkit)
318 def instrument_event_loop(value, toolkit):
319     if value or (toolkit in ('windows', 'gtk3', 'cocoa', 'android') and
320                  value.origin == 'default'):
321         return True
323 set_config('MOZ_INSTRUMENT_EVENT_LOOP', instrument_event_loop)
324 set_define('MOZ_INSTRUMENT_EVENT_LOOP', instrument_event_loop)
327 # Fontconfig Freetype
328 # ==============================================================
329 option(env='USE_FC_FREETYPE',
330        help='Force-enable the use of fontconfig freetype')
332 @depends('USE_FC_FREETYPE', toolkit)
333 def fc_freetype(value, toolkit):
334     if value or (toolkit == 'gtk3' and
335                  value.origin == 'default'):
336         return True
338 add_old_configure_assignment('USE_FC_FREETYPE', fc_freetype)
340 # Pango
341 # ==============================================================
342 pkg_check_modules('MOZ_PANGO',
343                   'pango >= 1.22.0 pangoft2 >= 1.22.0 pangocairo >= 1.22.0',
344                   when=toolkit_gtk)
346 # Fontconfig
347 # ==============================================================
348 fontconfig_info = pkg_check_modules('_FONTCONFIG', 'fontconfig >= 2.7.0',
349                                     when=fc_freetype)
351 @depends(fc_freetype)
352 def check_for_freetype2(fc_freetype):
353     if fc_freetype:
354         return True
356 # Check for freetype2. Flags are combined with fontconfig flags.
357 freetype2_info = pkg_check_modules('_FT2', 'freetype2 >= 6.1.0',
358                                    when=check_for_freetype2)
360 @depends(fontconfig_info, freetype2_info)
361 def freetype2_combined_info(fontconfig_info, freetype2_info):
362     if not freetype2_info:
363         return
364     if not fontconfig_info:
365         return freetype2_info
366     return namespace(
367         cflags=freetype2_info.cflags + fontconfig_info.cflags,
368         libs=freetype2_info.libs + fontconfig_info.libs,
369     )
371 add_old_configure_assignment('_HAVE_FREETYPE2',
372                              depends_if(freetype2_info)(lambda _: True))
374 # Apple platform decoder support
375 # ==============================================================
376 @depends(toolkit)
377 def applemedia(toolkit):
378     if toolkit in ('cocoa', 'uikit'):
379         return True
381 set_config('MOZ_APPLEMEDIA', applemedia)
382 set_define('MOZ_APPLEMEDIA', applemedia)
383 add_old_configure_assignment('MOZ_APPLEMEDIA', applemedia)
385 # Windows Media Foundation support
386 # ==============================================================
387 option('--disable-wmf',
388        help='Disable support for Windows Media Foundation')
390 @depends('--disable-wmf', target)
391 def wmf(value, target):
392     enabled = bool(value)
393     if value.origin == 'default':
394         # Enable Windows Media Foundation support by default.
395         # Note our minimum SDK version is Windows 7 SDK, so we are (currently)
396         # guaranteed to have a recent-enough SDK to build WMF.
397         enabled = target.os == 'WINNT'
398     if enabled and target.os != 'WINNT':
399         die('Cannot enable Windows Media Foundation support on %s', target.os)
400     if enabled:
401         return True
403 set_config('MOZ_WMF', wmf)
404 set_define('MOZ_WMF', wmf)
406 # FFmpeg H264/AAC Decoding Support
407 # ==============================================================
408 option('--disable-ffmpeg',
409        help='Disable FFmpeg for fragmented H264/AAC decoding')
411 @depends('--disable-ffmpeg', target)
412 def ffmpeg(value, target):
413     enabled = bool(value)
414     if value.origin == 'default':
415         enabled = target.os not in ('Android', 'WINNT')
416     if enabled:
417         return True
419 set_config('MOZ_FFMPEG', ffmpeg)
420 set_define('MOZ_FFMPEG', ffmpeg)
421 imply_option('--enable-fmp4', ffmpeg, '--enable-ffmpeg')
423 # Libaom AV1 Video Codec Support
424 # ==============================================================
425 option('--enable-av1',
426         help='Enable libaom for av1 video support')
428 @depends('--enable-av1', target, c_compiler)
429 def av1(value, target, c_compiler):
430     enabled = bool(value)
431     if value.origin == 'default':
432         if target.os == 'WINNT' and target.cpu == 'x86' and \
433                 c_compiler and c_compiler.type == 'msvc':
434             enabled = False
435         else:
436             enabled = True
437     if enabled:
438         return True
440 set_config('MOZ_AV1', av1)
441 set_define('MOZ_AV1', av1)
443 # Built-in fragmented MP4 support.
444 # ==============================================================
445 option('--disable-fmp4', env='MOZ_FMP4',
446        help='Disable support for in built Fragmented MP4 parsing')
448 @depends('--disable-fmp4', target, wmf, applemedia)
449 def fmp4(value, target, wmf, applemedia):
450     enabled = bool(value)
451     if value.origin == 'default':
452         # target.os == 'Android' includes all B2G versions
453         enabled = wmf or applemedia or target.os == 'Android'
454     if enabled:
455         return True
457 set_config('MOZ_FMP4', fmp4)
458 set_define('MOZ_FMP4', fmp4)
459 add_old_configure_assignment('MOZ_FMP4', fmp4)
461 @depends(target)
462 def sample_type_is_s16(target):
463     # Use integers over floats for audio on Android regardless of the CPU
464     # architecture, because audio backends for Android don't support floats.
465     # We also use integers on ARM because it's more efficient.
466     if target.os == 'Android' or target.cpu == 'arm':
467         return True
469 @depends(sample_type_is_s16)
470 def sample_type_is_float(t):
471     if not t:
472         return True
474 set_config('MOZ_SAMPLE_TYPE_S16', sample_type_is_s16)
475 set_define('MOZ_SAMPLE_TYPE_S16', sample_type_is_s16)
476 set_config('MOZ_SAMPLE_TYPE_FLOAT32', sample_type_is_float)
477 set_define('MOZ_SAMPLE_TYPE_FLOAT32', sample_type_is_float)
479 set_define('MOZ_VORBIS', sample_type_is_float)
480 set_config('MOZ_VORBIS', sample_type_is_float)
481 set_define('MOZ_TREMOR', sample_type_is_s16)
482 set_config('MOZ_TREMOR', sample_type_is_s16)
484 # OpenMAX IL Decoding Support
485 # ==============================================================
486 option('--enable-openmax',
487        help='Enable OpenMAX IL for video/audio decoding')
489 @depends('--enable-openmax')
490 def openmax(value):
491     enabled = bool(value)
492     if enabled:
493         return True
495 set_config('MOZ_OMX', openmax)
496 set_define('MOZ_OMX', openmax)
498 # EME Support
499 # ==============================================================
500 # Widevine is enabled by default in desktop browser builds.
501 @depends(build_project)
502 def eme_default(build_project):
503     if build_project == 'browser':
504         return 'widevine'
506 option('--enable-eme',
507        nargs='*',
508        choices=('widevine',),
509        default=eme_default,
510        help='{Enable|Disable} support for Encrypted Media Extensions')
512 @depends('--enable-eme', target)
513 def enable_eme(value, target):
514     # Widevine EME by default enabled on desktop Windows, MacOS and Linux,
515     # x86 and x64 builds.
516     if (target.kernel in ('Darwin', 'WINNT', 'Linux') and
517         target.os not in ('Android', 'iOS') and
518         target.cpu in ('x86', 'x86_64')):
519         return value
520     elif value and value.origin != 'default':
521         die('%s is not supported on %s' % (value.format('--enable-eme'), target.alias))
522     # Return the same type of OptionValue (Positive or Negative), with an empty tuple.
523     return value.__class__(())
525 @depends(enable_eme, fmp4)
526 def eme(value, fmp4):
527     enabled = bool(value)
528     if value.origin == 'default':
529         enabled = enabled or fmp4
530     if enabled and not fmp4:
531         die('Encrypted Media Extension support requires '
532             'Fragmented MP4 support')
533     if enabled:
534         return True
536 @depends(enable_eme)
537 def eme_modules(value):
538     return value
540 set_config('MOZ_EME_MODULES', eme_modules)
542 option(name='--enable-chrome-format',
543        help='Select FORMAT of chrome files during packaging.',
544        nargs=1,
545        choices=('omni', 'jar', 'flat'),
546        default='omni')
548 @depends('--enable-chrome-format')
549 def packager_format(value):
550     return value[0]
552 set_config('MOZ_PACKAGER_FORMAT', packager_format)
554 @depends(host, build_project)
555 def jar_maker_format(host, build_project):
556     # Multilocales for mobile/android use the same mergedirs for all locales,
557     # so we can't use symlinks for those builds.
558     if host.os == 'WINNT' or build_project == 'mobile/android':
559         return 'flat'
560     return 'symlink'
562 set_config('MOZ_JAR_MAKER_FILE_FORMAT', jar_maker_format)
564 @depends(toolkit)
565 def omnijar_name(toolkit):
566     # Fennec's static resources live in the assets/ folder of the
567     # APK.  Adding a path to the name here works because we only
568     # have one omnijar file in the final package (which is not the
569     # case on desktop), and necessitates some contortions during
570     # packaging so that the resources in the omnijar are considered
571     # as rooted at / and not as rooted at assets/ (which again is
572     # not the case on desktop: there are omnijars rooted at webrtc/,
573     # etc). packager.mk handles changing the rooting of the single
574     # omnijar.
575     return 'assets/omni.ja' if toolkit == 'android' else 'omni.ja'
577 set_config('OMNIJAR_NAME', omnijar_name)
579 project_flag('MOZ_PLACES',
580              help='Build Places if required',
581              set_as_define=True)
583 project_flag('MOZ_SERVICES_HEALTHREPORT',
584              help='Build Firefox Health Reporter Service',
585              set_for_old_configure=True,
586              set_as_define=True)
588 project_flag('MOZ_SERVICES_SYNC',
589              help='Build Sync Services if required')
591 project_flag('MOZ_ANDROID_HISTORY',
592              help='Enable Android History instead of Places',
593              set_as_define=True)
595 project_flag('MOZ_DEDICATED_PROFILES',
596              help='Enable dedicated profiles per install',
597              set_as_define=True)
599 project_flag('MOZ_BLOCK_PROFILE_DOWNGRADE',
600              help='Block users from starting profiles last used by a newer build',
601              set_as_define=True)
603 option(env='MOZ_ALLOW_LEGACY_EXTENSIONS',
604        default=milestone.is_nightly,
605        help='Allow legacy browser extensions')
607 @depends('MOZ_ALLOW_LEGACY_EXTENSIONS')
608 def legacy_extensions(value):
609     if bool(value):
610         return True
612 set_config('MOZ_ALLOW_LEGACY_EXTENSIONS', legacy_extensions)
613 set_define('MOZ_ALLOW_LEGACY_EXTENSIONS', legacy_extensions)
615 @depends('MOZ_PLACES', 'MOZ_ANDROID_HISTORY')
616 def check_places_and_android_history(places, android_history):
617     if places and android_history:
618         die('Cannot use MOZ_ANDROID_HISTORY alongside MOZ_PLACES.')
620 # gpsd support
621 # ==============================================================
622 option('--enable-gpsd', env='MOZ_GPSD',
623        help='Enable gpsd support')
625 @depends('--enable-gpsd')
626 def gpsd(value):
627     return bool(value)
629 system_gpsd = pkg_check_modules('MOZ_GPSD', 'libgps >= 3.11',
630                                 when=gpsd)
632 set_config('MOZ_GPSD', depends_if(system_gpsd)(lambda _: True))
634 # Miscellaneous programs
635 # ==============================================================
637 check_prog('TAR', ('gnutar', 'gtar', 'tar'))
638 check_prog('UNZIP', ('unzip',))
639 check_prog('ZIP', ('zip',))
640 check_prog('GN', ('gn',), allow_missing=True)
642 # Key files
643 # ==============================================================
644 include('../build/moz.configure/keyfiles.configure')
646 simple_keyfile('Mozilla API')
648 simple_keyfile('Google API')
650 id_and_secret_keyfile('Bing API')
652 simple_keyfile('Adjust SDK')
654 id_and_secret_keyfile('Leanplum SDK')
656 simple_keyfile('Pocket API')
659 # WebRender integration
660 # ==============================================================
662 option('--enable-webrender', nargs='?', choices=('build',),
663        help='Include WebRender in the build and/or enable it at runtime')
665 @depends('--enable-webrender')
666 def webrender(value):
667     build_webrender = None
668     enable_webrender = None
670     if value.origin == 'default':
671         # if nothing is specified, default to building
672         build_webrender = True
673     elif len(value) and value[0] == 'build':
674         # if explicitly set to 'build', then we build but don't enable
675         build_webrender = True
676     elif bool(value):
677         # if set to true, then build and enable
678         build_webrender = True
679         enable_webrender = True
681     # in all other cases, don't build it or enable it (defaults are fine)
682     return namespace(
683         build = build_webrender,
684         enable = enable_webrender,
685     )
687 set_config('MOZ_BUILD_WEBRENDER', webrender.build)
688 set_define('MOZ_BUILD_WEBRENDER', webrender.build)
689 set_config('MOZ_ENABLE_WEBRENDER', webrender.enable)
691 # SIMD acceleration for Rust code (currently just encoding_rs)
692 # ==============================================================
694 option('--enable-rust-simd', env='MOZ_RUST_SIMD',
695        help='Enable explicit SIMD in Rust code.')
697 @depends('--enable-rust-simd', target)
698 def rust_simd(value, target):
699     # As of 2018-06-05, the simd crate only works on aarch64,
700     # armv7, x86 and x86_64.
701     if target.cpu in ('aarch64', 'arm', 'x86', 'x86_64') and value:
702         return True
704 set_config('MOZ_RUST_SIMD', rust_simd)
705 set_define('MOZ_RUST_SIMD', rust_simd)
707 # Printing
708 # ==============================================================
709 @depends(target)
710 def ios_disable_printing(target):
711     if target.os == 'iOS':
712         return False
714 imply_option('--enable-printing', ios_disable_printing, reason='--target')
716 option('--disable-printing', help='Disable printing support')
718 @depends('--disable-printing')
719 def printing(value):
720     if value:
721         return True
723 set_config('NS_PRINTING', printing)
724 set_define('NS_PRINTING', printing)
725 set_define('NS_PRINT_PREVIEW', printing)
727 # Speech-dispatcher support
728 # ==============================================================
729 @depends(toolkit)
730 def no_speechd_on_non_gtk(toolkit):
731     if toolkit != 'gtk3':
732         return False
734 imply_option('--enable-synth-speechd', no_speechd_on_non_gtk,
735              reason='--enable-default-toolkit')
737 option('--disable-synth-speechd', help='Disable speech-dispatcher support')
739 set_config('MOZ_SYNTH_SPEECHD',
740            depends_if('--disable-synth-speechd')(lambda _: True))
742 # Speech API
743 # ==============================================================
744 option('--disable-webspeech', help='Disable support for HTML Speech API')
746 @depends('--disable-webspeech')
747 def webspeech(value):
748     if value:
749         return True
751 set_config('MOZ_WEBSPEECH', webspeech)
752 set_define('MOZ_WEBSPEECH', webspeech)
753 add_old_configure_assignment('MOZ_WEBSPEECH', webspeech)
755 # Speech API test backend
756 # ==============================================================
757 option('--enable-webspeechtestbackend', default=webspeech,
758        help='{Enable|Disable} support for HTML Speech API Test Backend')
760 @depends_if('--enable-webspeechtestbackend')
761 def webspeech_test_backend(value):
762     return True
764 set_config('MOZ_WEBSPEECH_TEST_BACKEND', webspeech_test_backend)
765 set_define('MOZ_WEBSPEECH_TEST_BACKEND', webspeech_test_backend)
767 # Enable IPDL's "expensive" unit tests
768 # ==============================================================
769 option('--enable-ipdl-tests', help='Enable expensive IPDL tests')
771 set_config('MOZ_IPDL_TESTS',
772            depends_if('--enable-ipdl-tests')(lambda _: True))
774 include('nss.configure')
776 # Graphics
777 # ==============================================================
778 option('--disable-skia', help='Disable use of Skia')
780 @depends('--disable-skia')
781 def skia(value):
782     if not value:
783         die('--disable-skia is not supported anymore')
784     else:
785         return True
787 set_config('MOZ_ENABLE_SKIA', skia)
788 set_define('MOZ_ENABLE_SKIA', skia)
789 set_define('USE_SKIA', skia)
791 @depends(skia, target)
792 def skia_android(skia, target):
793     if skia and target.os == 'Android':
794         return True
796 set_define('SK_BUILD_FOR_ANDROID_NDK', skia_android)
798 option('--disable-skia-gpu', help='Disable use of Skia-GPU')
800 @depends('--disable-skia-gpu', skia)
801 def skia_gpu(value, skia):
802     if value.origin == 'default':
803         if not skia:
804             return None
805     elif value and not skia:
806         die('Cannot enable Skia-GPU without enabling Skia')
807     if skia and value:
808         return True
810 set_config('MOZ_ENABLE_SKIA_GPU', skia_gpu)
811 set_define('USE_SKIA_GPU', skia_gpu)
813 option('--enable-skia-pdf', help='Enable Skia PDF')
815 @depends('--enable-skia-pdf', skia, target, milestone)
816 def skia_pdf(value, skia, target, milestone):
817     if value.origin == 'default':
818         if not skia:
819             return None
820         if milestone.is_nightly and target.os != 'WINNT':
821             return True
822     elif value and not skia:
823         die('Cannot enable Skia PDF without enabling Skia')
824     if skia and value:
825         return True
827 set_config('MOZ_ENABLE_SKIA_PDF', skia_pdf)
828 set_define('MOZ_ENABLE_SKIA_PDF', skia_pdf)
830 option('--enable-skia-pdf-sfntly', help='Enable SFNTLY font subsetting in Skia PDF')
832 @depends('--enable-skia-pdf-sfntly', skia_pdf)
833 def skia_pdf_sfntly(value, skia_pdf):
834     if value.origin == 'default':
835         return skia_pdf
836     if value and not skia_pdf:
837         die('Cannot enable SFNTLY subsetting without enabling Skia PDF')
838     if skia_pdf and value:
839         return True
841 set_config('MOZ_ENABLE_SKIA_PDF_SFNTLY', skia_pdf_sfntly)
842 set_define('MOZ_ENABLE_SKIA_PDF_SFNTLY', skia_pdf_sfntly)
844 @depends(skia_pdf_sfntly)
845 def sfntly_includes(skia_pdf_sfntly):
846     includes = []
847     if skia_pdf_sfntly:
848         includes += [
849             '/gfx/sfntly/cpp/src',
850         ]
851     return includes
853 set_config('SFNTLY_INCLUDES', sfntly_includes)
855 @depends(skia)
856 def skia_includes(skia):
857     includes = []
858     if skia:
859         includes += [
860             '/gfx/skia',
861             '/gfx/skia/skia/include/config',
862             '/gfx/skia/skia/include/core',
863             '/gfx/skia/skia/include/docs',
864             '/gfx/skia/skia/include/gpu',
865             '/gfx/skia/skia/include/utils',
866         ]
867     return includes
869 set_config('SKIA_INCLUDES', skia_includes)
871 option('--with-system-webp',
872        help='Use system libwebp (located with pkgconfig)')
874 system_webp = pkg_check_modules('MOZ_WEBP', 'libwebp >= 1.0.2 libwebpdemux >= 1.0.2',
875                                 when='--with-system-webp')
877 set_config('MOZ_SYSTEM_WEBP', depends(when=system_webp)(lambda: True))
879 # Build Freetype in the tree
880 # ==============================================================
881 @depends(target, skia_pdf)
882 def tree_freetype(target, skia_pdf):
883     if target.os == 'Android' or (skia_pdf and target.os == 'WINNT'):
884         return True
886 set_define('MOZ_TREE_FREETYPE', tree_freetype)
887 set_config('MOZ_TREE_FREETYPE', tree_freetype)
888 add_old_configure_assignment('MOZ_TREE_FREETYPE', tree_freetype)
890 set_define('HAVE_FT_BITMAP_SIZE_Y_PPEM', tree_freetype)
891 set_define('HAVE_FT_GLYPHSLOT_EMBOLDEN', tree_freetype)
892 set_define('HAVE_FT_LOAD_SFNT_TABLE', tree_freetype)
894 @depends(freetype2_combined_info, tree_freetype, check_build_environment)
895 def ft2_info(freetype2_combined_info, tree_freetype, build_env):
896     if tree_freetype:
897         return namespace(cflags=('-I%s/modules/freetype2/include' % build_env.topsrcdir,),
898                          libs=())
899     if freetype2_combined_info:
900         return freetype2_combined_info
902 set_config('FT2_LIBS', ft2_info.libs)
903 add_old_configure_assignment('FT2_LIBS',
904                              ft2_info.libs)
905 add_old_configure_assignment('FT2_CFLAGS',
906                              ft2_info.cflags)
908 # Marionette remote protocol
909 # ==============================================================
911 # Marionette is the Gecko remote protocol used for various remote control,
912 # automation, and testing purposes throughout Gecko, Firefox, and Fennec.
913 # Marionette lives in ../testing/marionette.
915 # Marionette is not really a toolkit feature, as much as a Gecko engine
916 # feature.  But it is enabled based on the toolkit (and target), so here
917 # it lives.
919 # It also backs ../testing/geckodriver, which is Mozilla's WebDriver
920 # implementation.
922 # For more information, see
923 # https://developer.mozilla.org/en-US/docs/Mozilla/QA/Marionette.
925 @depends(target)
926 def marionette(target):
927     """Enable Marionette by default, except on Android."""
928     if target.os != 'Android':
929         return True
931 imply_option('--enable-marionette', marionette, reason='Not Android')
933 option('--enable-marionette',
934        help='Enable Marionette remote protocol')
936 @depends('--enable-marionette')
937 def marionette(value):
938     if value:
939         return True
941 set_config('ENABLE_MARIONETTE', marionette)
943 # geckodriver WebDriver implementation
944 # ==============================================================
946 # Turn off geckodriver for build configs we don't handle yet,
947 # but allow --enable-geckodriver to override when compile environment is available.
948 # --disable-tests implies disabling geckodriver.
950 @depends('--enable-tests', target, cross_compiling, hazard_analysis, asan)
951 def geckodriver_default(enable_tests, target, cross_compile, hazard, asan):
952     if not enable_tests:
953         return False
954     # geckodriver depends on winapi 0.2.8, which doesn't work with AArch64.
955     if target.os == 'WINNT' and target.cpu == 'aarch64':
956         return False
957     if hazard or target.os == 'Android' or (asan and cross_compile):
958         return False
959     return True
961 option('--enable-geckodriver', default=geckodriver_default,
962        when='--enable-compile-environment',
963        help='{Build|Do not build} geckodriver')
965 @depends('--enable-geckodriver', when='--enable-compile-environment')
966 def geckodriver(enabled):
967     if enabled:
968         return True
970 set_config('ENABLE_GECKODRIVER', geckodriver)
972 # WebRTC
973 # ========================================================
974 @depends(target)
975 def webrtc_default(target):
976     # Turn off webrtc for OS's we don't handle yet, but allow
977     # --enable-webrtc to override.
978     os_match = False
979     for os_fragment in ('linux', 'mingw', 'android', 'linuxandroid',
980                         'dragonfly', 'freebsd', 'netbsd', 'openbsd',
981                         'darwin'):
982         if target.raw_os.startswith(os_fragment):
983             os_match = True
985     cpu_match = False
986     if (target.cpu in ('x86_64', 'arm', 'aarch64', 'x86', 'ia64', 'mips32', 'mips64') or
987         target.cpu.startswith('ppc')):
988         cpu_match = True
990     if os_match and cpu_match:
991         return True
992     return False
994 option('--disable-webrtc', default=webrtc_default,
995        help='{Enable|Disable} support for WebRTC')
997 @depends('--disable-webrtc')
998 def webrtc(enabled):
999     if enabled:
1000         return True
1002 set_config('MOZ_WEBRTC', webrtc)
1003 set_define('MOZ_WEBRTC', webrtc)
1004 add_old_configure_assignment('MOZ_WEBRTC', webrtc)
1005 set_config('MOZ_SCTP', webrtc)
1006 set_define('MOZ_SCTP', webrtc)
1007 set_config('MOZ_SRTP', webrtc)
1008 set_define('MOZ_SRTP', webrtc)
1009 set_config('MOZ_WEBRTC_SIGNALING', webrtc)
1010 set_define('MOZ_WEBRTC_SIGNALING', webrtc)
1011 set_config('MOZ_PEERCONNECTION', webrtc)
1012 set_define('MOZ_PEERCONNECTION', webrtc)
1013 # MOZ_WEBRTC_ASSERT_ALWAYS turns on a number of safety asserts in
1014 # opt/production builds (via MOZ_CRASH())
1015 set_config('MOZ_WEBRTC_ASSERT_ALWAYS', webrtc)
1016 set_define('MOZ_WEBRTC_ASSERT_ALWAYS', webrtc)
1018 option('--enable-hardware-aec-ns', when=webrtc,
1019        help='Enable support for hardware AEC and noise suppression')
1021 set_config('MOZ_WEBRTC_HARDWARE_AEC_NS',
1022            depends_if('--enable-hardware-aec-ns', when=webrtc)(lambda _: True))
1023 set_define('MOZ_WEBRTC_HARDWARE_AEC_NS',
1024            depends_if('--enable-hardware-aec-ns', when=webrtc)(lambda _: True))
1026 # RAW media
1027 # ==============================================================
1029 @depends(target, webrtc)
1030 def raw_media_default(target, webrtc):
1031     if target.os == 'Android':
1032         return True
1033     if webrtc:
1034         return True
1036 option('--enable-raw',
1037        default=raw_media_default,
1038        help='{Enable|Disable} support for RAW media')
1040 set_config('MOZ_RAW', depends_if('--enable-raw')(lambda _: True))
1041 set_define('MOZ_RAW', depends_if('--enable-raw')(lambda _: True))
1043 # ASan Reporter Addon
1044 # ==============================================================
1045 option('--enable-address-sanitizer-reporter',
1046        help='Enable Address Sanitizer Reporter Extension')
1048 @depends('--enable-address-sanitizer-reporter')
1049 def enable_asan_reporter(value):
1050     if value:
1051         return True
1053 set_config('MOZ_ASAN_REPORTER', enable_asan_reporter)
1054 set_define('MOZ_ASAN_REPORTER', enable_asan_reporter)
1055 add_old_configure_assignment('MOZ_ASAN_REPORTER', enable_asan_reporter)
1057 # Elfhack
1058 # ==============================================================
1059 with only_when('--enable-compile-environment'):
1060     @depends(host, target)
1061     def has_elfhack(host, target):
1062         return target.kernel == 'Linux' and host.kernel == 'Linux' and \
1063                target.cpu in ('arm', 'x86', 'x86_64')
1065     @depends('--enable-release')
1066     def default_elfhack(release):
1067         return bool(release)
1069     with only_when(has_elfhack):
1070         option('--disable-elf-hack', default=default_elfhack,
1071                help='{Enable|Disable} elf hacks')
1073         set_config('USE_ELF_HACK',
1074                    depends_if('--enable-elf-hack')(lambda _: True))
1077 @depends(check_build_environment)
1078 def idl_roots(build_env):
1079     return namespace(ipdl_root=os.path.join(build_env.topobjdir, 'ipc', 'ipdl'),
1080                      webidl_root=os.path.join(build_env.topobjdir,
1081                                               'dom', 'bindings'),
1082                      xpcom_root=os.path.join(build_env.topobjdir,
1083                                              'xpcom', 'components'))
1085 set_config('WEBIDL_ROOT', idl_roots.webidl_root)
1086 set_config('IPDL_ROOT', idl_roots.ipdl_root)
1087 set_config('XPCOM_ROOT', idl_roots.xpcom_root)
1089 # Proxy bypass protection
1090 # ==============================================================
1092 option('--enable-proxy-bypass-protection',
1093        help='Prevent suspected or confirmed proxy bypasses')
1095 @depends_if('--enable-proxy-bypass-protection')
1096 def proxy_bypass_protection(_):
1097     return True
1099 set_config('MOZ_PROXY_BYPASS_PROTECTION', proxy_bypass_protection)
1100 set_define('MOZ_PROXY_BYPASS_PROTECTION', proxy_bypass_protection)
1102 # MIDL
1103 # ==============================================================
1105 @depends(c_compiler, toolchain_prefix)
1106 def midl_names(c_compiler, toolchain_prefix):
1107     if c_compiler and c_compiler.type in ['gcc', 'clang']:
1108         # mingw
1109         widl = ('widl', )
1110         if toolchain_prefix:
1111             prefixed = tuple('%s%s' % (p, 'widl') for p in toolchain_prefix)
1112             widl = prefixed + widl
1113         return widl
1115     return ('midl',)
1117 @depends(target, '--enable-compile-environment')
1118 def check_for_midl(target, compile_environment):
1119     if target.os != 'WINNT':
1120         return
1122     if compile_environment:
1123         return True
1126 midl = check_prog('MIDL', midl_names, when=check_for_midl, allow_missing=True,
1127                   paths=sdk_bin_path)
1130 @depends(c_compiler, target, toolchain_search_path,
1131          when=depends(midl, target)(lambda m, t: m and t.kernel == 'WINNT'))
1132 @imports(_from='mozbuild.shellutil', _import='quote')
1133 def midl_flags(c_compiler, target, toolchain_search_path):
1134     if c_compiler and c_compiler.type in ('msvc', 'clang-cl'):
1135         env = {
1136             'x86': 'win32',
1137             'x86_64': 'x64',
1138             'aarch64': 'arm64',
1139         }[target.cpu]
1140         flags = ['-env', env]
1141         if c_compiler.type == 'msvc':
1142             flags += ['-cpp_cmd', c_compiler.compiler]
1143         else:
1144             # Ideally, we'd use the same flags setup as for msvc, but clang-cl
1145             # currently doesn't work as a preprocessor for midl, so we need to
1146             # find cl. https://bugs.llvm.org/show_bug.cgi?id=40140
1147             cl = find_program('cl', paths=toolchain_search_path)
1148             if not cl:
1149                 die('Could not find Microsoft Visual C/C++ compiler for MIDL')
1150             flags += ['-cpp_cmd', cl]
1151         return flags
1153     # mingw
1154     return {
1155         'x86': ['--win32', '-m32'],
1156         'x86_64': ['--win64', '-m64'],
1157     }[target.cpu]
1160 set_config('MIDL_FLAGS', midl_flags)
1162 # Accessibility
1163 # ==============================================================
1165 @depends(target)
1166 def a11y_default(target):
1167     # Accessibility doesn't work on aarch64-windows yet.
1168     if target.kernel == 'WINNT' and target.cpu == 'aarch64':
1169         return False
1170     return True
1172 option('--enable-accessibility',
1173        default=a11y_default, help='{Enable|Disable} accessibility support')
1175 @depends('--enable-accessibility', check_for_midl, midl, c_compiler)
1176 def accessibility(value, check_for_midl, midl, c_compiler):
1177     enabled = bool(value)
1179     if not enabled:
1180         return
1182     if check_for_midl and not midl:
1183         if c_compiler and c_compiler.type in ('gcc', 'clang'):
1184             die('You have accessibility enabled, but widl could not be found. '
1185                 'Add --disable-accessibility to your mozconfig or install widl. '
1186                 'See https://developer.mozilla.org/en-US/docs/Cross_Compile_Mozilla_for_Mingw32 for details.')
1187         else:
1188             die('MIDL could not be found. '
1189                 'Building accessibility without MIDL is not supported.')
1191     return enabled
1194 set_config('ACCESSIBILITY', accessibility)
1195 set_define('ACCESSIBILITY', accessibility)
1196 add_old_configure_assignment('ACCESSIBILITY', accessibility)
1198 # Addon signing
1199 # ==============================================================
1201 option('--with-unsigned-addon-scopes',
1202        nargs='+', choices=('app', 'system'),
1203        help='Addon scopes where signature is not required')
1205 @depends('--with-unsigned-addon-scopes')
1206 def unsigned_addon_scopes(scopes):
1207     return namespace(
1208         app='app' in scopes or None,
1209         system='system' in scopes or None,
1210     )
1212 set_config('MOZ_UNSIGNED_APP_SCOPE', unsigned_addon_scopes.app)
1213 set_config('MOZ_UNSIGNED_SYSTEM_SCOPE', unsigned_addon_scopes.system)
1215 # Launcher process (Windows only)
1216 # ==============================================================
1218 @depends(target, milestone)
1219 def launcher_process_default(target, milestone):
1220     return target.os == 'WINNT' and milestone.is_nightly
1222 option('--enable-launcher-process', default=launcher_process_default,
1223        help='{Enable|Disable} launcher process by default')
1225 @depends('--enable-launcher-process', target)
1226 def launcher(value, target):
1227     enabled = bool(value)
1228     if enabled and target.os != 'WINNT':
1229         die('Cannot enable launcher process on %s', target.os)
1230     if enabled:
1231         return True
1233 set_config('MOZ_LAUNCHER_PROCESS', launcher)
1234 set_define('MOZ_LAUNCHER_PROCESS', launcher)
1236 # Prio
1237 # ==============================================================
1238 @depends(c_compiler)
1239 def libprio(info):
1240     if info:
1241       # MSVC is not supported by libprio.
1242       if info.type in ('msvc',):
1243         return None
1244     return True
1246 set_config('MOZ_LIBPRIO', libprio)
1248 # Maintenance service (Windows only)
1249 # ==============================================================
1251 option('--enable-maintenance-service',
1252        when=target_is_windows, default=target_is_windows,
1253        help='{Enable|Disable} building of maintenance service')
1255 set_define('MOZ_MAINTENANCE_SERVICE',
1256            depends_if('--enable-maintenance-service',
1257                       when=target_is_windows)(lambda _: True))
1258 set_config('MOZ_MAINTENANCE_SERVICE',
1259            depends_if('--enable-maintenance-service',
1260                       when=target_is_windows)(lambda _: True))
1262 # Bundled fonts on desktop platform
1263 # ==============================================================
1265 @depends(target)
1266 def bundled_fonts_default(target):
1267     return target.os == 'WINNT' or target.kernel == 'Linux'
1269 @depends(build_project)
1270 def allow_bundled_fonts(project):
1271     return project == 'browser'
1273 option('--enable-bundled-fonts', default=bundled_fonts_default,
1274        when=allow_bundled_fonts,
1275        help='{Enable|Disable} support for bundled fonts on desktop platforms')
1277 set_define('MOZ_BUNDLED_FONTS',
1278            depends_if('--enable-bundled-fonts', when=allow_bundled_fonts)(lambda _: True))
1280 # Verify MAR signatures
1281 # ==============================================================
1283 option('--enable-verify-mar', help='Enable verifying MAR signatures')
1285 set_define('MOZ_VERIFY_MAR_SIGNATURE',
1286            depends_if('--enable-verify-mar')(lambda _: True))
1287 set_config('MOZ_VERIFY_MAR_SIGNATURE',
1288            depends_if('--enable-verify-mar')(lambda _: True))
1290 # TaskTracer
1291 # ==============================================================
1293 option('--enable-tasktracer', help='Enable TaskTracer')
1295 set_define('MOZ_TASK_TRACER', depends_if('--enable-tasktracer')(lambda _: True))
1296 set_config('MOZ_TASK_TRACER', depends_if('--enable-tasktracer')(lambda _: True))
1298 # Reflow counting
1299 # ==============================================================
1301 @depends(moz_debug)
1302 def reflow_perf(debug):
1303     if debug:
1304         return True
1306 option('--enable-reflow-perf',
1307        default=reflow_perf,
1308        help='{Enable|Disable} reflow performance tracing')
1310 # The difference in conditions here comes from the initial implementation
1311 # in old-configure, which was unexplained there as well.
1312 set_define('MOZ_REFLOW_PERF', depends_if('--enable-reflow-perf')(lambda _: True))
1313 set_define('MOZ_REFLOW_PERF_DSP', reflow_perf)
1315 # Layout debugger
1316 # ==============================================================
1318 @depends(moz_debug)
1319 def layout_debugger(debug):
1320     if debug:
1321         return True
1323 option('--enable-layout-debugger',
1324        default=layout_debugger,
1325        help='{Enable|Disable} layout debugger')
1327 set_config('MOZ_LAYOUT_DEBUGGER', depends_if('--enable-layout-debugger')(lambda _: True))
1330 # Shader Compiler for Windows (and MinGW Cross Compile)
1331 # ==============================================================
1333 with only_when(compile_environment):
1334     fxc = check_prog('FXC', ('fxc.exe', 'fxc2.exe'), when=depends(target)
1335                      (lambda t: t.kernel == 'WINNT'),
1336                      paths=sdk_bin_path)
1337     wine = check_prog('WINE', ['wine'], when=depends(target, host)
1338                       (lambda t, h: t.kernel == 'WINNT' and h.kernel == 'Linux'))
1341 # VPX
1342 # ===
1344 with only_when(compile_environment):
1345     option('--with-system-libvpx',
1346            help='Use system libvpx (located with pkgconfig)')
1348     with only_when('--with-system-libvpx'):
1349         vpx = pkg_check_modules('MOZ_LIBVPX', 'vpx >= 1.7.0')
1351         check_header('vpx/vpx_decoder.h', flags=vpx.cflags, onerror=lambda: die(
1352             "Couldn't find vpx/vpx_decoder.h, which is required to build "
1353             "with system libvpx. Use --without-system-libvpx to build "
1354             "with in-tree libvpx."))
1356         check_symbol('vpx_codec_dec_init_ver', flags=vpx.libs, onerror=lambda: die(
1357             "--with-system-libvpx requested but symbol vpx_codec_dec_init_ver "
1358             "not found"
1359         ))
1361         set_config('MOZ_SYSTEM_LIBVPX', True)
1364     @depends('--with-system-libvpx', target, gnu_as)
1365     def in_tree_vpx(system_libvpx, target, gnu_as):
1366         if system_libvpx:
1367             return
1369         use_yasm = (target.cpu in ('x86', 'x86_64')) or None
1370         need_yasm = False
1371         arm_asm = (target.cpu == 'arm' and gnu_as) or None
1373         if use_yasm:
1374             need_yasm = True
1375             if target.kernel == 'WINNT':
1376                 need_yasm = Version('1.1')
1378         return namespace(arm_asm=arm_asm, use_yasm=use_yasm, need_yasm=need_yasm)
1381     # Building with -mfpu=neon requires either the "softfp" or the
1382     # "hardfp" ABI. Depending on the compiler's default target, and the
1383     # CFLAGS, the default ABI might be neither, in which case it is the
1384     # "softfloat" ABI.
1385     # The "softfloat" ABI is binary-compatible with the "softfp" ABI, so
1386     # we can safely mix code built with both ABIs. So, if we detect
1387     # that compiling uses the "softfloat" ABI, force the use of the
1388     # "softfp" ABI instead.
1389     # Confusingly, the __SOFTFP__ preprocessor variable indicates the
1390     # "softfloat" ABI, not the "softfp" ABI.
1391     # Note: VPX_ASFLAGS is also used in CFLAGS.
1392     softfp = cxx_compiler.try_compile(body='''
1393         #ifndef __SOFTFP__
1394         #error "compiler target supports -mfpu=neon, so we don't have to add extra flags"
1395         #endif''', when=in_tree_vpx.arm_asm)
1398     @depends(in_tree_vpx, softfp, target)
1399     def vpx_as_flags(vpx, softfp, target):
1400         flags = []
1401         if vpx and vpx.arm_asm:
1402             # These flags are a lie; they're just used to enable the requisite
1403             # opcodes; actual arch detection is done at runtime.
1404             flags = ['-march=armv7-a', '-mfpu=neon']
1405             if softfp:
1406                 flags.append('-mfloat-abi=softfp')
1407         elif vpx and vpx.use_yasm and target.os != 'WINNT' and target.cpu != 'x86_64':
1408             flags = ['-DPIC']
1409         return flags
1412     set_config('VPX_USE_YASM', in_tree_vpx.use_yasm)
1413     set_config('VPX_ASFLAGS', vpx_as_flags)
1416 # JPEG
1417 # ====
1419 with only_when(compile_environment):
1420     option('--with-system-jpeg', nargs='?',
1421            help='Use system libjpeg (installed at given prefix)')
1423     @depends_if('--with-system-jpeg')
1424     def jpeg_flags(value):
1425         if len(value):
1426             return namespace(
1427                 cflags=('-I%s/include' % value[0],),
1428                 ldflags=('-L%s/lib' % value[0], '-ljpeg'),
1429             )
1430         return namespace(
1431             ldflags=('-ljpeg',),
1432         )
1434     with only_when('--with-system-jpeg'):
1435         check_symbol('jpeg_destroy_compress', flags=jpeg_flags.ldflags,
1436                      onerror=lambda: die('--with-system-jpeg requested but symbol '
1437                                          'jpeg_destroy_compress not found.'))
1439         c_compiler.try_compile(
1440             includes=[
1441                 'stdio.h',
1442                 'sys/types.h',
1443                 'jpeglib.h',
1444             ],
1445             body='''
1446                 #if JPEG_LIB_VERSION < 62
1447                 #error Insufficient JPEG library version
1448                 #endif
1449             ''',
1450             flags=jpeg_flags.cflags,
1451             check_msg='for sufficient jpeg library version',
1452             onerror=lambda: die('Insufficient JPEG library version for '
1453                                 '--with-system-jpeg (62 required)'),
1454         )
1456         c_compiler.try_compile(
1457             includes=[
1458                 'stdio.h',
1459                 'sys/types.h',
1460                 'jpeglib.h',
1461             ],
1462             body='''
1463                 #ifndef JCS_EXTENSIONS
1464                 #error libjpeg-turbo JCS_EXTENSIONS required
1465                 #endif
1466             ''',
1467             flags=jpeg_flags.cflags,
1468             check_msg='for sufficient libjpeg-turbo JCS_EXTENSIONS',
1469             onerror=lambda: die('libjpeg-turbo JCS_EXTENSIONS required for '
1470                                  '--with-system-jpeg'),
1471         )
1473         set_config('MOZ_JPEG_CFLAGS', jpeg_flags.cflags)
1474         set_config('MOZ_JPEG_LIBS', jpeg_flags.ldflags)
1476     @depends('--with-system-jpeg', target)
1477     def in_tree_jpeg(system_jpeg, target):
1478         if system_jpeg:
1479             return
1481         flags = ()
1482         use_yasm = None
1483         need_yasm = False
1484         if target.kernel == 'Darwin':
1485             if target.cpu == 'x86':
1486                 flags = ('-DPIC', '-DMACHO')
1487             elif target.cpu == 'x86_64':
1488                 flags = ('-D__x86_64__', '-DPIC', '-DMACHO')
1489         elif target.kernel == 'WINNT':
1490             if target.cpu == 'x86':
1491                 flags = ('-DPIC', '-DWIN32')
1492             elif target.cpu == 'x86_64':
1493                 flags = ('-D__x86_64__', '-DPIC', '-DWIN64', '-DMSVC')
1494         elif target.cpu == 'arm':
1495             flags = ('-march=armv7-a', '-mfpu=neon')
1496         elif target.cpu == 'aarch64':
1497             flags = ('-march=armv8-a',)
1498         elif target.cpu == 'mips32':
1499             flags = ('-mdspr2',)
1500         elif target.cpu == 'x86':
1501             flags = ('-DPIC', '-DELF')
1502         elif target.cpu == 'x86_64':
1503             flags = ('-D__x86_64__', '-DPIC', '-DELF')
1505         if target.cpu in ('x86', 'x86_64'):
1506             use_yasm = True
1507             if target.kernel == 'Linux' and target.os == 'GNU':
1508                 need_yasm = Version('1.0.1')
1509             else:
1510                 need_yasm = Version('1.1')
1512         return namespace(flags=flags, use_yasm=use_yasm, need_yasm=need_yasm)
1514     set_config('LIBJPEG_TURBO_USE_YASM', in_tree_jpeg.use_yasm)
1515     set_config('LIBJPEG_TURBO_ASFLAGS', in_tree_jpeg.flags)
1518 # Libav-fft Support
1519 # ==============================================================
1520 with only_when(compile_environment):
1521     @depends(target)
1522     def libav_fft(target):
1523         flags = None
1524         if target.kernel == 'WINNT' and target.cpu == 'x86':
1525             flags = ['-DPIC', '-DWIN32']
1526         elif target.cpu == 'x86_64':
1527             if target.kernel == 'Darwin':
1528                 flags = ['-D__x86_64__', '-DPIC', '-DMACHO']
1529             elif target.kernel == 'WINNT':
1530                 flags = ['-D__x86_64__', '-DPIC', '-DWIN64', '-DMSVC']
1531             else:
1532                 flags = ['-D__x86_64__', '-DPIC', '-DELF']
1533         if flags:
1534             if target.kernel == 'Linux' and target.os == 'GNU':
1535                 need_yasm = Version('1.0.1')
1536             else:
1537                 need_yasm = Version('1.1')
1538             return namespace(flags=flags, need_yasm=need_yasm)
1541     set_config('MOZ_LIBAV_FFT', depends(when=libav_fft)(lambda: True))
1542     set_define('MOZ_LIBAV_FFT', depends(when=libav_fft)(lambda: True))
1543     set_config('LIBAV_FFT_ASFLAGS', libav_fft.flags)
1546 # FFmpeg's ffvpx configuration
1547 # ==============================================================
1548 with only_when(compile_environment):
1549     @depends_if(yasm_version)
1550     def yasm_has_avx2(yasm_version):
1551         return yasm_version >= '1.2'
1554     set_config('YASM_HAS_AVX2', yasm_has_avx2)
1557     @depends(yasm_has_avx2, libav_fft, vpx_as_flags, target)
1558     def ffvpx(yasm_has_avx2, libav_fft, vpx_as_flags, target):
1559         enable = flac_only = use_yasm = False
1560         flags = []
1561         if target.cpu in ('x86', 'x86_64'):
1562             enable = True
1563             if libav_fft and libav_fft.flags:
1564                 use_yasm = True
1565                 flags.extend(libav_fft.flags)
1566                 if target.kernel == 'WINNT':
1567                     if target.cpu == 'x86':
1568                         # 32-bit windows need to prefix symbols with an underscore.
1569                         flags.extend(('-DPREFIX', '-Pconfig_win32.asm'))
1570                     else:
1571                         flags.append('-Pconfig_win64.asm')
1572                 elif target.kernel == 'Darwin':
1573                     # 32/64-bit macosx assemblers need to prefix symbols with an
1574                     # underscore.
1575                     flags.extend(('-DPREFIX', '-Pconfig_darwin64.asm'))
1576                 else:
1577                     # Default to unix.
1578                     flags.append('-Pconfig_unix64.asm')
1579             else:
1580                 flac_only = True
1581         elif target.cpu in ('arm', 'aarch64') and \
1582                 target.kernel not in ('WINNT', 'Darwin'):
1583             enable = flac_only = True
1584             flags.extend(vpx_as_flags)
1586         if use_yasm:
1587             # default disabled components
1588             flags.append('-Pdefaults_disabled.asm')
1589             if not yasm_has_avx2:
1590                 flags.extend((
1591                     '-DHAVE_AVX2=0',
1592                     '-DHAVE_AVX2_INTERNAL=0',
1593                     '-DHAVE_AVX2_EXTERNAL=0',
1594                 ))
1596         return namespace(
1597             enable=enable,
1598             use_yasm=use_yasm,
1599             flac_only=flac_only,
1600             flags=flags,
1601         )
1604     set_config('MOZ_FFVPX', True, when=ffvpx.enable)
1605     set_define('MOZ_FFVPX', True, when=ffvpx.enable)
1606     set_config('MOZ_FFVPX_FLACONLY', True, when=ffvpx.flac_only)
1607     set_define('MOZ_FFVPX_FLACONLY', True, when=ffvpx.flac_only)
1608     set_config('FFVPX_ASFLAGS', ffvpx.flags)
1609     set_config('FFVPX_USE_YASM', True, when=ffvpx.use_yasm)
1612 @depends(yasm_version, in_tree_vpx.need_yasm, in_tree_jpeg.use_yasm,
1613          libav_fft.need_yasm, ffvpx.use_yasm)
1614 @imports(_from='__builtin__', _import='sorted')
1615 def valid_yasm_version(yasm_version, for_vpx, for_jpeg, for_libav,
1616                        for_ffvpx=False):
1617     # Note: the default for for_ffvpx above only matters for unit tests.
1618     requires = {
1619         'vpx': for_vpx,
1620         'jpeg': for_jpeg,
1621         'libav': for_libav,
1622         'ffvpx': for_ffvpx,
1623     }
1624     requires = {k: v for (k, v) in requires.items() if v}
1625     if requires and not yasm_version:
1626         items = sorted(requires.keys())
1627         if len(items) > 1:
1628             what = ' and '.join((', '.join(items[:-1]), items[-1]))
1629         else:
1630             what = items[0]
1631         die('Yasm is required to build with %s, but you do not appear to have '
1632             'Yasm installed.' % what)
1634     versioned = {k: v for (k, v) in requires.items() if v is not True}
1635     by_version = sorted(versioned.items(), key=lambda x: x[1])
1636     if by_version:
1637         what, version = by_version[-1]
1638         if yasm_version < version:
1639             die('Yasm version %s or greater is required to build with %s.'
1640                 % (version, what))
1643 # ANGLE OpenGL->D3D translator for WebGL
1644 # ==============================================================
1646 with only_when(compile_environment & target_is_windows):
1647     def d3d_compiler_dll_result(value):
1648         if not value.path:
1649             return 'provided by the OS'
1650         return value.path
1652     @depends(target, valid_windows_sdk_dir, fxc)
1653     @checking('for D3D compiler DLL', d3d_compiler_dll_result)
1654     @imports('os.path')
1655     def d3d_compiler_dll(target, windows_sdk_dir, fxc):
1656         suffix = {
1657             'x86_64': 'x64',
1658         }.get(target.cpu, target.cpu)
1660         name = 'd3dcompiler_47.dll'
1662         if target.cpu == 'aarch64':
1663             # AArch64 Windows comes with d3dcompiler_47.dll installed
1664             return namespace(name=name, path=None)
1666         if windows_sdk_dir:
1667             path = os.path.join(windows_sdk_dir.path, 'Redist', 'D3D', suffix, name)
1668             error_extra = 'in Windows SDK at {}'.format(windows_sdk_dir.path)
1669         else:
1670             path = os.path.join(os.path.dirname(fxc), name)
1671             error_extra = 'alongside FXC at {}'.format(fxc)
1673         if os.path.exists(path):
1674             return namespace(name=name, path=path)
1675         die('Could not find {} {}'.format(name, error_extra))
1678     set_config('MOZ_ANGLE_RENDERER', True)
1679     set_config('MOZ_D3DCOMPILER_VISTA_DLL', d3d_compiler_dll.name,
1680                when=d3d_compiler_dll.path)
1681     set_config('MOZ_D3DCOMPILER_VISTA_DLL_PATH', d3d_compiler_dll.path)