# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- # vim: set filetype=python: # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # Set the MOZ_CONFIGURE_OPTIONS variable with all the options that # were passed somehow (environment, command line, mozconfig) @dependable @imports(_from="mozbuild.shellutil", _import="quote") @imports(_from="mozbuild.util", _import="ensure_unicode") @imports(_from="mozbuild.util", _import="system_encoding") @imports("__sandbox__") def all_configure_options(): result = [] previous = None for option in __sandbox__._options.values(): # __sandbox__._options contains items for both option.name and # option.env. But it's also an OrderedDict, meaning both are # consecutive. # Also ignore OLD_CONFIGURE and MOZCONFIG because they're not # interesting. if option == previous or option.env in ("OLD_CONFIGURE", "MOZCONFIG"): continue previous = option value = __sandbox__._value_for(option) # We only want options that were explicitly given on the command # line, the environment, or mozconfig, and that differ from the # defaults. if ( value is not None and value.origin not in ("default", "implied") and value != option.default ): result.append( ensure_unicode(__sandbox__._raw_options[option], system_encoding) ) # We however always include options that are sent to old configure # because we don't know their actual defaults. (Keep the conditions # separate for ease of understanding and ease of removal) elif ( option.help == "Help missing for old configure options" and option in __sandbox__._raw_options ): result.append( ensure_unicode(__sandbox__._raw_options[option], system_encoding) ) # We shouldn't need this, but currently, quote will return a byte string # if result is empty, and that's not wanted here. if not result: return "" return quote(*result) set_config("MOZ_CONFIGURE_OPTIONS", all_configure_options) @depends(target) def fold_libs(target): return target.os in ("WINNT", "OSX", "iOS", "Android") set_config("MOZ_FOLD_LIBS", fold_libs) # Profiling # ============================================================== # Some of the options here imply an option from js/moz.configure, # so, need to be declared before the include. option( "--enable-jprof", env="MOZ_JPROF", help="Enable jprof profiling tool (needs mozilla/tools/jprof)", ) @depends("--enable-jprof") def jprof(value): if value: return True set_config("MOZ_JPROF", jprof) set_define("MOZ_JPROF", jprof) imply_option("--enable-profiling", jprof) option("--disable-gecko-profiler", help="Disable the Gecko profiler") @depends("--disable-gecko-profiler", target) def gecko_profiler(enable_gecko_profiler, target): if not enable_gecko_profiler: return False if target.os == "Android": return target.cpu in ("aarch64", "arm", "x86", "x86_64") elif target.kernel == "Linux": return target.cpu in ("aarch64", "arm", "x86", "x86_64", "mips64") elif target.kernel == "FreeBSD": return target.cpu in ("aarch64", "x86_64") return target.kernel in ("Darwin", "WINNT") @depends(gecko_profiler) def gecko_profiler_define(value): if value: return True set_config("MOZ_GECKO_PROFILER", gecko_profiler_define) set_define("MOZ_GECKO_PROFILER", gecko_profiler_define) # Whether code to parse ELF binaries should be compiled for the Gecko profiler # (for symbol table dumping). @depends(gecko_profiler, target) def gecko_profiler_parse_elf(value, target): # Currently we only want to build this code on Linux (including Android) and BSD. # For Android, this is in order to dump symbols from Android system, where # on other platforms there exist alternatives that don't require bloating # up our binary size. For Linux more generally, we use this in profile # pre-symbolication support, since MozDescribeCodeAddress doesn't do # anything useful on that platform. (Ideally, we would update # MozDescribeCodeAddress to call into some Rust crates that parse ELF and # DWARF data, but build system issues currently prevent Rust from being # used in mozglue.) if value and (target.kernel == "Linux" or target.kernel == "FreeBSD"): return True set_config("MOZ_GECKO_PROFILER_PARSE_ELF", gecko_profiler_parse_elf) set_define("MOZ_GECKO_PROFILER_PARSE_ELF", gecko_profiler_parse_elf) # enable this by default if the profiler is enabled # Note: also requires jemalloc set_config("MOZ_PROFILER_MEMORY", gecko_profiler_define) set_define("MOZ_PROFILER_MEMORY", gecko_profiler_define) @depends( "--enable-debug", milestone, build_project, # Artifact builds are included because the downloaded artifacts can # have DMD enabled. when=artifact_builds | depends(when="--enable-replace-malloc")(lambda: True), ) def dmd_default(debug, milestone, build_project): return bool(build_project == "browser" and (debug or milestone.is_nightly)) option( "--enable-dmd", env="MOZ_DMD", default=dmd_default, help="{Enable|Disable} Dark Matter Detector (heap profiler). " "Also enables jemalloc, replace-malloc and profiling", ) @depends("--enable-dmd") def dmd(value): if value: return True set_config("MOZ_DMD", dmd) set_define("MOZ_DMD", dmd) imply_option("--enable-profiling", dmd) imply_option("--enable-jemalloc", dmd, when=compile_environment) imply_option("--enable-replace-malloc", dmd, when=compile_environment) # midir-based Web MIDI support # ============================================================== @depends(target) def midir_linux_support(target): return ( target.kernel == "Linux" and target.os != "Android" and target.cpu != "riscv64" ) @depends(target, midir_linux_support) def midir_support(target, midir_linux_support): if target.os in ("WINNT", "OSX") or midir_linux_support: return True set_config("MOZ_WEBMIDI_MIDIR_IMPL", midir_support) # Enable various cubeb backends # ============================================================== @depends(target) def audio_backends_default(target): if target.os == "Android": return ( "aaudio", "opensl", ) elif target.os in ("DragonFly", "FreeBSD", "SunOS"): return ("oss",) elif target.os == "OpenBSD": return ("sndio",) elif target.os == "OSX": return ("audiounit",) elif target.os == "iOS": return None elif target.os == "NetBSD": return ("sunaudio",) elif target.os == "SunOS": return ("sunaudio",) elif target.os == "WINNT": return ("wasapi",) else: return ("pulseaudio",) option( "--enable-audio-backends", nargs="+", choices=( "aaudio", "alsa", "audiounit", "jack", "opensl", "oss", "pulseaudio", "sndio", "sunaudio", "wasapi", ), default=audio_backends_default, help="{Enable|Disable} various cubeb backends", ) @depends("--enable-audio-backends", target) def imply_aaudio(values, target): if any("aaudio" in value for value in values) and target.os != "Android": die("Cannot enable AAudio on %s", target.os) return any("aaudio" in value for value in values) or None @depends("--enable-audio-backends", target) def imply_alsa(values, target): if ( any("alsa" in value for value in values) and target.kernel != "Linux" and target.os != "FreeBSD" ): die("Cannot enable ALSA on %s", target.os) return any("alsa" in value for value in values) or None @depends("--enable-audio-backends", target) def imply_audiounit(values, target): if ( any("audiounit" in value for value in values) and target.os != "OSX" and target.kernel != "Darwin" ): die("Cannot enable AudioUnit on %s", target.os) return any("audiounit" in value for value in values) or None @depends("--enable-audio-backends") def imply_jack(values): return any("jack" in value for value in values) or None @depends("--enable-audio-backends", target) def imply_opensl(values, target): if any("opensl" in value for value in values) and target.os != "Android": die("Cannot enable OpenSL on %s", target.os) return any("opensl" in value for value in values) or None @depends("--enable-audio-backends", target) def imply_oss(values, target): if any("oss" in value for value in values) and ( target.os in ("Android", "OSX", "iOS", "WINNT") ): die("Cannot enable OSS on %s", target.os) return any("oss" in value for value in values) or None @depends("--enable-audio-backends", target) def imply_pulseaudio(values, target): if any("pulseaudio" in value for value in values) and ( target.os in ("Android", "OSX", "iOS", "WINNT") ): die("Cannot enable PulseAudio on %s", target.os) return any("pulseaudio" in value for value in values) or None @depends("--enable-audio-backends", target) def imply_sndio(values, target): if any("sndio" in value for value in values) and ( target.os in ("Android", "OSX", "iOS", "WINNT") ): die("Cannot enable sndio on %s", target.os) return any("sndio" in value for value in values) or None @depends("--enable-audio-backends", target) def imply_sunaudio(values, target): if any("sunaudio" in value for value in values) and ( target.os != "NetBSD" and target.os != "SunOS" ): die("Cannot enable sunaudio on %s", target.os) return any("sunaudio" in value for value in values) or None @depends("--enable-audio-backends", target) def imply_wasapi(values, target): if any("wasapi" in value for value in values) and target.os != "WINNT": die("Cannot enable WASAPI on %s", target.os) return any("wasapi" in value for value in values) or None set_config("MOZ_AAUDIO", imply_aaudio, when="--enable-audio-backends") imply_option("--enable-alsa", imply_alsa, reason="--enable-audio-backends") set_config("MOZ_AUDIOUNIT_RUST", imply_audiounit, when="--enable-audio-backends") imply_option("--enable-jack", imply_jack, reason="--enable-audio-backends") set_config("MOZ_OPENSL", imply_opensl, when="--enable-audio-backends") set_config("MOZ_OSS", imply_oss, when="--enable-audio-backends") imply_option("--enable-pulseaudio", imply_pulseaudio, reason="--enable-audio-backends") imply_option("--enable-sndio", imply_sndio, reason="--enable-audio-backends") set_config("MOZ_SUNAUDIO", imply_sunaudio, when="--enable-audio-backends") set_config("MOZ_WASAPI", imply_wasapi, when="--enable-audio-backends") # ALSA cubeb backend # ============================================================== option("--enable-alsa", env="MOZ_ALSA", help="Enable ALSA audio backend.") @depends("--enable-alsa", midir_linux_support) def enable_alsa_or_midir_linux_support(alsa_enabled, midir_linux_support): return alsa_enabled or midir_linux_support pkg_check_modules("MOZ_ALSA", "alsa", when=enable_alsa_or_midir_linux_support) set_config("MOZ_ALSA", True, when="--enable-alsa") set_define("MOZ_ALSA", True, when="--enable-alsa") # JACK cubeb backend # ============================================================== system_lib_option("--enable-jack", env="MOZ_JACK", help="Enable JACK audio backend.") jack = pkg_check_modules("MOZ_JACK", "jack", when="--enable-jack") set_config("MOZ_JACK", depends_if(jack)(lambda _: True)) # PulseAudio cubeb backend # ============================================================== option( "--enable-pulseaudio", env="MOZ_PULSEAUDIO", help="{Enable|Disable} PulseAudio audio backend.", ) pulseaudio = pkg_check_modules("MOZ_PULSEAUDIO", "libpulse", when="--enable-pulseaudio") set_config("MOZ_PULSEAUDIO", depends_if(pulseaudio)(lambda _: True)) set_define("MOZ_PULSEAUDIO", depends_if(pulseaudio)(lambda _: True)) # sndio cubeb backend # ============================================================== system_lib_option("--enable-sndio", env="MOZ_SNDIO", help="Enable sndio audio backend.") sndio = pkg_check_modules("MOZ_SNDIO", "sndio", when="--enable-sndio") set_config("MOZ_SNDIO", depends_if(sndio)(lambda _: True)) # Javascript engine # ============================================================== include("../js/moz.configure") # NodeJS # ============================================================== include("../build/moz.configure/node.configure") # JsonCpp # ============================================================== set_define("JSON_USE_EXCEPTION", 0) # L10N # ============================================================== option("--with-l10n-base", nargs=1, env="L10NBASEDIR", help="Path to l10n repositories") @depends("--with-l10n-base", "MOZ_AUTOMATION", build_environment) @imports(_from="os.path", _import="isdir") @imports(_from="os.path", _import="expanduser") @imports(_from="os", _import="environ") def l10n_base(value, automation, build_env): if value: path = value[0] if not isdir(path): die("Invalid value --with-l10n-base, %s doesn't exist", path) elif automation: path = os.path.join(build_env.topsrcdir, "../l10n-central") else: path = os.path.join( environ.get( "MOZBUILD_STATE_PATH", expanduser(os.path.join("~", ".mozbuild")) ), "l10n-central", ) return os.path.realpath(os.path.abspath(path)) set_config("L10NBASEDIR", l10n_base) # Default toolkit # ============================================================== @depends(target) def toolkit_choices(target): if target.os == "WINNT": return ("cairo-windows",) elif target.os == "OSX": return ("cairo-cocoa",) elif target.os == "iOS": return ("cairo-uikit",) elif target.os == "Android": return ("cairo-android",) else: # cairo-gtk3 - X11 backend with optional Wayland backend (auto detected) # cairo-gtk3-wayland - Wayland backend with optional X11 backend (auto detected) # cairo-gtk3-x11-wayland - builds explicitly with X11 & Wayland backends return ( "cairo-gtk3", "cairo-gtk3-wayland", "cairo-gtk3-x11-wayland", "cairo-gtk3-wayland-only", "cairo-gtk3-x11-only", ) @depends(toolkit_choices) def toolkit_default(choices): return choices[0] option( "--enable-default-toolkit", nargs=1, choices=toolkit_choices, default=toolkit_default, help="Select default toolkit", ) @depends("--enable-default-toolkit") def full_toolkit(value): if value: return value[0] @depends(full_toolkit) def toolkit(toolkit): if toolkit.startswith("cairo-gtk3"): widget_toolkit = "gtk" else: widget_toolkit = toolkit.replace("cairo-", "") return widget_toolkit set_config("MOZ_WIDGET_TOOLKIT", toolkit) add_old_configure_assignment("MOZ_WIDGET_TOOLKIT", toolkit) @depends(toolkit) def toolkit_define(toolkit): if toolkit != "windows": return "MOZ_WIDGET_%s" % toolkit.upper() set_define(toolkit_define, True) @depends(toolkit) def toolkit_gtk(toolkit): return toolkit == "gtk" @depends(toolkit_gtk, full_toolkit) def toolkit_gtk_x11(toolkit_gtk, full_toolkit): return toolkit_gtk and full_toolkit != "cairo-gtk3-wayland-only" @depends(full_toolkit) def toolkit_gtk_x11_optional(full_toolkit): return full_toolkit == "cairo-gtk3-wayland" @depends(toolkit_gtk, full_toolkit) def toolkit_gtk_wayland(toolkit_gtk, full_toolkit): return toolkit_gtk and full_toolkit != "cairo-gtk3-x11-only" @depends(full_toolkit) def toolkit_gtk_wayland_optional(full_toolkit): return full_toolkit == "cairo-gtk3" # Wayland support # ============================================================== wayland_headers = pkg_check_modules( "MOZ_WAYLAND", "gtk+-wayland-3.0 >= 3.14 xkbcommon >= 0.4.1", allow_missing=toolkit_gtk_wayland_optional, when=toolkit_gtk_wayland, ) @depends(wayland_headers, toolkit_gtk, artifact_builds, toolkit_gtk_wayland) def wayland_headers(wayland, toolkit_gtk, artifacts, toolkit_gtk_wayland): if not toolkit_gtk_wayland: return False if toolkit_gtk and artifacts: return True return wayland set_config("MOZ_WAYLAND", depends_if(wayland_headers)(lambda _: True)) set_define("MOZ_WAYLAND", depends_if(wayland_headers)(lambda _: True)) # Hardware-accelerated video decode with VAAPI and V4L2 on Linux # ============================================================== set_config("MOZ_ENABLE_VAAPI", True, when=toolkit_gtk) set_define("MOZ_ENABLE_VAAPI", True, when=toolkit_gtk) @depends(target, toolkit_gtk) def v4l2(target, toolkit_gtk): # V4L2 decode is only used in GTK/Linux and generally only appears on # embedded SOCs. if target.cpu in ("arm", "aarch64", "riscv64") and toolkit_gtk: return True set_config("MOZ_ENABLE_V4L2", True, when=v4l2) set_define("MOZ_ENABLE_V4L2", True, when=v4l2) # GL Provider # ============================================================== option("--with-gl-provider", nargs=1, help="Set GL provider backend type") @depends("--with-gl-provider") def gl_provider(value): if value: return value[0] @depends(gl_provider) def gl_provider_define(provider): if provider: return "GLContextProvider%s" % provider set_define("MOZ_GL_PROVIDER", gl_provider_define) @depends(gl_provider, toolkit_gtk) def gl_default_provider(value, toolkit_gtk): if value: return value elif toolkit_gtk: return "EGL" set_config("MOZ_GL_PROVIDER", gl_provider) set_config("MOZ_GL_DEFAULT_PROVIDER", gl_default_provider) @depends(gl_default_provider) def gl_provider_define(provider): if provider: return "GL_PROVIDER_%s" % provider set_define(gl_provider_define, True) # PDF printing # ============================================================== @depends(toolkit) def pdf_printing(toolkit): if toolkit in ("windows", "gtk", "android"): return True set_config("MOZ_PDF_PRINTING", pdf_printing) set_define("MOZ_PDF_PRINTING", pdf_printing) # Event loop instrumentation # ============================================================== option(env="MOZ_INSTRUMENT_EVENT_LOOP", help="Force-enable event loop instrumentation") @depends("MOZ_INSTRUMENT_EVENT_LOOP", toolkit) def instrument_event_loop(value, toolkit): if value or ( toolkit in ("windows", "gtk", "cocoa", "android") and value.origin == "default" ): return True set_config("MOZ_INSTRUMENT_EVENT_LOOP", instrument_event_loop) set_define("MOZ_INSTRUMENT_EVENT_LOOP", instrument_event_loop) # Fontconfig Freetype # ============================================================== option(env="USE_FC_FREETYPE", help="Force-enable the use of fontconfig freetype") @depends("USE_FC_FREETYPE", toolkit) def fc_freetype(value, toolkit): if value or (toolkit == "gtk" and value.origin == "default"): return True set_define("USE_FC_FREETYPE", fc_freetype) # Pango # ============================================================== pkg_check_modules("MOZ_PANGO", "pango >= 1.22.0", when=toolkit_gtk) # Fontconfig # ============================================================== fontconfig_info = pkg_check_modules( "_FONTCONFIG", "fontconfig >= 2.7.0", when=fc_freetype ) @depends(fc_freetype) def check_for_freetype2(fc_freetype): if fc_freetype: return True # Check for freetype2. Flags are combined with fontconfig flags. freetype2_info = pkg_check_modules( "_FT2", "freetype2 >= 9.10.3", when=check_for_freetype2 ) @depends(fontconfig_info, freetype2_info) def freetype2_combined_info(fontconfig_info, freetype2_info): if not freetype2_info: return if not fontconfig_info: return freetype2_info return namespace( cflags=freetype2_info.cflags + fontconfig_info.cflags, libs=freetype2_info.libs + fontconfig_info.libs, ) set_define("MOZ_HAVE_FREETYPE2", depends_if(freetype2_info)(lambda _: True)) # Apple platform decoder support # ============================================================== @depends(toolkit) def applemedia(toolkit): if toolkit in ("cocoa", "uikit"): return True set_config("MOZ_APPLEMEDIA", applemedia) set_define("MOZ_APPLEMEDIA", applemedia) # Windows Media Foundation support # ============================================================== option("--disable-wmf", help="Disable support for Windows Media Foundation") @depends("--disable-wmf", target, "--help") def wmf(value, target, _): enabled = bool(value) if value.origin == "default": # Enable Windows Media Foundation support by default. # Note our minimum SDK version is Windows 7 SDK, so we are (currently) # guaranteed to have a recent-enough SDK to build WMF. enabled = target.os == "WINNT" if enabled and target.os != "WINNT": die("Cannot enable Windows Media Foundation support on %s", target.os) if enabled: return True @depends(artifact_builds, c_compiler, when=wmf) def wmfmediaengine(artifact_builds, c_compiler): if c_compiler: return c_compiler.type == "clang-cl" return bool(artifact_builds) set_config("MOZ_WMF", wmf) set_define("MOZ_WMF", wmf) set_config("MOZ_WMF_MEDIA_ENGINE", True, when=wmfmediaengine) set_define("MOZ_WMF_MEDIA_ENGINE", True, when=wmfmediaengine) # FFmpeg H264/AAC Decoding Support # ============================================================== option("--disable-ffmpeg", help="Disable FFmpeg for fragmented H264/AAC decoding") @depends("--disable-ffmpeg", target) def ffmpeg(value, target): enabled = bool(value) if value.origin == "default": enabled = target.os not in ("Android", "WINNT") if enabled: return True set_config("MOZ_FFMPEG", ffmpeg) set_define("MOZ_FFMPEG", ffmpeg) # AV1 Video Codec Support # ============================================================== option("--disable-av1", help="Disable av1 video support") @depends("--enable-av1") def av1(value): if value: return True @depends(target, when=av1 & compile_environment) def dav1d_asm(target): if target.cpu in ("aarch64", "x86", "x86_64"): return True @depends(target, when=av1 & compile_environment) def dav1d_nasm(target): if target.cpu in ("x86", "x86_64"): return namespace(version="2.14", what="AV1") set_config("MOZ_DAV1D_ASM", dav1d_asm) set_define("MOZ_DAV1D_ASM", dav1d_asm) set_config("MOZ_AV1", av1) set_define("MOZ_AV1", av1) # JXL Image Codec Support # ============================================================== option("--disable-jxl", help="Disable jxl image support") @depends("--disable-jxl", milestone.is_nightly) def jxl(value, is_nightly): if is_nightly and value: return True set_config("MOZ_JXL", jxl) set_define("MOZ_JXL", jxl) set_config("MOZ_SAMPLE_TYPE_FLOAT32", True) set_define("MOZ_SAMPLE_TYPE_FLOAT32", True) set_define("MOZ_VORBIS", True) set_config("MOZ_VORBIS", True) option( "--disable-real-time-tracing", help="Disable tracing of real-time audio callbacks", ) set_config("MOZ_REAL_TIME_TRACING", True, when="--enable-real-time-tracing") set_define("MOZ_REAL_TIME_TRACING", True, when="--enable-real-time-tracing") # OpenMAX IL Decoding Support # ============================================================== option("--enable-openmax", help="Enable OpenMAX IL for video/audio decoding") @depends("--enable-openmax") def openmax(value): enabled = bool(value) if enabled: return True set_config("MOZ_OMX", openmax) set_define("MOZ_OMX", openmax) # EME Support # ============================================================== @depends(target, wmf) def eme_choices(target, wmf): if ( target.kernel in ("WINNT", "Linux") and target.os != "Android" and target.cpu in ("x86", "x86_64") ): if wmf: return ("widevine", "wmfcdm") return ("widevine",) if target.kernel == "WINNT" and target.cpu == "aarch64": return ("widevine",) if target.os in ("OSX"): return ("widevine",) # Widevine is enabled by default in desktop browser builds. @depends(build_project, eme_choices) def eme_default(build_project, choices): if build_project == "browser": return choices option( "--enable-eme", nargs="+", choices=eme_choices, default=eme_default, when=eme_choices, help="{Enable|Disable} support for Encrypted Media Extensions", ) @depends("--enable-eme", when=eme_choices) def eme_modules(value): return value # Fallback to an empty list when eme_choices is empty, setting eme_modules to # None. set_config("MOZ_EME_MODULES", eme_modules | dependable([])) # Media Foundation CDM support # ============================================================== @depends(eme_modules, when=wmfmediaengine) def wmfcdm(modules): if "wmfcdm" in modules: return True set_config("MOZ_WMF_CDM", True, when=wmfcdm) set_define("MOZ_WMF_CDM", True, when=wmfcdm) option( name="--enable-chrome-format", help="Select FORMAT of chrome files during packaging.", nargs=1, choices=("omni", "jar", "flat"), default="omni", ) @depends("--enable-chrome-format") def packager_format(value): return value[0] set_config("MOZ_PACKAGER_FORMAT", packager_format) # The packager minifies two different types of files: non-JS (mostly property # files for l10n), and JS. Setting MOZ_PACKAGER_MINIFY only minifies the # former. Firefox doesn't yet minify JS, due to concerns about debuggability. # # Also, the JS minification setup really only works correctly on Android: # we need extra setup to use the newly-built shell for Linux and Windows, # and cross-compilation for macOS requires some extra care. @depends(target_is_android, "--enable-debug", milestone.is_nightly) def enable_minify_default(is_android, debug, is_nightly): if is_android and not debug and not is_nightly: return ("properties", "js") return ("properties",) option( name="--enable-minify", help="Select types of files to minify during packaging.", nargs="*", choices=("properties", "js"), default=enable_minify_default, ) @depends("--enable-minify") def enable_minify(value): if "js" in value and "properties" not in value: die("--enable-minify=js requires --enable-minify=properties.") return namespace( properties="properties" in value, js="js" in value, ) set_config("MOZ_PACKAGER_MINIFY", True, when=enable_minify.properties) set_config("MOZ_PACKAGER_MINIFY_JS", True, when=enable_minify.js) @depends(host, build_project) def jar_maker_format(host, build_project): # Multilocales for mobile/android use the same mergedirs for all locales, # so we can't use symlinks for those builds. if host.os == "WINNT" or build_project == "mobile/android": return "flat" return "symlink" set_config("MOZ_JAR_MAKER_FILE_FORMAT", jar_maker_format) @depends(toolkit) def omnijar_name(toolkit): # Fennec's static resources live in the assets/ folder of the # APK. Adding a path to the name here works because we only # have one omnijar file in the final package (which is not the # case on desktop). return "assets/omni.ja" if toolkit == "android" else "omni.ja" set_config("OMNIJAR_NAME", omnijar_name) project_flag("MOZ_PLACES", help="Build Places if required", set_as_define=True) project_flag( "MOZ_SERVICES_HEALTHREPORT", help="Build Firefox Health Reporter Service", set_as_define=True, ) project_flag( "MOZ_NORMANDY", help="Enable Normandy recipe runner", set_as_define=True, ) project_flag("MOZ_SERVICES_SYNC", help="Build Sync Services if required") project_flag( "MOZ_ANDROID_HISTORY", help="Enable Android History instead of Places", set_as_define=True, ) project_flag( "MOZ_DEDICATED_PROFILES", help="Enable dedicated profiles per install", set_as_define=True, ) project_flag( "MOZ_BLOCK_PROFILE_DOWNGRADE", help="Block users from starting profiles last used by a newer build", set_as_define=True, ) @depends("MOZ_PLACES", "MOZ_ANDROID_HISTORY") def check_places_and_android_history(places, android_history): if places and android_history: die("Cannot use MOZ_ANDROID_HISTORY alongside MOZ_PLACES.") if not places and not android_history: die("One of MOZ_ANDROID_HISTORY or MOZ_PLACES must be set.") option( env="MOZ_TELEMETRY_REPORTING", default=mozilla_official, help="Enable telemetry reporting", ) set_define("MOZ_TELEMETRY_REPORTING", True, when="MOZ_TELEMETRY_REPORTING") @depends("MOZ_TELEMETRY_REPORTING", milestone.is_nightly) def telemetry_on_by_default(reporting, is_nightly): return reporting and is_nightly set_define("MOZ_TELEMETRY_ON_BY_DEFAULT", True, when=telemetry_on_by_default) # gpsd support # ============================================================== system_lib_option("--enable-gpsd", env="MOZ_GPSD", help="Enable gpsd support") @depends("--enable-gpsd") def gpsd(value): return bool(value) system_gpsd = pkg_check_modules("MOZ_GPSD", "libgps >= 3.11", when=gpsd) set_config("MOZ_GPSD", depends_if(system_gpsd)(lambda _: True)) # Miscellaneous programs # ============================================================== check_prog("TAR", ("gnutar", "gtar", "tar")) check_prog("UNZIP", ("unzip",)) # Key files # ============================================================== include("../build/moz.configure/keyfiles.configure") simple_keyfile("Mozilla API") simple_keyfile("Google Location Service API") simple_keyfile("Google Safebrowsing API") id_and_secret_keyfile("Bing API") simple_keyfile("Adjust SDK") id_and_secret_keyfile("Leanplum SDK") simple_keyfile("Pocket API") # WebRender Debugger integration # ============================================================== option( "--enable-webrender-debugger", help="Build the websocket debug server in WebRender" ) set_config( "MOZ_WEBRENDER_DEBUGGER", depends_if("--enable-webrender-debugger")(lambda _: True) ) # Additional system headers defined at the application level # ============================================================== option( "--enable-app-system-headers", env="MOZ_APP_SYSTEM_HEADERS", help="Use additional system headers defined in $MOZ_BUILD_APP/app-system-headers.mozbuild", ) @depends("--enable-app-system-headers") def app_system_headers(value): if value: return True set_config("MOZ_APP_SYSTEM_HEADERS", app_system_headers) set_define("MOZ_APP_SYSTEM_HEADERS", app_system_headers) # Printing # ============================================================== @depends(target) def printing_default(target): return target.os != "iOS" option( "--disable-printing", default=printing_default, help="{Enable|Disable} printing support", ) @depends("--disable-printing") def printing(value): if value: return True set_config("NS_PRINTING", printing) set_define("NS_PRINTING", printing) set_define("NS_PRINT_PREVIEW", printing) # Speech-dispatcher support # ============================================================== @depends(toolkit) def no_speechd_on_non_gtk(toolkit): if toolkit != "gtk": return False imply_option( "--enable-synth-speechd", no_speechd_on_non_gtk, reason="--enable-default-toolkit" ) option("--disable-synth-speechd", help="Disable speech-dispatcher support") set_config("MOZ_SYNTH_SPEECHD", depends_if("--disable-synth-speechd")(lambda _: True)) # Speech API # ============================================================== option("--disable-webspeech", help="Disable support for HTML Speech API") @depends("--disable-webspeech") def webspeech(value): if value: return True set_config("MOZ_WEBSPEECH", webspeech) set_define("MOZ_WEBSPEECH", webspeech) # Speech API test backend # ============================================================== option( "--enable-webspeechtestbackend", default=webspeech, help="{Enable|Disable} support for HTML Speech API Test Backend", ) @depends_if("--enable-webspeechtestbackend") def webspeech_test_backend(value): return True set_config("MOZ_WEBSPEECH_TEST_BACKEND", webspeech_test_backend) set_define("MOZ_WEBSPEECH_TEST_BACKEND", webspeech_test_backend) # Graphics # ============================================================== @depends(target, milestone) def skia_pdf_default(target, milestone): return milestone.is_nightly and target.os != "WINNT" option("--enable-skia-pdf", default=skia_pdf_default, help="{Enable|Disable} Skia PDF") set_config("MOZ_ENABLE_SKIA_PDF", True, when="--enable-skia-pdf") set_define("MOZ_ENABLE_SKIA_PDF", True, when="--enable-skia-pdf") set_config( "SKIA_INCLUDES", [ "/gfx/skia", "/gfx/skia/skia", ], ) system_lib_option( "--with-system-webp", help="Use system libwebp (located with pkgconfig)" ) system_webp = pkg_check_modules( "MOZ_WEBP", "libwebp >= 1.0.2 libwebpdemux >= 1.0.2", when="--with-system-webp" ) set_config("MOZ_SYSTEM_WEBP", depends(when=system_webp)(lambda: True)) # Build Freetype in the tree # ============================================================== @depends(target, "--enable-skia-pdf") def tree_freetype(target, skia_pdf): if target.os == "Android" or (skia_pdf and target.os == "WINNT"): return True set_define("MOZ_TREE_FREETYPE", tree_freetype) set_config("MOZ_TREE_FREETYPE", tree_freetype) set_define("HAVE_FT_BITMAP_SIZE_Y_PPEM", tree_freetype) set_define("HAVE_FT_GLYPHSLOT_EMBOLDEN", tree_freetype) set_define("HAVE_FT_LOAD_SFNT_TABLE", tree_freetype) @depends(freetype2_combined_info, tree_freetype, build_environment) def ft2_info(freetype2_combined_info, tree_freetype, build_env): if tree_freetype: return namespace( cflags=("-I%s/modules/freetype2/include" % build_env.topsrcdir,), libs=() ) if freetype2_combined_info: return freetype2_combined_info set_config("FT2_LIBS", ft2_info.libs) @depends(target, tree_freetype, freetype2_info) def enable_cairo_ft(target, tree_freetype, freetype2_info): # Avoid defining MOZ_ENABLE_CAIRO_FT on Windows platforms because # "cairo-ft-font.c" includes , which only exists on posix platforms return freetype2_info or (tree_freetype and target.os != "WINNT") set_config("MOZ_ENABLE_CAIRO_FT", True, when=enable_cairo_ft) set_config("CAIRO_FT_CFLAGS", ft2_info.cflags, when=enable_cairo_ft) # WebDriver (HTTP / BiDi) # ============================================================== # # WebDriver is a remote control interface that enables introspection and # control of user agents. It provides a platform- and language-neutral wire # protocol as a way for out-of-process programs to remotely instruct the # behavior of web browsers. # # The Gecko implementation is backed by Marionette and Remote Agent. # Both protocols are not really toolkit features, as much as Gecko engine # features. But they are enabled based on the toolkit, so here it lives. # # Marionette remote protocol # ----------------------------------------------------------- # # Marionette is the Gecko remote protocol used for various remote control, # automation, and testing purposes throughout Gecko-based applications like # Firefox, Thunderbird, and any mobile browser built upon GeckoView. # # It also backs ../testing/geckodriver, which is Mozilla's WebDriver # implementation. # # The source of Marionette lives in ../remote/marionette. # # For more information, see: # https://firefox-source-docs.mozilla.org/testing/marionette/index.html # # Remote Agent (WebDriver BiDi / partial CDP) # ----------------------------------------------------------- # # The primary purpose is the implementation of the WebDriver BiDi specification. # But it also complements the existing Firefox Developer Tools Remote Debugging # Protocol (RDP) by implementing a subset of the Chrome DevTools Protocol (CDP). # # The source of Remote Agent lives in ../remote. # # For more information, see: # https://firefox-source-docs.mozilla.org/remote/index.html option( "--disable-webdriver", help="Disable support for WebDriver remote protocols", ) @depends("--disable-webdriver") def webdriver(enabled): if enabled: return True set_config("ENABLE_WEBDRIVER", webdriver) set_define("ENABLE_WEBDRIVER", webdriver) # geckodriver WebDriver implementation # ============================================================== # # Turn off geckodriver for build configs we don't handle yet, # but allow --enable-geckodriver to override when compile environment is available. # --disable-tests implies disabling geckodriver. # Disable building in CI @depends( "--enable-tests", target, cross_compiling, hazard_analysis, asan, "MOZ_AUTOMATION" ) def geckodriver_default(enable_tests, target, cross_compile, hazard, asan, automation): if not enable_tests: return False if hazard or target.os == "Android" or (asan and cross_compile): return False if automation: return False return True option( "--enable-geckodriver", default=geckodriver_default, when="--enable-compile-environment", help="{Build|Do not build} geckodriver", ) @depends("--enable-geckodriver", when="--enable-compile-environment") def geckodriver(enabled): if enabled: return True set_config("MOZ_GECKODRIVER", geckodriver) # WebRTC # ======================================================== @depends(target) def webrtc_default(target): # Turn off webrtc for OS's we don't handle yet, but allow # --enable-webrtc to override. os_match = target.kernel in ( "Linux", "WINNT", "DragonFly", "FreeBSD", "kFreeBSD", "NetBSD", "OpenBSD", ) if not os_match: os_match = target.os in ("OSX",) cpu_match = target.cpu in ( "x86_64", "arm", "aarch64", "x86", "ia64", "mips32", "mips64", "ppc", "ppc64", "riscv64", ) return os_match and cpu_match and target.endianness == "little" option( "--disable-webrtc", default=webrtc_default, help="{Enable|Disable} support for WebRTC", ) @depends("--disable-webrtc") def webrtc(enabled): if enabled: return True set_config("MOZ_WEBRTC", webrtc) set_define("MOZ_WEBRTC", webrtc) set_config("MOZ_SCTP", webrtc) set_define("MOZ_SCTP", webrtc) set_config("MOZ_SRTP", webrtc) set_define("MOZ_SRTP", webrtc) set_config("MOZ_WEBRTC_SIGNALING", webrtc) set_define("MOZ_WEBRTC_SIGNALING", webrtc) set_config("MOZ_PEERCONNECTION", webrtc) set_define("MOZ_PEERCONNECTION", webrtc) # MOZ_WEBRTC_ASSERT_ALWAYS turns on a number of safety asserts in # opt/production builds (via MOZ_CRASH()) set_config("MOZ_WEBRTC_ASSERT_ALWAYS", webrtc) set_define("MOZ_WEBRTC_ASSERT_ALWAYS", webrtc) # RAW media # ============================================================== @depends(target, webrtc) def raw_media_default(target, webrtc): if target.os == "Android": return True if webrtc: return True option( "--enable-raw", default=raw_media_default, help="{Enable|Disable} support for RAW media", ) set_config("MOZ_RAW", depends_if("--enable-raw")(lambda _: True)) set_define("MOZ_RAW", depends_if("--enable-raw")(lambda _: True)) # X11 # ============================================================== @depends(webrtc, when=toolkit_gtk) def x11_libs(webrtc): libs = [ "x11", "xcb", "xcb-shm", "x11-xcb", "xext", "xrandr >= 1.4.0", ] if webrtc: # third_party/libwebrtc/webrtc/webrtc_gn/moz.build adds those # manually, ensure they're available. libs += [ "xcomposite", "xcursor", "xdamage", "xfixes", "xi", ] return libs x11_headers = pkg_check_modules( "MOZ_X11", x11_libs, allow_missing=toolkit_gtk_x11_optional, when=toolkit_gtk_x11, ) set_config("MOZ_X11", True, when=x11_headers) set_define("MOZ_X11", True, when=x11_headers) pkg_check_modules( "MOZ_X11_SM", ["ice", "sm"], cflags_only=True, allow_missing=toolkit_gtk_x11_optional, when=toolkit_gtk_x11, ) # ASan Reporter Addon # ============================================================== option( "--enable-address-sanitizer-reporter", help="Enable Address Sanitizer Reporter Extension", ) @depends("--enable-address-sanitizer-reporter") def enable_asan_reporter(value): if value: return True set_config("MOZ_ASAN_REPORTER", enable_asan_reporter) set_define("MOZ_ASAN_REPORTER", enable_asan_reporter) # Checks for library functions # ============================================================== with only_when(compile_environment & depends(target.os)(lambda os: os != "WINNT")): set_define("HAVE_STAT64", check_symbol("stat64")) set_define("HAVE_LSTAT64", check_symbol("lstat64")) set_define("HAVE_TRUNCATE64", check_symbol("truncate64")) set_define("HAVE_STATVFS64", check_symbol("statvfs64")) set_define("HAVE_STATVFS", check_symbol("statvfs")) set_define("HAVE_STATFS64", check_symbol("statfs64")) set_define("HAVE_STATFS", check_symbol("statfs")) set_define("HAVE_LUTIMES", check_symbol("lutimes")) set_define("HAVE_POSIX_FADVISE", check_symbol("posix_fadvise")) set_define("HAVE_POSIX_FALLOCATE", check_symbol("posix_fallocate")) set_define("HAVE_EVENTFD", check_symbol("eventfd")) have_arc4random = check_symbol("arc4random") set_define("HAVE_ARC4RANDOM", have_arc4random) set_define("HAVE_ARC4RANDOM_BUF", check_symbol("arc4random_buf")) set_define("HAVE_MALLINFO", check_symbol("mallinfo")) # Checks for headers # ============================================================== with only_when(compile_environment & depends(target.os)(lambda os: os != "WINNT")): set_define("HAVE_SYSIOCCOM_H", check_header("sys/ioccom.h")) # Elfhack # ============================================================== with only_when("--enable-compile-environment"): @depends(host, target) def has_elfhack(host, target): return ( target.kernel == "Linux" and host.kernel == "Linux" and target.cpu in ("arm", "aarch64", "x86", "x86_64") ) option( "--disable-elf-hack", nargs="?", choices=("legacy", "relr"), help="{Enable|Disable} elf hacks", when=has_elfhack, ) @depends("--enable-elf-hack", when=has_elfhack) def may_enable_legacy_elfhack(enable): if enable and enable != ("relr",): return enable @depends("--enable-elf-hack", when=has_elfhack) def may_enable_relrhack(enable): if enable and enable != ("legacy",): return enable @depends( have_arc4random, android_version, when=target_has_linux_kernel, ) def may_use_pack_relative_relocs(have_arc4random, android_version): # Packed relative relocations are only supported on Android since # version 11 (API 30), and in glibc since version 2.36. # glibc 2.36 also added the arc4random function, which is our proxy # to detect this (or newer) version being used. # When targetting those newer versions, we allow ourselves to use # packed relative relocations rather than elfhack. if android_version: return android_version >= 30 return have_arc4random @depends( c_compiler, extra_toolchain_flags, linker_ldflags, readelf, when=may_use_pack_relative_relocs | may_enable_relrhack, ) @checking("for -z pack-relative-relocs option to ld", bool) @imports(_from="__builtin__", _import="FileNotFoundError") @imports("os") @imports(_from="tempfile", _import="mkstemp") @imports("textwrap") def has_pack_relative_relocs( c_compiler, extra_toolchain_flags, linker_ldflags, readelf, ): try: fd, path = mkstemp(prefix="conftest.") os.close(fd) pack_rel_relocs = ["-Wl,-z,pack-relative-relocs"] if ( try_invoke_compiler( # No configure_cache because it would not create the # expected output file. None, [c_compiler.compiler] + c_compiler.flags, c_compiler.language, # The resulting binary is expected to have relative # relocations, the `ptr` variable attempts to ensure # there is at least one. This requires the executable # being built as position independent. "int main() { return 0; }\nint (*ptr)() = main;", pack_rel_relocs + ["-pie", "-o", path] + (extra_toolchain_flags or []) + linker_ldflags, wrapper=c_compiler.wrapper, onerror=lambda: None, ) is not None ): # BFD ld ignores options it doesn't understand. So check # that we did get packed relative relocations (DT_RELR). env = os.environ.copy() env["LANG"] = "C" dyn = check_cmd_output(readelf, "-d", path, env=env).splitlines() tags = [ int(l.split()[0], 16) for l in dyn if l.strip().startswith("0x") ] # Older versions of readelf don't know about DT_RELR but will # still display the tag number. if 0x23 in tags: needed = [l for l in dyn if l.split()[1:2] == ["(NEEDED)"]] is_glibc = any(l.endswith("[libc.so.6]") for l in needed) # The mold linker doesn't add a GLIBC_ABI_DT_RELR version # dependency, which ld.so doesn't like. # https://github.com/rui314/mold/issues/653#issuecomment-1670274638 if is_glibc: versions = check_cmd_output(readelf, "-V", path, env=env) if "GLIBC_ABI_DT_RELR" in versions.split(): return pack_rel_relocs else: return pack_rel_relocs finally: try: os.remove(path) except FileNotFoundError: pass @depends( has_pack_relative_relocs, may_enable_legacy_elfhack, may_enable_relrhack, may_use_pack_relative_relocs, when=has_pack_relative_relocs, ) def pack_relative_relocs_flags( flags, may_enable_legacy_elfhack, may_enable_relrhack, may_use_pack_relative_relocs, ): # When relrhack is enabled, we don't pass the flag to the linker because # relrhack will take care of it. if may_enable_relrhack and may_enable_relrhack.origin != "default": return None # if elfhack is explicitly enabled instead of relrhack, we prioritize it # over packed relative relocs. if may_enable_legacy_elfhack and may_enable_legacy_elfhack.origin != "default": return None if may_use_pack_relative_relocs: return flags add_old_configure_assignment("PACK_REL_RELOC_FLAGS", pack_relative_relocs_flags) @depends( select_linker, pack_relative_relocs_flags, has_pack_relative_relocs, may_enable_legacy_elfhack, may_enable_relrhack, when=has_elfhack, ) def which_elf_hack( linker, pack_relative_relocs_flags, has_pack_relative_relocs, may_enable_legacy_elfhack, may_enable_relrhack, ): if pack_relative_relocs_flags: return if may_enable_relrhack: if has_pack_relative_relocs: return "relr" elif ( may_enable_relrhack.origin != "default" and not may_enable_legacy_elfhack ): die( "Cannot enable relrhack without linker support for -z pack-relative-relocs" ) if may_enable_legacy_elfhack: if linker and linker.KIND in ("lld", "mold"): if may_enable_legacy_elfhack.origin != "default": die( f"Cannot enable elfhack with {linker.KIND}." " Use --enable-linker=bfd, --enable-linker=gold, or --disable-elf-hack" ) else: return "legacy" set_config( "USE_ELF_HACK", True, when=depends(which_elf_hack)(lambda x: x == "legacy") ) use_relrhack = depends(which_elf_hack)(lambda x: x == "relr") set_config("RELRHACK", True, when=use_relrhack) @depends(c_compiler, linker_ldflags, when=use_relrhack) def relrhack_real_linker(c_compiler, linker_ldflags): ld = "ld" for flag in linker_ldflags: if flag.startswith("-fuse-ld="): ld = "ld." + flag[len("-fuse-ld=") :] ld = check_cmd_output( c_compiler.compiler, f"--print-prog-name={ld}", *c_compiler.flags ) return ld.rstrip() @depends(relrhack_real_linker, when=use_relrhack) def relrhack_linker(ld): return os.path.basename(ld) set_config("RELRHACK_LINKER", relrhack_linker) std_filesystem = host_cxx_compiler.try_run( header="#include ", body='auto foo = std::filesystem::absolute("");', flags=host_linker_ldflags, when=use_relrhack, onerror=lambda: None, ) stdcxxfs = host_cxx_compiler.try_run( header="#include ", body='auto foo = std::filesystem::absolute("");', flags=depends(host_linker_ldflags)( lambda flags: (flags or []) + ["-lstdc++fs"] ), check_msg="whether std::filesystem requires -lstdc++fs", when=use_relrhack & depends(std_filesystem)(lambda x: not x), onerror=lambda: None, ) set_config("RELRHACK_LIBS", ["stdc++fs"], when=stdcxxfs) @depends(build_environment, relrhack_real_linker, when=use_relrhack) def relrhack_ldflags(build_env, ld): flags = [ "-B", os.path.join(build_env.topobjdir, "build", "unix", "elfhack"), ] if os.path.basename(ld) != ld: flags.append(f"-Wl,--real-linker,{ld}") return flags set_config("RELRHACK_LDFLAGS", relrhack_ldflags) @depends(build_environment) def idl_roots(build_env): return namespace( ipdl_root=os.path.join(build_env.topobjdir, "ipc", "ipdl"), webidl_root=os.path.join(build_env.topobjdir, "dom", "bindings"), xpcom_root=os.path.join(build_env.topobjdir, "xpcom", "components"), ) set_config("WEBIDL_ROOT", idl_roots.webidl_root) set_config("IPDL_ROOT", idl_roots.ipdl_root) set_config("XPCOM_ROOT", idl_roots.xpcom_root) # Proxy bypass protection # ============================================================== option( "--enable-proxy-bypass-protection", help="Prevent suspected or confirmed proxy bypasses", ) @depends_if("--enable-proxy-bypass-protection") def proxy_bypass_protection(_): return True set_config("MOZ_PROXY_BYPASS_PROTECTION", proxy_bypass_protection) set_define("MOZ_PROXY_BYPASS_PROTECTION", proxy_bypass_protection) # Proxy direct failover # ============================================================== option( "--disable-proxy-direct-failover", help="Disable direct failover for system requests", ) @depends_if("--disable-proxy-direct-failover") def proxy_direct_failover(value): if value: return True set_config("MOZ_PROXY_DIRECT_FAILOVER", proxy_direct_failover) set_define("MOZ_PROXY_DIRECT_FAILOVER", proxy_direct_failover) # MIDL # ============================================================== @depends(c_compiler, toolchain_prefix) def midl_names(c_compiler, toolchain_prefix): if c_compiler and c_compiler.type in ["gcc", "clang"]: # mingw widl = ("widl",) if toolchain_prefix: prefixed = tuple("%s%s" % (p, "widl") for p in toolchain_prefix) widl = prefixed + widl return widl return ("midl.exe",) @depends(target, "--enable-compile-environment") def check_for_midl(target, compile_environment): if target.os != "WINNT": return if compile_environment: return True midl = check_prog( "MIDL", midl_names, when=check_for_midl, allow_missing=True, paths=sdk_bin_path, # MIDL being used from a python wrapper script, we can live with it # having spaces. allow_spaces=True, ) option(env="MIDL_FLAGS", nargs=1, help="Extra flags to pass to MIDL") @depends( "MIDL_FLAGS", target, midl, when=depends(midl, target)(lambda m, t: m and t.kernel == "WINNT"), ) def midl_flags(flags, target, midl): if flags: flags = flags[0].split() else: flags = [] if not midl.endswith("widl"): env = { "x86": "win32", "x86_64": "x64", "aarch64": "arm64", }[target.cpu] return flags + ["-nologo", "-no_cpp", "-env", env] # widl return ( flags + { "x86": ["--win32", "-m32"], "x86_64": ["--win64", "-m64"], }[target.cpu] ) set_config("MIDL_FLAGS", midl_flags) # Accessibility # ============================================================== option("--disable-accessibility", help="Disable accessibility support") @depends("--enable-accessibility", check_for_midl, midl, c_compiler) def accessibility(value, check_for_midl, midl, c_compiler): enabled = bool(value) if not enabled: return if check_for_midl and not midl: if c_compiler and c_compiler.type in ("gcc", "clang"): die( "You have accessibility enabled, but widl could not be found. " "Add --disable-accessibility to your mozconfig or install widl. " "See https://developer.mozilla.org/en-US/docs/Cross_Compile_Mozilla_for_Mingw32 for details." ) else: die( "MIDL could not be found. " "Building accessibility without MIDL is not supported." ) return enabled set_config("ACCESSIBILITY", accessibility) set_define("ACCESSIBILITY", accessibility) @depends(moz_debug, developer_options) def a11y_log(debug, developer_options): return debug or developer_options set_config("A11Y_LOG", True, when=a11y_log) set_define("A11Y_LOG", True, when=a11y_log) # Addon signing # ============================================================== @depends(milestone) def require_signing(milestone): return milestone.is_release_or_beta and not milestone.is_esr option( env="MOZ_REQUIRE_SIGNING", default=require_signing, help="Enforce that add-ons are signed by the trusted root", ) set_config("MOZ_REQUIRE_SIGNING", True, when="MOZ_REQUIRE_SIGNING") set_define("MOZ_REQUIRE_SIGNING", True, when="MOZ_REQUIRE_SIGNING") option( "--with-unsigned-addon-scopes", nargs="+", choices=("app", "system"), help="Addon scopes where signature is not required", ) @depends("--with-unsigned-addon-scopes") def unsigned_addon_scopes(scopes): return namespace( app="app" in scopes or None, system="system" in scopes or None, ) set_config("MOZ_UNSIGNED_APP_SCOPE", unsigned_addon_scopes.app) set_config("MOZ_UNSIGNED_SYSTEM_SCOPE", unsigned_addon_scopes.system) # Addon sideloading # ============================================================== option( "--allow-addon-sideload", default=milestone.is_esr, help="Addon sideloading is allowed", ) set_config("MOZ_ALLOW_ADDON_SIDELOAD", True, when="--allow-addon-sideload") # WebExtensions API WebIDL bindings # ============================================================== @depends(milestone) def extensions_webidl_bindings_default(milestone): # Only enable the webidl bindings for the WebExtensions APIs # in Nightly. return milestone.is_nightly option( "--enable-extensions-webidl-bindings", default=extensions_webidl_bindings_default, help="{Enable|Disable} building experimental WebExtensions WebIDL bindings", ) @depends("--enable-extensions-webidl-bindings") def extensions_webidl_enabled(value): return bool(value) set_config("MOZ_WEBEXT_WEBIDL_ENABLED", extensions_webidl_enabled) # Launcher process (Windows only) # ============================================================== @depends(target) def launcher_process_default(target): return target.os == "WINNT" option( "--enable-launcher-process", default=launcher_process_default, help="{Enable|Disable} launcher process by default", ) @depends("--enable-launcher-process", target) def launcher(value, target): enabled = bool(value) if enabled and target.os != "WINNT": die("Cannot enable launcher process on %s", target.os) if enabled: return True set_config("MOZ_LAUNCHER_PROCESS", launcher) set_define("MOZ_LAUNCHER_PROCESS", launcher) # llvm-dlltool (Windows only) # ============================================================== @depends(build_project, target, "--enable-compile-environment") def check_for_llvm_dlltool(build_project, target, compile_environment): if build_project != "browser": return if target.os != "WINNT": return return compile_environment llvm_dlltool = check_prog( "LLVM_DLLTOOL", ("llvm-dlltool",), what="llvm-dlltool", when=check_for_llvm_dlltool, paths=clang_search_path, ) @depends(target, when=llvm_dlltool) def llvm_dlltool_flags(target): arch = { "x86": "i386", "x86_64": "i386:x86-64", "aarch64": "arm64", }[target.cpu] return ["-m", arch] set_config("LLVM_DLLTOOL_FLAGS", llvm_dlltool_flags) # BITS download (Windows only) # ============================================================== option( "--enable-bits-download", when=target_is_windows, default=target_is_windows, help="{Enable|Disable} building BITS download support", ) set_define( "MOZ_BITS_DOWNLOAD", depends_if("--enable-bits-download", when=target_is_windows)(lambda _: True), ) set_config( "MOZ_BITS_DOWNLOAD", depends_if("--enable-bits-download", when=target_is_windows)(lambda _: True), ) # Bundled fonts on desktop platform # ============================================================== @depends(target) def bundled_fonts_default(target): return target.os == "WINNT" or target.kernel == "Linux" @depends(build_project) def allow_bundled_fonts(project): return project == "browser" or project == "comm/mail" option( "--enable-bundled-fonts", default=bundled_fonts_default, when=allow_bundled_fonts, help="{Enable|Disable} support for bundled fonts on desktop platforms", ) set_define( "MOZ_BUNDLED_FONTS", depends_if("--enable-bundled-fonts", when=allow_bundled_fonts)(lambda _: True), ) # Reflow counting # ============================================================== @depends(moz_debug) def reflow_perf(debug): if debug: return True option( "--enable-reflow-perf", default=reflow_perf, help="{Enable|Disable} reflow performance tracing", ) # The difference in conditions here comes from the initial implementation # in old-configure, which was unexplained there as well. set_define("MOZ_REFLOW_PERF", depends_if("--enable-reflow-perf")(lambda _: True)) set_define("MOZ_REFLOW_PERF_DSP", reflow_perf) # Layout debugger # ============================================================== @depends(moz_debug) def layout_debugger(debug): if debug: return True option( "--enable-layout-debugger", default=layout_debugger, help="{Enable|Disable} layout debugger", ) set_config("MOZ_LAYOUT_DEBUGGER", True, when="--enable-layout-debugger") set_define("MOZ_LAYOUT_DEBUGGER", True, when="--enable-layout-debugger") # Shader Compiler for Windows (and MinGW Cross Compile) # ============================================================== with only_when(compile_environment): fxc = check_prog( "FXC", ("fxc.exe", "fxc2.exe"), when=depends(target)(lambda t: t.kernel == "WINNT"), paths=sdk_bin_path, # FXC being used from a python wrapper script, we can live with it # having spaces. allow_spaces=True, ) # VPX # === with only_when(compile_environment): system_lib_option( "--with-system-libvpx", help="Use system libvpx (located with pkgconfig)" ) with only_when("--with-system-libvpx"): vpx = pkg_check_modules("MOZ_LIBVPX", "vpx >= 1.10.0") check_header( "vpx/vpx_decoder.h", flags=vpx.cflags, onerror=lambda: die( "Couldn't find vpx/vpx_decoder.h, which is required to build " "with system libvpx. Use --without-system-libvpx to build " "with in-tree libvpx." ), ) check_symbol( "vpx_codec_dec_init_ver", flags=vpx.libs, onerror=lambda: die( "--with-system-libvpx requested but symbol vpx_codec_dec_init_ver " "not found" ), ) set_config("MOZ_SYSTEM_LIBVPX", True) @depends("--with-system-libvpx", target) def in_tree_vpx(system_libvpx, target): if system_libvpx: return arm_asm = (target.cpu == "arm") or None return namespace(arm_asm=arm_asm) @depends(target, when=in_tree_vpx) def vpx_nasm(target): if target.cpu in ("x86", "x86_64"): if target.kernel == "WINNT": # Version 2.03 is needed for automatic safeseh support. return namespace(version="2.03", what="VPX") return namespace(what="VPX") @depends(in_tree_vpx, vpx_nasm, target, neon_flags) def vpx_as_flags(vpx, vpx_nasm, target, neon_flags): if vpx and vpx.arm_asm: # These flags are a lie; they're just used to enable the requisite # opcodes; actual arch detection is done at runtime. return neon_flags elif vpx and vpx_nasm and target.os != "WINNT" and target.cpu != "x86_64": return ("-DPIC",) set_config("VPX_USE_NASM", True, when=vpx_nasm) set_config("VPX_ASFLAGS", vpx_as_flags) # JPEG # ==== with only_when(compile_environment): system_lib_option( "--with-system-jpeg", nargs="?", help="Use system libjpeg (installed at given prefix)", ) @depends_if("--with-system-jpeg") def jpeg_flags(value): if len(value): return namespace( cflags=("-I%s/include" % value[0],), ldflags=("-L%s/lib" % value[0], "-ljpeg"), ) return namespace( ldflags=("-ljpeg",), ) with only_when("--with-system-jpeg"): check_symbol( "jpeg_destroy_compress", flags=jpeg_flags.ldflags, onerror=lambda: die( "--with-system-jpeg requested but symbol " "jpeg_destroy_compress not found." ), ) c_compiler.try_compile( includes=[ "stdio.h", "sys/types.h", "jpeglib.h", ], body=""" #if JPEG_LIB_VERSION < 62 #error Insufficient JPEG library version #endif """, flags=jpeg_flags.cflags, check_msg="for sufficient jpeg library version", onerror=lambda: die( "Insufficient JPEG library version for " "--with-system-jpeg (62 required)" ), ) c_compiler.try_compile( includes=[ "stdio.h", "sys/types.h", "jpeglib.h", ], body=""" #ifndef JCS_EXTENSIONS #error libjpeg-turbo JCS_EXTENSIONS required #endif """, flags=jpeg_flags.cflags, check_msg="for sufficient libjpeg-turbo JCS_EXTENSIONS", onerror=lambda: die( "libjpeg-turbo JCS_EXTENSIONS required for " "--with-system-jpeg" ), ) set_config("MOZ_JPEG_CFLAGS", jpeg_flags.cflags) set_config("MOZ_JPEG_LIBS", jpeg_flags.ldflags) @depends("--with-system-jpeg", target, neon_flags) def in_tree_jpeg_arm(system_jpeg, target, neon_flags): if system_jpeg: return if target.cpu == "arm": return neon_flags elif target.cpu == "aarch64": return ("-march=armv8-a",) @depends("--with-system-jpeg", target) def in_tree_jpeg_mips64(system_jpeg, target): if system_jpeg: return if target.cpu == "mips64": return ("-Wa,-mloongson-mmi", "-mloongson-ext") # Compiler check from https://github.com/libjpeg-turbo/libjpeg-turbo/blob/57ba02a408a9a55ccff25aae8b164632a3a4f177/simd/CMakeLists.txt#L419 jpeg_mips64_mmi = c_compiler.try_compile( body='int c = 0, a = 0, b = 0; asm("paddb %0, %1, %2" : "=f" (c) : "f" (a), "f" (b));', check_msg="for loongson mmi support", flags=in_tree_jpeg_mips64, when=in_tree_jpeg_mips64, ) @depends( "--with-system-jpeg", target, in_tree_jpeg_arm, in_tree_jpeg_mips64, jpeg_mips64_mmi, ) def in_tree_jpeg( system_jpeg, target, in_tree_jpeg_arm, in_tree_jpeg_mips64, jpeg_mips64_mmi ): if system_jpeg: return if target.cpu in ("arm", "aarch64"): return in_tree_jpeg_arm elif target.kernel == "Darwin": if target.cpu == "x86": return ("-DPIC", "-DMACHO") elif target.cpu == "x86_64": return ("-D__x86_64__", "-DPIC", "-DMACHO") elif target.kernel == "WINNT": if target.cpu == "x86": return ("-DPIC", "-DWIN32") elif target.cpu == "x86_64": return ("-D__x86_64__", "-DPIC", "-DWIN64", "-DMSVC") elif target.cpu == "mips32": return ("-mdspr2",) elif target.cpu == "mips64" and jpeg_mips64_mmi: return in_tree_jpeg_mips64 elif target.cpu == "x86": return ("-DPIC", "-DELF") elif target.cpu == "x86_64": return ("-D__x86_64__", "-DPIC", "-DELF") @depends(target, when=depends("--with-system-jpeg")(lambda x: not x)) def jpeg_nasm(target): if target.cpu in ("x86", "x86_64"): # libjpeg-turbo 2.0.6 requires nasm 2.10. return namespace(version="2.10", what="JPEG") # Compiler checks from https://github.com/libjpeg-turbo/libjpeg-turbo/blob/57ba02a408a9a55ccff25aae8b164632a3a4f177/simd/CMakeLists.txt#L258 jpeg_arm_neon_vld1_s16_x3 = c_compiler.try_compile( includes=["arm_neon.h"], body="int16_t input[12] = {}; int16x4x3_t output = vld1_s16_x3(input);", check_msg="for vld1_s16_x3 in arm_neon.h", flags=in_tree_jpeg_arm, when=in_tree_jpeg_arm, ) jpeg_arm_neon_vld1_u16_x2 = c_compiler.try_compile( includes=["arm_neon.h"], body="uint16_t input[8] = {}; uint16x4x2_t output = vld1_u16_x2(input);", check_msg="for vld1_u16_x2 in arm_neon.h", flags=in_tree_jpeg_arm, when=in_tree_jpeg_arm, ) jpeg_arm_neon_vld1q_u8_x4 = c_compiler.try_compile( includes=["arm_neon.h"], body="uint8_t input[64] = {}; uint8x16x4_t output = vld1q_u8_x4(input);", check_msg="for vld1q_u8_x4 in arm_neon.h", flags=in_tree_jpeg_arm, when=in_tree_jpeg_arm, ) set_config("LIBJPEG_TURBO_USE_NASM", True, when=jpeg_nasm) set_config("LIBJPEG_TURBO_SIMD_FLAGS", in_tree_jpeg) set_config("LIBJPEG_TURBO_HAVE_VLD1_S16_X3", jpeg_arm_neon_vld1_s16_x3) set_config("LIBJPEG_TURBO_HAVE_VLD1_U16_X2", jpeg_arm_neon_vld1_u16_x2) set_config("LIBJPEG_TURBO_HAVE_VLD1Q_U8_X4", jpeg_arm_neon_vld1q_u8_x4) set_config( "LIBJPEG_TURBO_NEON_INTRINSICS", jpeg_arm_neon_vld1_s16_x3 & jpeg_arm_neon_vld1_u16_x2 & jpeg_arm_neon_vld1q_u8_x4, ) # PNG # === with only_when(compile_environment): system_lib_option( "--with-system-png", nargs="?", help="Use system libpng", ) @depends("--with-system-png") def deprecated_system_png_path(value): if len(value) == 1: die( "--with-system-png=PATH is not supported anymore. Please use " "--with-system-png and set any necessary pkg-config environment variable." ) png = pkg_check_modules("MOZ_PNG", "libpng >= 1.6.35", when="--with-system-png") check_symbol( "png_get_acTL", flags=png.libs, onerror=lambda: die( "--with-system-png won't work because the system's libpng doesn't have APNG support" ), when="--with-system-png", ) set_config("MOZ_SYSTEM_PNG", True, when="--with-system-png") # FFmpeg's ffvpx configuration # ============================================================== @depends(target) def ffvpx(target): use_nasm = True audio_only = False flags = [] # This enables audio and video codecs paths on Windows x86 and x86_64, # macOS (all arch), and Linux x86_64. On other arch / OS combinations, # only audio codecs are enabled. if target.kernel == "WINNT": if target.cpu == "x86": # 32-bit windows need to prefix symbols with an underscore. flags = ["-DPIC", "-DWIN32", "-DPREFIX", "-Pconfig_win32.asm"] elif target.cpu == "x86_64": flags = [ "-D__x86_64__", "-DPIC", "-DWIN64", "-DMSVC", "-Pconfig_win64.asm", ] elif target.cpu == "aarch64": flags = ["-DPIC", "-DWIN64"] use_nasm = False elif target.kernel == "Darwin": # 32/64-bit macosx assemblers need to prefix symbols with an # underscore. flags = ["-DPIC", "-DMACHO", "-DPREFIX"] if target.cpu == "x86_64": flags += [ "-D__x86_64__", "-Pconfig_darwin64.asm", ] elif target.cpu == "aarch64": use_nasm = False elif target.cpu == "x86_64": flags = ["-D__x86_64__", "-DPIC", "-DELF", "-Pconfig_unix64.asm"] else: audio_only = True if audio_only: use_nasm = False return namespace( use_nasm=use_nasm, audio_only=audio_only, flags=flags, ) @depends(when=ffvpx.use_nasm) def ffvpx_nasm(): # nasm 2.10 for AVX-2 support. return namespace(version="2.10", what="FFVPX") # ffvpx_nasm can't indirectly depend on vpx_as_flags, because it depends # on a compiler test, so we have to do a little bit of dance here. @depends(ffvpx, vpx_as_flags, target) def ffvpx(ffvpx, vpx_as_flags, target): if ffvpx and vpx_as_flags and target.cpu in ("arm", "aarch64"): ffvpx.flags.extend(vpx_as_flags) return ffvpx set_config("MOZ_FFVPX_AUDIOONLY", True, when=ffvpx.audio_only) set_define("MOZ_FFVPX_AUDIOONLY", True, when=ffvpx.audio_only) set_config("FFVPX_ASFLAGS", ffvpx.flags) set_config("FFVPX_USE_NASM", True, when=ffvpx.use_nasm) # nasm detection # ============================================================== @depends(dav1d_nasm, vpx_nasm, jpeg_nasm, ffvpx_nasm, when=compile_environment) def need_nasm(*requirements): requires = { x.what: x.version if hasattr(x, "version") else True for x in requirements if x } if requires: items = sorted(requires.keys()) if len(items) > 1: what = " and ".join((", ".join(items[:-1]), items[-1])) else: what = items[0] versioned = {k: v for (k, v) in requires.items() if v is not True} return namespace(what=what, versioned=versioned) nasm = check_prog( "NASM", ["nasm"], allow_missing=True, bootstrap="nasm", when=need_nasm, ) @depends(nasm, need_nasm.what) def check_nasm(nasm, what): if not nasm and what: die("Nasm is required to build with %s, but it was not found." % what) return nasm @depends_if(check_nasm) @checking("nasm version") def nasm_version(nasm): version = ( check_cmd_output(nasm, "-v", onerror=lambda: die("Failed to get nasm version.")) .splitlines()[0] .split()[2] ) return Version(version) @depends(nasm_version, need_nasm.versioned, when=need_nasm.versioned) def check_nasm_version(nasm_version, versioned): by_version = sorted(versioned.items(), key=lambda x: x[1]) what, version = by_version[-1] if nasm_version < version: die( "Nasm version %s or greater is required to build with %s." % (version, what) ) return nasm_version @depends(target, when=check_nasm_version) def nasm_asflags(target): asflags = { ("Darwin", "x86"): ["-f", "macho32"], ("Darwin", "x86_64"): ["-f", "macho64"], ("WINNT", "x86"): ["-f", "win32"], ("WINNT", "x86_64"): ["-f", "win64"], }.get((target.kernel, target.cpu), None) if asflags is None: # We're assuming every x86 platform we support that's # not Windows or Mac is ELF. if target.cpu == "x86": asflags = ["-f", "elf32"] elif target.cpu == "x86_64": asflags = ["-f", "elf64"] return asflags set_config("NASM_ASFLAGS", nasm_asflags) # ANGLE OpenGL->D3D translator for WebGL # ============================================================== with only_when(compile_environment & target_is_windows): set_config("MOZ_ANGLE_RENDERER", True) # Remoting protocol support # ============================================================== @depends(toolkit) def has_remote(toolkit): if toolkit in ("gtk", "windows", "cocoa"): return True set_config("MOZ_HAS_REMOTE", has_remote) set_define("MOZ_HAS_REMOTE", has_remote) # RLBox Library Sandboxing wasm support # ============================================================== def wasm_sandboxing_libraries(): return ( "graphite", "ogg", "hunspell", "expat", "woff2", "soundtouch", ) @depends(dependable(wasm_sandboxing_libraries), build_project) def default_wasm_sandboxing_libraries(libraries, build_project): if build_project != "tools/rusttests": non_default_libs = {} return tuple(l for l in libraries if l not in non_default_libs) option( "--with-wasm-sandboxed-libraries", env="WASM_SANDBOXED_LIBRARIES", help="{Enable wasm sandboxing for the selected libraries|Disable wasm sandboxing}", nargs="+", choices=dependable(wasm_sandboxing_libraries), default=default_wasm_sandboxing_libraries, ) @depends("--with-wasm-sandboxed-libraries") def requires_wasm_sandboxing(libraries): if libraries: return True set_config("MOZ_USING_WASM_SANDBOXING", requires_wasm_sandboxing) set_define("MOZ_USING_WASM_SANDBOXING", requires_wasm_sandboxing) with only_when(requires_wasm_sandboxing & compile_environment): option( "--with-wasi-sysroot", env="WASI_SYSROOT", nargs=1, help="Path to wasi sysroot for wasm sandboxing", ) @depends("--with-wasi-sysroot", requires_wasm_sandboxing) def bootstrap_wasi_sysroot(wasi_sysroot, requires_wasm_sandboxing): return requires_wasm_sandboxing and not wasi_sysroot @depends( "--with-wasi-sysroot", bootstrap_path("sysroot-wasm32-wasi", when=bootstrap_wasi_sysroot), ) @imports("os") def wasi_sysroot(wasi_sysroot, bootstrapped_sysroot): if not wasi_sysroot: return bootstrapped_sysroot wasi_sysroot = wasi_sysroot[0] if not os.path.isdir(wasi_sysroot): die("Argument to --with-wasi-sysroot must be a directory") if not os.path.isabs(wasi_sysroot): die("Argument to --with-wasi-sysroot must be an absolute path") return wasi_sysroot @depends(wasi_sysroot) def wasi_sysroot_flags(wasi_sysroot): if wasi_sysroot: log.info("Using wasi sysroot in %s", wasi_sysroot) return ["--sysroot=%s" % wasi_sysroot] return [] set_config("WASI_SYSROOT", wasi_sysroot) def wasm_compiler_with_flags(compiler, sysroot_flags): if compiler: return ( compiler.wrapper + [compiler.compiler] + compiler.flags + sysroot_flags ) @template def wasm_compiler_error(msg): @depends("--with-wasm-sandboxed-libraries") def wasm_compiler_error(sandboxed_libs): suggest_disable = "" if sandboxed_libs.origin == "default": suggest_disable = " Or build with --without-wasm-sandboxed-libraries." return lambda: die(msg + suggest_disable) return wasm_compiler_error @template def check_wasm_compiler(compiler, language): compiler.try_compile( includes=["cstring" if language == "C++" else "string.h"], flags=wasi_sysroot_flags, check_msg="the wasm %s compiler can find wasi headers" % language, onerror=wasm_compiler_error( "Cannot find wasi headers or problem with the wasm compiler. " "Please fix the problem." ), ) compiler.try_run( flags=wasi_sysroot_flags, check_msg="the wasm %s linker can find wasi libraries" % language, onerror=wasm_compiler_error( "Cannot find wasi libraries or problem with the wasm linker. " "Please fix the problem." ), ) wasm_cc = compiler("C", wasm, other_compiler=c_compiler) check_wasm_compiler(wasm_cc, "C") @depends(wasm_cc, wasi_sysroot_flags) def wasm_cc_with_flags(wasm_cc, wasi_sysroot_flags): return wasm_compiler_with_flags(wasm_cc, wasi_sysroot_flags) set_config("WASM_CC", wasm_cc_with_flags) wasm_cxx = compiler( "C++", wasm, c_compiler=wasm_cc, other_compiler=cxx_compiler, other_c_compiler=c_compiler, ) check_wasm_compiler(wasm_cxx, "C++") @depends(wasm_cxx, wasi_sysroot_flags) def wasm_cxx_with_flags(wasm_cxx, wasi_sysroot_flags): return wasm_compiler_with_flags(wasm_cxx, wasi_sysroot_flags) set_config("WASM_CXX", wasm_cxx_with_flags) wasm_compile_flags = dependable(["-fno-exceptions", "-fno-strict-aliasing"]) option(env="WASM_CFLAGS", nargs=1, help="Options to pass to WASM_CC") @depends("WASM_CFLAGS", wasm_compile_flags) def wasm_cflags(value, wasm_compile_flags): if value: return wasm_compile_flags + value else: return wasm_compile_flags set_config("WASM_CFLAGS", wasm_cflags) option(env="WASM_CXXFLAGS", nargs=1, help="Options to pass to WASM_CXX") @depends("WASM_CXXFLAGS", wasm_compile_flags) def wasm_cxxflags(value, wasm_compile_flags): if value: return wasm_compile_flags + value else: return wasm_compile_flags set_config("WASM_CXXFLAGS", wasm_cxxflags) @depends("--with-wasm-sandboxed-libraries") def wasm_sandboxing(libraries): if not libraries: return return namespace(**{name: True for name in libraries}) @template def wasm_sandboxing_config_defines(): for lib in wasm_sandboxing_libraries(): set_config( "MOZ_WASM_SANDBOXING_%s" % lib.upper(), getattr(wasm_sandboxing, lib) ) set_define( "MOZ_WASM_SANDBOXING_%s" % lib.upper(), getattr(wasm_sandboxing, lib) ) wasm_sandboxing_config_defines() with only_when(compile_environment & wasm_sandboxing.hunspell): clock_in_wasi_sysroot = wasm_cc.try_run( header="#include ", body="clock();", check_msg="for clock() in wasi sysroot", flags=depends(wasi_sysroot_flags)( lambda sysroot_flags: ["-Werror"] + sysroot_flags ), ) wasi_emulated_clock = wasm_cc.try_run( header="#include ", body="clock();", check_msg="for emulated clock() in wasi sysroot", flags=depends(wasi_sysroot_flags)( lambda sysroot_flags: [ "-Werror", "-D_WASI_EMULATED_PROCESS_CLOCKS", "-lwasi-emulated-process-clocks", ] + sysroot_flags ), when=depends(clock_in_wasi_sysroot)(lambda x: not x), onerror=lambda: die("Can't find clock() in wasi sysroot."), ) set_config("MOZ_WASI_EMULATED_CLOCK", True, when=wasi_emulated_clock) # new Notification Store implementation # ============================================================== @depends(milestone) def new_notification_store(milestone): if milestone.is_nightly: return True set_config("MOZ_NEW_NOTIFICATION_STORE", True, when=new_notification_store) set_define("MOZ_NEW_NOTIFICATION_STORE", True, when=new_notification_store) # Auxiliary files persistence on application close # ============================================================== option( "--enable-disk-remnant-avoidance", help="Prevent persistence of auxiliary files on application close", ) set_config( "MOZ_AVOID_DISK_REMNANT_ON_CLOSE", True, when="--enable-disk-remnant-avoidance", ) # Glean SDK Integration Crate # ============================================================== @depends(target) def glean_android(target): return target.os == "Android" set_config("MOZ_GLEAN_ANDROID", True, when=glean_android) set_define("MOZ_GLEAN_ANDROID", True, when=glean_android) # dump_syms # ============================================================== check_prog( "DUMP_SYMS", ["dump_syms"], allow_missing=True, bootstrap="dump_syms", when=compile_environment, ) @depends(valid_windows_sdk_dir, host) @imports(_from="os", _import="environ") def pdbstr_paths(valid_windows_sdk_dir, host): if not valid_windows_sdk_dir: return vc_host = { "x86": "x86", "x86_64": "x64", }.get(host.cpu) return [ environ["PATH"], os.path.join(valid_windows_sdk_dir.path, "Debuggers", vc_host, "srcsrv"), ] @depends("MOZ_AUTOMATION", c_compiler) def allow_missing_wintools(automation, c_compiler): if not automation: return True if c_compiler and c_compiler.type != "clang-cl": return True check_prog( "PDBSTR", ["pdbstr.exe"], allow_missing=allow_missing_wintools, when=compile_environment & target_is_windows, paths=pdbstr_paths, allow_spaces=True, ) check_prog( "WINCHECKSEC", ["winchecksec.exe", "winchecksec"], bootstrap="winchecksec", allow_missing=allow_missing_wintools, when=compile_environment & target_is_windows, ) # Fork server @depends(target, build_project) def forkserver_default(target, build_project): return build_project == "browser" and ( (target.os == "GNU" and target.kernel == "Linux") or target.os == "FreeBSD" or target.os == "OpenBSD" ) option( "--enable-forkserver", default=forkserver_default, env="MOZ_ENABLE_FORKSERVER", help="{Enable|Disable} fork server", ) @depends("--enable-forkserver", target) def forkserver_flag(value, target): if ( target.os == "Android" or (target.os == "GNU" and target.kernel == "Linux") or target.os == "FreeBSD" or target.os == "OpenBSD" ): return bool(value) pass set_config("MOZ_ENABLE_FORKSERVER", forkserver_flag) set_define("MOZ_ENABLE_FORKSERVER", forkserver_flag, forkserver_flag) # Crash Reporter # ============================================================== with only_when(compile_environment & target_has_linux_kernel): # Check if we need to use the breakpad_getcontext fallback. getcontext = check_symbol("getcontext") set_config("HAVE_GETCONTEXT", getcontext) set_define("HAVE_GETCONTEXT", getcontext) # NSS # ============================================================== include("../build/moz.configure/nss.configure") # Enable or disable running in background task mode: headless for # periodic, short-lived, maintenance tasks. # ============================================================================== option( "--disable-backgroundtasks", help="Disable running in background task mode", ) set_config("MOZ_BACKGROUNDTASKS", True, when="--enable-backgroundtasks") set_define("MOZ_BACKGROUNDTASKS", True, when="--enable-backgroundtasks") # Update-related programs: updater, maintenance service, update agent, # default browser agent. # ============================================================== include("../build/moz.configure/update-programs.configure") # Mobile optimizations # ============================================================== option( "--enable-mobile-optimize", default=target_is_android, help="{Enable|Disable} mobile optimizations", ) set_define("MOZ_GFX_OPTIMIZE_MOBILE", True, when="--enable-mobile-optimize") # We ignore "paint will resample" on mobile for performance. # We may want to revisit this later. set_define("MOZ_IGNORE_PAINT_WILL_RESAMPLE", True, when="--enable-mobile-optimize") # Pref extensions # ============================================================== option("--disable-pref-extensions", help="Disable pref extensions such as autoconfig") set_config("MOZ_PREF_EXTENSIONS", True, when="--enable-pref-extensions") # Offer a way to disable the startup cache # ============================================================== option("--disable-startupcache", help="Disable startup cache") @depends("--enable-startupcache") def enable_startupcache(value): if value: return True set_define( "MOZ_DISABLE_STARTUPCACHE", True, when=depends(enable_startupcache)(lambda x: not x) ) # Branding # ============================================================== option( env="MOZ_APP_REMOTINGNAME", nargs=1, help="Used for the internal program name, which affects profile name " "and remoting. If not set, defaults to MOZ_APP_NAME if the update channel " "is release, and MOZ_APP_NAME-MOZ_UPDATE_CHANNEL otherwise.", ) @depends("MOZ_APP_REMOTINGNAME", moz_app_name, update_channel) def moz_app_remotingname(value, moz_app_name, update_channel): if value: return value[0] if update_channel == "release": return moz_app_name return moz_app_name + "-" + update_channel set_config("MOZ_APP_REMOTINGNAME", moz_app_remotingname) option( env="ANDROID_PACKAGE_NAME", nargs=1, help="Name of the Android package (default org.mozilla.$MOZ_APP_NAME)", ) @depends("ANDROID_PACKAGE_NAME", moz_app_name) def android_package_name(value, moz_app_name): if value: return value[0] if moz_app_name == "fennec": return "org.mozilla.fennec_aurora" return "org.mozilla.%s" % moz_app_name set_config("ANDROID_PACKAGE_NAME", android_package_name) # Miscellaneous options # ============================================================== option(env="MOZ_WINCONSOLE", nargs="?", help="Whether we can create a console window.") set_define("MOZ_WINCONSOLE", True, when=depends("MOZ_WINCONSOLE")(lambda x: x)) # Alternative Crashreporter setting option( "--with-crashreporter-url", env="MOZ_CRASHREPORTER_URL", default="https://crash-reports.mozilla.com/", nargs=1, help="Set an alternative crashreporter url", ) set_config( "MOZ_CRASHREPORTER_URL", depends("--with-crashreporter-url")(lambda x: x[0].rstrip("/")), ) # Crash reporter options # ============================================================== @depends(target) def oxidized_breakpad(target): if target.kernel == "Linux": return target.cpu in ("aarch64", "arm", "x86", "x86_64") return False set_config("MOZ_OXIDIZED_BREAKPAD", True, when=oxidized_breakpad) set_define("MOZ_OXIDIZED_BREAKPAD", True, when=oxidized_breakpad) # Wine # ============================================================== @depends(target, host) def want_wine(target, host): return target.kernel == "WINNT" and host.kernel != "WINNT" wine = check_prog( "WINE", ["wine64", "wine"], when=want_wine, bootstrap="wine/bin", ) # DOM Streams # ============================================================== # Set this to true so the JS engine knows we're doing a browser build. set_config("MOZ_DOM_STREAMS", True) set_define("MOZ_DOM_STREAMS", True) # libevent # ============================================================== with only_when(compile_environment): system_lib_option( "--with-system-libevent", nargs="?", help="Use system libevent", ) @depends("--with-system-libevent") def deprecated_system_libevent_path(value): if len(value) == 1: die( "--with-system-libevent=PATH is not supported anymore. Please use " "--with-system-libevent and set any necessary pkg-config environment variable." ) pkg_check_modules("MOZ_LIBEVENT", "libevent", when="--with-system-libevent") set_config("MOZ_SYSTEM_LIBEVENT", True, when="--with-system-libevent") # Crash reporting # ============================================================== @depends(target, developer_options, artifact_builds) def crashreporter_default(target, developer_options, artifacts): if target.os in ("WINNT", "OSX"): return True if target.kernel == "Linux" and target.cpu in ("x86", "x86_64", "arm", "aarch64"): # The crash reporter prevents crash stacktraces to be logged in the # logs on Android, so we leave it out by default in developer builds. return target.os != "Android" or not developer_options or artifacts option( "--enable-crashreporter", default=crashreporter_default, help="{Enable|Disable} crash reporting", ) set_config("MOZ_CRASHREPORTER", True, when="--enable-crashreporter") set_define("MOZ_CRASHREPORTER", True, when="--enable-crashreporter") with only_when(compile_environment): with only_when("--enable-crashreporter"): pkg_check_modules( "MOZ_GTHREAD", "gthread-2.0", when=depends(target)(lambda t: t.os == "GNU" and t.kernel == "Linux"), ) set_config( "MOZ_CRASHREPORTER_INJECTOR", True, when=depends(target)(lambda t: t.os == "WINNT" and t.bitness == 32), ) set_define( "MOZ_CRASHREPORTER_INJECTOR", True, when=depends(target)(lambda t: t.os == "WINNT" and t.bitness == 32), ) # If we have any service that uploads data (and requires data submission # policy alert), set MOZ_DATA_REPORTING. # ============================================================== @depends( "MOZ_TELEMETRY_REPORTING", "MOZ_SERVICES_HEALTHREPORT", "--enable-crashreporter", "MOZ_NORMANDY", ) def data_reporting(telemetry, healthreport, crashreporter, normandy): return telemetry or healthreport or crashreporter or normandy set_config("MOZ_DATA_REPORTING", True, when=data_reporting) set_define("MOZ_DATA_REPORTING", True, when=data_reporting) # Gtk+ # ============================================================== with only_when(toolkit_gtk): pkg_check_modules( "MOZ_GTK3", "gtk+-3.0 >= 3.14.0 gtk+-unix-print-3.0 glib-2.0 gobject-2.0 gio-unix-2.0", ) set_define("GDK_VERSION_MIN_REQUIRED", "GDK_VERSION_3_14") set_define("GDK_VERSION_MAX_ALLOWED", "GDK_VERSION_3_14") pkg_check_modules("GLIB", "glib-2.0 >= 2.42 gobject-2.0") set_define("GLIB_VERSION_MIN_REQUIRED", "GLIB_VERSION_2_42") set_define("GLIB_VERSION_MAX_ALLOWED", "GLIB_VERSION_2_42") set_define("MOZ_ACCESSIBILITY_ATK", True, when=accessibility) # DBus # ============================================================== with only_when(toolkit_gtk): option("--disable-dbus", help="Disable dbus support") with only_when("--enable-dbus"): pkg_check_modules("MOZ_DBUS", "dbus-1 >= 0.60") set_config("MOZ_ENABLE_DBUS", True) set_define("MOZ_ENABLE_DBUS", True) # Necko's wifi scanner # ============================================================== @depends(target) def necko_wifi_when(target): return target.os in ("WINNT", "OSX", "DragonFly", "FreeBSD") or ( target.kernel == "Linux" and target.os == "GNU" ) option("--disable-necko-wifi", help="Disable necko wifi scanner", when=necko_wifi_when) set_config("NECKO_WIFI", True, when="--enable-necko-wifi") set_define("NECKO_WIFI", True, when="--enable-necko-wifi") @depends( depends("--enable-necko-wifi", when=necko_wifi_when)(lambda x: x), depends("--enable-dbus", when=toolkit_gtk)(lambda x: x), when=depends(target)(lambda t: t.os == "GNU" and t.kernel == "Linux"), ) def necko_wifi_dbus(necko_wifi, dbus): if necko_wifi and not dbus: die( "Necko WiFi scanning needs DBus on your platform, remove --disable-dbus" " or use --disable-necko-wifi" ) return necko_wifi and dbus set_config("NECKO_WIFI_DBUS", True, when=necko_wifi_dbus) set_define("NECKO_WIFI_DBUS", True, when=necko_wifi_dbus) # Frontend JS debug mode # ============================================================== option("--enable-debug-js-modules", help="Enable debug mode for frontend JS libraries") set_config("DEBUG_JS_MODULES", True, when="--enable-debug-js-modules") # moz_dump_painting # ============================================================== option("--enable-dump-painting", help="Enable paint debugging") set_define( "MOZ_DUMP_PAINTING", True, when=depends("--enable-dump-painting", "--enable-debug")( lambda painting, debug: painting or debug ), ) set_define("MOZ_LAYERS_HAVE_LOG", True, when="--enable-dump-painting") # libproxy support # ============================================================== with only_when(toolkit_gtk): system_lib_option("--enable-libproxy", help="Enable libproxy support") with only_when("--enable-libproxy"): pkg_check_modules("MOZ_LIBPROXY", "libproxy-1.0") set_config("MOZ_ENABLE_LIBPROXY", True) set_define("MOZ_ENABLE_LIBPROXY", True) # Enable runtime logging # ============================================================== set_define("MOZ_LOGGING", True) set_define("FORCE_PR_LOG", True) # This will enable logging of addref, release, ctor, dtor. # ============================================================== option( "--enable-logrefcnt", default=moz_debug, help="{Enable|Disable} logging of refcounts", ) set_define("NS_BUILD_REFCNT_LOGGING", True, when="--enable-logrefcnt") # NegotiateAuth # ============================================================== option("--disable-negotiateauth", help="Disable GSS-API negotiation") set_config("MOZ_AUTH_EXTENSION", True, when="--enable-negotiateauth") set_define("MOZ_AUTH_EXTENSION", True, when="--enable-negotiateauth") # Parental control # ============================================================== option("--disable-parental-controls", help="Do not build parental controls") set_config( "MOZ_DISABLE_PARENTAL_CONTROLS", True, when=depends("--enable-parental-controls")(lambda x: not x), ) set_define( "MOZ_DISABLE_PARENTAL_CONTROLS", True, when=depends("--enable-parental-controls")(lambda x: not x), ) # Sandboxing support # ============================================================== @depends(target, tsan, asan) def sandbox_default(target, tsan, asan): # Only enable the sandbox by default on Linux, OpenBSD, macOS, and Windows if target.kernel == "Linux" and target.os == "GNU": # Bug 1182565: TSan conflicts with sandboxing on Linux. # Bug 1287971: LSan also conflicts with sandboxing on Linux. if tsan or asan: return False # Linux sandbox is only available on x86{,_64} and arm{,64}. return target.cpu in ("x86", "x86_64", "arm", "aarch64") return target.kernel in ("WINNT", "Darwin", "OpenBSD") option( "--enable-sandbox", default=sandbox_default, help="{Enable|Disable} sandboxing support", ) set_config("MOZ_SANDBOX", True, when="--enable-sandbox") set_define("MOZ_SANDBOX", True, when="--enable-sandbox") with only_when(depends(target.kernel)(lambda k: k not in ("Darwin", "WINNT"))): set_define("MOZ_CONTENT_TEMP_DIR", True, when="--enable-sandbox") # Searching of system directories for extensions. # ============================================================== # Note: this switch is meant to be used for test builds whose behavior should # not depend on what happens to be installed on the local machine. option( "--disable-system-extension-dirs", help="Disable searching system- and account-global directories for extensions" " of any kind; use only profile-specific extension directories", ) set_define("ENABLE_SYSTEM_EXTENSION_DIRS", True, when="--enable-system-extension-dirs") # Pixman # ============================================================== with only_when(compile_environment): system_lib_option( "--enable-system-pixman", help="Use system pixman (located with pkgconfig)" ) @depends("--enable-system-pixman") def in_tree_pixman(pixman): return not pixman set_config("MOZ_TREE_PIXMAN", True, when=in_tree_pixman) set_define("MOZ_TREE_PIXMAN", True, when=in_tree_pixman) pkg_check_modules("MOZ_PIXMAN", "pixman-1 >= 0.36.0", when="--enable-system-pixman") # Set MOZ_PIXMAN_CFLAGS to an explicit empty value when --enable-system-pixman is *not* used, # for layout/style/extra-bindgen-flags set_config("MOZ_PIXMAN_CFLAGS", [], when=in_tree_pixman) # Universalchardet # ============================================================== with only_when(compile_environment): option("--disable-universalchardet", help="Disable universal encoding detection") set_config("MOZ_UNIVERSALCHARDET", True, when="--enable-universalchardet") # Disable zipwriter # ============================================================== with only_when(compile_environment): option("--disable-zipwriter", help="Disable zipwriter component") set_config("MOZ_ZIPWRITER", True, when="--enable-zipwriter") # Location of the mozilla user directory # ============================================================== with only_when(compile_environment): @depends(target) def default_user_appdir(target): if target.kernel in ("WINNT", "Darwin"): return "Mozilla" return ".mozilla" option( "--with-user-appdir", nargs=1, default=default_user_appdir, help="Set user-specific appdir", ) @depends("--with-user-appdir") def user_appdir(appdir): if not appdir: die("--without-user-appdir is not a valid option.") if "/" in appdir[0]: die("--with-user-appdir must be a single relative path.") return '"{}"'.format(appdir[0]) set_define("MOZ_USER_DIR", user_appdir) # Check for sin_len and sin6_len - used by SCTP; only appears in Mac/*BSD generally # ============================================================== with only_when(compile_environment): have_sin_len = c_compiler.try_compile( includes=["netinet/in.h"], body="struct sockaddr_in x; void *foo = (void*) &x.sin_len;", check_msg="for sin_len in struct sockaddr_in", ) have_sin6_len = c_compiler.try_compile( includes=["netinet/in.h"], body="struct sockaddr_in6 x; void *foo = (void*) &x.sin6_len;", check_msg="for sin_len6 in struct sockaddr_in6", ) set_define("HAVE_SIN_LEN", have_sin_len) set_define("HAVE_SIN6_LEN", have_sin6_len) # HAVE_CONN_LEN must be the same as HAVE_SIN_LEN and HAVE_SIN6_LEN set_define("HAVE_SCONN_LEN", have_sin_len & have_sin6_len) set_define( "HAVE_SA_LEN", c_compiler.try_compile( includes=["netinet/in.h"], body="struct sockaddr x; void *foo = (void*) &x.sa_len;", check_msg="for sa_len in struct sockaddr", ), ) # Check for pthread_cond_timedwait_monotonic_np # ============================================================== with only_when(compile_environment): set_define( "HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC", c_compiler.try_compile( includes=["pthread.h"], body="pthread_cond_timedwait_monotonic_np(0, 0, 0);", # -Werror to catch any "implicit declaration" warning that means the function # is not supported. flags=["-Werror=implicit-function-declaration"], check_msg="for pthread_cond_timedwait_monotonic_np", ), ) # Custom dynamic linker for Android # ============================================================== with only_when(target_has_linux_kernel & compile_environment): option( env="MOZ_LINKER", default=depends(target.os, when="--enable-jemalloc")( lambda os: os == "Android" ), help="{Enable|Disable} custom dynamic linker", ) set_config("MOZ_LINKER", True, when="MOZ_LINKER") set_define("MOZ_LINKER", True, when="MOZ_LINKER") add_old_configure_assignment("MOZ_LINKER", True, when="MOZ_LINKER") moz_linker = depends(when="MOZ_LINKER")(lambda: True) # 32-bits ethtool_cmd.speed # ============================================================== with only_when(target_has_linux_kernel & compile_environment): set_config( "MOZ_WEBRTC_HAVE_ETHTOOL_SPEED_HI", c_compiler.try_compile( includes=["linux/ethtool.h"], body="struct ethtool_cmd cmd; cmd.speed_hi = 0;", check_msg="for 32-bits ethtool_cmd.speed", ), ) # Gamepad support # ============================================================== check_header( "linux/joystick.h", onerror=lambda: die( "Can't find header linux/joystick.h, needed for gamepad support." " Please install Linux kernel headers." ), when=target_has_linux_kernel & compile_environment, ) # Smart card support # ============================================================== @depends(build_project) def disable_smart_cards(build_project): return build_project == "mobile/android" set_config("MOZ_NO_SMART_CARDS", True, when=disable_smart_cards) set_define("MOZ_NO_SMART_CARDS", True, when=disable_smart_cards) # Enable UniFFI fixtures # ============================================================== # These are used to test the uniffi-bindgen-gecko-js code generation. They # should not be enabled in release builds. option( "--enable-uniffi-fixtures", help="Enable UniFFI Fixtures/Examples", ) set_config("MOZ_UNIFFI_FIXTURES", True, when="--enable-uniffi-fixtures") # System policies # ============================================================== option( "--disable-system-policies", help="Disable reading policies from Windows registry, macOS's file system attributes, and /etc/firefox", ) set_config("MOZ_SYSTEM_POLICIES", True, when="--enable-system-policies") # Allow disabling the creation a legacy profile # ============================================================== option( "--disable-legacy-profile-creation", help="Disable the creation a legacy profile, to be used by old versions " "of Firefox, when no profiles exist.", ) set_config("MOZ_CREATE_LEGACY_PROFILE", True, when="--enable-legacy-profile-creation") # STL wrapping # ============================================================== set_config("WRAP_STL_INCLUDES", True) set_config( "STL_FLAGS", depends(build_environment.dist)(lambda dist: [f"-I{dist}/stl_wrappers"]), ) # Perl detection # ============================================================== @depends(target) def need_perl(target): # Ideally, we'd also depend on gnu_as here, but that adds complications. return target.cpu == "arm" perl = check_prog("PERL", ("perl5", "perl"), when=need_perl) @template def perl_version_check(min_version): @depends(perl) @checking("for minimum required perl version >= %s" % min_version) def get_perl_version(perl): return Version( check_cmd_output( perl, "-e", "print $]", onerror=lambda: die("Failed to get perl version."), ) ) @depends(get_perl_version) def check_perl_version(version): if version < min_version: die("Perl %s or higher is required.", min_version) @depends(perl) @checking("for full perl installation") @imports("subprocess") def has_full_perl_installation(perl): ret = subprocess.call([perl, "-e", "use Config; exit(!-d $Config{archlib})"]) return ret == 0 @depends(has_full_perl_installation) def require_full_perl_installation(has_full_perl_installation): if not has_full_perl_installation: die( "Cannot find Config.pm or $Config{archlib}. " "A full perl installation is required." ) with only_when(need_perl): perl_version_check("5.006") # windows-rs as bootstrappable toolchain # ============================================================== # The in-tree windows crate's purpose is to avoid vendoring the # original windows crate, which is too large. # The ideal solution would be for cargo to allow exceptions to # vendoring, but it doesn't. # The adopted solution is to somehow use the crate contents from # a directory given via the mozbuild config, or bootstrapped. # # Unfortunately, doing `include!(mozbuild::windows_rs_path!("src/lib.rs"))` # in the crate's lib.rs doesn't work because of # https://github.com/rust-lang/rust/issues/66920. # # Previous versions of the windows crate had submodules declared # directly in lib.rs. Annotating each of them with # `#[path = concat!(mozbuild::windows_rs_path!("path/to/mod.rs"))]` # unfortunately also didn't work, because of # https://github.com/rust-lang/rust/issues/48250. # # Thankfully, newer versions of the windows crate now only have an # `include!` at the end of lib.rs, so we can get away with simply # replacing it with an `include!` that uses `mozbuild::windows_rs_path!`. # # We ensure that the in-tree contents match what we expect based on # the original crate. # The expectations are as such: # - Cargo.toml is identical to the original one with the addition of the # following two lines at the end (after an empty line): # [dependencies.mozbuild] # version = "0.1" # - src/lib.rs is mostly identical to the original one, with two notable # differences: # - the addition of `#![allow(warnings)]` on the first line, because if # the crate had been vendored normally, it would not be affected by # `-D warnings`, and `#![allow(warnings)]` mimicks that. # - the replacement of any # `include!("path/file.rs")` # with # `include!(mozbuild::windows_rs_path!("src/path/file.rs"))` with only_when(target_is_windows & compile_environment): option( env="MOZ_WINDOWS_RS_DIR", nargs=1, help="Path to the source of the 'windows' Rust crate", ) @depends( "MOZ_WINDOWS_RS_DIR", bootstrap_path( "windows-rs", when=depends("MOZ_WINDOWS_RS_DIR")(lambda x: not x), ), build_environment.topsrcdir, ) @checking("for the windows rust crate source") @imports(_from="__builtin__", _import="open") @imports("re") @imports("toml") def windows_rs_dir(dir, bootstrapped, topsrcdir): if bootstrapped: dir = bootstrapped elif dir: dir = dir[0] raw_cargo_toml = open( os.path.join(topsrcdir, "build/rust/windows/Cargo.toml") ).read() cargo_toml = toml.loads(raw_cargo_toml) expected_version = cargo_toml["package"]["version"] if not dir: raise FatalCheckError( "Cannot find the windows rust crate source.\n" f"Try downloading it with `cargo download -x windows={expected_version}`\n" "(you may need to `cargo install cargo-download` first)\n" f"and set `MOZ_WINDOWS_RS_DIR` to location of the `windows-{expected_version}`" " directory" ) raw_cargo_toml_orig = open(os.path.join(dir, "Cargo.toml")).read() cargo_toml = toml.loads(raw_cargo_toml_orig) version = cargo_toml["package"]["version"] if version != expected_version: raise FatalCheckError( f"The windows rust crate source in {dir} contains version " f"{version}, but expected {expected_version}." ) # Now that we've done the basic sanity check, let's go deeper. DEPENDENCIES = '\n[dependencies.mozbuild]\nversion = "0.1"\n' if not raw_cargo_toml.endswith(DEPENDENCIES): configure_error("In-tree windows crate is missing dependency on mozbuild") if raw_cargo_toml[: -len(DEPENDENCIES)] != raw_cargo_toml_orig: configure_error("In-tree windows crate Cargo.toml doesn't match original") lib_rs = open(os.path.join(topsrcdir, "build/rust/windows/src/lib.rs")).read() lib_rs_orig = open(os.path.join(dir, "src/lib.rs")).read() lib_rs_expected = "#![allow(warnings)]\n" + re.sub( r'include!\("([^"]*)"\)', r'include!(mozbuild::windows_rs_path!("src/\1"))', lib_rs_orig, ) if lib_rs != lib_rs_expected: configure_error("In-tree windows crate lib.rs doesn't match original") return dir set_config("MOZ_WINDOWS_RS_DIR", windows_rs_dir)