summaryrefslogtreecommitdiffstats
path: root/config
diff options
context:
space:
mode:
Diffstat (limited to 'config')
-rw-r--r--config/AB_rCD.mk20
-rw-r--r--config/Makefile.in49
-rw-r--r--config/MozZipFile.py143
-rw-r--r--config/autoconf-js.mk.in6
-rw-r--r--config/autoconf.mk.in6
-rw-r--r--config/baseconfig.mk73
-rw-r--r--config/check_js_msg_encoding.py69
-rw-r--r--config/check_js_opcode.py47
-rw-r--r--config/check_macroassembler_style.py342
-rwxr-xr-xconfig/check_source_count.py63
-rw-r--r--config/check_spidermonkey_style.py899
-rw-r--r--config/check_vanilla_allocations.py296
-rw-r--r--config/config.mk408
-rw-r--r--config/create_rc.py202
-rw-r--r--config/create_res.py102
-rw-r--r--config/createprecomplete.py72
-rw-r--r--config/emptyvars-js.mk.in1
-rw-r--r--config/emptyvars.mk.in1
-rw-r--r--config/external/fdlibm/moz.build12
-rw-r--r--config/external/ffi/moz.build149
-rw-r--r--config/external/ffi/preprocess_libffi_asm.py25
-rw-r--r--config/external/ffi/subst_header.py32
-rw-r--r--config/external/freetype2/moz.build14
-rw-r--r--config/external/gkcodecs/gkcodecs.symbols158
-rw-r--r--config/external/gkcodecs/moz.build18
-rw-r--r--config/external/icu/common/moz.build34
-rw-r--r--config/external/icu/common/sources.mozbuild305
-rw-r--r--config/external/icu/data/convert_icudata.py20
-rw-r--r--config/external/icu/data/icu_data.S29
-rw-r--r--config/external/icu/data/icudt73l.datbin0 -> 15519200 bytes
-rw-r--r--config/external/icu/data/moz.build40
-rw-r--r--config/external/icu/defs.mozbuild75
-rw-r--r--config/external/icu/i18n/moz.build24
-rw-r--r--config/external/icu/i18n/sources.mozbuild344
-rw-r--r--config/external/icu/icupkg/moz.build27
-rw-r--r--config/external/icu/icupkg/sources.mozbuild4
-rw-r--r--config/external/icu/moz.build22
-rw-r--r--config/external/icu/toolutil/moz.build20
-rw-r--r--config/external/icu/toolutil/sources.mozbuild27
-rw-r--r--config/external/lgpllibs/lgpllibs.symbols17
-rw-r--r--config/external/lgpllibs/moz.build18
-rw-r--r--config/external/moz.build75
-rw-r--r--config/external/nspr/_pl_bld.h6
-rw-r--r--config/external/nspr/_pr_bld.h6
-rw-r--r--config/external/nspr/ds/moz.build34
-rw-r--r--config/external/nspr/libc/moz.build45
-rw-r--r--config/external/nspr/moz.build28
-rw-r--r--config/external/nspr/pr/moz.build254
-rw-r--r--config/external/nspr/prcpucfg.h31
-rw-r--r--config/external/rlbox/moz.build31
-rw-r--r--config/external/rlbox/rlbox_config.h30
-rw-r--r--config/external/rlbox/rlbox_thread_locals.cpp17
-rw-r--r--config/external/rlbox_wasm2c_sandbox/moz.build27
-rw-r--r--config/external/rlbox_wasm2c_sandbox/moz.yaml31
-rw-r--r--config/external/rlbox_wasm2c_sandbox/rlbox_wasm2c_thread_locals.cpp54
-rw-r--r--config/external/sqlite/moz.build18
-rw-r--r--config/external/wasm2c_sandbox_compiler/moz.build82
-rw-r--r--config/external/wasm2c_sandbox_compiler/moz.yaml47
-rw-r--r--config/external/wasm2c_sandbox_compiler/preprocess_wasm2c_config.py139
-rw-r--r--config/external/zlib/moz.build21
-rw-r--r--config/faster/rules.mk95
-rw-r--r--config/gcc-stl-wrapper.template.h85
-rw-r--r--config/gcc_hidden.h6
-rw-r--r--config/install.bat10
-rw-r--r--config/make-stl-wrappers.py18
-rw-r--r--config/make-system-wrappers.py38
-rw-r--r--config/make-windows-h-wrapper.py94
-rw-r--r--config/makefiles/autotargets.mk93
-rw-r--r--config/makefiles/debugmake.mk114
-rw-r--r--config/makefiles/functions.mk41
-rw-r--r--config/makefiles/makeutils.mk121
-rw-r--r--config/makefiles/nonrecursive.mk68
-rw-r--r--config/makefiles/rust.mk613
-rw-r--r--config/makefiles/target_binaries.mk43
-rw-r--r--config/makefiles/xpidl/Makefile.in94
-rw-r--r--config/milestone.txt13
-rw-r--r--config/moz.build116
-rw-r--r--config/mozunit/mozunit/__init__.py6
-rw-r--r--config/mozunit/mozunit/mozunit.py336
-rw-r--r--config/mozunit/mozunit/pytest.ini4
-rw-r--r--config/mozunit/mozunit/pytest_plugin.py26
-rw-r--r--config/mozunit/setup.py19
-rw-r--r--config/msvc-stl-wrapper.template.h72
-rw-r--r--config/nsinstall.c411
-rw-r--r--config/nsinstall.py172
-rw-r--r--config/pathsub.c177
-rw-r--r--config/pathsub.h42
-rw-r--r--config/printconfigsetting.py24
-rw-r--r--config/printprereleasesuffix.py35
-rw-r--r--config/rebuild_check.py68
-rw-r--r--config/recurse.mk216
-rw-r--r--config/rules.mk1177
-rw-r--r--config/run-and-prefix.py36
-rw-r--r--config/run_spidermonkey_checks.py15
-rw-r--r--config/shlwapi-h-constant.decls.h23
-rw-r--r--config/shlwapi-h-unicode.decls.h24
-rw-r--r--config/shlwapi-h-wrapper.template.h43
-rw-r--r--config/static-checking-config.mk21
-rw-r--r--config/stl-headers.mozbuild60
-rw-r--r--config/system-headers.mozbuild1373
-rw-r--r--config/tests/chrome.manifest.flat4
-rw-r--r--config/tests/python.toml10
-rw-r--r--config/tests/ref-simple/one/file.xml1
-rw-r--r--config/tests/ref-simple/one/preproc2
-rw-r--r--config/tests/ref-simple/one/some.css6
-rw-r--r--config/tests/ref-simple/three/l10nfile.txt1
-rw-r--r--config/tests/ref-simple/two/otherfile.xml1
-rw-r--r--config/tests/src-simple/Makefile.in38
-rw-r--r--config/tests/src-simple/jar.mn22
-rw-r--r--config/tests/src-simple/l10n/l10nfile.txt1
-rw-r--r--config/tests/src-simple/moz.build7
-rw-r--r--config/tests/src-simple/thesrcdir/file.xml1
-rw-r--r--config/tests/src-simple/thesrcdir/preproc.in6
-rw-r--r--config/tests/src-simple/thesrcdir/some.css6
-rw-r--r--config/tests/src-simple/thetopsrcdir/otherfile.xml1
-rw-r--r--config/tests/test.manifest.flat4
-rw-r--r--config/tests/test.manifest.jar4
-rw-r--r--config/tests/test.manifest.symlink4
-rw-r--r--config/tests/test_mozbuild_reading.py104
-rw-r--r--config/tests/unit-mozunit.py87
-rw-r--r--config/tests/unit-nsinstall.py179
-rw-r--r--config/tests/unit-printprereleasesuffix.py79
-rw-r--r--config/tests/unitMozZipFile.py214
-rw-r--r--config/wasm2c.py14
-rw-r--r--config/windows-h-constant.decls.h65
-rw-r--r--config/windows-h-unicode.decls.h1130
-rw-r--r--config/windows-h-wrapper.template.h45
127 files changed, 13267 insertions, 0 deletions
diff --git a/config/AB_rCD.mk b/config/AB_rCD.mk
new file mode 100644
index 0000000000..98a508e44b
--- /dev/null
+++ b/config/AB_rCD.mk
@@ -0,0 +1,20 @@
+# 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/.
+
+# Turn 'en-US' into '' and general 'ab-CD' into '-ab-rCD' -- note
+# leading hyphen.
+#
+# For example, 'res{AB_rCD}' is 'res' for 'en-US' and 'res-en-rGB' for
+# 'en-GB'.
+#
+# Some locale codes are special, namely 'he' and 'id'. See
+# http://code.google.com/p/android/issues/detail?id=3639.
+#
+# This is for use in Android resource directories, which uses a
+# somewhat non-standard resource naming scheme for localized
+# resources: see
+# https://developer.android.com/guide/topics/resources/providing-resources.html#AlternativeResources.
+# Android 24+ uses the standard BCP-47 naming scheme, and Bug 1441305
+# tracks migrating to that naming scheme.
+AB_rCD = $(if $(filter en-US,$(AB_CD)),,-$(if $(filter he, $(AB_CD)),iw,$(if $(filter id, $(AB_CD)),in,$(subst -,-r,$(AB_CD)))))
diff --git a/config/Makefile.in b/config/Makefile.in
new file mode 100644
index 0000000000..79b6db87ad
--- /dev/null
+++ b/config/Makefile.in
@@ -0,0 +1,49 @@
+# -*- Makefile -*-
+#
+# 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/.
+
+# IMPORTANT: Disable NSBUILDROOT for this directory only, otherwise we have
+# a recursive rule for finding nsinstall and the Perl scripts.
+ifdef NSBUILDROOT
+override NSBUILDROOT :=
+endif
+
+include $(topsrcdir)/config/config.mk
+
+# L10n jobs are doing make -C config manually before anything else,
+# and need nsinstall to be built as a consequence.
+ifdef COMPILE_ENVIRONMENT
+export:: host
+
+ifneq (WINNT,$(HOST_OS_ARCH))
+# Ensure nsinstall is atomically created
+nsinstall$(HOST_BIN_SUFFIX): $(HOST_PROGRAM)
+ cp $^ $@.tmp
+ mv $@.tmp $@
+
+NSINSTALL_EXECUTABLES := nsinstall$(HOST_BIN_SUFFIX)
+NSINSTALL_DEST := $(DIST)/bin
+NSINSTALL_TARGET := host
+INSTALL_TARGETS += NSINSTALL
+endif
+endif
+
+include $(topsrcdir)/config/rules.mk
+
+FORCE:
+
+ifndef JS_STANDALONE
+check-preqs += check-jar-mn
+endif
+
+check:: $(check-preqs)
+
+check-jar-mn::
+ $(MAKE) -C tests/src-simple check-jar
+ $(MAKE) -C tests/src-simple check-flat
+ $(MAKE) -C tests/src-simple check-flat USE_EXTENSION_MANIFEST=1
+ifneq (,$(filter-out WINNT,$(OS_ARCH)))
+ $(MAKE) -C tests/src-simple check-symlink
+endif
diff --git a/config/MozZipFile.py b/config/MozZipFile.py
new file mode 100644
index 0000000000..6e74bc1eba
--- /dev/null
+++ b/config/MozZipFile.py
@@ -0,0 +1,143 @@
+# 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/.
+
+import os
+import time
+import zipfile
+
+import six
+from mozbuild.util import lock_file
+
+
+class ZipFile(zipfile.ZipFile):
+ """Class with methods to open, read, write, close, list zip files.
+
+ Subclassing zipfile.ZipFile to allow for overwriting of existing
+ entries, though only for writestr, not for write.
+ """
+
+ def __init__(self, file, mode="r", compression=zipfile.ZIP_STORED, lock=False):
+ if lock:
+ assert isinstance(file, six.text_type)
+ self.lockfile = lock_file(file + ".lck")
+ else:
+ self.lockfile = None
+
+ if mode == "a" and lock:
+ # appending to a file which doesn't exist fails, but we can't check
+ # existence util we hold the lock
+ if (not os.path.isfile(file)) or os.path.getsize(file) == 0:
+ mode = "w"
+
+ zipfile.ZipFile.__init__(self, file, mode, compression)
+ self._remove = []
+ self.end = self.fp.tell()
+ self.debug = 0
+
+ def writestr(self, zinfo_or_arcname, bytes):
+ """Write contents into the archive.
+
+ The contents is the argument 'bytes', 'zinfo_or_arcname' is either
+ a ZipInfo instance or the name of the file in the archive.
+ This method is overloaded to allow overwriting existing entries.
+ """
+ if not isinstance(zinfo_or_arcname, zipfile.ZipInfo):
+ zinfo = zipfile.ZipInfo(
+ filename=zinfo_or_arcname, date_time=time.localtime(time.time())
+ )
+ zinfo.compress_type = self.compression
+ # Add some standard UNIX file access permissions (-rw-r--r--).
+ zinfo.external_attr = (0x81A4 & 0xFFFF) << 16
+ else:
+ zinfo = zinfo_or_arcname
+
+ # Now to the point why we overwrote this in the first place,
+ # remember the entry numbers if we already had this entry.
+ # Optimizations:
+ # If the entry to overwrite is the last one, just reuse that.
+ # If we store uncompressed and the new content has the same size
+ # as the old, reuse the existing entry.
+
+ doSeek = False # store if we need to seek to the eof after overwriting
+ if zinfo.filename in self.NameToInfo:
+ # Find the last ZipInfo with our name.
+ # Last, because that's catching multiple overwrites
+ i = len(self.filelist)
+ while i > 0:
+ i -= 1
+ if self.filelist[i].filename == zinfo.filename:
+ break
+ zi = self.filelist[i]
+ if (
+ zinfo.compress_type == zipfile.ZIP_STORED
+ and zi.compress_size == len(bytes)
+ ) or (i + 1) == len(self.filelist):
+ # make sure we're allowed to write, otherwise done by writestr below
+ self._writecheck(zi)
+ # overwrite existing entry
+ self.fp.seek(zi.header_offset)
+ if (i + 1) == len(self.filelist):
+ # this is the last item in the file, just truncate
+ self.fp.truncate()
+ else:
+ # we need to move to the end of the file afterwards again
+ doSeek = True
+ # unhook the current zipinfo, the writestr of our superclass
+ # will add a new one
+ self.filelist.pop(i)
+ self.NameToInfo.pop(zinfo.filename)
+ else:
+ # Couldn't optimize, sadly, just remember the old entry for removal
+ self._remove.append(self.filelist.pop(i))
+ zipfile.ZipFile.writestr(self, zinfo, bytes)
+ self.filelist.sort(key=lambda l: l.header_offset)
+ if doSeek:
+ self.fp.seek(self.end)
+ self.end = self.fp.tell()
+
+ def close(self):
+ """Close the file, and for mode "w" and "a" write the ending
+ records.
+
+ Overwritten to compact overwritten entries.
+ """
+ if not self._remove:
+ # we don't have anything special to do, let's just call base
+ r = zipfile.ZipFile.close(self)
+ self.lockfile = None
+ return r
+
+ if self.fp.mode != "r+b":
+ # adjust file mode if we originally just wrote, now we rewrite
+ self.fp.close()
+ self.fp = open(self.filename, "r+b")
+ all = map(lambda zi: (zi, True), self.filelist) + map(
+ lambda zi: (zi, False), self._remove
+ )
+ all.sort(key=lambda l: l[0].header_offset)
+ # empty _remove for multiple closes
+ self._remove = []
+
+ lengths = [
+ all[i + 1][0].header_offset - all[i][0].header_offset
+ for i in xrange(len(all) - 1)
+ ]
+ lengths.append(self.end - all[-1][0].header_offset)
+ to_pos = 0
+ for (zi, keep), length in zip(all, lengths):
+ if not keep:
+ continue
+ oldoff = zi.header_offset
+ # python <= 2.4 has file_offset
+ if hasattr(zi, "file_offset"):
+ zi.file_offset = zi.file_offset + to_pos - oldoff
+ zi.header_offset = to_pos
+ self.fp.seek(oldoff)
+ content = self.fp.read(length)
+ self.fp.seek(to_pos)
+ self.fp.write(content)
+ to_pos += length
+ self.fp.truncate()
+ zipfile.ZipFile.close(self)
+ self.lockfile = None
diff --git a/config/autoconf-js.mk.in b/config/autoconf-js.mk.in
new file mode 100644
index 0000000000..ae4ad2c5e1
--- /dev/null
+++ b/config/autoconf-js.mk.in
@@ -0,0 +1,6 @@
+ifndef INCLUDED_AUTOCONF_MK
+INCLUDED_AUTOCONF_MK = autoconf-js.mk
+include $(DEPTH)/config/emptyvars-js.mk
+@ALLSUBSTS@
+include $(topsrcdir)/config/baseconfig.mk
+endif
diff --git a/config/autoconf.mk.in b/config/autoconf.mk.in
new file mode 100644
index 0000000000..fb52bc1975
--- /dev/null
+++ b/config/autoconf.mk.in
@@ -0,0 +1,6 @@
+ifndef INCLUDED_AUTOCONF_MK
+INCLUDED_AUTOCONF_MK = autoconf.mk
+include $(DEPTH)/config/emptyvars.mk
+@ALLSUBSTS@
+include $(topsrcdir)/config/baseconfig.mk
+endif
diff --git a/config/baseconfig.mk b/config/baseconfig.mk
new file mode 100644
index 0000000000..428beef48e
--- /dev/null
+++ b/config/baseconfig.mk
@@ -0,0 +1,73 @@
+# This file is normally included by autoconf.mk, but it is also used
+# directly in python/mozbuild/mozbuild/base.py for gmake validation.
+# We thus use INCLUDED_AUTOCONF_MK to enable/disable some parts depending
+# whether a normal build is happening or whether the check is running.
+installdir = $(libdir)/$(MOZ_APP_NAME)
+ifeq (.,$(DEPTH))
+DIST = dist
+else
+DIST = $(DEPTH)/dist
+endif
+ABS_DIST = $(topobjdir)/dist
+
+ifeq ($(HOST_OS_ARCH),WINNT)
+# We only support building with a non-msys gnu make version
+# strictly above 4.0.
+ifdef .PYMAKE
+$(error Pymake is no longer supported. Please upgrade to MozillaBuild 1.9 or newer and build with 'mach' or 'mozmake')
+endif
+
+ifeq (a,$(firstword a$(subst /, ,$(abspath .))))
+$(error MSYS make is not supported)
+endif
+# 4.0- happens to be greater than 4.0, lower than the mozmake version,
+# and lower than 4.0.1 or 4.1, whatever next version of gnu make will
+# be released.
+ifneq (4.0-,$(firstword $(sort 4.0- $(MAKE_VERSION))))
+$(error Make version too old. Only versions strictly greater than 4.0 are supported.)
+endif
+
+ifdef INCLUDED_AUTOCONF_MK
+ifeq (a,$(firstword a$(subst /, ,$(srcdir))))
+$(error MSYS-style srcdir are not supported for Windows builds.)
+endif
+endif
+endif # WINNT
+
+ifndef INCLUDED_AUTOCONF_MK
+default::
+else
+
+ifeq ($(MOZ_BUILD_APP),tools/rusttests)
+# Rusttest tiers aren't a subset of regular ALL_TIERS, so define them separately
+ALL_TIERS := pre-export export rusttests
+else
+# All possible tiers
+ALL_TIERS := artifact android-fat-aar-artifact pre-export export pre-compile rust compile misc libs android-stage-package android-archive-geckoview tools check
+endif
+
+# All tiers that may be used manually via `mach build $tier`
+RUNNABLE_TIERS := $(ALL_TIERS)
+ifndef MOZ_ARTIFACT_BUILDS
+RUNNABLE_TIERS := $(filter-out artifact,$(RUNNABLE_TIERS))
+endif
+ifndef MOZ_ANDROID_FAT_AAR_ARCHITECTURES
+RUNNABLE_TIERS := $(filter-out android-fat-aar-artifact,$(RUNNABLE_TIERS))
+endif
+ifneq ($(MOZ_BUILD_APP),mobile/android)
+RUNNABLE_TIERS := $(filter-out android-stage-package,$(RUNNABLE_TIERS))
+RUNNABLE_TIERS := $(filter-out android-archive-geckoview,$(RUNNABLE_TIERS))
+endif
+
+# All tiers that run automatically on `mach build`
+TIERS := $(filter-out pre-compile check,$(RUNNABLE_TIERS))
+ifndef COMPILE_ENVIRONMENT
+TIERS := $(filter-out rust compile,$(TIERS))
+endif
+ifndef MOZ_RUST_TIER
+TIERS := $(filter-out rust,$(TIERS))
+endif
+
+endif
+
+MOZILLA_DIR = $(topsrcdir)
diff --git a/config/check_js_msg_encoding.py b/config/check_js_msg_encoding.py
new file mode 100644
index 0000000000..6543405f90
--- /dev/null
+++ b/config/check_js_msg_encoding.py
@@ -0,0 +1,69 @@
+# vim: set ts=8 sts=4 et sw=4 tw=99:
+# 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/.
+
+# ----------------------------------------------------------------------------
+# This script checks encoding of the files that define JSErrorFormatStrings.
+#
+# JSErrorFormatString.format member should be in ASCII encoding.
+# ----------------------------------------------------------------------------
+
+import os
+import sys
+
+from mozversioncontrol import get_repository_from_env
+
+scriptname = os.path.basename(__file__)
+expected_encoding = "ascii"
+
+# The following files don't define JSErrorFormatString.
+ignore_files = [
+ "dom/base/domerr.msg",
+ "js/xpconnect/src/xpc.msg",
+]
+
+
+def log_pass(filename, text):
+ print("TEST-PASS | {} | {} | {}".format(scriptname, filename, text))
+
+
+def log_fail(filename, text):
+ print("TEST-UNEXPECTED-FAIL | {} | {} | {}".format(scriptname, filename, text))
+
+
+def check_single_file(filename):
+ with open(filename, "rb") as f:
+ data = f.read()
+ try:
+ data.decode(expected_encoding)
+ except Exception:
+ log_fail(filename, "not in {} encoding".format(expected_encoding))
+
+ log_pass(filename, "ok")
+ return True
+
+
+def check_files():
+ result = True
+
+ with get_repository_from_env() as repo:
+ root = repo.path
+
+ for filename, _ in repo.get_tracked_files_finder().find("**/*.msg"):
+ if filename not in ignore_files:
+ if not check_single_file(os.path.join(root, filename)):
+ result = False
+
+ return result
+
+
+def main():
+ if not check_files():
+ sys.exit(1)
+
+ sys.exit(0)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/config/check_js_opcode.py b/config/check_js_opcode.py
new file mode 100644
index 0000000000..b6a6c1f1c8
--- /dev/null
+++ b/config/check_js_opcode.py
@@ -0,0 +1,47 @@
+# vim: set ts=8 sts=4 et sw=4 tw=99:
+# 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/.
+
+# ----------------------------------------------------------------------------
+# This script checks bytecode documentation in js/src/vm/Opcodes.h
+# ----------------------------------------------------------------------------
+
+import os
+import sys
+
+scriptname = os.path.basename(__file__)
+topsrcdir = os.path.dirname(os.path.dirname(__file__))
+
+
+def log_pass(text):
+ print("TEST-PASS | {} | {}".format(scriptname, text))
+
+
+def log_fail(text):
+ print("TEST-UNEXPECTED-FAIL | {} | {}".format(scriptname, text))
+
+
+def check_opcode():
+ sys.path.insert(0, os.path.join(topsrcdir, "js", "src", "vm"))
+ import jsopcode
+
+ try:
+ jsopcode.get_opcodes(topsrcdir)
+ except Exception as e:
+ log_fail(e.args[0])
+ return False
+
+ log_pass("ok")
+ return True
+
+
+def main():
+ if not check_opcode():
+ sys.exit(1)
+
+ sys.exit(0)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/config/check_macroassembler_style.py b/config/check_macroassembler_style.py
new file mode 100644
index 0000000000..c10ef9789d
--- /dev/null
+++ b/config/check_macroassembler_style.py
@@ -0,0 +1,342 @@
+# vim: set ts=8 sts=4 et sw=4 tw=99:
+# 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/.
+
+# ----------------------------------------------------------------------------
+# This script checks that SpiderMonkey MacroAssembler methods are properly
+# annotated.
+#
+# The MacroAssembler has one interface for all platforms, but it might have one
+# definition per platform. The code of the MacroAssembler use a macro to
+# annotate the method declarations, in order to delete the function if it is not
+# present on the current platform, and also to locate the files in which the
+# methods are defined.
+#
+# This script scans the MacroAssembler.h header, for method declarations.
+# It also scans MacroAssembler-/arch/.cpp, MacroAssembler-/arch/-inl.h, and
+# MacroAssembler-inl.h for method definitions. The result of both scans are
+# uniformized, and compared, to determine if the MacroAssembler.h header as
+# proper methods annotations.
+# ----------------------------------------------------------------------------
+
+import difflib
+import os
+import re
+import sys
+
+architecture_independent = set(["generic"])
+all_unsupported_architectures_names = set(["mips32", "mips64", "mips_shared"])
+all_architecture_names = set(
+ ["x86", "x64", "arm", "arm64", "loong64", "riscv64", "wasm32"]
+)
+all_shared_architecture_names = set(
+ ["x86_shared", "arm", "arm64", "loong64", "riscv64", "wasm32"]
+)
+
+reBeforeArg = r"(?<=[(,\s])"
+reArgType = r"(?P<type>[\w\s:*&<>]+)"
+reArgName = r"(?P<name>\s\w+)"
+reArgDefault = r"(?P<default>(?:\s=(?:(?:\s[\w:]+\(\))|[^,)]+))?)"
+reAfterArg = "(?=[,)])"
+reMatchArg = re.compile(reBeforeArg + reArgType + reArgName + reArgDefault + reAfterArg)
+
+
+def get_normalized_signatures(signature, fileAnnot=None):
+ # Remove static
+ signature = signature.replace("static", "")
+ # Remove semicolon.
+ signature = signature.replace(";", " ")
+ # Normalize spaces.
+ signature = re.sub(r"\s+", " ", signature).strip()
+ # Remove new-line induced spaces after opening braces.
+ signature = re.sub(r"\(\s+", "(", signature).strip()
+ # Match arguments, and keep only the type.
+ signature = reMatchArg.sub(r"\g<type>", signature)
+ # Remove class name
+ signature = signature.replace("MacroAssembler::", "")
+
+ # Extract list of architectures
+ archs = ["generic"]
+ if fileAnnot:
+ archs = [fileAnnot["arch"]]
+
+ if "DEFINED_ON(" in signature:
+ archs = re.sub(
+ r".*DEFINED_ON\((?P<archs>[^()]*)\).*", r"\g<archs>", signature
+ ).split(",")
+ archs = [a.strip() for a in archs]
+ signature = re.sub(r"\s+DEFINED_ON\([^()]*\)", "", signature)
+
+ elif "PER_ARCH" in signature:
+ archs = all_architecture_names
+ signature = re.sub(r"\s+PER_ARCH", "", signature)
+
+ elif "PER_SHARED_ARCH" in signature:
+ archs = all_shared_architecture_names
+ signature = re.sub(r"\s+PER_SHARED_ARCH", "", signature)
+
+ elif "OOL_IN_HEADER" in signature:
+ assert archs == ["generic"]
+ signature = re.sub(r"\s+OOL_IN_HEADER", "", signature)
+
+ else:
+ # No signature annotation, the list of architectures remains unchanged.
+ pass
+
+ # Extract inline annotation
+ inline = False
+ if fileAnnot:
+ inline = fileAnnot["inline"]
+
+ if "inline " in signature:
+ signature = re.sub(r"inline\s+", "", signature)
+ inline = True
+
+ inlinePrefx = ""
+ if inline:
+ inlinePrefx = "inline "
+ signatures = [{"arch": a, "sig": inlinePrefx + signature} for a in archs]
+
+ return signatures
+
+
+file_suffixes = set(
+ [
+ a.replace("_", "-")
+ for a in all_architecture_names.union(all_shared_architecture_names).union(
+ all_unsupported_architectures_names
+ )
+ ]
+)
+
+
+def get_file_annotation(filename):
+ origFilename = filename
+ filename = filename.split("/")[-1]
+
+ inline = False
+ if filename.endswith(".cpp"):
+ filename = filename[: -len(".cpp")]
+ elif filename.endswith("-inl.h"):
+ inline = True
+ filename = filename[: -len("-inl.h")]
+ elif filename.endswith(".h"):
+ # This allows the definitions block in MacroAssembler.h to be
+ # style-checked.
+ inline = True
+ filename = filename[: -len(".h")]
+ else:
+ raise Exception("unknown file name", origFilename)
+
+ arch = "generic"
+ for suffix in file_suffixes:
+ if filename == "MacroAssembler-" + suffix:
+ arch = suffix
+ break
+
+ return {"inline": inline, "arch": arch.replace("-", "_")}
+
+
+def get_macroassembler_definitions(filename):
+ try:
+ fileAnnot = get_file_annotation(filename)
+ except Exception:
+ return []
+
+ style_section = False
+ lines = ""
+ signatures = []
+ with open(filename, encoding="utf-8") as f:
+ for line in f:
+ if "//{{{ check_macroassembler_style" in line:
+ if style_section:
+ raise "check_macroassembler_style section already opened."
+ style_section = True
+ braces_depth = 0
+ elif "//}}} check_macroassembler_style" in line:
+ style_section = False
+ if not style_section:
+ continue
+
+ # Ignore preprocessor directives.
+ if line.startswith("#"):
+ continue
+
+ # Remove comments from the processed line.
+ line = re.sub(r"//.*", "", line)
+
+ # Locate and count curly braces.
+ open_curly_brace = line.find("{")
+ was_braces_depth = braces_depth
+ braces_depth = braces_depth + line.count("{") - line.count("}")
+
+ # Raise an error if the check_macroassembler_style macro is used
+ # across namespaces / classes scopes.
+ if braces_depth < 0:
+ raise "check_macroassembler_style annotations are not well scoped."
+
+ # If the current line contains an opening curly brace, check if
+ # this line combines with the previous one can be identified as a
+ # MacroAssembler function signature.
+ if open_curly_brace != -1 and was_braces_depth == 0:
+ lines = lines + line[:open_curly_brace]
+ if "MacroAssembler::" in lines:
+ signatures.extend(get_normalized_signatures(lines, fileAnnot))
+ lines = ""
+ continue
+
+ # We do not aggregate any lines if we are scanning lines which are
+ # in-between a set of curly braces.
+ if braces_depth > 0:
+ continue
+ if was_braces_depth != 0:
+ line = line[line.rfind("}") + 1 :]
+
+ # This logic is used to remove template instantiation, static
+ # variable definitions and function declaration from the next
+ # function definition.
+ last_semi_colon = line.rfind(";")
+ if last_semi_colon != -1:
+ lines = ""
+ line = line[last_semi_colon + 1 :]
+
+ # Aggregate lines of non-braced text, which corresponds to the space
+ # where we are expecting to find function definitions.
+ lines = lines + line
+
+ return signatures
+
+
+def get_macroassembler_declaration(filename):
+ style_section = False
+ lines = ""
+ signatures = []
+ with open(filename, encoding="utf-8") as f:
+ for line in f:
+ if "//{{{ check_macroassembler_decl_style" in line:
+ style_section = True
+ elif "//}}} check_macroassembler_decl_style" in line:
+ style_section = False
+ if not style_section:
+ continue
+
+ # Ignore preprocessor directives.
+ if line.startswith("#"):
+ continue
+
+ line = re.sub(r"//.*", "", line)
+ if len(line.strip()) == 0 or "public:" in line or "private:" in line:
+ lines = ""
+ continue
+
+ lines = lines + line
+
+ # Continue until we have a complete declaration
+ if ";" not in lines:
+ continue
+
+ # Skip member declarations: which are lines ending with a
+ # semi-colon without any list of arguments.
+ if ")" not in lines:
+ lines = ""
+ continue
+
+ signatures.extend(get_normalized_signatures(lines))
+ lines = ""
+
+ return signatures
+
+
+def append_signatures(d, sigs):
+ for s in sigs:
+ if s["sig"] not in d:
+ d[s["sig"]] = []
+ d[s["sig"]].append(s["arch"])
+ return d
+
+
+def generate_file_content(signatures):
+ output = []
+ for s in sorted(signatures.keys()):
+ archs = set(sorted(signatures[s]))
+ archs -= all_unsupported_architectures_names
+ if len(archs.symmetric_difference(architecture_independent)) == 0:
+ output.append(s + ";\n")
+ if s.startswith("inline"):
+ # TODO, bug 1432600: This is mistaken for OOL_IN_HEADER
+ # functions. (Such annotation is already removed by the time
+ # this function sees the signature here.)
+ output.append(" is defined in MacroAssembler-inl.h\n")
+ else:
+ output.append(" is defined in MacroAssembler.cpp\n")
+ else:
+ if len(archs.symmetric_difference(all_architecture_names)) == 0:
+ output.append(s + " PER_ARCH;\n")
+ elif len(archs.symmetric_difference(all_shared_architecture_names)) == 0:
+ output.append(s + " PER_SHARED_ARCH;\n")
+ else:
+ output.append(s + " DEFINED_ON(" + ", ".join(sorted(archs)) + ");\n")
+ for a in sorted(archs):
+ a = a.replace("_", "-")
+ masm = "%s/MacroAssembler-%s" % (a, a)
+ if s.startswith("inline"):
+ output.append(" is defined in %s-inl.h\n" % masm)
+ else:
+ output.append(" is defined in %s.cpp\n" % masm)
+ return output
+
+
+def check_style():
+ # We read from the header file the signature of each function.
+ decls = dict() # type: dict(signature => ['x86', 'x64'])
+
+ # We infer from each file the signature of each MacroAssembler function.
+ defs = dict() # type: dict(signature => ['x86', 'x64'])
+
+ root_dir = os.path.join("js", "src", "jit")
+ for dirpath, dirnames, filenames in os.walk(root_dir):
+ for filename in filenames:
+ if "MacroAssembler" not in filename:
+ continue
+
+ filepath = os.path.join(dirpath, filename).replace("\\", "/")
+
+ if filepath.endswith("MacroAssembler.h"):
+ decls = append_signatures(
+ decls, get_macroassembler_declaration(filepath)
+ )
+ defs = append_signatures(defs, get_macroassembler_definitions(filepath))
+
+ if not decls or not defs:
+ raise Exception("Did not find any definitions or declarations")
+
+ # Compare declarations and definitions output.
+ difflines = difflib.unified_diff(
+ generate_file_content(decls),
+ generate_file_content(defs),
+ fromfile="check_macroassembler_style.py declared syntax",
+ tofile="check_macroassembler_style.py found definitions",
+ )
+ ok = True
+ for diffline in difflines:
+ ok = False
+ print(diffline, end="")
+ return ok
+
+
+def main():
+ ok = check_style()
+
+ if ok:
+ print("TEST-PASS | check_macroassembler_style.py | ok")
+ else:
+ print(
+ "TEST-UNEXPECTED-FAIL | check_macroassembler_style.py | actual output does not match expected output; diff is above" # noqa: E501
+ )
+
+ sys.exit(0 if ok else 1)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/config/check_source_count.py b/config/check_source_count.py
new file mode 100755
index 0000000000..a0a3f2c6d4
--- /dev/null
+++ b/config/check_source_count.py
@@ -0,0 +1,63 @@
+#!/usr/bin/env 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/.
+
+
+# Usage: check_source_count.py SEARCH_TERM COUNT ERROR_LOCATION REPLACEMENT [FILES...]
+# Checks that FILES contains exactly COUNT matches of SEARCH_TERM. If it does
+# not, an error message is printed, quoting ERROR_LOCATION, which should
+# probably be the filename and line number of the erroneous call to
+# check_source_count.py.
+import re
+import sys
+
+search_string = sys.argv[1]
+expected_count = int(sys.argv[2])
+error_location = sys.argv[3]
+replacement = sys.argv[4]
+files = sys.argv[5:]
+
+details = {}
+
+count = 0
+for f in files:
+ text = file(f).read()
+ match = re.findall(search_string, text)
+ if match:
+ num = len(match)
+ count += num
+ details[f] = num
+
+if count == expected_count:
+ print(
+ "TEST-PASS | check_source_count.py {0} | {1}".format(
+ search_string, expected_count
+ )
+ )
+
+else:
+ print(
+ "TEST-UNEXPECTED-FAIL | check_source_count.py {0} | ".format(search_string),
+ end="",
+ )
+ if count < expected_count:
+ print(
+ "There are fewer occurrences of /{0}/ than expected. "
+ "This may mean that you have removed some, but forgotten to "
+ "account for it {1}.".format(search_string, error_location)
+ )
+ else:
+ print(
+ "There are more occurrences of /{0}/ than expected. We're trying "
+ "to prevent an increase in the number of {1}'s, using {2} if "
+ "possible. If it is unavoidable, you should update the expected "
+ "count {3}.".format(
+ search_string, search_string, replacement, error_location
+ )
+ )
+
+ print("Expected: {0}; found: {1}".format(expected_count, count))
+ for k in sorted(details):
+ print("Found {0} occurences in {1}".format(details[k], k))
+ sys.exit(-1)
diff --git a/config/check_spidermonkey_style.py b/config/check_spidermonkey_style.py
new file mode 100644
index 0000000000..1bb02888d6
--- /dev/null
+++ b/config/check_spidermonkey_style.py
@@ -0,0 +1,899 @@
+# vim: set ts=8 sts=4 et sw=4 tw=99:
+# 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/.
+
+# ----------------------------------------------------------------------------
+# This script checks various aspects of SpiderMonkey code style. The current checks are as
+# follows.
+#
+# We check the following things in headers.
+#
+# - No cyclic dependencies.
+#
+# - No normal header should #include a inlines.h/-inl.h file.
+#
+# - #ifndef wrappers should have the right form. (XXX: not yet implemented)
+# - Every header file should have one.
+# - The guard name used should be appropriate for the filename.
+#
+# We check the following things in all files.
+#
+# - #includes should have full paths, e.g. "jit/Ion.h", not "Ion.h".
+#
+# - #includes should use the appropriate form for system headers (<...>) and
+# local headers ("...").
+#
+# - #includes should be ordered correctly.
+# - Each one should be in the correct section.
+# - Alphabetical order should be used within sections.
+# - Sections should be in the right order.
+# Note that the presence of #if/#endif blocks complicates things, to the
+# point that it's not always clear where a conditionally-compiled #include
+# statement should go, even to a human. Therefore, we check the #include
+# statements within each #if/#endif block (including nested ones) in
+# isolation, but don't try to do any order checking between such blocks.
+# ----------------------------------------------------------------------------
+
+import difflib
+import os
+import re
+import sys
+
+# We don't bother checking files in these directories, because they're (a) auxiliary or (b)
+# imported code that doesn't follow our coding style.
+ignored_js_src_dirs = [
+ "js/src/config/", # auxiliary stuff
+ "js/src/ctypes/libffi/", # imported code
+ "js/src/devtools/", # auxiliary stuff
+ "js/src/editline/", # imported code
+ "js/src/gdb/", # auxiliary stuff
+ "js/src/vtune/", # imported code
+ "js/src/zydis/", # imported code
+]
+
+# We ignore #includes of these files, because they don't follow the usual rules.
+included_inclnames_to_ignore = set(
+ [
+ "ffi.h", # generated in ctypes/libffi/
+ "devtools/Instruments.h", # we ignore devtools/ in general
+ "double-conversion/double-conversion.h", # strange MFBT case
+ "javascript-trace.h", # generated in $OBJDIR if HAVE_DTRACE is defined
+ "frontend/ReservedWordsGenerated.h", # generated in $OBJDIR
+ "frontend/smoosh_generated.h", # generated in $OBJDIR
+ "gc/StatsPhasesGenerated.h", # generated in $OBJDIR
+ "gc/StatsPhasesGenerated.inc", # generated in $OBJDIR
+ "jit/ABIFunctionTypeGenerated.h", # generated in $OBJDIR"
+ "jit/AtomicOperationsGenerated.h", # generated in $OBJDIR
+ "jit/CacheIROpsGenerated.h", # generated in $OBJDIR
+ "jit/LIROpsGenerated.h", # generated in $OBJDIR
+ "jit/MIROpsGenerated.h", # generated in $OBJDIR
+ "js/PrefsGenerated.h", # generated in $OBJDIR
+ "js/ProfilingCategoryList.h", # comes from mozglue/baseprofiler
+ "mozilla/glue/Debug.h", # comes from mozglue/misc, shadowed by <mozilla/Debug.h>
+ "jscustomallocator.h", # provided by embedders; allowed to be missing
+ "js-config.h", # generated in $OBJDIR
+ "fdlibm.h", # fdlibm
+ "FuzzerDefs.h", # included without a path
+ "FuzzingInterface.h", # included without a path
+ "ICU4XGraphemeClusterSegmenter.h", # ICU4X
+ "ICU4XSentenceSegmenter.h", # ICU4X
+ "ICU4XWordSegmenter.h", # ICU4X
+ "mozmemory.h", # included without a path
+ "pratom.h", # NSPR
+ "prcvar.h", # NSPR
+ "prerror.h", # NSPR
+ "prinit.h", # NSPR
+ "prio.h", # NSPR
+ "private/pprio.h", # NSPR
+ "prlink.h", # NSPR
+ "prlock.h", # NSPR
+ "prprf.h", # NSPR
+ "prthread.h", # NSPR
+ "prtypes.h", # NSPR
+ "selfhosted.out.h", # generated in $OBJDIR
+ "shellmoduleloader.out.h", # generated in $OBJDIR
+ "unicode/locid.h", # ICU
+ "unicode/uchar.h", # ICU
+ "unicode/uniset.h", # ICU
+ "unicode/unistr.h", # ICU
+ "unicode/utypes.h", # ICU
+ "vtune/VTuneWrapper.h", # VTune
+ "wasm/WasmBuiltinModuleGenerated.h", # generated in $OBJDIR"
+ "zydis/ZydisAPI.h", # Zydis
+ ]
+)
+
+deprecated_inclnames = {
+ "mozilla/Unused.h": "Use [[nodiscard]] and (void)expr casts instead.",
+}
+
+# JSAPI functions should be included through headers from js/public instead of
+# using the old, catch-all jsapi.h file.
+deprecated_inclnames_in_header = {
+ "jsapi.h": "Prefer including headers from js/public.",
+}
+
+# Temporary exclusions for files which still need to include jsapi.h.
+deprecated_inclnames_in_header_excludes = {
+ "js/src/vm/Compartment-inl.h", # for JS::InformalValueTypeName
+ "js/src/jsapi-tests/tests.h", # for JS_ValueToSource
+}
+
+# These files have additional constraints on where they are #included, so we
+# ignore #includes of them when checking #include ordering.
+oddly_ordered_inclnames = set(
+ [
+ "ctypes/typedefs.h", # Included multiple times in the body of ctypes/CTypes.h
+ # Included in the body of frontend/TokenStream.h
+ "frontend/ReservedWordsGenerated.h",
+ "gc/StatsPhasesGenerated.h", # Included in the body of gc/Statistics.h
+ "gc/StatsPhasesGenerated.inc", # Included in the body of gc/Statistics.cpp
+ "psapi.h", # Must be included after "util/WindowsWrapper.h" on Windows
+ "machine/endian.h", # Must be included after <sys/types.h> on BSD
+ "process.h", # Windows-specific
+ "winbase.h", # Must precede other system headers(?)
+ "windef.h", # Must precede other system headers(?)
+ "windows.h", # Must precede other system headers(?)
+ ]
+)
+
+# The files in tests/style/ contain code that fails this checking in various
+# ways. Here is the output we expect. If the actual output differs from
+# this, one of the following must have happened.
+# - New SpiderMonkey code violates one of the checked rules.
+# - The tests/style/ files have changed without expected_output being changed
+# accordingly.
+# - This script has been broken somehow.
+#
+expected_output = """\
+js/src/tests/style/BadIncludes.h:3: error:
+ the file includes itself
+
+js/src/tests/style/BadIncludes.h:6: error:
+ "BadIncludes2.h" is included using the wrong path;
+ did you forget a prefix, or is the file not yet committed?
+
+js/src/tests/style/BadIncludes.h:8: error:
+ <tests/style/BadIncludes2.h> should be included using
+ the #include "..." form
+
+js/src/tests/style/BadIncludes.h:10: error:
+ "stdio.h" is included using the wrong path;
+ did you forget a prefix, or is the file not yet committed?
+
+js/src/tests/style/BadIncludes.h:12: error:
+ "mozilla/Unused.h" is deprecated: Use [[nodiscard]] and (void)expr casts instead.
+
+js/src/tests/style/BadIncludes2.h:1: error:
+ vanilla header includes an inline-header file "tests/style/BadIncludes2-inl.h"
+
+js/src/tests/style/BadIncludesOrder-inl.h:5:6: error:
+ "vm/JSScript-inl.h" should be included after "vm/Interpreter-inl.h"
+
+js/src/tests/style/BadIncludesOrder-inl.h:6:7: error:
+ "vm/Interpreter-inl.h" should be included after "js/Value.h"
+
+js/src/tests/style/BadIncludesOrder-inl.h:7:8: error:
+ "js/Value.h" should be included after "ds/LifoAlloc.h"
+
+js/src/tests/style/BadIncludesOrder-inl.h:9: error:
+ "jsapi.h" is deprecated: Prefer including headers from js/public.
+
+js/src/tests/style/BadIncludesOrder-inl.h:8:9: error:
+ "ds/LifoAlloc.h" should be included after "jsapi.h"
+
+js/src/tests/style/BadIncludesOrder-inl.h:9:10: error:
+ "jsapi.h" should be included after <stdio.h>
+
+js/src/tests/style/BadIncludesOrder-inl.h:10:11: error:
+ <stdio.h> should be included after "mozilla/HashFunctions.h"
+
+js/src/tests/style/BadIncludesOrder-inl.h:20: error:
+ "jsapi.h" is deprecated: Prefer including headers from js/public.
+
+js/src/tests/style/BadIncludesOrder-inl.h:28:29: error:
+ "vm/JSScript.h" should be included after "vm/JSFunction.h"
+
+(multiple files): error:
+ header files form one or more cycles
+
+ tests/style/HeaderCycleA1.h
+ -> tests/style/HeaderCycleA2.h
+ -> tests/style/HeaderCycleA3.h
+ -> tests/style/HeaderCycleA1.h
+
+ tests/style/HeaderCycleB1-inl.h
+ -> tests/style/HeaderCycleB2-inl.h
+ -> tests/style/HeaderCycleB3-inl.h
+ -> tests/style/HeaderCycleB4-inl.h
+ -> tests/style/HeaderCycleB1-inl.h
+ -> tests/style/jsheadercycleB5inlines.h
+ -> tests/style/HeaderCycleB1-inl.h
+ -> tests/style/HeaderCycleB4-inl.h
+
+""".splitlines(
+ True
+)
+
+actual_output = []
+
+
+def out(*lines):
+ for line in lines:
+ actual_output.append(line + "\n")
+
+
+def error(filename, linenum, *lines):
+ location = filename
+ if linenum is not None:
+ location += ":" + str(linenum)
+ out(location + ": error:")
+ for line in lines:
+ out(" " + line)
+ out("")
+
+
+class FileKind(object):
+ C = 1
+ CPP = 2
+ INL_H = 3
+ H = 4
+ TBL = 5
+ MSG = 6
+
+ @staticmethod
+ def get(filename):
+ if filename.endswith(".c"):
+ return FileKind.C
+
+ if filename.endswith(".cpp"):
+ return FileKind.CPP
+
+ if filename.endswith(("inlines.h", "-inl.h")):
+ return FileKind.INL_H
+
+ if filename.endswith(".h"):
+ return FileKind.H
+
+ if filename.endswith(".tbl"):
+ return FileKind.TBL
+
+ if filename.endswith(".msg"):
+ return FileKind.MSG
+
+ error(filename, None, "unknown file kind")
+
+
+def check_style(enable_fixup):
+ # We deal with two kinds of name.
+ # - A "filename" is a full path to a file from the repository root.
+ # - An "inclname" is how a file is referred to in a #include statement.
+ #
+ # Examples (filename -> inclname)
+ # - "mfbt/Attributes.h" -> "mozilla/Attributes.h"
+ # - "mozglue/misc/TimeStamp.h -> "mozilla/TimeStamp.h"
+ # - "memory/mozalloc/mozalloc.h -> "mozilla/mozalloc.h"
+ # - "js/public/Vector.h" -> "js/Vector.h"
+ # - "js/src/vm/String.h" -> "vm/String.h"
+
+ non_js_dirnames = (
+ "mfbt/",
+ "memory/mozalloc/",
+ "mozglue/",
+ "intl/components/",
+ ) # type: tuple(str)
+ non_js_inclnames = set() # type: set(inclname)
+ js_names = dict() # type: dict(filename, inclname)
+
+ # Process files in js/src.
+ js_src_root = os.path.join("js", "src")
+ for dirpath, dirnames, filenames in os.walk(js_src_root):
+ if dirpath == js_src_root:
+ # Skip any subdirectories that contain a config.status file
+ # (likely objdirs).
+ builddirs = []
+ for dirname in dirnames:
+ path = os.path.join(dirpath, dirname, "config.status")
+ if os.path.isfile(path):
+ builddirs.append(dirname)
+ for dirname in builddirs:
+ dirnames.remove(dirname)
+ for filename in filenames:
+ filepath = os.path.join(dirpath, filename).replace("\\", "/")
+ if not filepath.startswith(
+ tuple(ignored_js_src_dirs)
+ ) and filepath.endswith((".c", ".cpp", ".h", ".tbl", ".msg")):
+ inclname = filepath[len("js/src/") :]
+ js_names[filepath] = inclname
+
+ # Look for header files in directories in non_js_dirnames.
+ for non_js_dir in non_js_dirnames:
+ for dirpath, dirnames, filenames in os.walk(non_js_dir):
+ for filename in filenames:
+ if filename.endswith(".h"):
+ inclname = "mozilla/" + filename
+ if non_js_dir == "intl/components/":
+ inclname = "mozilla/intl/" + filename
+ non_js_inclnames.add(inclname)
+
+ # Look for header files in js/public.
+ js_public_root = os.path.join("js", "public")
+ for dirpath, dirnames, filenames in os.walk(js_public_root):
+ for filename in filenames:
+ if filename.endswith((".h", ".msg")):
+ filepath = os.path.join(dirpath, filename).replace("\\", "/")
+ inclname = "js/" + filepath[len("js/public/") :]
+ js_names[filepath] = inclname
+
+ all_inclnames = non_js_inclnames | set(js_names.values())
+
+ edges = dict() # type: dict(inclname, set(inclname))
+
+ # We don't care what's inside the MFBT and MOZALLOC files, but because they
+ # are #included from JS files we have to add them to the inclusion graph.
+ for inclname in non_js_inclnames:
+ edges[inclname] = set()
+
+ # Process all the JS files.
+ for filename in sorted(js_names.keys()):
+ inclname = js_names[filename]
+ file_kind = FileKind.get(filename)
+ if (
+ file_kind == FileKind.C
+ or file_kind == FileKind.CPP
+ or file_kind == FileKind.H
+ or file_kind == FileKind.INL_H
+ ):
+ included_h_inclnames = set() # type: set(inclname)
+
+ with open(filename, encoding="utf-8") as f:
+ code = read_file(f)
+
+ if enable_fixup:
+ code = code.sorted(inclname)
+ with open(filename, "w") as f:
+ f.write(code.to_source())
+
+ check_file(
+ filename, inclname, file_kind, code, all_inclnames, included_h_inclnames
+ )
+
+ edges[inclname] = included_h_inclnames
+
+ find_cycles(all_inclnames, edges)
+
+ # Compare expected and actual output.
+ difflines = difflib.unified_diff(
+ expected_output,
+ actual_output,
+ fromfile="check_spidermonkey_style.py expected output",
+ tofile="check_spidermonkey_style.py actual output",
+ )
+ ok = True
+ for diffline in difflines:
+ ok = False
+ print(diffline, end="")
+
+ return ok
+
+
+def module_name(name):
+ """Strip the trailing .cpp, .h, inlines.h or -inl.h from a filename."""
+
+ return (
+ name.replace("inlines.h", "")
+ .replace("-inl.h", "")
+ .replace(".h", "")
+ .replace(".cpp", "")
+ ) # NOQA: E501
+
+
+def is_module_header(enclosing_inclname, header_inclname):
+ """Determine if an included name is the "module header", i.e. should be
+ first in the file."""
+
+ module = module_name(enclosing_inclname)
+
+ # Normal case, for example:
+ # module == "vm/Runtime", header_inclname == "vm/Runtime.h".
+ if module == module_name(header_inclname):
+ return True
+
+ # A public header, for example:
+ #
+ # module == "vm/CharacterEncoding",
+ # header_inclname == "js/CharacterEncoding.h"
+ #
+ # or (for implementation files for js/public/*/*.h headers)
+ #
+ # module == "vm/SourceHook",
+ # header_inclname == "js/experimental/SourceHook.h"
+ m = re.match(r"js\/.*?([^\/]+)\.h", header_inclname)
+ if m is not None and module.endswith("/" + m.group(1)):
+ return True
+
+ return False
+
+
+class Include(object):
+ """Important information for a single #include statement."""
+
+ def __init__(self, include_prefix, inclname, line_suffix, linenum, is_system):
+ self.include_prefix = include_prefix
+ self.line_suffix = line_suffix
+ self.inclname = inclname
+ self.linenum = linenum
+ self.is_system = is_system
+
+ def is_style_relevant(self):
+ # Includes are style-relevant; that is, they're checked by the pairwise
+ # style-checking algorithm in check_file.
+ return True
+
+ def section(self, enclosing_inclname):
+ """Identify which section inclname belongs to.
+
+ The section numbers are as follows.
+ 0. Module header (e.g. jsfoo.h or jsfooinlines.h within jsfoo.cpp)
+ 1. mozilla/Foo.h
+ 2. <foo.h> or <foo>
+ 3. jsfoo.h, prmjtime.h, etc
+ 4. foo/Bar.h
+ 5. jsfooinlines.h
+ 6. foo/Bar-inl.h
+ 7. non-.h, e.g. *.tbl, *.msg (these can be scattered throughout files)
+ """
+
+ if self.is_system:
+ return 2
+
+ if not self.inclname.endswith(".h"):
+ return 7
+
+ # A couple of modules have the .h file in js/ and the .cpp file elsewhere and so need
+ # special handling.
+ if is_module_header(enclosing_inclname, self.inclname):
+ return 0
+
+ if "/" in self.inclname:
+ if self.inclname.startswith("mozilla/"):
+ return 1
+
+ if self.inclname.endswith("-inl.h"):
+ return 6
+
+ return 4
+
+ if self.inclname.endswith("inlines.h"):
+ return 5
+
+ return 3
+
+ def quote(self):
+ if self.is_system:
+ return "<" + self.inclname + ">"
+ else:
+ return '"' + self.inclname + '"'
+
+ def sort_key(self, enclosing_inclname):
+ return (self.section(enclosing_inclname), self.inclname.lower())
+
+ def to_source(self):
+ return self.include_prefix + self.quote() + self.line_suffix + "\n"
+
+
+class CppBlock(object):
+ """C preprocessor block: a whole file or a single #if/#elif/#else block.
+
+ A #if/#endif block is the contents of a #if/#endif (or similar) section.
+ The top-level block, which is not within a #if/#endif pair, is also
+ considered a block.
+
+ Each kid is either an Include (representing a #include), OrdinaryCode, or
+ a nested CppBlock."""
+
+ def __init__(self, start_line=""):
+ self.start = start_line
+ self.end = ""
+ self.kids = []
+
+ def is_style_relevant(self):
+ return True
+
+ def append_ordinary_line(self, line):
+ if len(self.kids) == 0 or not isinstance(self.kids[-1], OrdinaryCode):
+ self.kids.append(OrdinaryCode())
+ self.kids[-1].lines.append(line)
+
+ def style_relevant_kids(self):
+ """Return a list of kids in this block that are style-relevant."""
+ return [kid for kid in self.kids if kid.is_style_relevant()]
+
+ def sorted(self, enclosing_inclname):
+ """Return a hopefully-sorted copy of this block. Implements --fixup.
+
+ When in doubt, this leaves the code unchanged.
+ """
+
+ def pretty_sorted_includes(includes):
+ """Return a new list containing the given includes, in order,
+ with blank lines separating sections."""
+ keys = [inc.sort_key(enclosing_inclname) for inc in includes]
+ if sorted(keys) == keys:
+ return includes # if nothing is out of order, don't touch anything
+
+ output = []
+ current_section = None
+ for (section, _), inc in sorted(zip(keys, includes)):
+ if current_section is not None and section != current_section:
+ output.append(OrdinaryCode(["\n"])) # blank line
+ output.append(inc)
+ current_section = section
+ return output
+
+ def should_try_to_sort(includes):
+ if "tests/style/BadIncludes" in enclosing_inclname:
+ return False # don't straighten the counterexample
+ if any(inc.inclname in oddly_ordered_inclnames for inc in includes):
+ return False # don't sort batches containing odd includes
+ if includes == sorted(
+ includes, key=lambda inc: inc.sort_key(enclosing_inclname)
+ ):
+ return False # it's already sorted, avoid whitespace-only fixups
+ return True
+
+ # The content of the eventual output of this method.
+ output = []
+
+ # The current batch of includes to sort. This list only ever contains Include objects
+ # and whitespace OrdinaryCode objects.
+ batch = []
+
+ def flush_batch():
+ """Sort the contents of `batch` and move it to `output`."""
+
+ assert all(
+ isinstance(item, Include)
+ or (isinstance(item, OrdinaryCode) and "".join(item.lines).isspace())
+ for item in batch
+ )
+
+ # Here we throw away the blank lines.
+ # `pretty_sorted_includes` puts them back.
+ includes = []
+ last_include_index = -1
+ for i, item in enumerate(batch):
+ if isinstance(item, Include):
+ includes.append(item)
+ last_include_index = i
+ cutoff = last_include_index + 1
+
+ if should_try_to_sort(includes):
+ output.extend(pretty_sorted_includes(includes) + batch[cutoff:])
+ else:
+ output.extend(batch)
+ del batch[:]
+
+ for kid in self.kids:
+ if isinstance(kid, CppBlock):
+ flush_batch()
+ output.append(kid.sorted(enclosing_inclname))
+ elif isinstance(kid, Include):
+ batch.append(kid)
+ else:
+ assert isinstance(kid, OrdinaryCode)
+ if kid.to_source().isspace():
+ batch.append(kid)
+ else:
+ flush_batch()
+ output.append(kid)
+ flush_batch()
+
+ result = CppBlock()
+ result.start = self.start
+ result.end = self.end
+ result.kids = output
+ return result
+
+ def to_source(self):
+ return self.start + "".join(kid.to_source() for kid in self.kids) + self.end
+
+
+class OrdinaryCode(object):
+ """A list of lines of code that aren't #include/#if/#else/#endif lines."""
+
+ def __init__(self, lines=None):
+ self.lines = lines if lines is not None else []
+
+ def is_style_relevant(self):
+ return False
+
+ def to_source(self):
+ return "".join(self.lines)
+
+
+# A "snippet" is one of:
+#
+# * Include - representing an #include line
+# * CppBlock - a whole file or #if/#elif/#else block; contains a list of snippets
+# * OrdinaryCode - representing lines of non-#include-relevant code
+
+
+def read_file(f):
+ block_stack = [CppBlock()]
+
+ # Extract the #include statements as a tree of snippets.
+ for linenum, line in enumerate(f, start=1):
+ if line.lstrip().startswith("#"):
+ # Look for a |#include "..."| line.
+ m = re.match(r'(\s*#\s*include\s+)"([^"]*)"(.*)', line)
+ if m is not None:
+ prefix, inclname, suffix = m.groups()
+ block_stack[-1].kids.append(
+ Include(prefix, inclname, suffix, linenum, is_system=False)
+ )
+ continue
+
+ # Look for a |#include <...>| line.
+ m = re.match(r"(\s*#\s*include\s+)<([^>]*)>(.*)", line)
+ if m is not None:
+ prefix, inclname, suffix = m.groups()
+ block_stack[-1].kids.append(
+ Include(prefix, inclname, suffix, linenum, is_system=True)
+ )
+ continue
+
+ # Look for a |#{if,ifdef,ifndef}| line.
+ m = re.match(r"\s*#\s*(if|ifdef|ifndef)\b", line)
+ if m is not None:
+ # Open a new block.
+ new_block = CppBlock(line)
+ block_stack[-1].kids.append(new_block)
+ block_stack.append(new_block)
+ continue
+
+ # Look for a |#{elif,else}| line.
+ m = re.match(r"\s*#\s*(elif|else)\b", line)
+ if m is not None:
+ # Close the current block, and open an adjacent one.
+ block_stack.pop()
+ new_block = CppBlock(line)
+ block_stack[-1].kids.append(new_block)
+ block_stack.append(new_block)
+ continue
+
+ # Look for a |#endif| line.
+ m = re.match(r"\s*#\s*endif\b", line)
+ if m is not None:
+ # Close the current block.
+ block_stack.pop().end = line
+ if len(block_stack) == 0:
+ raise ValueError("#endif without #if at line " + str(linenum))
+ continue
+
+ # Otherwise, we have an ordinary line.
+ block_stack[-1].append_ordinary_line(line)
+
+ if len(block_stack) > 1:
+ raise ValueError("unmatched #if")
+ return block_stack[-1]
+
+
+def check_file(
+ filename, inclname, file_kind, code, all_inclnames, included_h_inclnames
+):
+ def check_include_statement(include):
+ """Check the style of a single #include statement."""
+
+ if include.is_system:
+ # Check it is not a known local file (in which case it's probably a system header).
+ if (
+ include.inclname in included_inclnames_to_ignore
+ or include.inclname in all_inclnames
+ ):
+ error(
+ filename,
+ include.linenum,
+ include.quote() + " should be included using",
+ 'the #include "..." form',
+ )
+
+ else:
+ msg = deprecated_inclnames.get(include.inclname)
+ if msg:
+ error(
+ filename,
+ include.linenum,
+ include.quote() + " is deprecated: " + msg,
+ )
+
+ if file_kind == FileKind.H or file_kind == FileKind.INL_H:
+ msg = deprecated_inclnames_in_header.get(include.inclname)
+ if msg and filename not in deprecated_inclnames_in_header_excludes:
+ error(
+ filename,
+ include.linenum,
+ include.quote() + " is deprecated: " + msg,
+ )
+
+ if include.inclname not in included_inclnames_to_ignore:
+ included_kind = FileKind.get(include.inclname)
+
+ # Check the #include path has the correct form.
+ if include.inclname not in all_inclnames:
+ error(
+ filename,
+ include.linenum,
+ include.quote() + " is included using the wrong path;",
+ "did you forget a prefix, or is the file not yet committed?",
+ )
+
+ # Record inclusions of .h files for cycle detection later.
+ # (Exclude .tbl and .msg files.)
+ elif included_kind == FileKind.H or included_kind == FileKind.INL_H:
+ included_h_inclnames.add(include.inclname)
+
+ # Check a H file doesn't #include an INL_H file.
+ if file_kind == FileKind.H and included_kind == FileKind.INL_H:
+ error(
+ filename,
+ include.linenum,
+ "vanilla header includes an inline-header file "
+ + include.quote(),
+ )
+
+ # Check a file doesn't #include itself. (We do this here because the cycle
+ # detection below doesn't detect this case.)
+ if inclname == include.inclname:
+ error(filename, include.linenum, "the file includes itself")
+
+ def check_includes_order(include1, include2):
+ """Check the ordering of two #include statements."""
+
+ if (
+ include1.inclname in oddly_ordered_inclnames
+ or include2.inclname in oddly_ordered_inclnames
+ ):
+ return
+
+ section1 = include1.section(inclname)
+ section2 = include2.section(inclname)
+ if (section1 > section2) or (
+ (section1 == section2)
+ and (include1.inclname.lower() > include2.inclname.lower())
+ ):
+ error(
+ filename,
+ str(include1.linenum) + ":" + str(include2.linenum),
+ include1.quote() + " should be included after " + include2.quote(),
+ )
+
+ # Check the extracted #include statements, both individually, and the ordering of
+ # adjacent pairs that live in the same block.
+ def pair_traverse(prev, this):
+ if isinstance(this, Include):
+ check_include_statement(this)
+ if isinstance(prev, Include):
+ check_includes_order(prev, this)
+ else:
+ kids = this.style_relevant_kids()
+ for prev2, this2 in zip([None] + kids[0:-1], kids):
+ pair_traverse(prev2, this2)
+
+ pair_traverse(None, code)
+
+
+def find_cycles(all_inclnames, edges):
+ """Find and draw any cycles."""
+
+ SCCs = tarjan(all_inclnames, edges)
+
+ # The various sorted() calls below ensure the output is deterministic.
+
+ def draw_SCC(c):
+ cset = set(c)
+ drawn = set()
+
+ def draw(v, indent):
+ out(" " * indent + ("-> " if indent else " ") + v)
+ if v in drawn:
+ return
+ drawn.add(v)
+ for succ in sorted(edges[v]):
+ if succ in cset:
+ draw(succ, indent + 1)
+
+ draw(sorted(c)[0], 0)
+ out("")
+
+ have_drawn_an_SCC = False
+ for scc in sorted(SCCs):
+ if len(scc) != 1:
+ if not have_drawn_an_SCC:
+ error("(multiple files)", None, "header files form one or more cycles")
+ have_drawn_an_SCC = True
+
+ draw_SCC(scc)
+
+
+# Tarjan's algorithm for finding the strongly connected components (SCCs) of a graph.
+# https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm
+def tarjan(V, E):
+ vertex_index = {}
+ vertex_lowlink = {}
+ index = 0
+ S = []
+ all_SCCs = []
+
+ def strongconnect(v, index):
+ # Set the depth index for v to the smallest unused index
+ vertex_index[v] = index
+ vertex_lowlink[v] = index
+ index += 1
+ S.append(v)
+
+ # Consider successors of v
+ for w in E[v]:
+ if w not in vertex_index:
+ # Successor w has not yet been visited; recurse on it
+ index = strongconnect(w, index)
+ vertex_lowlink[v] = min(vertex_lowlink[v], vertex_lowlink[w])
+ elif w in S:
+ # Successor w is in stack S and hence in the current SCC
+ vertex_lowlink[v] = min(vertex_lowlink[v], vertex_index[w])
+
+ # If v is a root node, pop the stack and generate an SCC
+ if vertex_lowlink[v] == vertex_index[v]:
+ i = S.index(v)
+ scc = S[i:]
+ del S[i:]
+ all_SCCs.append(scc)
+
+ return index
+
+ for v in V:
+ if v not in vertex_index:
+ index = strongconnect(v, index)
+
+ return all_SCCs
+
+
+def main():
+ if sys.argv[1:] == ["--fixup"]:
+ # Sort #include directives in-place. Fixup mode doesn't solve
+ # all possible silliness that the script checks for; it's just a
+ # hack for the common case where renaming a header causes style
+ # errors.
+ fixup = True
+ elif sys.argv[1:] == []:
+ fixup = False
+ else:
+ print(
+ "TEST-UNEXPECTED-FAIL | check_spidermonkey_style.py | unexpected command "
+ "line options: " + repr(sys.argv[1:])
+ )
+ sys.exit(1)
+
+ ok = check_style(fixup)
+
+ if ok:
+ print("TEST-PASS | check_spidermonkey_style.py | ok")
+ else:
+ print(
+ "TEST-UNEXPECTED-FAIL | check_spidermonkey_style.py | "
+ + "actual output does not match expected output; diff is above."
+ )
+ print(
+ "TEST-UNEXPECTED-FAIL | check_spidermonkey_style.py | "
+ + "Hint: If the problem is that you renamed a header, and many #includes "
+ + "are no longer in alphabetical order, commit your work and then try "
+ + "`check_spidermonkey_style.py --fixup`. "
+ + "You need to commit first because --fixup modifies your files in place."
+ )
+
+ sys.exit(0 if ok else 1)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/config/check_vanilla_allocations.py b/config/check_vanilla_allocations.py
new file mode 100644
index 0000000000..928f7cd6a7
--- /dev/null
+++ b/config/check_vanilla_allocations.py
@@ -0,0 +1,296 @@
+# vim: set ts=8 sts=4 et sw=4 tw=79:
+# 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/.
+
+# ----------------------------------------------------------------------------
+# All heap allocations in SpiderMonkey must go through js_malloc, js_calloc,
+# js_realloc, and js_free. This is so that any embedder who uses a custom
+# allocator (by defining JS_USE_CUSTOM_ALLOCATOR) will see all heap allocation
+# go through that custom allocator.
+#
+# Therefore, the presence of any calls to "vanilla" allocation/free functions
+# from within SpiderMonkey itself (e.g. malloc(), free()) is a bug. Calls from
+# within mozglue and non-SpiderMonkey locations are fine; there is a list of
+# exceptions that can be added to as the need arises.
+#
+# This script checks for the presence of such disallowed vanilla
+# allocation/free function in SpiderMonkey when it's built as a library. It
+# relies on |nm| from the GNU binutils, and so only works on Linux, but one
+# platform is good enough to catch almost all violations.
+#
+# This checking is only 100% reliable in a JS_USE_CUSTOM_ALLOCATOR build in
+# which the default definitions of js_malloc et al (in Utility.h) -- which call
+# malloc et al -- are replaced with empty definitions. This is because the
+# presence and possible inlining of the default js_malloc et al can cause
+# malloc/calloc/realloc/free calls show up in unpredictable places.
+#
+# Unfortunately, that configuration cannot be tested on Mozilla's standard
+# testing infrastructure. Instead, by default this script only tests that none
+# of the other vanilla allocation/free functions (operator new, memalign, etc)
+# are present. If given the --aggressive flag, it will also check for
+# malloc/calloc/realloc/free.
+#
+# Note: We don't check for |operator delete| and |operator delete[]|. These
+# can be present somehow due to virtual destructors, but this is not too
+# because vanilla delete/delete[] calls don't make sense without corresponding
+# vanilla new/new[] calls, and any explicit calls will be caught by Valgrind's
+# mismatched alloc/free checking.
+# ----------------------------------------------------------------------------
+
+import argparse
+import re
+import subprocess
+import sys
+from collections import defaultdict
+
+import buildconfig
+
+# The obvious way to implement this script is to search for occurrences of
+# malloc et al, succeed if none are found, and fail is some are found.
+# However, "none are found" does not necessarily mean "none are present" --
+# this script could be buggy. (Or the output format of |nm| might change in
+# the future.)
+#
+# So util/Utility.cpp deliberately contains a (never-called) function that
+# contains a single use of all the vanilla allocation/free functions. And this
+# script fails if it (a) finds uses of those functions in files other than
+# util/Utility.cpp, *or* (b) fails to find them in util/Utility.cpp.
+
+# Tracks overall success of the test.
+has_failed = False
+
+
+def fail(msg):
+ print("TEST-UNEXPECTED-FAIL | check_vanilla_allocations.py |", msg)
+ global has_failed
+ has_failed = True
+
+
+def main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ "--aggressive",
+ action="store_true",
+ help="also check for malloc, calloc, realloc and free",
+ )
+ parser.add_argument("file", type=str, help="name of the file to check")
+ args = parser.parse_args()
+
+ # Run |nm|. Options:
+ # -C: demangle symbol names
+ # -A: show an object filename for each undefined symbol
+ nm = buildconfig.substs.get("NM") or "nm"
+ cmd = [nm, "-C", "-A", args.file]
+ lines = subprocess.check_output(
+ cmd, universal_newlines=True, stderr=subprocess.PIPE
+ ).split("\n")
+
+ # alloc_fns contains all the vanilla allocation/free functions that we look
+ # for. Regexp chars are escaped appropriately.
+
+ operator_news = [
+ # Matches |operator new(unsigned T)|, where |T| is |int| or |long|.
+ r"operator new(unsigned",
+ # Matches |operator new[](unsigned T)|, where |T| is |int| or |long|.
+ r"operator new[](unsigned",
+ ]
+
+ # operator new may end up inlined and replaced with moz_xmalloc.
+ inlined_operator_news = [
+ r"moz_xmalloc",
+ ]
+
+ alloc_fns = (
+ operator_news
+ + inlined_operator_news
+ + [
+ r"memalign",
+ # These three aren't available on all Linux configurations.
+ # r'posix_memalign',
+ # r'aligned_alloc',
+ # r'valloc',
+ ]
+ )
+
+ if args.aggressive:
+ alloc_fns += [r"malloc", r"calloc", r"realloc", r"free", r"strdup"]
+
+ # This is like alloc_fns, but regexp chars are not escaped.
+ alloc_fns_escaped = [re.escape(fn) for fn in alloc_fns]
+
+ # This regexp matches the relevant lines in the output of |nm|, which look
+ # like the following.
+ #
+ # js/src/libjs_static.a:Utility.o: U malloc
+ # js/src/libjs_static.a:Utility.o: 00000000000007e0 T js::SetSourceOptions(...)
+ #
+ # It may also, in LTO builds, look like
+ # js/src/libjs_static.a:Utility.o: ---------------- T js::SetSourceOptions(...)
+ #
+ nm_line_re = re.compile(r"([^:/ ]+):\s*(?:[0-9a-fA-F]*|-*)\s+([TUw]) (.*)")
+ alloc_fns_re = re.compile(r"|".join(alloc_fns_escaped))
+
+ # This tracks which allocation/free functions have been seen.
+ functions = defaultdict(set)
+ files = defaultdict(int)
+
+ # Files to ignore allocation/free functions from.
+ ignored_files = [
+ # Ignore implicit call to operator new in std::condition_variable_any.
+ #
+ # From intl/icu/source/common/umutex.h:
+ # On Linux, the default constructor of std::condition_variable_any
+ # produces an in-line reference to global operator new(), [...].
+ "umutex.o",
+ # Ignore allocations from decimal conversion functions inside mozglue.
+ "Decimal.o",
+ # Ignore use of std::string in regexp AST debug output.
+ "regexp-ast.o",
+ # mozglue/misc/Debug.cpp contains a call to `printf_stderr("%s", aStr.str().c_str())`
+ # where `aStr` is a `std::stringstream`. In inlined opt builds, this calls
+ # `operator new()` and `operator delete` for a temporary.
+ "Debug.o",
+ ]
+ all_ignored_files = set((f, 1) for f in ignored_files)
+
+ # Would it be helpful to emit detailed line number information after a failure?
+ emit_line_info = False
+
+ prev_filename = None
+ for line in lines:
+ m = nm_line_re.search(line)
+ if m is None:
+ continue
+
+ filename, symtype, fn = m.groups()
+ if prev_filename != filename:
+ # When the same filename appears multiple times, separated by other
+ # file names, this denotes a different file. Thankfully, we can more
+ # or less safely assume that dir1/Foo.o and dir2/Foo.o are not going
+ # to be next to each other.
+ files[filename] += 1
+ prev_filename = filename
+
+ # The stdc++compat library has an implicit call to operator new in
+ # thread::_M_start_thread.
+ if "stdc++compat" in filename:
+ continue
+
+ # The memory allocator code contains calls to memalign. These are ok, so
+ # we whitelist them.
+ if "_memory_" in filename:
+ continue
+
+ # Ignore the fuzzing code imported from m-c
+ if "Fuzzer" in filename:
+ continue
+
+ # Ignore the profiling pseudo-stack, since it needs to run even when
+ # SpiderMonkey's allocator isn't initialized.
+ if "ProfilingStack" in filename:
+ continue
+
+ if symtype == "T":
+ # We can't match intl/components files by file name because in
+ # non-unified builds they overlap with files in js/src.
+ # So we check symbols they define, and consider files with symbols
+ # in the mozilla::intl namespace to be those.
+ if fn.startswith("mozilla::intl::"):
+ all_ignored_files.add((filename, files[filename]))
+ else:
+ m = alloc_fns_re.match(fn)
+ if m:
+ functions[(filename, files[filename])].add(m.group(0))
+
+ util_Utility_cpp = functions.pop(("Utility.o", 1))
+ if ("Utility.o", 2) in functions:
+ fail("There should be only one Utility.o file")
+
+ for f, n in all_ignored_files:
+ functions.pop((f, n), None)
+ if f in ignored_files and (f, 2) in functions:
+ fail(f"There should be only one {f} file")
+
+ for filename, n in sorted(functions):
+ for fn in functions[(filename, n)]:
+ # An allocation is present in a non-special file. Fail!
+ fail("'" + fn + "' present in " + filename)
+ # Try to give more precise information about the offending code.
+ emit_line_info = True
+
+ # Check that all functions we expect are used in util/Utility.cpp. (This
+ # will fail if the function-detection code breaks at any point.)
+ # operator new and its inlined equivalent are mutually exclusive.
+ has_operator_news = any(fn in operator_news for fn in util_Utility_cpp)
+ has_inlined_operator_news = any(
+ fn in inlined_operator_news for fn in util_Utility_cpp
+ )
+ if has_operator_news and has_inlined_operator_news:
+ fail(
+ "Both operator new and moz_xmalloc aren't expected in util/Utility.cpp at the same time"
+ )
+
+ for fn in alloc_fns:
+ if fn not in util_Utility_cpp:
+ if (
+ (fn in operator_news and not has_inlined_operator_news)
+ or (fn in inlined_operator_news and not has_operator_news)
+ or (fn not in operator_news and fn not in inlined_operator_news)
+ ):
+ fail("'" + fn + "' isn't used as expected in util/Utility.cpp")
+ else:
+ util_Utility_cpp.remove(fn)
+
+ # This should never happen, but check just in case.
+ if util_Utility_cpp:
+ fail(
+ "unexpected allocation fns used in util/Utility.cpp: "
+ + ", ".join(util_Utility_cpp)
+ )
+
+ # If we found any improper references to allocation functions, try to use
+ # DWARF debug info to get more accurate line number information about the
+ # bad calls. This is a lot slower than 'nm -A', and it is not always
+ # precise when building with --enable-optimized.
+ if emit_line_info:
+ print("check_vanilla_allocations.py: Source lines with allocation calls:")
+ print(
+ "check_vanilla_allocations.py: Accurate in unoptimized builds; "
+ "util/Utility.cpp expected."
+ )
+
+ # Run |nm|. Options:
+ # -u: show only undefined symbols
+ # -C: demangle symbol names
+ # -l: show line number information for each undefined symbol
+ cmd = ["nm", "-u", "-C", "-l", args.file]
+ lines = subprocess.check_output(
+ cmd, universal_newlines=True, stderr=subprocess.PIPE
+ ).split("\n")
+
+ # This regexp matches the relevant lines in the output of |nm -l|,
+ # which look like the following.
+ #
+ # U malloc util/Utility.cpp:117
+ #
+ alloc_lines_re = (
+ r"[Uw] ((" + r"|".join(alloc_fns_escaped) + r").*)\s+(\S+:\d+)$"
+ )
+
+ for line in lines:
+ m = re.search(alloc_lines_re, line)
+ if m:
+ print(
+ "check_vanilla_allocations.py:", m.group(1), "called at", m.group(3)
+ )
+
+ if has_failed:
+ sys.exit(1)
+
+ print("TEST-PASS | check_vanilla_allocations.py | ok")
+ sys.exit(0)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/config/config.mk b/config/config.mk
new file mode 100644
index 0000000000..a86733519e
--- /dev/null
+++ b/config/config.mk
@@ -0,0 +1,408 @@
+#
+# 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/.
+
+#
+# config.mk
+#
+# Determines the platform and builds the macros needed to load the
+# appropriate platform-specific .mk file, then defines all (most?)
+# of the generic macros.
+#
+
+varize = $(subst -,_,$(subst a,A,$(subst b,B,$(subst c,C,$(subst d,D,$(subst e,E,$(subst f,F,$(subst g,G,$(subst h,H,$(subst i,I,$(subst j,J,$(subst k,K,$(subst l,L,$(subst m,M,$(subst n,N,$(subst o,O,$(subst p,P,$(subst q,Q,$(subst r,R,$(subst s,S,$(subst t,T,$(subst u,U,$(subst v,V,$(subst w,W,$(subst x,X,$(subst y,Y,$(subst z,Z,$1)))))))))))))))))))))))))))
+
+# Define an include-at-most-once flag
+ifdef INCLUDED_CONFIG_MK
+$(error Do not include config.mk twice!)
+endif
+INCLUDED_CONFIG_MK = 1
+
+EXIT_ON_ERROR = set -e; # Shell loops continue past errors without this.
+
+ifndef topsrcdir
+topsrcdir = $(DEPTH)
+endif
+
+ifndef INCLUDED_AUTOCONF_MK
+include $(DEPTH)/config/autoconf.mk
+endif
+
+-include $(DEPTH)/.mozconfig.mk
+
+# MDDEPDIR is the subdirectory where dependency files are stored
+MDDEPDIR := .deps
+
+ifndef EXTERNALLY_MANAGED_MAKE_FILE
+# Import the automatically generated backend file. If this file doesn't exist,
+# the backend hasn't been properly configured. We want this to be a fatal
+# error, hence not using "-include".
+ifndef STANDALONE_MAKEFILE
+GLOBAL_DEPS += backend.mk
+include backend.mk
+
+# Add e.g. `export:: $(EXPORT_TARGETS)` rules. The *_TARGETS variables are defined
+# in backend.mk.
+$(foreach tier,$(RUNNABLE_TIERS),$(eval $(if $(filter .,$(DEPTH)),recurse_$(tier):,$(tier)::) $($(call varize,$(tier))_TARGETS)))
+endif
+
+endif
+
+space = $(NULL) $(NULL)
+
+# Include defs.mk files that can be found in $(srcdir)/$(DEPTH),
+# $(srcdir)/$(DEPTH-1), $(srcdir)/$(DEPTH-2), etc., and $(srcdir)
+# where $(DEPTH-1) is one level less of depth, $(DEPTH-2), two, etc.
+# i.e. for DEPTH=../../.., DEPTH-1 is ../.. and DEPTH-2 is ..
+# These defs.mk files are used to define variables in a directory
+# and all its subdirectories, recursively.
+__depth := $(subst /, ,$(DEPTH))
+ifeq (.,$(__depth))
+__depth :=
+endif
+$(foreach __d,$(__depth) .,$(eval __depth = $(wordlist 2,$(words $(__depth)),$(__depth))$(eval -include $(subst $(space),/,$(strip $(srcdir) $(__depth) defs.mk)))))
+
+COMMA = ,
+
+# Sanity check some variables
+CHECK_VARS := \
+ XPI_NAME \
+ LIBRARY_NAME \
+ MODULE \
+ DEPTH \
+ XPI_PKGNAME \
+ SHARED_LIBRARY_NAME \
+ SONAME \
+ STATIC_LIBRARY_NAME \
+ $(NULL)
+
+# checks for internal spaces or trailing spaces in the variable
+# named by $x
+check-variable = $(if $(filter-out 0 1,$(words $($(x))z)),$(error Spaces are not allowed in $(x)))
+
+$(foreach x,$(CHECK_VARS),$(check-variable))
+
+ifndef INCLUDED_FUNCTIONS_MK
+include $(MOZILLA_DIR)/config/makefiles/functions.mk
+endif
+
+RM = rm -f
+
+# FINAL_TARGET specifies the location into which we copy end-user-shipped
+# build products (typelibs, components, chrome). It may already be specified by
+# a moz.build file.
+#
+# If XPI_NAME is set, the files will be shipped to $(DIST)/xpi-stage/$(XPI_NAME)
+# instead of $(DIST)/bin. In both cases, if DIST_SUBDIR is set, the files will be
+# shipped to a $(DIST_SUBDIR) subdirectory.
+FINAL_TARGET ?= $(if $(XPI_NAME),$(DIST)/xpi-stage/$(XPI_NAME),$(DIST)/bin)$(DIST_SUBDIR:%=/%)
+# Override the stored value for the check to make sure that the variable is not
+# redefined in the Makefile.in value.
+FINAL_TARGET_FROZEN := '$(FINAL_TARGET)'
+
+ifdef XPI_NAME
+ACDEFINES += -DXPI_NAME=$(XPI_NAME)
+endif
+
+CC := $(CC_WRAPPER) $(CC)
+CXX := $(CXX_WRAPPER) $(CXX)
+MKDIR ?= mkdir
+SLEEP ?= sleep
+TOUCH ?= touch
+
+#
+# Build using PIC by default
+#
+_ENABLE_PIC=1
+
+# Don't build SIMPLE_PROGRAMS with PGO, since they don't need it anyway,
+# and we don't have the same build logic to re-link them in the second pass.
+ifdef SIMPLE_PROGRAMS
+NO_PROFILE_GUIDED_OPTIMIZE = 1
+endif
+
+# No sense in profiling unit tests
+ifdef CPP_UNIT_TESTS
+NO_PROFILE_GUIDED_OPTIMIZE = 1
+endif
+
+# Enable profile-based feedback
+ifdef MOZ_PROFILE_GENERATE
+ifneq (1,$(NO_PROFILE_GUIDED_OPTIMIZE))
+PGO_CFLAGS += -DNS_FREE_PERMANENT_DATA=1
+PGO_CFLAGS += $(if $(filter $(notdir $<),$(notdir $(NO_PROFILE_GUIDED_OPTIMIZE))),,$(PROFILE_GEN_CFLAGS))
+endif # NO_PROFILE_GUIDED_OPTIMIZE
+PGO_LDFLAGS += $(PROFILE_GEN_LDFLAGS)
+endif # MOZ_PROFILE_GENERATE
+
+ifdef MOZ_PROFILE_USE
+ifneq (1,$(NO_PROFILE_GUIDED_OPTIMIZE))
+PGO_CFLAGS += $(if $(filter $(notdir $<),$(notdir $(NO_PROFILE_GUIDED_OPTIMIZE))),,$(PROFILE_USE_CFLAGS))
+endif # NO_PROFILE_GUIDED_OPTIMIZE
+PGO_LDFLAGS += $(PROFILE_USE_LDFLAGS)
+endif # MOZ_PROFILE_USE
+
+# Overloaded by comm builds to refer to $(commtopsrcdir), so that
+# `mail` resolves in en-US builds and in repacks.
+LOCALE_TOPDIR ?= $(topsrcdir)
+MAKE_JARS_FLAGS = \
+ -t $(LOCALE_TOPDIR) \
+ -f $(MOZ_JAR_MAKER_FILE_FORMAT) \
+ $(NULL)
+
+ifdef USE_EXTENSION_MANIFEST
+MAKE_JARS_FLAGS += -e
+endif
+
+TAR_CREATE_FLAGS = -chf
+
+#
+# Default command macros; can be overridden in <arch>.mk.
+#
+CCC = $(CXX)
+
+INCLUDES = \
+ -I$(srcdir) \
+ -I$(CURDIR) \
+ $(LOCAL_INCLUDES) \
+ -I$(ABS_DIST)/include \
+ $(NULL)
+
+include $(MOZILLA_DIR)/config/static-checking-config.mk
+
+ifndef MOZ_LTO
+MOZ_LTO_CFLAGS :=
+MOZ_LTO_LDFLAGS :=
+endif
+
+LDFLAGS = $(MOZ_LTO_LDFLAGS) $(COMPUTED_LDFLAGS) $(PGO_LDFLAGS)
+
+COMPILE_CFLAGS = $(MOZ_LTO_CFLAGS) $(COMPUTED_CFLAGS) $(PGO_CFLAGS) $(_DEPEND_CFLAGS) $(MK_COMPILE_DEFINES)
+COMPILE_CXXFLAGS = $(MOZ_LTO_CFLAGS) $(COMPUTED_CXXFLAGS) $(PGO_CFLAGS) $(_DEPEND_CFLAGS) $(MK_COMPILE_DEFINES)
+COMPILE_CMFLAGS = $(MOZ_LTO_CFLAGS) $(OS_COMPILE_CMFLAGS) $(MOZBUILD_CMFLAGS)
+COMPILE_CMMFLAGS = $(MOZ_LTO_CFLAGS) $(OS_COMPILE_CMMFLAGS) $(MOZBUILD_CMMFLAGS)
+ASFLAGS = $(COMPUTED_ASFLAGS)
+SFLAGS = $(COMPUTED_SFLAGS)
+
+HOST_CFLAGS = $(COMPUTED_HOST_CFLAGS) $(_HOST_DEPEND_CFLAGS)
+HOST_CXXFLAGS = $(COMPUTED_HOST_CXXFLAGS) $(_HOST_DEPEND_CFLAGS)
+HOST_C_LDFLAGS = $(COMPUTED_HOST_C_LDFLAGS)
+HOST_CXX_LDFLAGS = $(COMPUTED_HOST_CXX_LDFLAGS)
+
+WASM_CFLAGS = $(COMPUTED_WASM_CFLAGS) $(_DEPEND_CFLAGS) $(MK_COMPILE_DEFINES)
+WASM_CXXFLAGS = $(COMPUTED_WASM_CXXFLAGS) $(_DEPEND_CFLAGS) $(MK_COMPILE_DEFINES)
+
+ifdef MOZ_LTO
+ifeq (Darwin,$(OS_TARGET))
+# When linking on macOS, debug info is not linked along with the final binary,
+# and the dwarf data stays in object files until they are "linked" with the
+# dsymutil tool.
+# With LTO, object files are temporary, and are not kept around, which
+# means there's no object file for dsymutil to do its job. Consequently,
+# there is no debug info for LTOed compilation units.
+# The macOS linker has however an option to explicitly keep those object
+# files, which dsymutil will then find.
+# The catch is that the linker uses sequential numbers for those object
+# files, and doesn't avoid conflicts from multiple linkers running at
+# the same time. So in directories with multiple binaries, object files
+# from the first linked binaries would be overwritten by those of the
+# last linked binary. So we use a subdirectory containing the name of the
+# linked binary.
+LDFLAGS += -Wl,-object_path_lto,$(@F).lto.o/
+endif
+endif
+
+# We only add color flags if neither the flag to disable color
+# (e.g. "-fno-color-diagnostics" nor a flag to control color
+# (e.g. "-fcolor-diagnostics=never") is present.
+define colorize_flags
+ifeq (,$(filter $(COLOR_CFLAGS:-f%=-fno-%),$$(1))$(findstring $(COLOR_CFLAGS),$$(1)))
+$(1) += $(COLOR_CFLAGS)
+endif
+endef
+
+color_flags_vars := \
+ COMPILE_CFLAGS \
+ COMPILE_CXXFLAGS \
+ COMPILE_CMFLAGS \
+ COMPILE_CMMFLAGS \
+ WASM_CFLAGS \
+ WASM_CXXFLAGS \
+ $(NULL)
+
+ifdef MACH_STDOUT_ISATTY
+ifdef COLOR_CFLAGS
+# TODO Bug 1319166 - iTerm2 interprets some bytes sequences as a
+# request to show a print dialog. Don't enable color on iTerm2 until
+# a workaround is in place.
+ifneq ($(TERM_PROGRAM),iTerm.app)
+$(foreach var,$(color_flags_vars),$(eval $(call colorize_flags,$(var))))
+endif
+endif
+endif
+
+#
+# Name of the binary code directories
+#
+# Override defaults
+
+DEPENDENCIES = .md
+
+# Export to propagate to cl and submake for third-party code.
+# Eventually, we'll want to just use -I.
+ifdef INCLUDE
+export INCLUDE
+endif
+
+# Export to propagate to link.exe and submake for third-party code.
+# Eventually, we'll want to just use -LIBPATH.
+ifdef LIB
+export LIB
+endif
+
+ifdef MOZ_USING_CCACHE
+ifdef CLANG_CXX
+export CCACHE_CPP2=1
+endif
+endif
+
+ifdef CCACHE_PREFIX
+export CCACHE_PREFIX
+endif
+
+# Set link flags according to whether we want a console.
+ifeq ($(OS_ARCH),WINNT)
+ifdef MOZ_WINCONSOLE
+ifeq ($(MOZ_WINCONSOLE),1)
+WIN32_EXE_LDFLAGS += $(WIN32_CONSOLE_EXE_LDFLAGS)
+else # MOZ_WINCONSOLE
+WIN32_EXE_LDFLAGS += $(WIN32_GUI_EXE_LDFLAGS)
+endif
+else
+# For setting subsystem version
+WIN32_EXE_LDFLAGS += $(WIN32_CONSOLE_EXE_LDFLAGS)
+endif
+endif # WINNT
+
+ifeq ($(OS_ARCH),WINNT)
+ifneq (,$(filter msvc clang-cl,$(CC_TYPE)))
+ifneq ($(TARGET_CPU),x86)
+# Normal operation on 64-bit Windows needs 2 MB of stack. (Bug 582910)
+# ASAN requires 6 MB of stack.
+# Setting the stack to 8 MB to match the capability of other systems
+# to deal with frame construction for unreasonably deep DOM trees
+# with worst-case styling. This uses address space unnecessarily for
+# non-main threads, but that should be tolerable on 64-bit systems.
+# (Bug 256180)
+WIN32_EXE_LDFLAGS += -STACK:8388608
+else
+# Since this setting affects the default stack size for non-main
+# threads, too, to avoid burning the address space, increase only
+# 512 KB over the default. Just enough to be able to deal with
+# reasonable styling applied to DOM trees whose depth is near what
+# Blink's HTML parser can output, esp.
+# layout/base/crashtests/507119.html (Bug 256180)
+ifndef MOZ_DEBUG
+WIN32_EXE_LDFLAGS += -STACK:1572864
+else
+# In debug builds, layout code has extra logging helpers on the stack,
+# which can go over the 1.5MB limit on some deeply-nested crashtests.
+WIN32_EXE_LDFLAGS += -STACK:2097152
+endif
+endif
+else
+ifneq ($(TARGET_CPU),x86)
+MOZ_PROGRAM_LDFLAGS += -Wl,-Xlink=-STACK:8388608
+else
+MOZ_PROGRAM_LDFLAGS += -Wl,-Xlink=-STACK:1572864
+endif
+endif
+endif
+
+-include $(topsrcdir)/$(MOZ_BUILD_APP)/app-config.mk
+
+######################################################################
+
+ifeq ($(OS_ARCH),Darwin)
+ifndef NSDISTMODE
+NSDISTMODE=absolute_symlink
+endif
+PWD := $(CURDIR)
+endif
+
+NSINSTALL_PY := $(PYTHON3) $(abspath $(MOZILLA_DIR)/config/nsinstall.py)
+ifneq (,$(or $(filter WINNT,$(HOST_OS_ARCH)),$(if $(COMPILE_ENVIRONMENT),,1)))
+NSINSTALL = $(NSINSTALL_PY)
+else
+NSINSTALL = $(DEPTH)/config/nsinstall$(HOST_BIN_SUFFIX)
+endif # WINNT
+
+
+ifeq (,$(CROSS_COMPILE)$(filter-out WINNT, $(OS_ARCH)))
+INSTALL = $(NSINSTALL) -t
+
+else
+
+# This isn't laid out as conditional directives so that NSDISTMODE can be
+# target-specific.
+INSTALL = $(if $(filter copy, $(NSDISTMODE)), $(NSINSTALL) -t, $(if $(filter absolute_symlink, $(NSDISTMODE)), $(NSINSTALL) -L $(PWD), $(NSINSTALL) -R))
+
+endif # WINNT
+
+# The default for install_cmd is simply INSTALL
+install_cmd ?= $(INSTALL) $(1)
+
+# Use nsinstall in copy mode to install files on the system
+SYSINSTALL = $(NSINSTALL) -t
+# This isn't necessarily true, just here
+sysinstall_cmd = install_cmd
+
+#
+# Localization build automation
+#
+
+# Because you might wish to "make locales AB_CD=ab-CD", we don't hardcode
+# MOZ_UI_LOCALE directly, but use an intermediate variable that can be
+# overridden by the command line. (Besides, AB_CD is prettier).
+AB_CD = $(MOZ_UI_LOCALE)
+
+include $(MOZILLA_DIR)/config/AB_rCD.mk
+
+# Many locales directories want this definition.
+ACDEFINES += -DAB_CD=$(AB_CD)
+
+EXPAND_LOCALE_SRCDIR = $(if $(filter en-US,$(AB_CD)),$(LOCALE_TOPDIR)/$(1)/en-US,$(REAL_LOCALE_MERGEDIR)/$(subst /locales,,$(1)))
+
+ifdef relativesrcdir
+LOCALE_RELATIVEDIR ?= $(relativesrcdir)
+endif
+
+ifdef LOCALE_RELATIVEDIR
+LOCALE_SRCDIR ?= $(call EXPAND_LOCALE_SRCDIR,$(LOCALE_RELATIVEDIR))
+endif
+
+ifdef relativesrcdir
+MAKE_JARS_FLAGS += --relativesrcdir=$(LOCALE_RELATIVEDIR)
+ifneq (en-US,$(AB_CD))
+ifdef IS_LANGUAGE_REPACK
+MAKE_JARS_FLAGS += --l10n-base=$(REAL_LOCALE_MERGEDIR)
+endif
+else
+MAKE_JARS_FLAGS += -c $(LOCALE_SRCDIR)
+endif # en-US
+else
+MAKE_JARS_FLAGS += -c $(LOCALE_SRCDIR)
+endif # ! relativesrcdir
+
+MERGE_FILE = $(LOCALE_SRCDIR)/$(1)
+MERGE_RELATIVE_FILE = $(call EXPAND_LOCALE_SRCDIR,$(2))/$(1)
+
+ifneq (WINNT,$(OS_ARCH))
+RUN_TEST_PROGRAM = $(DIST)/bin/run-mozilla.sh
+endif # ! WINNT
+
+# Enable verbose logs when not using `make -s`
+ifeq (,$(findstring s, $(filter-out --%, $(MAKEFLAGS))))
+export BUILD_VERBOSE_LOG = 1
+endif
diff --git a/config/create_rc.py b/config/create_rc.py
new file mode 100644
index 0000000000..d75959d4e0
--- /dev/null
+++ b/config/create_rc.py
@@ -0,0 +1,202 @@
+# 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/.
+
+import io
+import os
+import sys
+from datetime import datetime
+
+import buildconfig
+from mozbuild.preprocessor import Preprocessor
+
+TEMPLATE = """
+// 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/.
+
+#include<winuser.h>
+#include<winver.h>
+
+// Note: if you contain versioning information in an included
+// RC script, it will be discarded
+// Use module.ver to explicitly set these values
+
+// Do not edit this file. Changes won't affect the build.
+
+{include}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+1 VERSIONINFO
+ FILEVERSION {fileversion}
+ PRODUCTVERSION {productversion}
+ FILEFLAGSMASK 0x3fL
+ FILEFLAGS {fileflags}
+ FILEOS VOS__WINDOWS32
+ FILETYPE VFT_DLL
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "000004b0"
+ BEGIN
+ VALUE "Comments", "{comment}"
+ VALUE "LegalCopyright", "{copyright}"
+ VALUE "CompanyName", "{company}"
+ VALUE "FileDescription", "{description}"
+ VALUE "FileVersion", "{mfversion}"
+ VALUE "ProductVersion", "{mpversion}"
+ VALUE "InternalName", "{module}"
+ VALUE "LegalTrademarks", "{trademarks}"
+ VALUE "OriginalFilename", "{binary}"
+ VALUE "ProductName", "{productname}"
+ VALUE "BuildID", "{buildid}"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0, 1200
+ END
+END
+
+"""
+
+
+def preprocess(path, defines):
+ pp = Preprocessor(defines=defines, marker="%")
+ pp.context.update(defines)
+ pp.out = io.StringIO()
+ pp.do_filter("substitution")
+ pp.do_include(io.open(path, "r", encoding="latin1"))
+ pp.out.seek(0)
+ return pp.out
+
+
+def parse_module_ver(path, defines):
+ result = {}
+ for line in preprocess(path, defines):
+ content, *comment = line.split("#", 1)
+ if not content.strip():
+ continue
+ entry, value = content.split("=", 1)
+ result[entry.strip()] = value.strip()
+ return result
+
+
+def get_buildid():
+ path = os.path.join(buildconfig.topobjdir, "buildid.h")
+ define, MOZ_BUILDID, buildid = io.open(path, "r", encoding="utf-8").read().split()
+ return buildid
+
+
+def days_from_2000_to_buildid(buildid):
+ start = datetime(2000, 1, 1, 0, 0, 0)
+ buildid_time = datetime.strptime(buildid, "%Y%m%d%H%M%S")
+ return (buildid_time - start).days
+
+
+def digits_only(s):
+ for l in range(len(s), 0, -1):
+ if s[:l].isdigit():
+ return s[:l]
+ return "0"
+
+
+def split_and_normalize_version(version, len):
+ return ([digits_only(x) for x in version.split(".")] + ["0"] * len)[:len]
+
+
+def has_manifest(module_rc, manifest_id):
+ for line in module_rc.splitlines():
+ line = line.split(None, 2)
+ if len(line) < 2:
+ continue
+ id, what, *rest = line
+ if id == manifest_id and what in ("24", "RT_MANIFEST"):
+ return True
+ return False
+
+
+def generate_module_rc(binary="", rcinclude=None):
+ deps = set()
+ buildid = get_buildid()
+ milestone = buildconfig.substs["GRE_MILESTONE"]
+ app_version = buildconfig.substs.get("MOZ_APP_VERSION") or milestone
+ app_winversion = ",".join(split_and_normalize_version(app_version, 4))
+ milestone_winversion = ",".join(
+ split_and_normalize_version(milestone, 3)
+ + [str(days_from_2000_to_buildid(buildid))]
+ )
+ display_name = buildconfig.substs.get("MOZ_APP_DISPLAYNAME", "Mozilla")
+
+ milestone_string = milestone
+
+ flags = ["0"]
+ if buildconfig.substs.get("MOZ_DEBUG"):
+ flags.append("VS_FF_DEBUG")
+ milestone_string += " Debug"
+ if not buildconfig.substs.get("MOZILLA_OFFICIAL"):
+ flags.append("VS_FF_PRIVATEBUILD")
+ if buildconfig.substs.get("NIGHTLY_BUILD"):
+ flags.append("VS_FF_PRERELEASE")
+
+ defines = {
+ "MOZ_APP_DISPLAYNAME": display_name,
+ "MOZ_APP_VERSION": app_version,
+ "MOZ_APP_WINVERSION": app_winversion,
+ }
+
+ relobjdir = os.path.relpath(".", buildconfig.topobjdir)
+ srcdir = os.path.join(buildconfig.topsrcdir, relobjdir)
+ module_ver = os.path.join(srcdir, "module.ver")
+ if os.path.exists(module_ver):
+ deps.add(module_ver)
+ overrides = parse_module_ver(module_ver, defines)
+ else:
+ overrides = {}
+
+ if rcinclude:
+ include = "// From included resource {}\n{}".format(
+ rcinclude, preprocess(rcinclude, defines).read()
+ )
+ else:
+ include = ""
+
+ data = TEMPLATE.format(
+ include=include,
+ fileversion=overrides.get("WIN32_MODULE_FILEVERSION", milestone_winversion),
+ productversion=overrides.get(
+ "WIN32_MODULE_PRODUCTVERSION", milestone_winversion
+ ),
+ fileflags=" | ".join(flags),
+ comment=overrides.get("WIN32_MODULE_COMMENT", ""),
+ copyright=overrides.get("WIN32_MODULE_COPYRIGHT", "License: MPL 2"),
+ company=overrides.get("WIN32_MODULE_COMPANYNAME", "Mozilla Foundation"),
+ description=overrides.get("WIN32_MODULE_DESCRIPTION", ""),
+ mfversion=overrides.get("WIN32_MODULE_FILEVERSION_STRING", milestone_string),
+ mpversion=overrides.get("WIN32_MODULE_PRODUCTVERSION_STRING", milestone_string),
+ module=overrides.get("WIN32_MODULE_NAME", ""),
+ trademarks=overrides.get("WIN32_MODULE_TRADEMARKS", "Mozilla"),
+ binary=overrides.get("WIN32_MODULE_ORIGINAL_FILENAME", binary),
+ productname=overrides.get("WIN32_MODULE_PRODUCTNAME", display_name),
+ buildid=buildid,
+ )
+
+ manifest_id = "2" if binary.lower().endswith(".dll") else "1"
+ if binary and not has_manifest(data, manifest_id):
+ manifest_path = os.path.join(srcdir, binary + ".manifest")
+ if os.path.exists(manifest_path):
+ manifest_path = manifest_path.replace("\\", "\\\\")
+ data += '\n{} RT_MANIFEST "{}"\n'.format(manifest_id, manifest_path)
+
+ with io.open("{}.rc".format(binary or "module"), "w", encoding="latin1") as fh:
+ fh.write(data)
+
+
+if __name__ == "__main__":
+ generate_module_rc(*sys.argv[1:])
diff --git a/config/create_res.py b/config/create_res.py
new file mode 100644
index 0000000000..8e1db7d101
--- /dev/null
+++ b/config/create_res.py
@@ -0,0 +1,102 @@
+# 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/.
+
+import os
+import subprocess
+import sys
+import tempfile
+from argparse import Action, ArgumentParser
+
+import buildconfig
+
+
+class CPPFlag(Action):
+ all_flags = []
+
+ def __call__(self, parser, namespace, values, option_string=None):
+ if "windres" in buildconfig.substs["RC"].lower():
+ if option_string == "-U":
+ return
+ if option_string == "-I":
+ option_string = "--include-dir"
+
+ self.all_flags.extend((option_string, values))
+
+
+def generate_res():
+ parser = ArgumentParser()
+ parser.add_argument(
+ "-D", action=CPPFlag, metavar="VAR[=VAL]", help="Define a variable"
+ )
+ parser.add_argument("-U", action=CPPFlag, metavar="VAR", help="Undefine a variable")
+ parser.add_argument(
+ "-I", action=CPPFlag, metavar="DIR", help="Search path for includes"
+ )
+ parser.add_argument("-o", dest="output", metavar="OUTPUT", help="Output file")
+ parser.add_argument("input", help="Input file")
+ args = parser.parse_args()
+
+ is_windres = "windres" in buildconfig.substs["RC"].lower()
+
+ verbose = os.environ.get("BUILD_VERBOSE_LOG")
+
+ # llvm-rc doesn't preprocess on its own, so preprocess manually
+ # Theoretically, not windres could be rc.exe, but configure won't use it
+ # unless you really ask for it, and it will still work with preprocessed
+ # output.
+ try:
+ if not is_windres:
+ fd, path = tempfile.mkstemp(suffix=".rc")
+ command = buildconfig.substs["CXXCPP"] + CPPFlag.all_flags
+ command.extend(("-DRC_INVOKED", args.input))
+
+ cpu_arch_dict = {"x86_64": "_AMD64_", "x86": "_X86_", "aarch64": "_ARM64_"}
+
+ # add a preprocessor #define that specifies the CPU architecture
+ cpu_arch_ppd = cpu_arch_dict[buildconfig.substs["TARGET_CPU"]]
+
+ command.extend(("-D", cpu_arch_ppd))
+
+ if verbose:
+ print("Executing:", " ".join(command))
+ with os.fdopen(fd, "wb") as fh:
+ retcode = subprocess.run(command, stdout=fh).returncode
+ if retcode:
+ # Rely on the subprocess printing out any relevant error
+ return retcode
+ else:
+ path = args.input
+
+ command = [buildconfig.substs["RC"]]
+ if is_windres:
+ command.extend(("-O", "coff"))
+
+ # Even though llvm-rc doesn't preprocess, we still need to pass at least
+ # the -I flags.
+ command.extend(CPPFlag.all_flags)
+
+ if args.output:
+ if is_windres:
+ command.extend(("-o", args.output))
+ else:
+ # Use win1252 code page for the input.
+ command.extend(("-c", "1252", "-Fo" + args.output))
+
+ command.append(path)
+
+ if verbose:
+ print("Executing:", " ".join(command))
+ retcode = subprocess.run(command).returncode
+ if retcode:
+ # Rely on the subprocess printing out any relevant error
+ return retcode
+ finally:
+ if path != args.input:
+ os.remove(path)
+
+ return 0
+
+
+if __name__ == "__main__":
+ sys.exit(generate_res())
diff --git a/config/createprecomplete.py b/config/createprecomplete.py
new file mode 100644
index 0000000000..8c5fceefaa
--- /dev/null
+++ b/config/createprecomplete.py
@@ -0,0 +1,72 @@
+# Any copyright is dedicated to the Public Domain.
+# http://creativecommons.org/publicdomain/zero/1.0/
+
+# Creates the precomplete file containing the remove and rmdir application
+# update instructions which is used to remove files and directories that are no
+# longer present in a complete update. The current working directory is used for
+# the location to enumerate and to create the precomplete file.
+
+import io
+import os
+
+
+def get_build_entries(root_path):
+ """Iterates through the root_path, creating a list for each file and
+ directory. Excludes any file paths ending with channel-prefs.js.
+ """
+ rel_file_path_set = set()
+ rel_dir_path_set = set()
+ for root, dirs, files in os.walk(root_path):
+ for file_name in files:
+ parent_dir_rel_path = root[len(root_path) + 1 :]
+ rel_path_file = os.path.join(parent_dir_rel_path, file_name)
+ rel_path_file = rel_path_file.replace("\\", "/")
+ if not (
+ rel_path_file.endswith("channel-prefs.js")
+ or rel_path_file.endswith("update-settings.ini")
+ or rel_path_file.find("distribution/") != -1
+ ):
+ rel_file_path_set.add(rel_path_file)
+
+ for dir_name in dirs:
+ parent_dir_rel_path = root[len(root_path) + 1 :]
+ rel_path_dir = os.path.join(parent_dir_rel_path, dir_name)
+ rel_path_dir = rel_path_dir.replace("\\", "/") + "/"
+ if rel_path_dir.find("distribution/") == -1:
+ rel_dir_path_set.add(rel_path_dir)
+
+ rel_file_path_list = list(rel_file_path_set)
+ rel_file_path_list.sort(reverse=True)
+ rel_dir_path_list = list(rel_dir_path_set)
+ rel_dir_path_list.sort(reverse=True)
+
+ return rel_file_path_list, rel_dir_path_list
+
+
+def generate_precomplete(root_path):
+ """Creates the precomplete file containing the remove and rmdir
+ application update instructions. The given directory is used
+ for the location to enumerate and to create the precomplete file.
+ """
+ rel_path_precomplete = "precomplete"
+ # If inside a Mac bundle use the root of the bundle for the path.
+ if os.path.basename(root_path) == "Resources":
+ root_path = os.path.abspath(os.path.join(root_path, "../../"))
+ rel_path_precomplete = "Contents/Resources/precomplete"
+
+ precomplete_file_path = os.path.join(root_path, rel_path_precomplete)
+ # Open the file so it exists before building the list of files and open it
+ # in binary mode to prevent OS specific line endings.
+ precomplete_file = io.open(precomplete_file_path, mode="wt", newline="\n")
+ rel_file_path_list, rel_dir_path_list = get_build_entries(root_path)
+ for rel_file_path in rel_file_path_list:
+ precomplete_file.write('remove "' + rel_file_path + '"\n')
+
+ for rel_dir_path in rel_dir_path_list:
+ precomplete_file.write('rmdir "' + rel_dir_path + '"\n')
+
+ precomplete_file.close()
+
+
+if __name__ == "__main__":
+ generate_precomplete(os.getcwd())
diff --git a/config/emptyvars-js.mk.in b/config/emptyvars-js.mk.in
new file mode 100644
index 0000000000..388cf2a359
--- /dev/null
+++ b/config/emptyvars-js.mk.in
@@ -0,0 +1 @@
+@ALLEMPTYSUBSTS@
diff --git a/config/emptyvars.mk.in b/config/emptyvars.mk.in
new file mode 100644
index 0000000000..388cf2a359
--- /dev/null
+++ b/config/emptyvars.mk.in
@@ -0,0 +1 @@
+@ALLEMPTYSUBSTS@
diff --git a/config/external/fdlibm/moz.build b/config/external/fdlibm/moz.build
new file mode 100644
index 0000000000..343645f0ce
--- /dev/null
+++ b/config/external/fdlibm/moz.build
@@ -0,0 +1,12 @@
+# -*- 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/.
+
+with Files("**"):
+ BUG_COMPONENT = ("Core", "JavaScript Engine")
+
+DIRS += [
+ "../../../modules/fdlibm",
+]
diff --git a/config/external/ffi/moz.build b/config/external/ffi/moz.build
new file mode 100644
index 0000000000..ee0dc884e0
--- /dev/null
+++ b/config/external/ffi/moz.build
@@ -0,0 +1,149 @@
+# -*- 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/.
+
+FINAL_LIBRARY = "js"
+
+if CONFIG["MOZ_SYSTEM_FFI"]:
+ OS_LIBS += CONFIG["MOZ_FFI_LIBS"]
+else:
+ AllowCompilerWarnings()
+ NoVisibilityFlags()
+
+ CONFIGURE_DEFINE_FILES += [
+ "/js/src/ctypes/libffi/fficonfig.h",
+ ]
+ LOCAL_INCLUDES += [
+ "!/js/src/ctypes/libffi",
+ "!/js/src/ctypes/libffi/include",
+ "/js/src/ctypes/libffi/include",
+ "/js/src/ctypes/libffi/src/%s" % CONFIG["FFI_TARGET_DIR"],
+ ]
+
+ DEFINES["TARGET"] = CONFIG["FFI_TARGET"]
+ DEFINES[CONFIG["FFI_TARGET"]] = True
+ DEFINES["FFI_NO_RAW_API"] = True
+ DEFINES["FFI_BUILDING"] = True
+ DEFINES["HAVE_AS_ASCII_PSEUDO_OP"] = True
+ DEFINES["HAVE_AS_STRING_PSEUDO_OP"] = True
+
+ if CONFIG["MOZ_DEBUG"]:
+ DEFINES["FFI_DEBUG"] = True
+ if not CONFIG["MOZ_NO_DEBUG_RTL"]:
+ DEFINES["USE_DEBUG_RTL"] = True
+ SOURCES += [
+ "/js/src/ctypes/libffi/src/debug.c",
+ ]
+
+ if CONFIG["OS_TARGET"] != "WINNT":
+ DEFINES["HAVE_HIDDEN_VISIBILITY_ATTRIBUTE"] = True
+
+ if CONFIG["INTEL_ARCHITECTURE"]:
+ DEFINES["HAVE_AS_X86_PCREL"] = True
+
+ # Don't bother setting EH_FRAME_FLAGS on Windows.
+ # Quoted defines confuse msvcc.sh, and the value isn't used there.
+ if CONFIG["OS_TARGET"] != "WINNT":
+ if CONFIG["FFI_TARGET"] == "ARM":
+ DEFINES["EH_FRAME_FLAGS"] = '"aw"'
+ else:
+ DEFINES["EH_FRAME_FLAGS"] = '"a"'
+
+ # Common source files.
+ SOURCES += [
+ "/js/src/ctypes/libffi/src/closures.c",
+ "/js/src/ctypes/libffi/src/java_raw_api.c",
+ "/js/src/ctypes/libffi/src/prep_cif.c",
+ "/js/src/ctypes/libffi/src/raw_api.c",
+ "/js/src/ctypes/libffi/src/types.c",
+ ]
+
+ # Per-platform sources and flags.
+ ffi_srcs = ()
+ ffi_h_defines = []
+ if CONFIG["FFI_TARGET"] == "X86_WIN64":
+ if CONFIG["CC_TYPE"] == "clang-cl":
+ ffi_srcs = ("ffiw64.c",)
+ # libffi asm needs to be preprocessed for MSVC's assembler
+ GeneratedFile(
+ "win64_intel.asm",
+ inputs=[
+ "/js/src/ctypes/libffi/src/x86/win64_intel.S",
+ "!/js/src/ctypes/libffi/fficonfig.h",
+ "!/js/src/ctypes/libffi/include/ffi.h",
+ ],
+ script="preprocess_libffi_asm.py",
+ flags=["$(DEFINES)", "$(LOCAL_INCLUDES)"],
+ )
+ SOURCES += ["!win64_intel.asm"]
+ else:
+ ffi_srcs = ("ffiw64.c", "win64.S")
+
+ elif CONFIG["FFI_TARGET"] == "X86_64":
+ DEFINES["HAVE_AS_X86_64_UNWIND_SECTION_TYPE"] = True
+ ffi_srcs = ("ffi64.c", "unix64.S", "ffiw64.c", "win64.S")
+
+ elif CONFIG["FFI_TARGET"] == "X86_WIN32" and CONFIG["CC_TYPE"] == "clang-cl":
+ ffi_srcs = ("ffi.c",)
+ # libffi asm needs to be preprocessed for MSVC's assembler
+ GeneratedFile(
+ "sysv_intel.asm",
+ inputs=[
+ "/js/src/ctypes/libffi/src/x86/sysv_intel.S",
+ "!/js/src/ctypes/libffi/fficonfig.h",
+ "!/js/src/ctypes/libffi/include/ffi.h",
+ ],
+ script="preprocess_libffi_asm.py",
+ flags=["$(DEFINES)", "$(LOCAL_INCLUDES)"],
+ )
+ SOURCES += ["!sysv_intel.asm"]
+ ASFLAGS += ["-safeseh"]
+
+ elif CONFIG["FFI_TARGET"] == "ARM_WIN64":
+ ffi_srcs = ("ffi.c",)
+
+ # libffi asm needs to be preprocessed for MSVC's assembler
+ GeneratedFile(
+ "win64_armasm.asm",
+ inputs=[
+ "/js/src/ctypes/libffi/src/aarch64/win64_armasm.S",
+ "!/js/src/ctypes/libffi/fficonfig.h",
+ "!/js/src/ctypes/libffi/include/ffi.h",
+ ],
+ script="preprocess_libffi_asm.py",
+ flags=["$(DEFINES)", "$(LOCAL_INCLUDES)"],
+ )
+ SOURCES += ["!win64_armasm.asm"]
+
+ else:
+ ffi_srcs = ("ffi.c", "sysv.S")
+
+ if CONFIG["FFI_TARGET"] in ("X86_WIN32", "X86_DARWIN") and CONFIG["CC_TYPE"] in (
+ "gcc",
+ "clang",
+ ):
+ DEFINES["SYMBOL_UNDERSCORE"] = True
+
+ if CONFIG["OS_ARCH"] == "Darwin" and CONFIG["TARGET_CPU"] in ("arm", "aarch64"):
+ DEFINES["FFI_EXEC_TRAMPOLINE_TABLE"] = True
+ ffi_h_defines.append("FFI_EXEC_TRAMPOLINE_TABLE")
+
+ elif (
+ CONFIG["OS_ARCH"] in ("Darwin", "FreeBSD", "GNU_kFreeBSD", "OpenBSD", "SunOS")
+ or CONFIG["OS_TARGET"] == "Android"
+ ):
+ DEFINES["FFI_MMAP_EXEC_WRIT"] = True
+
+ SOURCES += [
+ "/js/src/ctypes/libffi/src/%s/%s" % (CONFIG["FFI_TARGET_DIR"], s)
+ for s in sorted(ffi_srcs)
+ ]
+
+ GeneratedFile(
+ "/js/src/ctypes/libffi/include/ffi.h",
+ script="subst_header.py",
+ inputs=["/js/src/ctypes/libffi/include/ffi.h.in"],
+ flags=ffi_h_defines,
+ )
diff --git a/config/external/ffi/preprocess_libffi_asm.py b/config/external/ffi/preprocess_libffi_asm.py
new file mode 100644
index 0000000000..4808c3a7e4
--- /dev/null
+++ b/config/external/ffi/preprocess_libffi_asm.py
@@ -0,0 +1,25 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Souce Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distibuted with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+import os
+import shlex
+import subprocess
+
+import buildconfig
+import mozpack.path as mozpath
+
+
+def main(output, input_asm, ffi_h, ffi_config_h, defines, includes):
+ defines = shlex.split(defines)
+ includes = shlex.split(includes)
+ # CPP uses -E which generates #line directives. -EP suppresses them.
+ # -TC forces the compiler to treat the input as C.
+ cpp = buildconfig.substs["CPP"] + ["-EP"] + ["-TC"]
+ input_asm = mozpath.relpath(input_asm, os.getcwd())
+ args = cpp + defines + includes + [input_asm]
+ print(" ".join(args))
+ preprocessed = subprocess.check_output(args)
+ output.write(preprocessed)
diff --git a/config/external/ffi/subst_header.py b/config/external/ffi/subst_header.py
new file mode 100644
index 0000000000..e1448ff889
--- /dev/null
+++ b/config/external/ffi/subst_header.py
@@ -0,0 +1,32 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Souce Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distibuted with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+import sys
+
+import buildconfig
+from mozbuild.preprocessor import Preprocessor
+
+
+def main(output, input_file, *defines):
+ pp = Preprocessor()
+ pp.context.update(
+ {
+ "FFI_EXEC_TRAMPOLINE_TABLE": "0",
+ "HAVE_LONG_DOUBLE": "0",
+ "TARGET": buildconfig.substs["FFI_TARGET"],
+ "VERSION": "",
+ }
+ )
+ for d in defines:
+ pp.context.update({d: "1"})
+ pp.do_filter("substitution")
+ pp.setMarker(None)
+ pp.out = output
+ pp.do_include(input_file)
+
+
+if __name__ == "__main__":
+ main(*sys.agv[1:])
diff --git a/config/external/freetype2/moz.build b/config/external/freetype2/moz.build
new file mode 100644
index 0000000000..3d025e1ee4
--- /dev/null
+++ b/config/external/freetype2/moz.build
@@ -0,0 +1,14 @@
+# -*- 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/.
+
+Library("freetype")
+
+if CONFIG["MOZ_TREE_FREETYPE"]:
+ DIRS += [
+ "/modules/freetype2",
+ ]
+else:
+ OS_LIBS += CONFIG["FT2_LIBS"]
diff --git a/config/external/gkcodecs/gkcodecs.symbols b/config/external/gkcodecs/gkcodecs.symbols
new file mode 100644
index 0000000000..12cb274c70
--- /dev/null
+++ b/config/external/gkcodecs/gkcodecs.symbols
@@ -0,0 +1,158 @@
+# libaom symbols
+aom_codec_av1_cx
+aom_codec_av1_dx
+aom_codec_build_config
+aom_codec_control
+aom_codec_dec_init_ver
+aom_codec_decode
+aom_codec_destroy
+aom_codec_destroy
+aom_codec_enc_config_default
+aom_codec_enc_init_ver
+aom_codec_encode
+aom_codec_err_to_string
+aom_codec_error
+aom_codec_error_detail
+aom_codec_get_caps
+aom_codec_get_cx_data
+aom_codec_get_frame
+aom_codec_peek_stream_info
+aom_codec_set_option
+aom_codec_version
+aom_codec_version_str
+aom_img_free
+aom_img_plane_height
+aom_img_plane_width
+aom_img_wrap
+#if defined(X86_WIN64)
+aom_winx64_fstcw
+#endif
+av1_apply_encoding_flags
+av1_change_config
+av1_convert_sect5obus_to_annexb
+av1_copy_new_frame_enc
+av1_copy_reference_enc
+av1_create_compressor
+av1_get_active_map
+av1_get_compressed_data
+av1_get_global_headers
+av1_get_last_show_frame
+av1_get_preview_raw_frame
+av1_get_quantizer
+av1_initialize_enc
+av1_qindex_to_quantizer
+av1_quantizer_to_qindex
+av1_receive_raw_frame
+av1_remove_compressor
+av1_set_active_map
+av1_set_internal_size
+av1_set_reference_enc
+av1_use_as_reference
+# libogg symbols
+ogg_calloc_func
+ogg_free_func
+ogg_malloc_func
+ogg_page_bos
+ogg_page_granulepos
+ogg_page_serialno
+ogg_realloc_func
+ogg_set_mem_functions
+ogg_stream_check
+ogg_stream_clear
+ogg_stream_eos
+ogg_stream_flush
+ogg_stream_init
+ogg_stream_packetin
+ogg_stream_packetout
+ogg_stream_pagein
+ogg_stream_pageout
+ogg_stream_reset
+ogg_sync_buffer
+ogg_sync_clear
+ogg_sync_init
+ogg_sync_pageseek
+ogg_sync_reset
+ogg_sync_wrote
+# libopus symbols
+opus_decode
+opus_decoder_create
+opus_decoder_ctl
+opus_decoder_destroy
+opus_encode
+opus_encode_float
+opus_encoder_create
+opus_encoder_ctl
+opus_encoder_destroy
+opus_get_version_string
+opus_multistream_decode
+opus_multistream_decode_float
+opus_multistream_decoder_create
+opus_multistream_decoder_ctl
+opus_multistream_decoder_destroy
+opus_multistream_encode
+opus_multistream_encoder_create
+opus_multistream_encoder_ctl
+opus_multistream_encoder_destroy
+opus_packet_get_nb_channels
+opus_packet_get_nb_frames
+opus_packet_get_samples_per_frame
+opus_packet_parse
+opus_strerror
+# libtheora symbols
+th_comment_clear
+th_comment_init
+th_decode_alloc
+th_decode_free
+th_decode_headerin
+th_decode_packetin
+th_decode_ycbcr_out
+th_granule_frame
+th_info_clear
+th_info_init
+th_packet_isheader
+th_packet_iskeyframe
+th_setup_free
+vorbis_block_clear
+vorbis_block_init
+vorbis_comment_clear
+vorbis_comment_init
+vorbis_dsp_clear
+vorbis_info_clear
+vorbis_info_init
+vorbis_packet_blocksize
+vorbis_synthesis
+vorbis_synthesis_blockin
+vorbis_synthesis_headerin
+vorbis_synthesis_init
+vorbis_synthesis_pcmout
+vorbis_synthesis_read
+vorbis_synthesis_restart
+# libvpx symbols
+#ifndef MOZ_SYSTEM_LIBVPX
+vpx_codec_build_config
+vpx_codec_control_
+vpx_codec_dec_init_ver
+vpx_codec_decode
+vpx_codec_destroy
+vpx_codec_enc_config_default
+vpx_codec_enc_config_set
+vpx_codec_enc_init_multi_ver
+vpx_codec_enc_init_ver
+vpx_codec_encode
+vpx_codec_err_to_string
+vpx_codec_error
+vpx_codec_error_detail
+vpx_codec_get_caps
+vpx_codec_get_cx_data
+vpx_codec_get_frame
+vpx_codec_set_frame_buffer_functions
+vpx_codec_version
+vpx_codec_version_str
+vpx_codec_vp8_cx
+vpx_codec_vp8_dx
+vpx_codec_vp9_cx
+vpx_codec_vp9_dx
+vpx_img_alloc
+vpx_img_free
+vpx_img_wrap
+#endif
diff --git a/config/external/gkcodecs/moz.build b/config/external/gkcodecs/moz.build
new file mode 100644
index 0000000000..040f6809de
--- /dev/null
+++ b/config/external/gkcodecs/moz.build
@@ -0,0 +1,18 @@
+# -*- 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/.
+
+# The gkcodecs library contains code from third-party libraries implementing
+# encoding an decoding for particular audio and video codecs.
+#
+# They are compiled in a separate shared library to be able to be available
+# both from libxul (when decoding using the codec integration layer Gecko
+# provides) and from ffmpeg (when decoding and encoding through ffmpeg).
+
+GeckoSharedLibrary("gkcodecs", linkage=None)
+SHARED_LIBRARY_NAME = "gkcodecs"
+SYMBOLS_FILE = "gkcodecs.symbols"
+if CONFIG["MOZ_SYSTEM_LIBVPX"]:
+ DEFINES["MOZ_SYSTEM_LIBVPX"] = True
diff --git a/config/external/icu/common/moz.build b/config/external/icu/common/moz.build
new file mode 100644
index 0000000000..b670c06222
--- /dev/null
+++ b/config/external/icu/common/moz.build
@@ -0,0 +1,34 @@
+# -*- 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/.
+
+Library("icuuc")
+FINAL_LIBRARY = "icu"
+
+DEFINES["U_COMMON_IMPLEMENTATION"] = True
+
+LOCAL_INCLUDES += ["/intl/icu/source/i18n"]
+
+include("../defs.mozbuild")
+include("sources.mozbuild")
+
+SOURCES += sources
+
+if CONFIG["TARGET_ENDIANNESS"] == "big":
+ HostLibrary("host_icuuc")
+ HOST_DEFINES["U_COMMON_IMPLEMENTATION"] = True
+ HOST_SOURCES += sources
+ HOST_SOURCES += other_sources
+
+# Clang 16 added an error that can be downgraded, but won't be downgradable
+# in clang 17.
+# https://unicode-org.atlassian.net/browse/ICU-22113
+if (
+ CONFIG["CC_TYPE"] in ("clang", "clang-cl")
+ and int(CONFIG["CC_VERSION"].split(".")[0]) == 16
+):
+ SOURCES["/intl/icu/source/common/ubidi.cpp"].flags += [
+ "-Wno-error=enum-constexpr-conversion"
+ ]
diff --git a/config/external/icu/common/sources.mozbuild b/config/external/icu/common/sources.mozbuild
new file mode 100644
index 0000000000..a8ac190241
--- /dev/null
+++ b/config/external/icu/common/sources.mozbuild
@@ -0,0 +1,305 @@
+# THIS FILE IS GENERATED BY /intl/icu_sources_data.py DO NOT EDIT
+sources = [
+ "/intl/icu/source/common/appendable.cpp",
+ "/intl/icu/source/common/bmpset.cpp",
+ "/intl/icu/source/common/brkeng.cpp",
+ "/intl/icu/source/common/brkiter.cpp",
+ "/intl/icu/source/common/bytesinkutil.cpp",
+ "/intl/icu/source/common/bytestream.cpp",
+ "/intl/icu/source/common/bytestrie.cpp",
+ "/intl/icu/source/common/bytestriebuilder.cpp",
+ "/intl/icu/source/common/caniter.cpp",
+ "/intl/icu/source/common/characterproperties.cpp",
+ "/intl/icu/source/common/chariter.cpp",
+ "/intl/icu/source/common/charstr.cpp",
+ "/intl/icu/source/common/cmemory.cpp",
+ "/intl/icu/source/common/cstring.cpp",
+ "/intl/icu/source/common/dictbe.cpp",
+ "/intl/icu/source/common/dictionarydata.cpp",
+ "/intl/icu/source/common/dtintrv.cpp",
+ "/intl/icu/source/common/edits.cpp",
+ "/intl/icu/source/common/emojiprops.cpp",
+ "/intl/icu/source/common/errorcode.cpp",
+ "/intl/icu/source/common/filteredbrk.cpp",
+ "/intl/icu/source/common/filterednormalizer2.cpp",
+ "/intl/icu/source/common/loadednormalizer2impl.cpp",
+ "/intl/icu/source/common/localebuilder.cpp",
+ "/intl/icu/source/common/localematcher.cpp",
+ "/intl/icu/source/common/localeprioritylist.cpp",
+ "/intl/icu/source/common/locavailable.cpp",
+ "/intl/icu/source/common/locbased.cpp",
+ "/intl/icu/source/common/locdispnames.cpp",
+ "/intl/icu/source/common/locdistance.cpp",
+ "/intl/icu/source/common/locdspnm.cpp",
+ "/intl/icu/source/common/locid.cpp",
+ "/intl/icu/source/common/loclikely.cpp",
+ "/intl/icu/source/common/loclikelysubtags.cpp",
+ "/intl/icu/source/common/locmap.cpp",
+ "/intl/icu/source/common/locresdata.cpp",
+ "/intl/icu/source/common/locutil.cpp",
+ "/intl/icu/source/common/lsr.cpp",
+ "/intl/icu/source/common/lstmbe.cpp",
+ "/intl/icu/source/common/messagepattern.cpp",
+ "/intl/icu/source/common/mlbe.cpp",
+ "/intl/icu/source/common/normalizer2.cpp",
+ "/intl/icu/source/common/normalizer2impl.cpp",
+ "/intl/icu/source/common/normlzr.cpp",
+ "/intl/icu/source/common/parsepos.cpp",
+ "/intl/icu/source/common/patternprops.cpp",
+ "/intl/icu/source/common/propname.cpp",
+ "/intl/icu/source/common/punycode.cpp",
+ "/intl/icu/source/common/putil.cpp",
+ "/intl/icu/source/common/rbbi.cpp",
+ "/intl/icu/source/common/rbbi_cache.cpp",
+ "/intl/icu/source/common/rbbidata.cpp",
+ "/intl/icu/source/common/rbbinode.cpp",
+ "/intl/icu/source/common/rbbirb.cpp",
+ "/intl/icu/source/common/rbbiscan.cpp",
+ "/intl/icu/source/common/rbbisetb.cpp",
+ "/intl/icu/source/common/rbbistbl.cpp",
+ "/intl/icu/source/common/rbbitblb.cpp",
+ "/intl/icu/source/common/resbund.cpp",
+ "/intl/icu/source/common/resource.cpp",
+ "/intl/icu/source/common/restrace.cpp",
+ "/intl/icu/source/common/ruleiter.cpp",
+ "/intl/icu/source/common/schriter.cpp",
+ "/intl/icu/source/common/serv.cpp",
+ "/intl/icu/source/common/servlk.cpp",
+ "/intl/icu/source/common/servlkf.cpp",
+ "/intl/icu/source/common/servls.cpp",
+ "/intl/icu/source/common/servnotf.cpp",
+ "/intl/icu/source/common/servrbf.cpp",
+ "/intl/icu/source/common/servslkf.cpp",
+ "/intl/icu/source/common/sharedobject.cpp",
+ "/intl/icu/source/common/simpleformatter.cpp",
+ "/intl/icu/source/common/static_unicode_sets.cpp",
+ "/intl/icu/source/common/stringpiece.cpp",
+ "/intl/icu/source/common/stringtriebuilder.cpp",
+ "/intl/icu/source/common/uarrsort.cpp",
+ "/intl/icu/source/common/ubidi.cpp",
+ "/intl/icu/source/common/ubidi_props.cpp",
+ "/intl/icu/source/common/ubidiln.cpp",
+ "/intl/icu/source/common/ubidiwrt.cpp",
+ "/intl/icu/source/common/ubrk.cpp",
+ "/intl/icu/source/common/ucase.cpp",
+ "/intl/icu/source/common/ucasemap.cpp",
+ "/intl/icu/source/common/ucasemap_titlecase_brkiter.cpp",
+ "/intl/icu/source/common/uchar.cpp",
+ "/intl/icu/source/common/ucharstrie.cpp",
+ "/intl/icu/source/common/ucharstriebuilder.cpp",
+ "/intl/icu/source/common/ucharstrieiterator.cpp",
+ "/intl/icu/source/common/uchriter.cpp",
+ "/intl/icu/source/common/ucln_cmn.cpp",
+ "/intl/icu/source/common/ucmndata.cpp",
+ "/intl/icu/source/common/ucnv.cpp",
+ "/intl/icu/source/common/ucnv_bld.cpp",
+ "/intl/icu/source/common/ucnv_cb.cpp",
+ "/intl/icu/source/common/ucnv_cnv.cpp",
+ "/intl/icu/source/common/ucnv_err.cpp",
+ "/intl/icu/source/common/ucnv_io.cpp",
+ "/intl/icu/source/common/ucnv_u16.cpp",
+ "/intl/icu/source/common/ucnv_u32.cpp",
+ "/intl/icu/source/common/ucnv_u7.cpp",
+ "/intl/icu/source/common/ucnv_u8.cpp",
+ "/intl/icu/source/common/ucnvbocu.cpp",
+ "/intl/icu/source/common/ucnvlat1.cpp",
+ "/intl/icu/source/common/ucnvscsu.cpp",
+ "/intl/icu/source/common/ucol_swp.cpp",
+ "/intl/icu/source/common/ucptrie.cpp",
+ "/intl/icu/source/common/ucurr.cpp",
+ "/intl/icu/source/common/udata.cpp",
+ "/intl/icu/source/common/udatamem.cpp",
+ "/intl/icu/source/common/udataswp.cpp",
+ "/intl/icu/source/common/uenum.cpp",
+ "/intl/icu/source/common/uhash.cpp",
+ "/intl/icu/source/common/uhash_us.cpp",
+ "/intl/icu/source/common/uinit.cpp",
+ "/intl/icu/source/common/uinvchar.cpp",
+ "/intl/icu/source/common/uiter.cpp",
+ "/intl/icu/source/common/ulist.cpp",
+ "/intl/icu/source/common/uloc.cpp",
+ "/intl/icu/source/common/uloc_keytype.cpp",
+ "/intl/icu/source/common/uloc_tag.cpp",
+ "/intl/icu/source/common/umapfile.cpp",
+ "/intl/icu/source/common/umath.cpp",
+ "/intl/icu/source/common/umutablecptrie.cpp",
+ "/intl/icu/source/common/umutex.cpp",
+ "/intl/icu/source/common/unames.cpp",
+ "/intl/icu/source/common/unifiedcache.cpp",
+ "/intl/icu/source/common/unifilt.cpp",
+ "/intl/icu/source/common/unifunct.cpp",
+ "/intl/icu/source/common/uniset.cpp",
+ "/intl/icu/source/common/uniset_closure.cpp",
+ "/intl/icu/source/common/uniset_props.cpp",
+ "/intl/icu/source/common/unisetspan.cpp",
+ "/intl/icu/source/common/unistr.cpp",
+ "/intl/icu/source/common/unistr_case.cpp",
+ "/intl/icu/source/common/unistr_case_locale.cpp",
+ "/intl/icu/source/common/unistr_cnv.cpp",
+ "/intl/icu/source/common/unistr_props.cpp",
+ "/intl/icu/source/common/unistr_titlecase_brkiter.cpp",
+ "/intl/icu/source/common/unormcmp.cpp",
+ "/intl/icu/source/common/uobject.cpp",
+ "/intl/icu/source/common/uprops.cpp",
+ "/intl/icu/source/common/uresbund.cpp",
+ "/intl/icu/source/common/uresdata.cpp",
+ "/intl/icu/source/common/uscript.cpp",
+ "/intl/icu/source/common/uscript_props.cpp",
+ "/intl/icu/source/common/uset.cpp",
+ "/intl/icu/source/common/uset_props.cpp",
+ "/intl/icu/source/common/usetiter.cpp",
+ "/intl/icu/source/common/usprep.cpp",
+ "/intl/icu/source/common/ustack.cpp",
+ "/intl/icu/source/common/ustr_cnv.cpp",
+ "/intl/icu/source/common/ustr_titlecase_brkiter.cpp",
+ "/intl/icu/source/common/ustrcase.cpp",
+ "/intl/icu/source/common/ustrcase_locale.cpp",
+ "/intl/icu/source/common/ustrenum.cpp",
+ "/intl/icu/source/common/ustrfmt.cpp",
+ "/intl/icu/source/common/ustring.cpp",
+ "/intl/icu/source/common/ustrtrns.cpp",
+ "/intl/icu/source/common/utext.cpp",
+ "/intl/icu/source/common/utf_impl.cpp",
+ "/intl/icu/source/common/util.cpp",
+ "/intl/icu/source/common/utrace.cpp",
+ "/intl/icu/source/common/utrie.cpp",
+ "/intl/icu/source/common/utrie2.cpp",
+ "/intl/icu/source/common/utrie2_builder.cpp",
+ "/intl/icu/source/common/utrie_swap.cpp",
+ "/intl/icu/source/common/uts46.cpp",
+ "/intl/icu/source/common/utypes.cpp",
+ "/intl/icu/source/common/uvector.cpp",
+ "/intl/icu/source/common/uvectr32.cpp",
+ "/intl/icu/source/common/uvectr64.cpp",
+ "/intl/icu/source/common/wintz.cpp",
+]
+other_sources = [
+ "/intl/icu/source/common/bytestrieiterator.cpp",
+ "/intl/icu/source/common/cstr.cpp",
+ "/intl/icu/source/common/cwchar.cpp",
+ "/intl/icu/source/common/icudataver.cpp",
+ "/intl/icu/source/common/icuplug.cpp",
+ "/intl/icu/source/common/pluralmap.cpp",
+ "/intl/icu/source/common/propsvec.cpp",
+ "/intl/icu/source/common/resbund_cnv.cpp",
+ "/intl/icu/source/common/ubiditransform.cpp",
+ "/intl/icu/source/common/ucat.cpp",
+ "/intl/icu/source/common/ucnv2022.cpp",
+ "/intl/icu/source/common/ucnv_ct.cpp",
+ "/intl/icu/source/common/ucnv_ext.cpp",
+ "/intl/icu/source/common/ucnv_lmb.cpp",
+ "/intl/icu/source/common/ucnv_set.cpp",
+ "/intl/icu/source/common/ucnvdisp.cpp",
+ "/intl/icu/source/common/ucnvhz.cpp",
+ "/intl/icu/source/common/ucnvisci.cpp",
+ "/intl/icu/source/common/ucnvmbcs.cpp",
+ "/intl/icu/source/common/ucnvsel.cpp",
+ "/intl/icu/source/common/uidna.cpp",
+ "/intl/icu/source/common/unorm.cpp",
+ "/intl/icu/source/common/ures_cnv.cpp",
+ "/intl/icu/source/common/usc_impl.cpp",
+ "/intl/icu/source/common/ushape.cpp",
+ "/intl/icu/source/common/ustr_wcs.cpp",
+ "/intl/icu/source/common/util_props.cpp",
+]
+EXPORTS.unicode += [
+ "/intl/icu/source/common/unicode/appendable.h",
+ "/intl/icu/source/common/unicode/brkiter.h",
+ "/intl/icu/source/common/unicode/bytestream.h",
+ "/intl/icu/source/common/unicode/bytestrie.h",
+ "/intl/icu/source/common/unicode/bytestriebuilder.h",
+ "/intl/icu/source/common/unicode/caniter.h",
+ "/intl/icu/source/common/unicode/casemap.h",
+ "/intl/icu/source/common/unicode/char16ptr.h",
+ "/intl/icu/source/common/unicode/chariter.h",
+ "/intl/icu/source/common/unicode/dbbi.h",
+ "/intl/icu/source/common/unicode/docmain.h",
+ "/intl/icu/source/common/unicode/dtintrv.h",
+ "/intl/icu/source/common/unicode/edits.h",
+ "/intl/icu/source/common/unicode/enumset.h",
+ "/intl/icu/source/common/unicode/errorcode.h",
+ "/intl/icu/source/common/unicode/filteredbrk.h",
+ "/intl/icu/source/common/unicode/icudataver.h",
+ "/intl/icu/source/common/unicode/icuplug.h",
+ "/intl/icu/source/common/unicode/idna.h",
+ "/intl/icu/source/common/unicode/localebuilder.h",
+ "/intl/icu/source/common/unicode/localematcher.h",
+ "/intl/icu/source/common/unicode/localpointer.h",
+ "/intl/icu/source/common/unicode/locdspnm.h",
+ "/intl/icu/source/common/unicode/locid.h",
+ "/intl/icu/source/common/unicode/messagepattern.h",
+ "/intl/icu/source/common/unicode/normalizer2.h",
+ "/intl/icu/source/common/unicode/normlzr.h",
+ "/intl/icu/source/common/unicode/parseerr.h",
+ "/intl/icu/source/common/unicode/parsepos.h",
+ "/intl/icu/source/common/unicode/platform.h",
+ "/intl/icu/source/common/unicode/ptypes.h",
+ "/intl/icu/source/common/unicode/putil.h",
+ "/intl/icu/source/common/unicode/rbbi.h",
+ "/intl/icu/source/common/unicode/rep.h",
+ "/intl/icu/source/common/unicode/resbund.h",
+ "/intl/icu/source/common/unicode/schriter.h",
+ "/intl/icu/source/common/unicode/simpleformatter.h",
+ "/intl/icu/source/common/unicode/std_string.h",
+ "/intl/icu/source/common/unicode/strenum.h",
+ "/intl/icu/source/common/unicode/stringoptions.h",
+ "/intl/icu/source/common/unicode/stringpiece.h",
+ "/intl/icu/source/common/unicode/stringtriebuilder.h",
+ "/intl/icu/source/common/unicode/symtable.h",
+ "/intl/icu/source/common/unicode/ubidi.h",
+ "/intl/icu/source/common/unicode/ubiditransform.h",
+ "/intl/icu/source/common/unicode/ubrk.h",
+ "/intl/icu/source/common/unicode/ucasemap.h",
+ "/intl/icu/source/common/unicode/ucat.h",
+ "/intl/icu/source/common/unicode/uchar.h",
+ "/intl/icu/source/common/unicode/ucharstrie.h",
+ "/intl/icu/source/common/unicode/ucharstriebuilder.h",
+ "/intl/icu/source/common/unicode/uchriter.h",
+ "/intl/icu/source/common/unicode/uclean.h",
+ "/intl/icu/source/common/unicode/ucnv.h",
+ "/intl/icu/source/common/unicode/ucnv_cb.h",
+ "/intl/icu/source/common/unicode/ucnv_err.h",
+ "/intl/icu/source/common/unicode/ucnvsel.h",
+ "/intl/icu/source/common/unicode/uconfig.h",
+ "/intl/icu/source/common/unicode/ucpmap.h",
+ "/intl/icu/source/common/unicode/ucptrie.h",
+ "/intl/icu/source/common/unicode/ucurr.h",
+ "/intl/icu/source/common/unicode/udata.h",
+ "/intl/icu/source/common/unicode/udisplaycontext.h",
+ "/intl/icu/source/common/unicode/uenum.h",
+ "/intl/icu/source/common/unicode/uidna.h",
+ "/intl/icu/source/common/unicode/uiter.h",
+ "/intl/icu/source/common/unicode/uldnames.h",
+ "/intl/icu/source/common/unicode/uloc.h",
+ "/intl/icu/source/common/unicode/umachine.h",
+ "/intl/icu/source/common/unicode/umisc.h",
+ "/intl/icu/source/common/unicode/umutablecptrie.h",
+ "/intl/icu/source/common/unicode/unifilt.h",
+ "/intl/icu/source/common/unicode/unifunct.h",
+ "/intl/icu/source/common/unicode/unimatch.h",
+ "/intl/icu/source/common/unicode/uniset.h",
+ "/intl/icu/source/common/unicode/unistr.h",
+ "/intl/icu/source/common/unicode/unorm.h",
+ "/intl/icu/source/common/unicode/unorm2.h",
+ "/intl/icu/source/common/unicode/uobject.h",
+ "/intl/icu/source/common/unicode/urename.h",
+ "/intl/icu/source/common/unicode/urep.h",
+ "/intl/icu/source/common/unicode/ures.h",
+ "/intl/icu/source/common/unicode/uscript.h",
+ "/intl/icu/source/common/unicode/uset.h",
+ "/intl/icu/source/common/unicode/usetiter.h",
+ "/intl/icu/source/common/unicode/ushape.h",
+ "/intl/icu/source/common/unicode/usprep.h",
+ "/intl/icu/source/common/unicode/ustring.h",
+ "/intl/icu/source/common/unicode/ustringtrie.h",
+ "/intl/icu/source/common/unicode/utext.h",
+ "/intl/icu/source/common/unicode/utf.h",
+ "/intl/icu/source/common/unicode/utf16.h",
+ "/intl/icu/source/common/unicode/utf32.h",
+ "/intl/icu/source/common/unicode/utf8.h",
+ "/intl/icu/source/common/unicode/utf_old.h",
+ "/intl/icu/source/common/unicode/utrace.h",
+ "/intl/icu/source/common/unicode/utypes.h",
+ "/intl/icu/source/common/unicode/uvernum.h",
+ "/intl/icu/source/common/unicode/uversion.h",
+]
diff --git a/config/external/icu/data/convert_icudata.py b/config/external/icu/data/convert_icudata.py
new file mode 100644
index 0000000000..b09affb9d8
--- /dev/null
+++ b/config/external/icu/data/convert_icudata.py
@@ -0,0 +1,20 @@
+# 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/.
+
+import os
+import subprocess
+
+import buildconfig
+
+
+def main(output, data_file):
+ output.close()
+ subprocess.run(
+ [
+ os.path.join(buildconfig.topobjdir, "dist", "host", "bin", "icupkg"),
+ "-tb",
+ data_file,
+ output.name,
+ ]
+ )
diff --git a/config/external/icu/data/icu_data.S b/config/external/icu/data/icu_data.S
new file mode 100644
index 0000000000..6ca4ce5973
--- /dev/null
+++ b/config/external/icu/data/icu_data.S
@@ -0,0 +1,29 @@
+/* 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/. */
+
+#if defined(_WIN32) && defined(__i386__)
+// Mark the object as SAFESEH-enabled.
+.def @feat.00;
+.scl 3;
+.type 0;
+.endef
+.global @feat.00
+.set @feat.00, 1
+#endif
+
+.global ICU_DATA_SYMBOL
+#if defined(__APPLE__)
+.data
+.const
+#elif defined(__wasi__)
+.section .rodata,"",@
+#else
+.section .rodata
+#endif
+.balign 16
+ICU_DATA_SYMBOL:
+.incbin ICU_DATA_FILE
+#ifdef __wasi__
+.size ICU_DATA_SYMBOL, . - ICU_DATA_SYMBOL
+#endif
diff --git a/config/external/icu/data/icudt73l.dat b/config/external/icu/data/icudt73l.dat
new file mode 100644
index 0000000000..b7c80341a8
--- /dev/null
+++ b/config/external/icu/data/icudt73l.dat
Binary files differ
diff --git a/config/external/icu/data/moz.build b/config/external/icu/data/moz.build
new file mode 100644
index 0000000000..88926c94fa
--- /dev/null
+++ b/config/external/icu/data/moz.build
@@ -0,0 +1,40 @@
+# -*- 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/.
+
+# Build a library containing the ICU data for use in the JS shell, so that
+# JSAPI consumers don't have to deal with setting ICU's data path.
+Library("icudata")
+
+LOCAL_INCLUDES += ["."]
+
+prefix = ""
+if (CONFIG["OS_ARCH"] == "WINNT" and CONFIG["TARGET_CPU"] == "x86") or CONFIG[
+ "OS_ARCH"
+] == "Darwin":
+ prefix = "_"
+
+data_file = {
+ "little": "icudt%sl.dat" % CONFIG["MOZ_ICU_VERSION"],
+ "big": "icudt%sb.dat" % CONFIG["MOZ_ICU_VERSION"],
+}
+data_dir = {
+ "little": SRCDIR,
+ "big": OBJDIR,
+}
+endianness = CONFIG["TARGET_ENDIANNESS"] or "little"
+DEFINES["ICU_DATA_FILE"] = '"%s/%s"' % (data_dir[endianness], data_file[endianness])
+DEFINES["ICU_DATA_SYMBOL"] = "%sicudt%s_dat" % (prefix, CONFIG["MOZ_ICU_VERSION"])
+SOURCES += [
+ "icu_data.S",
+]
+
+if CONFIG["OS_ARCH"] == "WINNT" and CONFIG["CC_TYPE"] == "clang-cl":
+ USE_INTEGRATED_CLANGCL_AS = True
+
+if CONFIG["TARGET_ENDIANNESS"] == "big":
+ GeneratedFile(
+ data_file["big"], script="convert_icudata.py", inputs=[data_file["little"]]
+ )
diff --git a/config/external/icu/defs.mozbuild b/config/external/icu/defs.mozbuild
new file mode 100644
index 0000000000..d6d75358ef
--- /dev/null
+++ b/config/external/icu/defs.mozbuild
@@ -0,0 +1,75 @@
+# -*- 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/.
+
+# Also see <http://www.icu-project.org/repos/icu/tags/latest/icu4c/readme.html#RecBuild> for the
+# recommended build options when compiling ICU.
+# Don't use icu namespace automatically in client code.
+DEFINES["U_USING_ICU_NAMESPACE"] = 0
+# Don't include obsolete header files.
+DEFINES["U_NO_DEFAULT_INCLUDE_UTF_HEADERS"] = 1
+DEFINES["U_HIDE_OBSOLETE_UTF_OLD_H"] = 1
+
+# Remove chunks of the library that we don't need (yet).
+DEFINES["UCONFIG_NO_LEGACY_CONVERSION"] = True
+DEFINES["UCONFIG_NO_TRANSLITERATION"] = True
+DEFINES["UCONFIG_NO_REGULAR_EXPRESSIONS"] = True
+DEFINES["UCONFIG_NO_BREAK_ITERATION"] = True
+
+# We don't need to pass data to and from legacy char* APIs.
+DEFINES["U_CHARSET_IS_UTF8"] = True
+
+# Add 'explicit' keyword to UnicodeString constructors.
+DEFINES["UNISTR_FROM_CHAR_EXPLICIT"] = "explicit"
+DEFINES["UNISTR_FROM_STRING_EXPLICIT"] = "explicit"
+
+# Disable dynamic loading of ICU data as a loadable library.
+DEFINES["U_ENABLE_DYLOAD"] = 0
+
+if not CONFIG["HAVE_LANGINFO_CODESET"]:
+ DEFINES["U_HAVE_NL_LANGINFO_CODESET"] = 0
+
+if CONFIG["MOZ_DEBUG"]:
+ DEFINES["U_DEBUG"] = 1
+
+# ICU requires RTTI
+if CONFIG["CC_TYPE"] in ("clang", "gcc"):
+ CXXFLAGS += ["-frtti"]
+elif CONFIG["OS_TARGET"] == "WINNT":
+ # Remove the -GR- flag so we don't get a bunch of warning spam.
+ COMPILE_FLAGS["OS_CXXFLAGS"] = [
+ f for f in COMPILE_FLAGS["OS_CXXFLAGS"] if f != "-GR-"
+ ] + ["-GR"]
+
+DisableStlWrapping()
+AllowCompilerWarnings()
+
+# We allow compiler warnings, but we can at least cut down on spammy
+# warnings that get triggered for every file.
+if CONFIG["CC_TYPE"] in ("clang", "clang-cl"):
+ CFLAGS += [
+ "-Wno-c++20-compat",
+ "-Wno-comma",
+ "-Wno-implicit-const-int-float-conversion",
+ "-Wno-macro-redefined",
+ "-Wno-microsoft-include",
+ "-Wno-tautological-unsigned-enum-zero-compare",
+ "-Wno-unreachable-code-loop-increment",
+ "-Wno-unreachable-code-return",
+ ]
+ CXXFLAGS += [
+ "-Wno-c++20-compat",
+ "-Wno-comma",
+ "-Wno-implicit-const-int-float-conversion",
+ "-Wno-macro-redefined",
+ "-Wno-microsoft-include",
+ "-Wno-tautological-unsigned-enum-zero-compare",
+ "-Wno-unreachable-code-loop-increment",
+ "-Wno-unreachable-code-return",
+ ]
+
+for k, v in DEFINES.items():
+ if k != "UCONFIG_NO_LEGACY_CONVERSION":
+ HOST_DEFINES[k] = v
diff --git a/config/external/icu/i18n/moz.build b/config/external/icu/i18n/moz.build
new file mode 100644
index 0000000000..098aa7843f
--- /dev/null
+++ b/config/external/icu/i18n/moz.build
@@ -0,0 +1,24 @@
+# -*- 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/.
+
+Library("icui18n")
+FINAL_LIBRARY = "icu"
+
+DEFINES["U_I18N_IMPLEMENTATION"] = True
+
+LOCAL_INCLUDES += ["/intl/icu/source/common"]
+LOCAL_INCLUDES += ["/mfbt/double-conversion"]
+
+include("../defs.mozbuild")
+include("sources.mozbuild")
+
+SOURCES += sources
+
+if CONFIG["TARGET_ENDIANNESS"] == "big":
+ HostLibrary("host_icui18n")
+ HOST_DEFINES["U_I18N_IMPLEMENTATION"] = True
+ HOST_SOURCES += sources
+ HOST_SOURCES += other_sources
diff --git a/config/external/icu/i18n/sources.mozbuild b/config/external/icu/i18n/sources.mozbuild
new file mode 100644
index 0000000000..b985d9be73
--- /dev/null
+++ b/config/external/icu/i18n/sources.mozbuild
@@ -0,0 +1,344 @@
+# THIS FILE IS GENERATED BY /intl/icu_sources_data.py DO NOT EDIT
+sources = [
+ "/intl/icu/source/i18n/astro.cpp",
+ "/intl/icu/source/i18n/basictz.cpp",
+ "/intl/icu/source/i18n/bocsu.cpp",
+ "/intl/icu/source/i18n/buddhcal.cpp",
+ "/intl/icu/source/i18n/calendar.cpp",
+ "/intl/icu/source/i18n/cecal.cpp",
+ "/intl/icu/source/i18n/chnsecal.cpp",
+ "/intl/icu/source/i18n/choicfmt.cpp",
+ "/intl/icu/source/i18n/coleitr.cpp",
+ "/intl/icu/source/i18n/coll.cpp",
+ "/intl/icu/source/i18n/collation.cpp",
+ "/intl/icu/source/i18n/collationbuilder.cpp",
+ "/intl/icu/source/i18n/collationcompare.cpp",
+ "/intl/icu/source/i18n/collationdata.cpp",
+ "/intl/icu/source/i18n/collationdatabuilder.cpp",
+ "/intl/icu/source/i18n/collationdatareader.cpp",
+ "/intl/icu/source/i18n/collationdatawriter.cpp",
+ "/intl/icu/source/i18n/collationfastlatin.cpp",
+ "/intl/icu/source/i18n/collationfastlatinbuilder.cpp",
+ "/intl/icu/source/i18n/collationfcd.cpp",
+ "/intl/icu/source/i18n/collationiterator.cpp",
+ "/intl/icu/source/i18n/collationkeys.cpp",
+ "/intl/icu/source/i18n/collationroot.cpp",
+ "/intl/icu/source/i18n/collationrootelements.cpp",
+ "/intl/icu/source/i18n/collationruleparser.cpp",
+ "/intl/icu/source/i18n/collationsets.cpp",
+ "/intl/icu/source/i18n/collationsettings.cpp",
+ "/intl/icu/source/i18n/collationtailoring.cpp",
+ "/intl/icu/source/i18n/collationweights.cpp",
+ "/intl/icu/source/i18n/compactdecimalformat.cpp",
+ "/intl/icu/source/i18n/coptccal.cpp",
+ "/intl/icu/source/i18n/curramt.cpp",
+ "/intl/icu/source/i18n/currfmt.cpp",
+ "/intl/icu/source/i18n/currpinf.cpp",
+ "/intl/icu/source/i18n/currunit.cpp",
+ "/intl/icu/source/i18n/dangical.cpp",
+ "/intl/icu/source/i18n/datefmt.cpp",
+ "/intl/icu/source/i18n/dayperiodrules.cpp",
+ "/intl/icu/source/i18n/dcfmtsym.cpp",
+ "/intl/icu/source/i18n/decContext.cpp",
+ "/intl/icu/source/i18n/decimfmt.cpp",
+ "/intl/icu/source/i18n/decNumber.cpp",
+ "/intl/icu/source/i18n/displayoptions.cpp",
+ "/intl/icu/source/i18n/dtfmtsym.cpp",
+ "/intl/icu/source/i18n/dtitvfmt.cpp",
+ "/intl/icu/source/i18n/dtitvinf.cpp",
+ "/intl/icu/source/i18n/dtptngen.cpp",
+ "/intl/icu/source/i18n/dtrule.cpp",
+ "/intl/icu/source/i18n/erarules.cpp",
+ "/intl/icu/source/i18n/ethpccal.cpp",
+ "/intl/icu/source/i18n/fmtable.cpp",
+ "/intl/icu/source/i18n/format.cpp",
+ "/intl/icu/source/i18n/formatted_string_builder.cpp",
+ "/intl/icu/source/i18n/formattedval_iterimpl.cpp",
+ "/intl/icu/source/i18n/formattedval_sbimpl.cpp",
+ "/intl/icu/source/i18n/formattedvalue.cpp",
+ "/intl/icu/source/i18n/fphdlimp.cpp",
+ "/intl/icu/source/i18n/fpositer.cpp",
+ "/intl/icu/source/i18n/gregocal.cpp",
+ "/intl/icu/source/i18n/gregoimp.cpp",
+ "/intl/icu/source/i18n/hebrwcal.cpp",
+ "/intl/icu/source/i18n/indiancal.cpp",
+ "/intl/icu/source/i18n/islamcal.cpp",
+ "/intl/icu/source/i18n/iso8601cal.cpp",
+ "/intl/icu/source/i18n/japancal.cpp",
+ "/intl/icu/source/i18n/listformatter.cpp",
+ "/intl/icu/source/i18n/measfmt.cpp",
+ "/intl/icu/source/i18n/measunit.cpp",
+ "/intl/icu/source/i18n/measunit_extra.cpp",
+ "/intl/icu/source/i18n/measure.cpp",
+ "/intl/icu/source/i18n/msgfmt.cpp",
+ "/intl/icu/source/i18n/nfrs.cpp",
+ "/intl/icu/source/i18n/nfrule.cpp",
+ "/intl/icu/source/i18n/nfsubs.cpp",
+ "/intl/icu/source/i18n/number_affixutils.cpp",
+ "/intl/icu/source/i18n/number_asformat.cpp",
+ "/intl/icu/source/i18n/number_capi.cpp",
+ "/intl/icu/source/i18n/number_compact.cpp",
+ "/intl/icu/source/i18n/number_currencysymbols.cpp",
+ "/intl/icu/source/i18n/number_decimalquantity.cpp",
+ "/intl/icu/source/i18n/number_decimfmtprops.cpp",
+ "/intl/icu/source/i18n/number_fluent.cpp",
+ "/intl/icu/source/i18n/number_formatimpl.cpp",
+ "/intl/icu/source/i18n/number_grouping.cpp",
+ "/intl/icu/source/i18n/number_integerwidth.cpp",
+ "/intl/icu/source/i18n/number_longnames.cpp",
+ "/intl/icu/source/i18n/number_mapper.cpp",
+ "/intl/icu/source/i18n/number_modifiers.cpp",
+ "/intl/icu/source/i18n/number_multiplier.cpp",
+ "/intl/icu/source/i18n/number_notation.cpp",
+ "/intl/icu/source/i18n/number_output.cpp",
+ "/intl/icu/source/i18n/number_padding.cpp",
+ "/intl/icu/source/i18n/number_patternmodifier.cpp",
+ "/intl/icu/source/i18n/number_patternstring.cpp",
+ "/intl/icu/source/i18n/number_rounding.cpp",
+ "/intl/icu/source/i18n/number_scientific.cpp",
+ "/intl/icu/source/i18n/number_simple.cpp",
+ "/intl/icu/source/i18n/number_skeletons.cpp",
+ "/intl/icu/source/i18n/number_symbolswrapper.cpp",
+ "/intl/icu/source/i18n/number_usageprefs.cpp",
+ "/intl/icu/source/i18n/number_utils.cpp",
+ "/intl/icu/source/i18n/numfmt.cpp",
+ "/intl/icu/source/i18n/numparse_affixes.cpp",
+ "/intl/icu/source/i18n/numparse_compositions.cpp",
+ "/intl/icu/source/i18n/numparse_currency.cpp",
+ "/intl/icu/source/i18n/numparse_decimal.cpp",
+ "/intl/icu/source/i18n/numparse_impl.cpp",
+ "/intl/icu/source/i18n/numparse_parsednumber.cpp",
+ "/intl/icu/source/i18n/numparse_scientific.cpp",
+ "/intl/icu/source/i18n/numparse_symbols.cpp",
+ "/intl/icu/source/i18n/numparse_validators.cpp",
+ "/intl/icu/source/i18n/numrange_capi.cpp",
+ "/intl/icu/source/i18n/numrange_fluent.cpp",
+ "/intl/icu/source/i18n/numrange_impl.cpp",
+ "/intl/icu/source/i18n/numsys.cpp",
+ "/intl/icu/source/i18n/olsontz.cpp",
+ "/intl/icu/source/i18n/persncal.cpp",
+ "/intl/icu/source/i18n/pluralranges.cpp",
+ "/intl/icu/source/i18n/plurfmt.cpp",
+ "/intl/icu/source/i18n/plurrule.cpp",
+ "/intl/icu/source/i18n/quantityformatter.cpp",
+ "/intl/icu/source/i18n/rbnf.cpp",
+ "/intl/icu/source/i18n/rbtz.cpp",
+ "/intl/icu/source/i18n/region.cpp",
+ "/intl/icu/source/i18n/reldatefmt.cpp",
+ "/intl/icu/source/i18n/reldtfmt.cpp",
+ "/intl/icu/source/i18n/rulebasedcollator.cpp",
+ "/intl/icu/source/i18n/scriptset.cpp",
+ "/intl/icu/source/i18n/search.cpp",
+ "/intl/icu/source/i18n/selfmt.cpp",
+ "/intl/icu/source/i18n/sharedbreakiterator.cpp",
+ "/intl/icu/source/i18n/simpletz.cpp",
+ "/intl/icu/source/i18n/smpdtfmt.cpp",
+ "/intl/icu/source/i18n/smpdtfst.cpp",
+ "/intl/icu/source/i18n/sortkey.cpp",
+ "/intl/icu/source/i18n/standardplural.cpp",
+ "/intl/icu/source/i18n/string_segment.cpp",
+ "/intl/icu/source/i18n/stsearch.cpp",
+ "/intl/icu/source/i18n/taiwncal.cpp",
+ "/intl/icu/source/i18n/timezone.cpp",
+ "/intl/icu/source/i18n/tmunit.cpp",
+ "/intl/icu/source/i18n/tmutamt.cpp",
+ "/intl/icu/source/i18n/tmutfmt.cpp",
+ "/intl/icu/source/i18n/tzfmt.cpp",
+ "/intl/icu/source/i18n/tzgnames.cpp",
+ "/intl/icu/source/i18n/tznames.cpp",
+ "/intl/icu/source/i18n/tznames_impl.cpp",
+ "/intl/icu/source/i18n/tzrule.cpp",
+ "/intl/icu/source/i18n/tztrans.cpp",
+ "/intl/icu/source/i18n/ucal.cpp",
+ "/intl/icu/source/i18n/ucln_in.cpp",
+ "/intl/icu/source/i18n/ucol.cpp",
+ "/intl/icu/source/i18n/ucol_res.cpp",
+ "/intl/icu/source/i18n/ucol_sit.cpp",
+ "/intl/icu/source/i18n/ucoleitr.cpp",
+ "/intl/icu/source/i18n/udat.cpp",
+ "/intl/icu/source/i18n/udateintervalformat.cpp",
+ "/intl/icu/source/i18n/udatpg.cpp",
+ "/intl/icu/source/i18n/ufieldpositer.cpp",
+ "/intl/icu/source/i18n/uitercollationiterator.cpp",
+ "/intl/icu/source/i18n/ulistformatter.cpp",
+ "/intl/icu/source/i18n/umsg.cpp",
+ "/intl/icu/source/i18n/units_complexconverter.cpp",
+ "/intl/icu/source/i18n/units_converter.cpp",
+ "/intl/icu/source/i18n/units_data.cpp",
+ "/intl/icu/source/i18n/units_router.cpp",
+ "/intl/icu/source/i18n/unum.cpp",
+ "/intl/icu/source/i18n/unumsys.cpp",
+ "/intl/icu/source/i18n/upluralrules.cpp",
+ "/intl/icu/source/i18n/usearch.cpp",
+ "/intl/icu/source/i18n/uspoof.cpp",
+ "/intl/icu/source/i18n/uspoof_impl.cpp",
+ "/intl/icu/source/i18n/utf16collationiterator.cpp",
+ "/intl/icu/source/i18n/utf8collationiterator.cpp",
+ "/intl/icu/source/i18n/utmscale.cpp",
+ "/intl/icu/source/i18n/vtzone.cpp",
+ "/intl/icu/source/i18n/windtfmt.cpp",
+ "/intl/icu/source/i18n/winnmfmt.cpp",
+ "/intl/icu/source/i18n/wintzimpl.cpp",
+ "/intl/icu/source/i18n/zonemeta.cpp",
+]
+other_sources = [
+ "/intl/icu/source/i18n/alphaindex.cpp",
+ "/intl/icu/source/i18n/anytrans.cpp",
+ "/intl/icu/source/i18n/brktrans.cpp",
+ "/intl/icu/source/i18n/casetrn.cpp",
+ "/intl/icu/source/i18n/cpdtrans.cpp",
+ "/intl/icu/source/i18n/csdetect.cpp",
+ "/intl/icu/source/i18n/csmatch.cpp",
+ "/intl/icu/source/i18n/csr2022.cpp",
+ "/intl/icu/source/i18n/csrecog.cpp",
+ "/intl/icu/source/i18n/csrmbcs.cpp",
+ "/intl/icu/source/i18n/csrsbcs.cpp",
+ "/intl/icu/source/i18n/csrucode.cpp",
+ "/intl/icu/source/i18n/csrutf8.cpp",
+ "/intl/icu/source/i18n/double-conversion-bignum-dtoa.cpp",
+ "/intl/icu/source/i18n/double-conversion-bignum.cpp",
+ "/intl/icu/source/i18n/double-conversion-cached-powers.cpp",
+ "/intl/icu/source/i18n/double-conversion-double-to-string.cpp",
+ "/intl/icu/source/i18n/double-conversion-fast-dtoa.cpp",
+ "/intl/icu/source/i18n/double-conversion-string-to-double.cpp",
+ "/intl/icu/source/i18n/double-conversion-strtod.cpp",
+ "/intl/icu/source/i18n/esctrn.cpp",
+ "/intl/icu/source/i18n/fmtable_cnv.cpp",
+ "/intl/icu/source/i18n/funcrepl.cpp",
+ "/intl/icu/source/i18n/gender.cpp",
+ "/intl/icu/source/i18n/inputext.cpp",
+ "/intl/icu/source/i18n/name2uni.cpp",
+ "/intl/icu/source/i18n/nortrans.cpp",
+ "/intl/icu/source/i18n/nultrans.cpp",
+ "/intl/icu/source/i18n/quant.cpp",
+ "/intl/icu/source/i18n/rbt.cpp",
+ "/intl/icu/source/i18n/rbt_data.cpp",
+ "/intl/icu/source/i18n/rbt_pars.cpp",
+ "/intl/icu/source/i18n/rbt_rule.cpp",
+ "/intl/icu/source/i18n/rbt_set.cpp",
+ "/intl/icu/source/i18n/regexcmp.cpp",
+ "/intl/icu/source/i18n/regeximp.cpp",
+ "/intl/icu/source/i18n/regexst.cpp",
+ "/intl/icu/source/i18n/regextxt.cpp",
+ "/intl/icu/source/i18n/rematch.cpp",
+ "/intl/icu/source/i18n/remtrans.cpp",
+ "/intl/icu/source/i18n/repattrn.cpp",
+ "/intl/icu/source/i18n/scientificnumberformatter.cpp",
+ "/intl/icu/source/i18n/strmatch.cpp",
+ "/intl/icu/source/i18n/strrepl.cpp",
+ "/intl/icu/source/i18n/titletrn.cpp",
+ "/intl/icu/source/i18n/tolowtrn.cpp",
+ "/intl/icu/source/i18n/toupptrn.cpp",
+ "/intl/icu/source/i18n/translit.cpp",
+ "/intl/icu/source/i18n/transreg.cpp",
+ "/intl/icu/source/i18n/tridpars.cpp",
+ "/intl/icu/source/i18n/ucsdet.cpp",
+ "/intl/icu/source/i18n/ulocdata.cpp",
+ "/intl/icu/source/i18n/unesctrn.cpp",
+ "/intl/icu/source/i18n/uni2name.cpp",
+ "/intl/icu/source/i18n/uregex.cpp",
+ "/intl/icu/source/i18n/uregexc.cpp",
+ "/intl/icu/source/i18n/uregion.cpp",
+ "/intl/icu/source/i18n/uspoof_build.cpp",
+ "/intl/icu/source/i18n/uspoof_conf.cpp",
+ "/intl/icu/source/i18n/utrans.cpp",
+ "/intl/icu/source/i18n/vzone.cpp",
+ "/intl/icu/source/i18n/zrule.cpp",
+ "/intl/icu/source/i18n/ztrans.cpp",
+]
+EXPORTS.unicode += [
+ "/intl/icu/source/i18n/unicode/alphaindex.h",
+ "/intl/icu/source/i18n/unicode/basictz.h",
+ "/intl/icu/source/i18n/unicode/calendar.h",
+ "/intl/icu/source/i18n/unicode/choicfmt.h",
+ "/intl/icu/source/i18n/unicode/coleitr.h",
+ "/intl/icu/source/i18n/unicode/coll.h",
+ "/intl/icu/source/i18n/unicode/compactdecimalformat.h",
+ "/intl/icu/source/i18n/unicode/curramt.h",
+ "/intl/icu/source/i18n/unicode/currpinf.h",
+ "/intl/icu/source/i18n/unicode/currunit.h",
+ "/intl/icu/source/i18n/unicode/datefmt.h",
+ "/intl/icu/source/i18n/unicode/dcfmtsym.h",
+ "/intl/icu/source/i18n/unicode/decimfmt.h",
+ "/intl/icu/source/i18n/unicode/displayoptions.h",
+ "/intl/icu/source/i18n/unicode/dtfmtsym.h",
+ "/intl/icu/source/i18n/unicode/dtitvfmt.h",
+ "/intl/icu/source/i18n/unicode/dtitvinf.h",
+ "/intl/icu/source/i18n/unicode/dtptngen.h",
+ "/intl/icu/source/i18n/unicode/dtrule.h",
+ "/intl/icu/source/i18n/unicode/fieldpos.h",
+ "/intl/icu/source/i18n/unicode/fmtable.h",
+ "/intl/icu/source/i18n/unicode/format.h",
+ "/intl/icu/source/i18n/unicode/formattednumber.h",
+ "/intl/icu/source/i18n/unicode/formattedvalue.h",
+ "/intl/icu/source/i18n/unicode/fpositer.h",
+ "/intl/icu/source/i18n/unicode/gender.h",
+ "/intl/icu/source/i18n/unicode/gregocal.h",
+ "/intl/icu/source/i18n/unicode/listformatter.h",
+ "/intl/icu/source/i18n/unicode/measfmt.h",
+ "/intl/icu/source/i18n/unicode/measunit.h",
+ "/intl/icu/source/i18n/unicode/measure.h",
+ "/intl/icu/source/i18n/unicode/msgfmt.h",
+ "/intl/icu/source/i18n/unicode/nounit.h",
+ "/intl/icu/source/i18n/unicode/numberformatter.h",
+ "/intl/icu/source/i18n/unicode/numberrangeformatter.h",
+ "/intl/icu/source/i18n/unicode/numfmt.h",
+ "/intl/icu/source/i18n/unicode/numsys.h",
+ "/intl/icu/source/i18n/unicode/plurfmt.h",
+ "/intl/icu/source/i18n/unicode/plurrule.h",
+ "/intl/icu/source/i18n/unicode/rbnf.h",
+ "/intl/icu/source/i18n/unicode/rbtz.h",
+ "/intl/icu/source/i18n/unicode/regex.h",
+ "/intl/icu/source/i18n/unicode/region.h",
+ "/intl/icu/source/i18n/unicode/reldatefmt.h",
+ "/intl/icu/source/i18n/unicode/scientificnumberformatter.h",
+ "/intl/icu/source/i18n/unicode/search.h",
+ "/intl/icu/source/i18n/unicode/selfmt.h",
+ "/intl/icu/source/i18n/unicode/simplenumberformatter.h",
+ "/intl/icu/source/i18n/unicode/simpletz.h",
+ "/intl/icu/source/i18n/unicode/smpdtfmt.h",
+ "/intl/icu/source/i18n/unicode/sortkey.h",
+ "/intl/icu/source/i18n/unicode/stsearch.h",
+ "/intl/icu/source/i18n/unicode/tblcoll.h",
+ "/intl/icu/source/i18n/unicode/timezone.h",
+ "/intl/icu/source/i18n/unicode/tmunit.h",
+ "/intl/icu/source/i18n/unicode/tmutamt.h",
+ "/intl/icu/source/i18n/unicode/tmutfmt.h",
+ "/intl/icu/source/i18n/unicode/translit.h",
+ "/intl/icu/source/i18n/unicode/tzfmt.h",
+ "/intl/icu/source/i18n/unicode/tznames.h",
+ "/intl/icu/source/i18n/unicode/tzrule.h",
+ "/intl/icu/source/i18n/unicode/tztrans.h",
+ "/intl/icu/source/i18n/unicode/ucal.h",
+ "/intl/icu/source/i18n/unicode/ucol.h",
+ "/intl/icu/source/i18n/unicode/ucoleitr.h",
+ "/intl/icu/source/i18n/unicode/ucsdet.h",
+ "/intl/icu/source/i18n/unicode/udat.h",
+ "/intl/icu/source/i18n/unicode/udateintervalformat.h",
+ "/intl/icu/source/i18n/unicode/udatpg.h",
+ "/intl/icu/source/i18n/unicode/udisplayoptions.h",
+ "/intl/icu/source/i18n/unicode/ufieldpositer.h",
+ "/intl/icu/source/i18n/unicode/uformattable.h",
+ "/intl/icu/source/i18n/unicode/uformattednumber.h",
+ "/intl/icu/source/i18n/unicode/uformattedvalue.h",
+ "/intl/icu/source/i18n/unicode/ugender.h",
+ "/intl/icu/source/i18n/unicode/ulistformatter.h",
+ "/intl/icu/source/i18n/unicode/ulocdata.h",
+ "/intl/icu/source/i18n/unicode/umsg.h",
+ "/intl/icu/source/i18n/unicode/unirepl.h",
+ "/intl/icu/source/i18n/unicode/unum.h",
+ "/intl/icu/source/i18n/unicode/unumberformatter.h",
+ "/intl/icu/source/i18n/unicode/unumberoptions.h",
+ "/intl/icu/source/i18n/unicode/unumberrangeformatter.h",
+ "/intl/icu/source/i18n/unicode/unumsys.h",
+ "/intl/icu/source/i18n/unicode/upluralrules.h",
+ "/intl/icu/source/i18n/unicode/uregex.h",
+ "/intl/icu/source/i18n/unicode/uregion.h",
+ "/intl/icu/source/i18n/unicode/ureldatefmt.h",
+ "/intl/icu/source/i18n/unicode/usearch.h",
+ "/intl/icu/source/i18n/unicode/usimplenumberformatter.h",
+ "/intl/icu/source/i18n/unicode/uspoof.h",
+ "/intl/icu/source/i18n/unicode/utmscale.h",
+ "/intl/icu/source/i18n/unicode/utrans.h",
+ "/intl/icu/source/i18n/unicode/vtzone.h",
+]
diff --git a/config/external/icu/icupkg/moz.build b/config/external/icu/icupkg/moz.build
new file mode 100644
index 0000000000..39314fbda7
--- /dev/null
+++ b/config/external/icu/icupkg/moz.build
@@ -0,0 +1,27 @@
+# -*- 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/.
+
+HostProgram("icupkg")
+
+LOCAL_INCLUDES += [
+ "/intl/icu/source/common",
+ "/intl/icu/source/i18n",
+ "/intl/icu/source/tools/toolutil",
+]
+
+include("../defs.mozbuild")
+include("sources.mozbuild")
+
+HOST_SOURCES += sources
+HOST_SOURCES += [
+ "/intl/icu/source/stubdata/stubdata.cpp",
+]
+
+HOST_USE_LIBS += [
+ "host_icui18n",
+ "host_icutoolutil",
+ "host_icuuc",
+]
diff --git a/config/external/icu/icupkg/sources.mozbuild b/config/external/icu/icupkg/sources.mozbuild
new file mode 100644
index 0000000000..8040087ccd
--- /dev/null
+++ b/config/external/icu/icupkg/sources.mozbuild
@@ -0,0 +1,4 @@
+# THIS FILE IS GENERATED BY /intl/icu_sources_data.py DO NOT EDIT
+sources = [
+ "/intl/icu/source/tools/icupkg/icupkg.cpp",
+]
diff --git a/config/external/icu/moz.build b/config/external/icu/moz.build
new file mode 100644
index 0000000000..296d60d521
--- /dev/null
+++ b/config/external/icu/moz.build
@@ -0,0 +1,22 @@
+# -*- 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/.
+
+Library("icu")
+
+if CONFIG["MOZ_SYSTEM_ICU"]:
+ OS_LIBS += CONFIG["MOZ_ICU_LIBS"]
+else:
+ DIRS += [
+ "common",
+ "data",
+ "i18n",
+ ]
+ if CONFIG["TARGET_ENDIANNESS"] == "big":
+ DIRS += [
+ "toolutil",
+ "icupkg",
+ ]
+ USE_LIBS += ["icudata"]
diff --git a/config/external/icu/toolutil/moz.build b/config/external/icu/toolutil/moz.build
new file mode 100644
index 0000000000..e8dc827c2b
--- /dev/null
+++ b/config/external/icu/toolutil/moz.build
@@ -0,0 +1,20 @@
+# -*- 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/.
+
+HostLibrary("host_icutoolutil")
+FINAL_LIBRARY = "icu"
+
+DEFINES["U_TOOLUTIL_IMPLEMENTATION"] = True
+
+LOCAL_INCLUDES += [
+ "/intl/icu/source/common",
+ "/intl/icu/source/i18n",
+]
+
+include("../defs.mozbuild")
+include("sources.mozbuild")
+
+HOST_SOURCES += sources
diff --git a/config/external/icu/toolutil/sources.mozbuild b/config/external/icu/toolutil/sources.mozbuild
new file mode 100644
index 0000000000..1230133e27
--- /dev/null
+++ b/config/external/icu/toolutil/sources.mozbuild
@@ -0,0 +1,27 @@
+# THIS FILE IS GENERATED BY /intl/icu_sources_data.py DO NOT EDIT
+sources = [
+ "/intl/icu/source/tools/toolutil/collationinfo.cpp",
+ "/intl/icu/source/tools/toolutil/dbgutil.cpp",
+ "/intl/icu/source/tools/toolutil/denseranges.cpp",
+ "/intl/icu/source/tools/toolutil/filestrm.cpp",
+ "/intl/icu/source/tools/toolutil/filetools.cpp",
+ "/intl/icu/source/tools/toolutil/flagparser.cpp",
+ "/intl/icu/source/tools/toolutil/package.cpp",
+ "/intl/icu/source/tools/toolutil/pkg_genc.cpp",
+ "/intl/icu/source/tools/toolutil/pkg_gencmn.cpp",
+ "/intl/icu/source/tools/toolutil/pkg_icu.cpp",
+ "/intl/icu/source/tools/toolutil/pkgitems.cpp",
+ "/intl/icu/source/tools/toolutil/ppucd.cpp",
+ "/intl/icu/source/tools/toolutil/swapimpl.cpp",
+ "/intl/icu/source/tools/toolutil/toolutil.cpp",
+ "/intl/icu/source/tools/toolutil/ucbuf.cpp",
+ "/intl/icu/source/tools/toolutil/ucln_tu.cpp",
+ "/intl/icu/source/tools/toolutil/ucm.cpp",
+ "/intl/icu/source/tools/toolutil/ucmstate.cpp",
+ "/intl/icu/source/tools/toolutil/udbgutil.cpp",
+ "/intl/icu/source/tools/toolutil/unewdata.cpp",
+ "/intl/icu/source/tools/toolutil/uoptions.cpp",
+ "/intl/icu/source/tools/toolutil/uparse.cpp",
+ "/intl/icu/source/tools/toolutil/writesrc.cpp",
+ "/intl/icu/source/tools/toolutil/xmlparser.cpp",
+]
diff --git a/config/external/lgpllibs/lgpllibs.symbols b/config/external/lgpllibs/lgpllibs.symbols
new file mode 100644
index 0000000000..2d7c36dae2
--- /dev/null
+++ b/config/external/lgpllibs/lgpllibs.symbols
@@ -0,0 +1,17 @@
+_ZN7mozilla15RLBoxSoundTouch10numSamplesEv
+_ZN7mozilla15RLBoxSoundTouch10putSamplesEPKfj
+_ZN7mozilla15RLBoxSoundTouch10setSettingEii
+_ZN7mozilla15RLBoxSoundTouch11numChannelsEv
+_ZN7mozilla15RLBoxSoundTouch11setChannelsEj
+_ZN7mozilla15RLBoxSoundTouch13setSampleRateEj
+_ZN7mozilla15RLBoxSoundTouch14receiveSamplesEPfj
+_ZN7mozilla15RLBoxSoundTouch18resizeSampleBufferEj
+_ZN7mozilla15RLBoxSoundTouch21numUnprocessedSamplesEv
+_ZN7mozilla15RLBoxSoundTouch5flushEv
+_ZN7mozilla15RLBoxSoundTouch7setRateEd
+_ZN7mozilla15RLBoxSoundTouch8setPitchEd
+_ZN7mozilla15RLBoxSoundTouch8setTempoEd
+_ZN7mozilla15RLBoxSoundTouchC1Ev
+_ZN7mozilla15RLBoxSoundTouchC2Ev
+_ZN7mozilla15RLBoxSoundTouchD1Ev
+_ZN7mozilla15RLBoxSoundTouchD2Ev
diff --git a/config/external/lgpllibs/moz.build b/config/external/lgpllibs/moz.build
new file mode 100644
index 0000000000..1ef140baea
--- /dev/null
+++ b/config/external/lgpllibs/moz.build
@@ -0,0 +1,18 @@
+# -*- 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/.
+
+# The lgpllibs library stores symbols from third-party LGPL licensed libraries,
+# such as libav and libsoundtouch. It fulfills the requirement of dynamically
+# linking these symbols into gecko.
+#
+# Any library added here should also be reflected in the about:license page.
+
+GeckoSharedLibrary("lgpllibs", linkage=None)
+SHARED_LIBRARY_NAME = "lgpllibs"
+
+# For some reason, mingw builds export way too many symbols.
+if CONFIG["TARGET_OS"] == "WINNT" and CONFIG["CC_TYPE"] != "clang-cl":
+ SYMBOLS_FILE = "lgpllibs.symbols"
diff --git a/config/external/moz.build b/config/external/moz.build
new file mode 100644
index 0000000000..2fc8df5799
--- /dev/null
+++ b/config/external/moz.build
@@ -0,0 +1,75 @@
+# -*- 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/.
+
+external_dirs = []
+
+DIRS += [
+ "gkcodecs",
+ "lgpllibs",
+ "rlbox",
+ "sqlite",
+]
+
+if CONFIG["MOZ_USING_WASM_SANDBOXING"]:
+ DIRS += [
+ "rlbox_wasm2c_sandbox",
+ "wasm2c_sandbox_compiler",
+ ]
+
+if not CONFIG["MOZ_SYSTEM_JPEG"]:
+ external_dirs += ["media/libjpeg"]
+
+DIRS += [
+ "/third_party/msgpack",
+ "/third_party/sipcc",
+]
+
+# There's no "native" brotli or woff2 yet, but probably in the future...
+external_dirs += ["modules/brotli"]
+external_dirs += ["modules/woff2"]
+
+external_dirs += ["modules/xz-embedded"]
+
+if CONFIG["MOZ_VORBIS"]:
+ external_dirs += ["media/libvorbis"]
+
+if not CONFIG["MOZ_SYSTEM_LIBVPX"]:
+ external_dirs += ["media/libvpx"]
+
+if CONFIG["MOZ_AV1"]:
+ external_dirs += ["media/libaom"]
+ external_dirs += ["media/libdav1d"]
+
+if not CONFIG["MOZ_SYSTEM_PNG"]:
+ external_dirs += ["media/libpng"]
+
+if not CONFIG["MOZ_SYSTEM_WEBP"]:
+ external_dirs += ["media/libwebp"]
+
+if CONFIG["TARGET_CPU"] == "arm":
+ external_dirs += ["media/openmax_dl/dl"]
+
+if CONFIG["MOZ_FFVPX"]:
+ external_dirs += ["media/ffvpx"]
+
+if CONFIG["MOZ_JXL"]:
+ external_dirs += ["media/libjxl", "media/highway"]
+
+external_dirs += [
+ "media/kiss_fft",
+ "media/libcubeb",
+ "media/libmkv",
+ "media/libnestegg",
+ "media/libogg",
+ "media/libopus",
+ "media/libtheora",
+ "media/libspeex_resampler",
+ "media/libsoundtouch",
+ "media/mp4parse-rust",
+ "media/psshparser",
+]
+
+DIRS += ["../../" + i for i in external_dirs]
diff --git a/config/external/nspr/_pl_bld.h b/config/external/nspr/_pl_bld.h
new file mode 100644
index 0000000000..57fb0e988f
--- /dev/null
+++ b/config/external/nspr/_pl_bld.h
@@ -0,0 +1,6 @@
+/*
+ * This file was previously generated at build time to set some preprocessor
+ * macros for use by plvrsion.c, but that file will set the values to (empty)
+ * defaults if they're not set, so this is just a stub to avoid having to
+ * generate another header file at build time.
+ */
diff --git a/config/external/nspr/_pr_bld.h b/config/external/nspr/_pr_bld.h
new file mode 100644
index 0000000000..1e36c69f13
--- /dev/null
+++ b/config/external/nspr/_pr_bld.h
@@ -0,0 +1,6 @@
+/*
+ * This file was previously generated at build time to set some preprocessor
+ * macros for use by prvrsion.c, but that file will set the values to (empty)
+ * defaults if they're not set, so this is just a stub to avoid having to
+ * generate another header file at build time.
+ */
diff --git a/config/external/nspr/ds/moz.build b/config/external/nspr/ds/moz.build
new file mode 100644
index 0000000000..d2676e2093
--- /dev/null
+++ b/config/external/nspr/ds/moz.build
@@ -0,0 +1,34 @@
+# -*- 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/.
+
+if CONFIG["MOZ_FOLD_LIBS"]:
+ Library("plds4")
+else:
+ SharedLibrary("plds4")
+ SOURCES += ["/nsprpub/lib/ds/plvrsion.c"]
+ USE_LIBS += ["nspr4"]
+
+# We allow warnings for third-party code that can be updated from upstream.
+# TODO: fix NSPR warnings and remove this
+AllowCompilerWarnings()
+
+DEFINES["_NSPR_BUILD_"] = True
+
+LOCAL_INCLUDES += [
+ "/config/external/nspr",
+ "/nsprpub/pr/include",
+]
+
+EXPORTS.nspr += [
+ "/nsprpub/lib/ds/plarena.h",
+ "/nsprpub/lib/ds/plarenas.h",
+ "/nsprpub/lib/ds/plhash.h",
+]
+
+SOURCES += [
+ "/nsprpub/lib/ds/plarena.c",
+ "/nsprpub/lib/ds/plhash.c",
+]
diff --git a/config/external/nspr/libc/moz.build b/config/external/nspr/libc/moz.build
new file mode 100644
index 0000000000..62bb8814f6
--- /dev/null
+++ b/config/external/nspr/libc/moz.build
@@ -0,0 +1,45 @@
+# -*- 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/.
+
+if CONFIG["MOZ_FOLD_LIBS"]:
+ Library("plc4")
+else:
+ SharedLibrary("plc4")
+ SOURCES += ["/nsprpub/lib/libc/src/plvrsion.c"]
+ USE_LIBS += ["nspr4"]
+
+# We allow warnings for third-party code that can be updated from upstream.
+# TODO: fix NSPR warnings and remove this
+AllowCompilerWarnings()
+
+DEFINES["_NSPR_BUILD_"] = True
+
+LOCAL_INCLUDES += [
+ "/config/external/nspr",
+]
+
+EXPORTS.nspr += [
+ "/nsprpub/lib/libc/include/plbase64.h",
+ "/nsprpub/lib/libc/include/plerror.h",
+ "/nsprpub/lib/libc/include/plgetopt.h",
+ "/nsprpub/lib/libc/include/plstr.h",
+]
+
+SOURCES += [
+ "/nsprpub/lib/libc/src/base64.c",
+ "/nsprpub/lib/libc/src/plerror.c",
+ "/nsprpub/lib/libc/src/plgetopt.c",
+ "/nsprpub/lib/libc/src/strcase.c",
+ "/nsprpub/lib/libc/src/strcat.c",
+ "/nsprpub/lib/libc/src/strchr.c",
+ "/nsprpub/lib/libc/src/strcmp.c",
+ "/nsprpub/lib/libc/src/strcpy.c",
+ "/nsprpub/lib/libc/src/strdup.c",
+ "/nsprpub/lib/libc/src/strlen.c",
+ "/nsprpub/lib/libc/src/strpbrk.c",
+ "/nsprpub/lib/libc/src/strstr.c",
+ "/nsprpub/lib/libc/src/strtok.c",
+]
diff --git a/config/external/nspr/moz.build b/config/external/nspr/moz.build
new file mode 100644
index 0000000000..f2b3d4e8c1
--- /dev/null
+++ b/config/external/nspr/moz.build
@@ -0,0 +1,28 @@
+# -*- 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/.
+
+Library("nspr")
+
+if CONFIG["MOZ_BUILD_NSPR"]:
+ DIRS += [
+ "pr",
+ "ds",
+ "libc",
+ ]
+ if CONFIG["MOZ_FOLD_LIBS"]:
+ # When folding libraries, nspr is actually in the nss library.
+ USE_LIBS += [
+ "nss",
+ ]
+ else:
+ USE_LIBS += [
+ "nspr4",
+ "plc4",
+ "plds4",
+ ]
+ EXPORTS.nspr += ["prcpucfg.h"]
+else:
+ OS_LIBS += CONFIG["NSPR_LIBS"]
diff --git a/config/external/nspr/pr/moz.build b/config/external/nspr/pr/moz.build
new file mode 100644
index 0000000000..cf1ebf1cc0
--- /dev/null
+++ b/config/external/nspr/pr/moz.build
@@ -0,0 +1,254 @@
+# -*- 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/.
+
+if CONFIG["MOZ_FOLD_LIBS"]:
+ Library("nspr4")
+else:
+ SharedLibrary("nspr4")
+
+# We allow warnings for third-party code that can be updated from upstream.
+# TODO: fix NSPR warnings and remove this
+AllowCompilerWarnings()
+
+DEFINES["_NSPR_BUILD_"] = True
+if CONFIG["OS_ARCH"] == "Linux":
+ OS_LIBS += CONFIG["REALTIME_LIBS"]
+ DEFINES["LINUX"] = True
+ DEFINES["HAVE_FCNTL_FILE_LOCKING"] = True
+ DEFINES["HAVE_POINTER_LOCALTIME_R"] = True
+ DEFINES["_GNU_SOURCE"] = True
+ SOURCES += ["/nsprpub/pr/src/md/unix/linux.c"]
+ if CONFIG["TARGET_CPU"] == "x86_64":
+ SOURCES += ["/nsprpub/pr/src/md/unix/os_Linux_x86_64.s"]
+ elif CONFIG["TARGET_CPU"] == "x86":
+ DEFINES["i386"] = True
+ SOURCES += ["/nsprpub/pr/src/md/unix/os_Linux_x86.s"]
+ elif CONFIG["TARGET_CPU"] == "ppc":
+ SOURCES += ["/nsprpub/pr/src/md/unix/os_Linux_ppc.s"]
+elif CONFIG["OS_TARGET"] in ("FreeBSD", "OpenBSD", "NetBSD"):
+ DEFINES["HAVE_BSD_FLOCK"] = True
+ DEFINES["HAVE_SOCKLEN_T"] = True
+ DEFINES["HAVE_POINTER_LOCALTIME_R"] = True
+ DEFINES[CONFIG["OS_TARGET"].upper()] = True
+ SOURCES += ["/nsprpub/pr/src/md/unix/%s.c" % CONFIG["OS_TARGET"].lower()]
+elif CONFIG["OS_TARGET"] == "Darwin":
+ OS_LIBS += ["-framework CoreServices"]
+ # See also IncreaseDescriptorLimits in toolkit/xre/nsAppRunner.cpp
+ DEFINES["FD_SETSIZE"] = 4096
+ DEFINES["_DARWIN_UNLIMITED_SELECT"] = True
+ DEFINES["HAS_CONNECTX"] = True
+ DEFINES["DARWIN"] = True
+ DEFINES["HAVE_BSD_FLOCK"] = True
+ DEFINES["HAVE_SOCKLEN_T"] = True
+ DEFINES["HAVE_POINTER_LOCALTIME_R"] = True
+ SOURCES += [
+ "/nsprpub/pr/src/md/unix/darwin.c",
+ "/nsprpub/pr/src/md/unix/os_Darwin.s",
+ ]
+ DEFINES["HAVE_CRT_EXTERNS_H"] = True
+elif CONFIG["OS_TARGET"] == "SunOS":
+ DEFINES["HAVE_FCNTL_FILE_LOCKING"] = True
+ DEFINES["HAVE_SOCKLEN_T"] = True
+ DEFINES["_PR_HAVE_OFF64_T"] = True
+ DEFINES["_PR_INET6"] = True
+ DEFINES["SOLARIS"] = True
+ SOURCES += ["/nsprpub/pr/src/md/unix/solaris.c"]
+ if CONFIG["TARGET_CPU"] == "x86_64":
+ SOURCES += ["/nsprpub/pr/src/md/unix/os_SunOS_x86_64.s"]
+ elif CONFIG["TARGET_CPU"] == "x86":
+ SOURCES += ["/nsprpub/pr/src/md/unix/os_SunOS_x86.s"]
+ elif CONFIG["TARGET_CPU"] == "sparc64":
+ ASFLAGS += ["-x", "assembler-with-cpp", "-D_ASM"]
+ SOURCES += ["/nsprpub/pr/src/md/unix/os_SunOS_sparcv9.s"]
+elif CONFIG["OS_TARGET"] == "WINNT":
+ OS_LIBS += [
+ "advapi32",
+ "wsock32",
+ "ws2_32",
+ "mswsock",
+ "winmm",
+ ]
+ DEFINES["XP_PC"] = True
+ DEFINES["WIN32"] = True
+ # For historical reasons we use the WIN95 NSPR target instead of
+ # WINNT.
+ DEFINES["WIN95"] = True
+ DEFINES["WINNT"] = False
+ DEFINES["_PR_GLOBAL_THREADS_ONLY"] = True
+ if not CONFIG["DEBUG"]:
+ DEFINES["DO_NOT_WAIT_FOR_CONNECT_OVERLAPPED_OPERATIONS"] = True
+ if CONFIG["TARGET_CPU"] == "x86_64":
+ DEFINES["_AMD64_"] = True
+ elif CONFIG["TARGET_CPU"] == "x86":
+ DEFINES["_X86_"] = True
+ elif CONFIG["TARGET_CPU"] == "aarch64":
+ DEFINES["_ARM64_"] = True
+ else:
+ error("Unsupported TARGET_CPU value: %s" % CONFIG["TARGET_CPU"])
+else:
+ error(
+ 'Not a supported OS_TARGET for NSPR in moz.build: "%s". Use --with-system-nspr'
+ % CONFIG["OS_TARGET"]
+ )
+
+
+LOCAL_INCLUDES += [
+ "/config/external/nspr",
+ "/nsprpub/pr/include",
+ "/nsprpub/pr/include/private",
+]
+
+SOURCES += [
+ "/nsprpub/pr/src/io/prpolevt.c", # conflicting definition of PRFilePrivate
+ "/nsprpub/pr/src/misc/praton.c", # duplicate definition of index_hex
+]
+
+UNIFIED_SOURCES += [
+ "/nsprpub/pr/src/io/prfdcach.c",
+ "/nsprpub/pr/src/io/priometh.c",
+ "/nsprpub/pr/src/io/pripv6.c",
+ "/nsprpub/pr/src/io/prlayer.c",
+ "/nsprpub/pr/src/io/prlog.c",
+ "/nsprpub/pr/src/io/prmapopt.c",
+ "/nsprpub/pr/src/io/prmmap.c",
+ "/nsprpub/pr/src/io/prmwait.c",
+ "/nsprpub/pr/src/io/prprf.c",
+ "/nsprpub/pr/src/io/prscanf.c",
+ "/nsprpub/pr/src/io/prstdio.c",
+ "/nsprpub/pr/src/linking/prlink.c",
+ "/nsprpub/pr/src/malloc/prmalloc.c",
+ "/nsprpub/pr/src/malloc/prmem.c",
+ "/nsprpub/pr/src/md/prosdep.c",
+ "/nsprpub/pr/src/memory/prseg.c",
+ "/nsprpub/pr/src/memory/prshma.c",
+ "/nsprpub/pr/src/misc/pratom.c",
+ "/nsprpub/pr/src/misc/prdtoa.c",
+ "/nsprpub/pr/src/misc/prenv.c",
+ "/nsprpub/pr/src/misc/prerr.c",
+ "/nsprpub/pr/src/misc/prerror.c",
+ "/nsprpub/pr/src/misc/prerrortable.c",
+ "/nsprpub/pr/src/misc/prinit.c",
+ "/nsprpub/pr/src/misc/prinrval.c",
+ "/nsprpub/pr/src/misc/pripc.c",
+ "/nsprpub/pr/src/misc/prlog2.c",
+ "/nsprpub/pr/src/misc/prnetdb.c",
+ "/nsprpub/pr/src/misc/prrng.c",
+ "/nsprpub/pr/src/misc/prsystem.c",
+ "/nsprpub/pr/src/misc/prtime.c",
+ "/nsprpub/pr/src/misc/prtpool.c",
+ "/nsprpub/pr/src/threads/prcmon.c",
+ "/nsprpub/pr/src/threads/prrwlock.c",
+ "/nsprpub/pr/src/threads/prtpd.c",
+]
+
+if CONFIG["OS_TARGET"] != "WINNT":
+ DEFINES["_PR_PTHREADS"] = True
+ UNIFIED_SOURCES += [
+ "/nsprpub/pr/src/md/unix/unix.c",
+ "/nsprpub/pr/src/md/unix/unix_errors.c",
+ "/nsprpub/pr/src/md/unix/uxproces.c",
+ "/nsprpub/pr/src/md/unix/uxrng.c",
+ "/nsprpub/pr/src/md/unix/uxshm.c",
+ "/nsprpub/pr/src/pthreads/ptio.c",
+ "/nsprpub/pr/src/pthreads/ptmisc.c",
+ "/nsprpub/pr/src/pthreads/ptsynch.c",
+ "/nsprpub/pr/src/pthreads/ptthread.c",
+ ]
+else:
+ SOURCES += [
+ # ntinrval.c needs windows.h without WIN32_LEAN_AND_MEAN, so it can't be
+ # unified after any file that pulled in windows.h in lean-and-mean mode.
+ "/nsprpub/pr/src/md/windows/ntinrval.c",
+ # w32poll.c needs a custom value of FD_SETSIZE for winsock.h.
+ "/nsprpub/pr/src/md/windows/w32poll.c",
+ # w95sock.c needs winsock2.h which conflicts with winsock.h.
+ "/nsprpub/pr/src/md/windows/w95sock.c",
+ ]
+ UNIFIED_SOURCES += [
+ "/nsprpub/pr/src/io/prdir.c",
+ "/nsprpub/pr/src/io/prfile.c",
+ "/nsprpub/pr/src/io/prio.c",
+ "/nsprpub/pr/src/io/prsocket.c",
+ "/nsprpub/pr/src/md/windows/ntgc.c",
+ "/nsprpub/pr/src/md/windows/ntmisc.c",
+ "/nsprpub/pr/src/md/windows/ntsec.c",
+ "/nsprpub/pr/src/md/windows/ntsem.c",
+ "/nsprpub/pr/src/md/windows/w32ipcsem.c",
+ "/nsprpub/pr/src/md/windows/w32rng.c",
+ "/nsprpub/pr/src/md/windows/w32shm.c",
+ "/nsprpub/pr/src/md/windows/w95cv.c",
+ "/nsprpub/pr/src/md/windows/w95dllmain.c",
+ "/nsprpub/pr/src/md/windows/w95io.c",
+ "/nsprpub/pr/src/md/windows/w95thred.c",
+ "/nsprpub/pr/src/md/windows/win32_errors.c",
+ "/nsprpub/pr/src/misc/pripcsem.c",
+ "/nsprpub/pr/src/threads/combined/prucpu.c",
+ "/nsprpub/pr/src/threads/combined/prucv.c",
+ "/nsprpub/pr/src/threads/combined/prulock.c",
+ "/nsprpub/pr/src/threads/combined/prustack.c",
+ "/nsprpub/pr/src/threads/combined/pruthr.c",
+ "/nsprpub/pr/src/threads/prcthr.c",
+ "/nsprpub/pr/src/threads/prdump.c",
+ "/nsprpub/pr/src/threads/prmon.c",
+ "/nsprpub/pr/src/threads/prsem.c",
+ ]
+
+EXPORTS.nspr += [
+ "/nsprpub/pr/include/nspr.h",
+ "/nsprpub/pr/include/pratom.h",
+ "/nsprpub/pr/include/prbit.h",
+ "/nsprpub/pr/include/prclist.h",
+ "/nsprpub/pr/include/prcmon.h",
+ "/nsprpub/pr/include/prcvar.h",
+ "/nsprpub/pr/include/prdtoa.h",
+ "/nsprpub/pr/include/prenv.h",
+ "/nsprpub/pr/include/prerr.h",
+ "/nsprpub/pr/include/prerror.h",
+ "/nsprpub/pr/include/prinet.h",
+ "/nsprpub/pr/include/prinit.h",
+ "/nsprpub/pr/include/prinrval.h",
+ "/nsprpub/pr/include/prio.h",
+ "/nsprpub/pr/include/pripcsem.h",
+ "/nsprpub/pr/include/prlink.h",
+ "/nsprpub/pr/include/prlock.h",
+ "/nsprpub/pr/include/prlog.h",
+ "/nsprpub/pr/include/prlong.h",
+ "/nsprpub/pr/include/prmem.h",
+ "/nsprpub/pr/include/prmon.h",
+ "/nsprpub/pr/include/prmwait.h",
+ "/nsprpub/pr/include/prnetdb.h",
+ "/nsprpub/pr/include/prpdce.h",
+ "/nsprpub/pr/include/prprf.h",
+ "/nsprpub/pr/include/prproces.h",
+ "/nsprpub/pr/include/prrng.h",
+ "/nsprpub/pr/include/prrwlock.h",
+ "/nsprpub/pr/include/prshm.h",
+ "/nsprpub/pr/include/prshma.h",
+ "/nsprpub/pr/include/prsystem.h",
+ "/nsprpub/pr/include/prthread.h",
+ "/nsprpub/pr/include/prtime.h",
+ "/nsprpub/pr/include/prtpool.h",
+ "/nsprpub/pr/include/prtrace.h",
+ "/nsprpub/pr/include/prtypes.h",
+ "/nsprpub/pr/include/prvrsion.h",
+ "/nsprpub/pr/include/prwin16.h",
+]
+
+EXPORTS.nspr.md += [
+ "/nsprpub/pr/include/md/_darwin.cfg",
+ "/nsprpub/pr/include/md/_freebsd.cfg",
+ "/nsprpub/pr/include/md/_linux.cfg",
+ "/nsprpub/pr/include/md/_netbsd.cfg",
+ "/nsprpub/pr/include/md/_openbsd.cfg",
+ "/nsprpub/pr/include/md/_solaris.cfg",
+ "/nsprpub/pr/include/md/_win95.cfg",
+]
+
+EXPORTS.nspr.private += [
+ "/nsprpub/pr/include/private/pprio.h",
+ "/nsprpub/pr/include/private/pprthred.h",
+ "/nsprpub/pr/include/private/prpriv.h",
+]
diff --git a/config/external/nspr/prcpucfg.h b/config/external/nspr/prcpucfg.h
new file mode 100644
index 0000000000..e5c5aeead9
--- /dev/null
+++ b/config/external/nspr/prcpucfg.h
@@ -0,0 +1,31 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#ifndef NSPR_PRCPUCFG_H_
+#define NSPR_PRCPUCFG_H_
+
+/*
+ * Need to support conditionals that are defined in both the top-level build
+ * system as well as NSS' build system for now.
+ */
+#if defined(XP_DARWIN) || defined(DARWIN)
+# include "md/_darwin.cfg"
+#elif defined(XP_WIN) || defined(_WINDOWS)
+# include "md/_win95.cfg"
+#elif defined(__FreeBSD__)
+# include "md/_freebsd.cfg"
+#elif defined(__NetBSD__)
+# include "md/_netbsd.cfg"
+#elif defined(__OpenBSD__)
+# include "md/_openbsd.cfg"
+#elif defined(__linux__)
+# include "md/_linux.cfg"
+#elif defined(__sun__)
+# include "md/_solaris.cfg"
+#else
+# error "Unsupported platform!"
+#endif
+
+#endif /* NSPR_PRCPUCFG_H_ */
diff --git a/config/external/rlbox/moz.build b/config/external/rlbox/moz.build
new file mode 100644
index 0000000000..28b09d3314
--- /dev/null
+++ b/config/external/rlbox/moz.build
@@ -0,0 +1,31 @@
+# -*- 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/.
+
+with Files("**"):
+ BUG_COMPONENT = ("Core", "Security: RLBox")
+
+EXPORTS.mozilla.rlbox += [
+ "/third_party/rlbox/include/rlbox.hpp",
+ "/third_party/rlbox/include/rlbox_app_pointer.hpp",
+ "/third_party/rlbox/include/rlbox_conversion.hpp",
+ "/third_party/rlbox/include/rlbox_helpers.hpp",
+ "/third_party/rlbox/include/rlbox_noop_sandbox.hpp",
+ "/third_party/rlbox/include/rlbox_policy_types.hpp",
+ "/third_party/rlbox/include/rlbox_range.hpp",
+ "/third_party/rlbox/include/rlbox_sandbox.hpp",
+ "/third_party/rlbox/include/rlbox_stdlib.hpp",
+ "/third_party/rlbox/include/rlbox_stdlib_polyfill.hpp",
+ "/third_party/rlbox/include/rlbox_struct_support.hpp",
+ "/third_party/rlbox/include/rlbox_type_traits.hpp",
+ "/third_party/rlbox/include/rlbox_types.hpp",
+ "/third_party/rlbox/include/rlbox_unwrap.hpp",
+ "/third_party/rlbox/include/rlbox_wrapper_traits.hpp",
+ "rlbox_config.h",
+]
+
+SOURCES += ["rlbox_thread_locals.cpp"]
+
+FINAL_LIBRARY = "xul"
diff --git a/config/external/rlbox/rlbox_config.h b/config/external/rlbox/rlbox_config.h
new file mode 100644
index 0000000000..c9aa34e4db
--- /dev/null
+++ b/config/external/rlbox/rlbox_config.h
@@ -0,0 +1,30 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#ifndef RLBOX_CONFIG
+#define RLBOX_CONFIG
+
+#include "mozilla/Assertions.h"
+
+// All uses of rlbox's function and callbacks invocations are on a single
+// thread right now, so we disable rlbox thread checks for performance
+// See (Bug 1739298) for more details
+#define RLBOX_SINGLE_THREADED_INVOCATIONS
+
+#define RLBOX_CUSTOM_ABORT(msg) MOZ_CRASH_UNSAFE_PRINTF("RLBox crash: %s", msg)
+
+// The MingW compiler does not correctly handle static thread_local inline
+// members. This toggles a workaround that allows the host application (firefox)
+// to provide TLS storage via functions. This can be removed if the MingW bug is
+// fixed.
+#define RLBOX_EMBEDDER_PROVIDES_TLS_STATIC_VARIABLES
+
+// When instantiating a wasm sandbox, rlbox requires the name of the wasm module
+// being instantiated. LLVM and wasm2c use the module name by choosing the name
+// used to generate the wasm file. In Firefox this is a static library called
+// rlbox
+#define RLBOX_WASM2C_MODULE_NAME rlbox
+
+#endif
diff --git a/config/external/rlbox/rlbox_thread_locals.cpp b/config/external/rlbox/rlbox_thread_locals.cpp
new file mode 100644
index 0000000000..157177c0e0
--- /dev/null
+++ b/config/external/rlbox/rlbox_thread_locals.cpp
@@ -0,0 +1,17 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+// Load general firefox configuration of RLBox
+#include "mozilla/rlbox/rlbox_config.h"
+
+#define RLBOX_USE_STATIC_CALLS() rlbox_noop_sandbox_lookup_symbol
+#include "mozilla/rlbox/rlbox_noop_sandbox.hpp"
+
+#include "mozilla/rlbox/rlbox.hpp"
+
+// The MingW compiler does not correctly handle static thread_local inline
+// members. We instead TLS storage via functions. This can be removed if the
+// MingW bug is fixed.
+RLBOX_NOOP_SANDBOX_STATIC_VARIABLES();
diff --git a/config/external/rlbox_wasm2c_sandbox/moz.build b/config/external/rlbox_wasm2c_sandbox/moz.build
new file mode 100644
index 0000000000..4600f12c19
--- /dev/null
+++ b/config/external/rlbox_wasm2c_sandbox/moz.build
@@ -0,0 +1,27 @@
+# -*- 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/.
+
+with Files("**"):
+ BUG_COMPONENT = ("Core", "Security: RLBox")
+
+EXPORTS.mozilla.rlbox += [
+ "/third_party/rlbox_wasm2c_sandbox/include/rlbox_wasm2c_sandbox.hpp",
+ "/third_party/rlbox_wasm2c_sandbox/include/rlbox_wasm2c_tls.hpp",
+]
+EXPORTS += [
+ "/third_party/rlbox_wasm2c_sandbox/include/wasm2c_rt_mem.h",
+ "/third_party/rlbox_wasm2c_sandbox/include/wasm2c_rt_minwasi.h",
+]
+
+SOURCES += [
+ "/third_party/rlbox_wasm2c_sandbox/src/wasm2c_rt_mem.c",
+ "/third_party/rlbox_wasm2c_sandbox/src/wasm2c_rt_minwasi.c",
+ "rlbox_wasm2c_thread_locals.cpp",
+]
+
+LOCAL_INCLUDES += ["/third_party/wasm2c/wasm2c/"]
+
+FINAL_LIBRARY = "xul"
diff --git a/config/external/rlbox_wasm2c_sandbox/moz.yaml b/config/external/rlbox_wasm2c_sandbox/moz.yaml
new file mode 100644
index 0000000000..dd4e660052
--- /dev/null
+++ b/config/external/rlbox_wasm2c_sandbox/moz.yaml
@@ -0,0 +1,31 @@
+schema: 1
+
+bugzilla:
+ product: Core
+ component: "General"
+
+origin:
+ name: rlbox_wasm2c_sandbox
+ description: rlbox integration for the wasm2c sandboxed code
+ url: https://github.com/PLSysSec/rlbox_wasm2c_sandbox/tree/upstream-wasm2c
+
+ release: 0938ae96c5467bdf2210cf21be47ae576cbcc3cd (2023-08-29T00:00:41Z).
+ revision: 0938ae96c5467bdf2210cf21be47ae576cbcc3cd
+
+ license: MIT
+ license-file: LICENSE
+
+vendoring:
+ url: https://github.com/PLSysSec/rlbox_wasm2c_sandbox
+ source-hosting: github
+ vendor-directory: third_party/rlbox_wasm2c_sandbox
+
+ exclude:
+ # dirs
+ - test
+ # files
+ - ".*"
+ - AppSandbox.md
+ - CMakeLists.txt
+ - LibrarySandbox.md
+ - README.md
diff --git a/config/external/rlbox_wasm2c_sandbox/rlbox_wasm2c_thread_locals.cpp b/config/external/rlbox_wasm2c_sandbox/rlbox_wasm2c_thread_locals.cpp
new file mode 100644
index 0000000000..0fadb5af40
--- /dev/null
+++ b/config/external/rlbox_wasm2c_sandbox/rlbox_wasm2c_thread_locals.cpp
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#ifdef MOZ_USING_WASM_SANDBOXING
+
+// For MOZ_CRASH_UNSAFE_PRINTF
+# include "mozilla/Assertions.h"
+
+# include "mozilla/mozalloc_oom.h"
+
+// Load general firefox configuration of RLBox
+# include "mozilla/rlbox/rlbox_config.h"
+# include "mozilla/rlbox/rlbox_wasm2c_tls.hpp"
+# include "wasm-rt.h"
+
+# ifndef WASM_RT_GROW_FAILED_CRASH
+# include "nsExceptionHandler.h"
+# endif
+
+// The MingW compiler does not correctly handle static thread_local inline
+// members. We instead TLS storage via functions. This can be removed if the
+// MingW bug is fixed.
+RLBOX_WASM2C_SANDBOX_STATIC_VARIABLES();
+
+extern "C" {
+
+// Any error encountered by the wasm2c runtime or wasm sandboxed library code
+// is configured to call the below trap handler.
+void moz_wasm2c_trap_handler(wasm_rt_trap_t code) {
+ MOZ_CRASH_UNSAFE_PRINTF("wasm2c crash: %s", wasm_rt_strerror(code));
+}
+
+// The below function is called if a malloc in sandboxed code returns null
+// This indicates that the sandbox has run out of memory.
+void moz_wasm2c_memgrow_failed() {
+# ifdef WASM_RT_GROW_FAILED_CRASH
+ MOZ_CRASH("wasm2c memory grow failed");
+# else
+ CrashReporter::AnnotateCrashReport(
+ CrashReporter::Annotation::WasmLibrarySandboxMallocFailed, true);
+# endif
+}
+
+// This function is called when mozalloc_handle_oom is called from within
+// the sandbox. We redirect to that function, ignoring the ctx argument, which
+// is the sandbox itself.
+void w2c_env_mozalloc_handle_oom(void* ctx, uint32_t size) {
+ mozalloc_handle_oom(size);
+}
+}
+
+#endif
diff --git a/config/external/sqlite/moz.build b/config/external/sqlite/moz.build
new file mode 100644
index 0000000000..6294924c56
--- /dev/null
+++ b/config/external/sqlite/moz.build
@@ -0,0 +1,18 @@
+# -*- 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/.
+
+DIRS += ["../../../third_party/sqlite3/src"]
+if CONFIG["MOZ_FOLD_LIBS"]:
+ Library("sqlite")
+ # When folding libraries, sqlite is actually in the nss library.
+ USE_LIBS += [
+ "nss",
+ ]
+else:
+ SharedLibrary("sqlite")
+ SHARED_LIBRARY_NAME = "mozsqlite3"
+
+ SYMBOLS_FILE = "/third_party/sqlite3/src/sqlite.symbols"
diff --git a/config/external/wasm2c_sandbox_compiler/moz.build b/config/external/wasm2c_sandbox_compiler/moz.build
new file mode 100644
index 0000000000..1ec6490a78
--- /dev/null
+++ b/config/external/wasm2c_sandbox_compiler/moz.build
@@ -0,0 +1,82 @@
+# -*- 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/.
+
+with Files("**"):
+ BUG_COMPONENT = ("Core", "Security: RLBox")
+
+LOCAL_INCLUDES += [
+ "/third_party/picosha2/",
+ "/third_party/wasm2c/include/",
+]
+
+GeneratedFile(
+ "wabt/config.h",
+ script="preprocess_wasm2c_config.py",
+ entry_point="generate_config",
+ inputs=["/third_party/wasm2c/src/config.h.in"],
+)
+
+# Wabt sources
+HOST_SOURCES += [
+ "/third_party/wasm2c/src/apply-names.cc",
+ "/third_party/wasm2c/src/binary-reader-ir.cc",
+ "/third_party/wasm2c/src/binary-reader-logging.cc",
+ "/third_party/wasm2c/src/binary-reader-objdump.cc",
+ "/third_party/wasm2c/src/binary-reader-opcnt.cc",
+ "/third_party/wasm2c/src/binary-reader.cc",
+ "/third_party/wasm2c/src/binary-writer-spec.cc",
+ "/third_party/wasm2c/src/binary-writer.cc",
+ "/third_party/wasm2c/src/binary.cc",
+ "/third_party/wasm2c/src/binding-hash.cc",
+ "/third_party/wasm2c/src/color.cc",
+ "/third_party/wasm2c/src/common.cc",
+ "/third_party/wasm2c/src/config.cc",
+ "/third_party/wasm2c/src/decompiler.cc",
+ "/third_party/wasm2c/src/emscripten-helpers.cc",
+ "/third_party/wasm2c/src/error-formatter.cc",
+ "/third_party/wasm2c/src/expr-visitor.cc",
+ "/third_party/wasm2c/src/feature.cc",
+ "/third_party/wasm2c/src/filenames.cc",
+ "/third_party/wasm2c/src/generate-names.cc",
+ "/third_party/wasm2c/src/ir-util.cc",
+ "/third_party/wasm2c/src/ir.cc",
+ "/third_party/wasm2c/src/leb128.cc",
+ "/third_party/wasm2c/src/lexer-source-line-finder.cc",
+ "/third_party/wasm2c/src/lexer-source.cc",
+ "/third_party/wasm2c/src/literal.cc",
+ "/third_party/wasm2c/src/opcode-code-table.c",
+ "/third_party/wasm2c/src/opcode.cc",
+ "/third_party/wasm2c/src/option-parser.cc",
+ "/third_party/wasm2c/src/resolve-names.cc",
+ "/third_party/wasm2c/src/sha256.cc",
+ "/third_party/wasm2c/src/shared-validator.cc",
+ "/third_party/wasm2c/src/stream.cc",
+ "/third_party/wasm2c/src/token.cc",
+ "/third_party/wasm2c/src/tracing.cc",
+ "/third_party/wasm2c/src/type-checker.cc",
+ "/third_party/wasm2c/src/utf8.cc",
+ "/third_party/wasm2c/src/validator.cc",
+ "/third_party/wasm2c/src/wast-lexer.cc",
+ "/third_party/wasm2c/src/wast-parser.cc",
+ "/third_party/wasm2c/src/wat-writer.cc",
+]
+
+# wasm2c sources
+HOST_SOURCES += [
+ "/third_party/wasm2c/src/c-writer.cc",
+ "/third_party/wasm2c/src/prebuilt/wasm2c_header_bottom.cc",
+ "/third_party/wasm2c/src/prebuilt/wasm2c_header_top.cc",
+ "/third_party/wasm2c/src/prebuilt/wasm2c_simd_source_declarations.cc",
+ "/third_party/wasm2c/src/prebuilt/wasm2c_source_declarations.cc",
+ "/third_party/wasm2c/src/prebuilt/wasm2c_source_includes.cc",
+ "/third_party/wasm2c/src/tools/wasm2c.cc",
+]
+
+HOST_CXXFLAGS += [
+ "-Wno-implicit-fallthrough",
+]
+
+HostProgram("wasm2c")
diff --git a/config/external/wasm2c_sandbox_compiler/moz.yaml b/config/external/wasm2c_sandbox_compiler/moz.yaml
new file mode 100644
index 0000000000..cbc6938025
--- /dev/null
+++ b/config/external/wasm2c_sandbox_compiler/moz.yaml
@@ -0,0 +1,47 @@
+schema: 1
+
+bugzilla:
+ product: Core
+ component: "General"
+
+origin:
+ name: wasm2c_sandbox_compiler
+ description: wasm2c fork used for rlbox sandboxing
+ url: https://github.com/WebAssembly/wabt
+
+ release: 963f973469b45969ce198e0c86d3af316790a780 (2023-05-12T21:56:46Z).
+ revision: 963f973469b45969ce198e0c86d3af316790a780
+
+ license: Apache-2.0
+ license-file: LICENSE
+
+vendoring:
+ url: https://github.com/WebAssembly/wabt
+ source-hosting: github
+ vendor-directory: third_party/wasm2c
+ exclude:
+ # dirs
+ - cmake
+ - docs
+ - fuzz-in
+ - include/wabt/interp
+ - man
+ - scripts
+ - src/interp
+ - src/template
+ - test
+ - third_party
+ - wasm2c/examples
+ # files
+ - .*
+ - CMakeLists.txt
+ - Contributing.md
+ - Makefile
+ - README.md
+ - ubsan.blacklist
+ - src/tools/s*
+ - src/tools/wasm-*
+ - src/tools/wast*
+ - src/tools/wat*
+ - src/tools/wasm2w*
+ - wasm2c/wasm-rt-exceptions*
diff --git a/config/external/wasm2c_sandbox_compiler/preprocess_wasm2c_config.py b/config/external/wasm2c_sandbox_compiler/preprocess_wasm2c_config.py
new file mode 100644
index 0000000000..3edb8f4e06
--- /dev/null
+++ b/config/external/wasm2c_sandbox_compiler/preprocess_wasm2c_config.py
@@ -0,0 +1,139 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Souce Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distibuted with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+import itertools
+
+# The wasm2c source relies on CMAKE to generate a config file to be used to build the project
+# Since we do not use cmake, this script automates the generation of a similar config suitable
+# for firefox builds
+# The script has a list of known variables it can replace and throws an error if it encounters a
+# new variable (for instance when the in-tree source is updated)
+
+# This python script knows how to replace the following variables normally configured by cmake for
+# the wasm2c source
+known_vars = [
+ '#cmakedefine WABT_VERSION_STRING "@WABT_VERSION_STRING@"',
+ "#cmakedefine WABT_DEBUG @WABT_DEBUG@",
+ "#cmakedefine01 HAVE_ALLOCA_H",
+ "#cmakedefine01 HAVE_UNISTD_H",
+ "#cmakedefine01 HAVE_SNPRINTF",
+ "#cmakedefine01 HAVE_SSIZE_T",
+ "#cmakedefine01 HAVE_STRCASECMP",
+ "#cmakedefine01 HAVE_WIN32_VT100",
+ "#cmakedefine01 WABT_BIG_ENDIAN",
+ "#cmakedefine01 HAVE_OPENSSL_SHA_H",
+ "#cmakedefine01 COMPILER_IS_CLANG",
+ "#cmakedefine01 COMPILER_IS_GNU",
+ "#cmakedefine01 COMPILER_IS_MSVC",
+ "#cmakedefine01 WITH_EXCEPTIONS",
+ "#define SIZEOF_SIZE_T @SIZEOF_SIZE_T@",
+]
+
+# The above variables are replaced with the code shown below
+replaced_variables = """
+// mozilla-config.h defines the following which is used
+// - HAVE_ALLOCA_H
+// - HAVE_UNISTD_H
+#include "mozilla-config.h"
+
+#define WABT_VERSION_STRING "Firefox-in-tree-version"
+
+#define WABT_DEBUG 0
+
+/* We don't require color printing of wasm2c errors on any platform */
+#define HAVE_WIN32_VT100 0
+
+#ifdef _WIN32
+ // Ignore whatever is set in mozilla-config.h wrt alloca because it is
+ // wrong when cross-compiling on Windows.
+ #undef HAVE_ALLOCA_H
+ // It is wrong when cross-compiling on Windows.
+ #undef HAVE_UNISTD_H
+ /* Whether ssize_t is defined by stddef.h */
+ #define HAVE_SSIZE_T 0
+ /* Whether strcasecmp is defined by strings.h */
+ #define HAVE_STRCASECMP 0
+#else
+ #define HAVE_SSIZE_T 1
+ #define HAVE_STRCASECMP 1
+#endif
+
+#if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && defined(__ORDER_BIG_ENDIAN__)
+# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+# define WABT_BIG_ENDIAN 0
+# elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+# define WABT_BIG_ENDIAN 1
+# else
+# error "Can't handle mixed-endian architectures"
+# endif
+#else
+# error "Don't know how to determine endianness"
+#endif
+
+/* Use internal Pico-SHA. Never use OpenSSL */
+#define HAVE_OPENSSL_SHA_H 0
+
+/* Whether snprintf is defined by stdio.h */
+#define HAVE_SNPRINTF 1
+
+#if defined(_MSC_VER)
+ #define COMPILER_IS_GNU 0
+ #define COMPILER_IS_CLANG 0
+ #define COMPILER_IS_MSVC 1
+#elif defined(__GNUC__)
+ #if defined(__clang__)
+ #define COMPILER_IS_GNU 0
+ #define COMPILER_IS_CLANG 1
+ #define COMPILER_IS_MSVC 0
+ #else
+ #define COMPILER_IS_GNU 1
+ #define COMPILER_IS_CLANG 0
+ #define COMPILER_IS_MSVC 0
+ #endif
+#else
+ #error "Unknown compiler"
+#endif
+
+#define WITH_EXCEPTIONS 0
+
+#if SIZE_MAX == 0xffffffffffffffff
+ #define SIZEOF_SIZE_T 8
+#elif SIZE_MAX == 0xffffffff
+ #define SIZEOF_SIZE_T 4
+#else
+ #error "Unknown size of size_t"
+#endif
+"""
+
+
+def generate_config(output, config_h_in):
+ file_config_h_in = open(config_h_in, "r")
+ lines = file_config_h_in.readlines()
+
+ # Remove the known cmake variables
+ for known_var in known_vars:
+ lines = [x for x in lines if not x.startswith(known_var)]
+
+ # Do a sanity check to make sure there are no unknown variables
+ remaining_vars = [x for x in lines if x.startswith("#cmakedefine") or "@" in x]
+ if len(remaining_vars) > 0:
+ raise BaseException("Unknown cmake variables: " + str(remaining_vars))
+
+ pos = lines.index("#define WABT_CONFIG_H_\n")
+ skipped = itertools.takewhile(
+ lambda x: not (x.strip()) or x.startswith("#include "), lines[pos + 1 :]
+ )
+ pos += len(list(skipped))
+ pre_include_lines = lines[0:pos]
+ post_include_lines = lines[pos:]
+ output_str = (
+ "".join(pre_include_lines)
+ + "\n"
+ + replaced_variables
+ + "\n"
+ + "".join(post_include_lines)
+ )
+ output.write(output_str)
diff --git a/config/external/zlib/moz.build b/config/external/zlib/moz.build
new file mode 100644
index 0000000000..755400fa7f
--- /dev/null
+++ b/config/external/zlib/moz.build
@@ -0,0 +1,21 @@
+# -*- 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/.
+
+Library("zlib")
+
+if CONFIG["MOZ_SYSTEM_ZLIB"]:
+ OS_LIBS += CONFIG["MOZ_ZLIB_LIBS"]
+else:
+ if CONFIG["ZLIB_IN_MOZGLUE"]:
+ # Can't do this until mozglue is handled by moz.build instead of
+ # config/rules.mk.
+ # USE_LIBS += [
+ # 'mozglue'
+ # ]
+ pass
+ DIRS += [
+ "../../../modules/zlib",
+ ]
diff --git a/config/faster/rules.mk b/config/faster/rules.mk
new file mode 100644
index 0000000000..79833a1034
--- /dev/null
+++ b/config/faster/rules.mk
@@ -0,0 +1,95 @@
+# 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/.
+
+# /!\ Please make sure to update the following comment when you touch this
+# file. Thank you /!\
+
+# The traditional Mozilla build system relied on going through the entire
+# build tree a number of times with different targets, and many of the
+# things happening at each step required other things happening in previous
+# steps without any documentation of those dependencies.
+#
+# This new build system tries to start afresh by establishing what files or
+# operations are needed for the build, and applying the necessary rules to
+# have those in place, relying on make dependencies to get them going.
+#
+# As of writing, only building non-compiled parts of Firefox is supported
+# here (a few other things are also left out). This is a starting point, with
+# the intent to grow this build system to make it more complete.
+#
+# This file contains rules and dependencies to get things working. The intent
+# is for a Makefile to define some dependencies and variables, and include
+# this file. What needs to be defined there, and ends up being generated by
+# python/mozbuild/mozbuild/backend/fastermake.py is the following:
+# - TOPSRCDIR/TOPOBJDIR, respectively the top source directory and the top
+# object directory
+# - PYTHON, the path to the python executable
+# - ACDEFINES, which contains a set of -Dvar=name to be used during
+# preprocessing
+# - INSTALL_MANIFESTS, which defines the list of base directories handled
+# by install manifests, see further below
+#
+# A convention used between this file and the Makefile including it is that
+# global Make variables names are uppercase, while "local" Make variables
+# applied to specific targets are lowercase.
+
+# Targets to be triggered for a default build
+default: $(addprefix install-,$(INSTALL_MANIFESTS))
+
+ifndef NO_XPIDL
+# Targets from the recursive make backend to be built for a default build
+default: $(TOPOBJDIR)/config/makefiles/xpidl/xpidl
+endif
+
+# Mac builds require to copy things in dist/bin/*.app
+# TODO: remove the MOZ_WIDGET_TOOLKIT and MOZ_BUILD_APP variables from
+# faster/Makefile and python/mozbuild/mozbuild/test/backend/test_build.py
+# when this is not required anymore.
+# We however don't need to do this when using the hybrid
+# FasterMake/RecursiveMake backend (FASTER_RECURSIVE_MAKE is set when
+# recursing from the RecursiveMake backend)
+ifndef FASTER_RECURSIVE_MAKE
+ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
+default:
+ $(MAKE) -C $(TOPOBJDIR)/$(MOZ_BUILD_APP)/app repackage
+endif
+endif
+
+.PHONY: FORCE
+
+# Files under the faster/ sub-directory, however, are not meant to use the
+# fallback
+$(TOPOBJDIR)/faster/%: ;
+
+# Generic rule to fall back to the recursive make backend.
+# This needs to stay after other $(TOPOBJDIR)/* rules because GNU Make
+# <3.82 apply pattern rules in definition order, not stem length like
+# modern GNU Make.
+$(TOPOBJDIR)/%: FORCE
+ $(MAKE) -C $(dir $@) $(notdir $@)
+
+# Install files using install manifests
+#
+# The list of base directories is given in INSTALL_MANIFESTS. The
+# corresponding install manifests are named correspondingly, with forward
+# slashes replaced with underscores, and prefixed with `install_`. That is,
+# the install manifest for `dist/bin` would be `install_dist_bin`.
+$(addprefix install-,$(INSTALL_MANIFESTS)): install-%: $(addprefix $(TOPOBJDIR)/,buildid.h source-repo.h)
+ @# For now, force preprocessed files to be reprocessed every time.
+ @# The overhead is not that big, and this avoids waiting for proper
+ @# support for defines tracking in process_install_manifest.
+ @touch install_$(subst /,_,$*)
+ $(PYTHON3) -m mozbuild.action.process_install_manifest \
+ $(if $(filter copy,$(NSDISTMODE)),--no-symlinks) \
+ --track install_$(subst /,_,$*).track \
+ $(TOPOBJDIR)/$* \
+ -DAB_CD=en-US \
+ $(ACDEFINES) \
+ install_$(subst /,_,$*)
+
+# ============================================================================
+# Below is a set of additional dependencies and variables used to build things
+# that are not supported by data in moz.build.
+
+$(TOPOBJDIR)/build/.deps/application.ini.stub: $(TOPOBJDIR)/buildid.h $(TOPOBJDIR)/source-repo.h
diff --git a/config/gcc-stl-wrapper.template.h b/config/gcc-stl-wrapper.template.h
new file mode 100644
index 0000000000..c714977d5d
--- /dev/null
+++ b/config/gcc-stl-wrapper.template.h
@@ -0,0 +1,85 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=8 et :
+ */
+/* 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/. */
+
+#ifndef mozilla_${HEADER}_h
+#define mozilla_${HEADER}_h
+
+#if defined(__cpp_exceptions) && __cpp_exceptions
+# error "STL code can only be used with -fno-exceptions"
+#endif
+
+// Silence "warning: #include_next is a GCC extension"
+#pragma GCC system_header
+
+#if defined(DEBUG) && !defined(_GLIBCXX_DEBUG)
+// Enable checked iterators and other goodies
+//
+// FIXME/bug 551254: gcc's debug STL implementation requires -frtti.
+// Figure out how to resolve this with -fno-rtti. Maybe build with
+// -frtti in DEBUG builds?
+//
+// # define _GLIBCXX_DEBUG 1
+#endif
+
+// Don't include mozalloc.h for cstdlib, cmath, type_traits, limits and iosfwd.
+// See bug 1245076 (cstdlib), bug 1720641 (cmath), bug 1594027 (type_traits,
+// limits) and bug 1694575 (iosfwd).
+// Please be careful when adding more exceptions, especially regarding
+// the header not directly or indirectly including <new>.
+#ifndef moz_dont_include_mozalloc_for_cstdlib
+# define moz_dont_include_mozalloc_for_cstdlib
+#endif
+
+#ifndef moz_dont_include_mozalloc_for_cmath
+# define moz_dont_include_mozalloc_for_cmath
+#endif
+
+#ifndef moz_dont_include_mozalloc_for_type_traits
+# define moz_dont_include_mozalloc_for_type_traits
+#endif
+
+#ifndef moz_dont_include_mozalloc_for_limits
+# define moz_dont_include_mozalloc_for_limits
+#endif
+
+#ifndef moz_dont_include_mozalloc_for_iosfwd
+# define moz_dont_include_mozalloc_for_iosfwd
+#endif
+
+// Include mozalloc after the STL header and all other headers it includes
+// have been preprocessed.
+#if !defined(MOZ_INCLUDE_MOZALLOC_H) && \
+ !defined(moz_dont_include_mozalloc_for_${HEADER})
+# define MOZ_INCLUDE_MOZALLOC_H
+# define MOZ_INCLUDE_MOZALLOC_H_FROM_${HEADER}
+#endif
+
+#pragma GCC visibility push(default)
+#include_next <${HEADER}>
+#pragma GCC visibility pop
+
+#ifdef MOZ_INCLUDE_MOZALLOC_H_FROM_${HEADER}
+// See if we're in code that can use mozalloc.
+# if !defined(NS_NO_XPCOM) && !defined(MOZ_NO_MOZALLOC)
+# include "mozilla/mozalloc.h"
+# else
+# error "STL code can only be used with infallible ::operator new()"
+# endif
+#endif
+
+// gcc calls a __throw_*() function from bits/functexcept.h when it
+// wants to "throw an exception". functexcept exists nominally to
+// support -fno-exceptions, but since we'll always use the system
+// libstdc++, and it's compiled with exceptions, then in practice
+// these __throw_*() functions will always throw exceptions (shades of
+// -fshort-wchar). We don't want that and so define our own inlined
+// __throw_*().
+#ifndef mozilla_throw_gcc_h
+# include "mozilla/throw_gcc.h"
+#endif
+
+#endif // if mozilla_${HEADER}_h
diff --git a/config/gcc_hidden.h b/config/gcc_hidden.h
new file mode 100644
index 0000000000..075e68c88b
--- /dev/null
+++ b/config/gcc_hidden.h
@@ -0,0 +1,6 @@
+/* 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/. */
+
+/* Begin all files as hidden visibility */
+#pragma GCC visibility push(hidden)
diff --git a/config/install.bat b/config/install.bat
new file mode 100644
index 0000000000..f429b6765f
--- /dev/null
+++ b/config/install.bat
@@ -0,0 +1,10 @@
+@echo off
+rem This Source Code Form is subject to the terms of the Mozilla Public
+rem License, v. 2.0. If a copy of the MPL was not distributed with this
+rem file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+@echo on
+
+@if not exist %2\nul mkdir %2
+@rm -f %2\%1
+@cp %1 %2
diff --git a/config/make-stl-wrappers.py b/config/make-stl-wrappers.py
new file mode 100644
index 0000000000..ba4d6f74f7
--- /dev/null
+++ b/config/make-stl-wrappers.py
@@ -0,0 +1,18 @@
+# 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/.
+import os
+import string
+
+from mozbuild.util import FileAvoidWrite
+
+# The 'unused' arg is the output file from the file_generate action. We actually
+# generate all the files in header_list
+
+
+def gen_wrappers(unused, template_file, outdir, compiler, *header_list):
+ template = open(template_file, "r").read()
+
+ for header in header_list:
+ with FileAvoidWrite(os.path.join(outdir, header)) as f:
+ f.write(string.Template(template).substitute(HEADER=header))
diff --git a/config/make-system-wrappers.py b/config/make-system-wrappers.py
new file mode 100644
index 0000000000..a4b3d51af1
--- /dev/null
+++ b/config/make-system-wrappers.py
@@ -0,0 +1,38 @@
+# 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/.
+import os
+
+from mozbuild.util import FileAvoidWrite
+
+header_template = """#pragma GCC system_header
+#pragma GCC visibility push(default)
+{includes}
+#pragma GCC visibility pop
+"""
+
+include_next_template = "#include_next <{header}>"
+
+
+# The 'unused' arg is the output file from the file_generate action. We actually
+# generate all the files in header_list
+def gen_wrappers(unused, outdir, *header_list):
+ for header in header_list:
+ with FileAvoidWrite(os.path.join(outdir, header)) as f:
+ includes = include_next_template.format(header=header)
+ if header == "wayland-util.h":
+ # wayland-util.h in Wayland < 1.12 includes math.h inside an
+ # extern "C" block, which breaks including the header from C++.
+ # This was fixed in Wayland 1.12, but for versions earlier than
+ # that, we work around that by force-including math.h first.
+ includes = "#include <math.h>\n" + includes
+ elif header == "wayland-client.h":
+ # The system wayland-client.h uses quote includes for
+ # wayland-util.h, which means wayland-util.h is picked from the
+ # directory containing wayland-client.h first, and there's no
+ # way around that with -I, -isystem, or other flags. So, we
+ # force to include it from our wrapper, before including the
+ # system header, so that our wayland-util.h wrapper is picked
+ # first.
+ includes = '#include "wayland-util.h"\n' + includes
+ f.write(header_template.format(includes=includes))
diff --git a/config/make-windows-h-wrapper.py b/config/make-windows-h-wrapper.py
new file mode 100644
index 0000000000..91d335ba42
--- /dev/null
+++ b/config/make-windows-h-wrapper.py
@@ -0,0 +1,94 @@
+# 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/.
+
+import re
+import string
+import textwrap
+
+comment_re = re.compile(r"//[^\n]*\n|/\*.*\*/", re.S)
+decl_re = re.compile(
+ r"""^(.+)\s+ # type
+ (\w+)\s* # name
+ (?:\((.*)\))?$ # optional param tys
+ """,
+ re.X | re.S,
+)
+
+
+def read_decls(filename):
+ """Parse & yield C-style decls from an input file"""
+ with open(filename, "r") as fd:
+ # Strip comments from the source text.
+ text = comment_re.sub("", fd.read())
+
+ # Parse individual declarations.
+ raw_decls = [d.strip() for d in text.split(";") if d.strip()]
+ for raw in raw_decls:
+ match = decl_re.match(raw)
+ if match is None:
+ raise "Invalid decl: %s" % raw
+
+ ty, name, params = match.groups()
+ if params is not None:
+ params = [a.strip() for a in params.split(",") if a.strip()]
+ yield ty, name, params
+
+
+def generate(fd, consts_path, unicodes_path, template_path, compiler):
+ # Parse the template
+ with open(template_path, "r") as template_fd:
+ template = string.Template(template_fd.read())
+
+ decls = ""
+
+ # Each constant should be saved to a temporary, and then re-assigned to a
+ # constant with the correct name, allowing the value to be determined by
+ # the actual definition.
+ for ty, name, args in read_decls(consts_path):
+ assert args is None, "parameters in const decl!"
+
+ decls += textwrap.dedent(
+ """
+ #ifdef {name}
+ constexpr {ty} _tmp_{name} = {name};
+ #undef {name}
+ constexpr {ty} {name} = _tmp_{name};
+ #endif
+ """.format(
+ ty=ty, name=name
+ )
+ )
+
+ # Each unicode declaration defines a static inline function with the
+ # correct types which calls the 'A' or 'W'-suffixed versions of the
+ # function. Full types are required here to ensure that '0' to 'nullptr'
+ # coersions are preserved.
+ for ty, name, args in read_decls(unicodes_path):
+ assert args is not None, "argument list required for unicode decl"
+
+ # Parameter & argument string list
+ params = ", ".join("%s a%d" % (ty, i) for i, ty in enumerate(args))
+ args = ", ".join("a%d" % i for i in range(len(args)))
+
+ decls += textwrap.dedent(
+ """
+ #ifdef {name}
+ #undef {name}
+ static inline {ty} WINAPI
+ {name}({params})
+ #ifdef UNICODE
+ {{
+ return {name}W({args});
+ }}
+ #else
+ = delete;
+ #endif
+ #endif
+ """.format(
+ ty=ty, name=name, params=params, args=args
+ )
+ )
+
+ # Write out the resulting file
+ fd.write(template.substitute(decls=decls))
diff --git a/config/makefiles/autotargets.mk b/config/makefiles/autotargets.mk
new file mode 100644
index 0000000000..a3a073b359
--- /dev/null
+++ b/config/makefiles/autotargets.mk
@@ -0,0 +1,93 @@
+# -*- makefile -*-
+# vim:set ts=8 sw=8 sts=8 noet:
+#
+# 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/.
+#
+
+ifndef INCLUDED_AUTOTARGETS_MK #{
+
+# Conditional does not wrap the entire file so multiple
+# includes will be able to accumulate dependencies.
+
+###########################################################################
+# AUTO_DEPS - A list of deps/targets drived from other macros.
+###########################################################################
+
+MKDIR ?= mkdir -p
+TOUCH ?= touch
+
+# declare for local use, rules.mk may not have been loaded
+space = $(NULL) $(NULL)
+
+# Deps will be considered intermediate when used as a pre-requisite for
+# wildcard targets. Inhibit their removal, mkdir -p is a standalone op.
+.PRECIOUS: %/.mkdir.done
+
+#########################
+##---] FUNCTIONS [---##
+#########################
+
+# Squeeze can be overzealous, restore root for abspath
+getPathPrefix =$(if $(filter /%,$(1)),/)
+
+# Squeeze '//' from the path, easily created by string functions
+_slashSqueeze =$(foreach val,$(getargv),$(call getPathPrefix,$(val))$(subst $(space),/,$(strip $(subst /,$(space),$(val)))))
+
+# Squeeze extraneous directory slashes from the path
+# o protect embedded spaces within the path
+# o replace //+ sequences with /
+slash_strip = \
+ $(strip \
+ $(subst <--[**]-->,$(space),\
+ $(call _slashSqueeze,\
+ $(subst $(space),<--[**]-->,$(1))\
+ )))
+
+# Extract directory path from a dependency file.
+mkdir_stem =$(foreach val,$(getargv),$(subst /.mkdir.done,$(NULL),$(val)))
+
+## Generate timestamp file for threadsafe directory creation
+mkdir_deps =$(foreach dir,$(getargv),$(call slash_strip,$(dir)/.mkdir.done))
+
+#######################
+##---] TARGETS [---##
+#######################
+
+%/.mkdir.done: # mkdir -p -p => mkdir -p
+ $(subst $(space)-p,$(null),$(MKDIR)) -p '$(dir $@)'
+# Make the timestamp old enough for not being a problem with symbolic links
+# targets depending on it. Use Jan 3, 1980 to accomodate any timezone where
+# 198001010000 would translate to something older than FAT epoch.
+ @$(TOUCH) -t 198001030000 '$@'
+
+# A handful of makefiles are attempting "mkdir dot".
+# tbpl/valgrind builds are using this target
+# https://bugzilla.mozilla.org/show_bug.cgi?id=837754
+.mkdir.done:
+ @echo 'WARNING: $(MKDIR) -dot- requested by $(MAKE) -C $(CURDIR) $(MAKECMDGOALS)'
+ @$(TOUCH) -t 198001030000 '$@'
+
+INCLUDED_AUTOTARGETS_MK = 1
+endif #}
+
+
+## Accumulate deps and cleanup
+ifneq (,$(GENERATED_DIRS))
+ GENERATED_DIRS := $(strip $(sort $(GENERATED_DIRS)))
+ tmpauto :=$(call mkdir_deps,GENERATED_DIRS)
+ GENERATED_DIRS_DEPS +=$(tmpauto)
+endif
+
+#################################################################
+# One ring/dep to rule them all:
+# config/rules.mk::all target is available by default
+# Add $(AUTO_DEPS) as an explicit target dependency when needed.
+#################################################################
+
+AUTO_DEPS +=$(GENERATED_DIRS_DEPS)
+AUTO_DEPS := $(strip $(sort $(AUTO_DEPS)))
+
+# Complain loudly if deps have not loaded so getargv != $(NULL)
+$(call requiredfunction,getargv)
diff --git a/config/makefiles/debugmake.mk b/config/makefiles/debugmake.mk
new file mode 100644
index 0000000000..bf2db445a3
--- /dev/null
+++ b/config/makefiles/debugmake.mk
@@ -0,0 +1,114 @@
+# -*- makefile -*-
+# vim:set ts=8 sw=8 sts=8 noet:
+#
+# 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/.
+#
+
+###########################################################################
+## Intent: Helper targets for displaying variables and state information
+###########################################################################
+
+# Support usage outside of config/rules.mk
+ifndef INCLUDED_DEBUGMAKE_MK #{
+
+define CR
+
+
+endef
+
+define shell_quote
+'$(subst $(CR),\$(CR),$(subst ','\'',$(1)))'
+endef
+
+echo-variable-%:
+ @echo $(call shell_quote,$($*))
+
+echo-dirs:
+ @echo $(call shell_quote,$(DIRS))
+
+define print_var
+@printf '%20s = %s\n' $1 $(call shell_quote,$($1))
+
+endef
+
+define print_vars
+$(foreach var,$1,$(call print_var,$(var)))
+endef
+
+showtargs:
+ifneq (,$(filter $(PROGRAM) $(HOST_PROGRAM) $(SIMPLE_PROGRAMS) $(LIBRARY) $(SHARED_LIBRARY),$(TARGETS)))
+ @echo --------------------------------------------------------------------------------
+ $(call print_vars,\
+ PROGRAM \
+ SIMPLE_PROGRAMS \
+ LIBRARY \
+ SHARED_LIBRARY \
+ LIBS \
+ DEF_FILE \
+ IMPORT_LIBRARY \
+ STATIC_LIBS \
+ SHARED_LIBS \
+ EXTRA_DSO_LDOPTS \
+ DEPENDENT_LIBS \
+ )
+ @echo --------------------------------------------------------------------------------
+endif
+ $(LOOP_OVER_DIRS)
+
+showbuild showhost: _DEPEND_CFLAGS=
+showbuild showhost: COMPILE_PDB_FLAG=
+showbuild:
+ $(call print_vars,\
+ MOZ_WIDGET_TOOLKIT \
+ CC \
+ CXX \
+ CCC \
+ CPP \
+ LD \
+ AR \
+ MKSHLIB \
+ MKCSHLIB \
+ RC \
+ CFLAGS \
+ OS_CFLAGS \
+ COMPILE_CFLAGS \
+ CXXFLAGS \
+ OS_CXXFLAGS \
+ COMPILE_CXXFLAGS \
+ COMPILE_CMFLAGS \
+ COMPILE_CMMFLAGS \
+ LDFLAGS \
+ OS_LDFLAGS \
+ DSO_LDOPTS \
+ OS_INCLUDES \
+ OS_LIBS \
+ BIN_FLAGS \
+ INCLUDES \
+ DEFINES \
+ ACDEFINES \
+ BIN_SUFFIX \
+ LIB_SUFFIX \
+ DLL_SUFFIX \
+ IMPORT_LIB_SUFFIX \
+ INSTALL \
+ VPATH \
+ )
+
+showhost:
+ $(call print_vars,\
+ HOST_CC \
+ HOST_CXX \
+ HOST_CFLAGS \
+ HOST_LDFLAGS \
+ HOST_LIBS \
+ HOST_EXTRA_LIBS \
+ HOST_EXTRA_DEPS \
+ HOST_PROGRAM \
+ HOST_OBJS \
+ HOST_PROGOBJS \
+ )
+
+INCLUDED_DEBUGMAKE_MK = 1
+endif #}
diff --git a/config/makefiles/functions.mk b/config/makefiles/functions.mk
new file mode 100644
index 0000000000..65c9a6749f
--- /dev/null
+++ b/config/makefiles/functions.mk
@@ -0,0 +1,41 @@
+#
+# 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/.
+
+#
+# functions.mk
+#
+# Defines functions that are needed by various Makefiles throughout the build
+# system, which are needed before config.mk can be included.
+#
+
+# Define an include-at-most-once flag
+ifdef INCLUDED_FUNCTIONS_MK
+$(error Do not include functions.mk twice!)
+endif
+INCLUDED_FUNCTIONS_MK = 1
+
+core_abspath = $(error core_abspath is unsupported, use $$(abspath) instead)
+core_realpath = $(error core_realpath is unsupported)
+
+core_winabspath = $(error core_winabspath is unsupported)
+
+# Run a named Python build action. The first argument is the name of the build
+# action. The second argument are the arguments to pass to the action (space
+# delimited arguments). e.g.
+#
+# libs::
+# $(call py_action,purge_manifests,_build_manifests/purge/foo.manifest)
+#
+# The first argument can optionally contain the name of the file being created
+# or processed. e.g.
+# libs::
+# $(call py_action,purge_manifests foo.manifest,_build_manifests/purge/foo.manifest)
+# This optional name will be displayed in build profiles.
+define py_action
+$(call BUILDSTATUS,START_$(firstword $(1)) $(or $(word 2,$(1)),$(2)))
+$(if $(3),cd $(3) && )$(PYTHON3) -m mozbuild.action.$(firstword $(1)) $(2)
+$(call BUILDSTATUS,END_$(firstword $(1)) $(or $(word 2,$(1)),$(2)))
+
+endef
diff --git a/config/makefiles/makeutils.mk b/config/makefiles/makeutils.mk
new file mode 100644
index 0000000000..95c7791a4b
--- /dev/null
+++ b/config/makefiles/makeutils.mk
@@ -0,0 +1,121 @@
+# -*- makefile -*-
+# vim:set ts=8 sw=8 sts=8 noet:
+#
+# 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/.
+
+## Identify function argument types
+istype =$(if $(value ${1}),list,scalar)
+isval =$(if $(filter-out list,$(call istype,${1})),true)
+isvar =$(if $(filter-out scalar,$(call istype,${1})),true)
+
+# Access up to 9 arguments passed, option needed to emulate $*
+# Inline for function expansion, do not use $(call )
+argv =$(strip
+argv +=$(if $(1), $(1))$(if $(2), $(2))$(if $(3), $(3))$(if $(4), $(4))
+argv +=$(if $(5), $(5))$(if $(6), $(6))$(if $(7), $(7))$(if $(8), $(8))
+argv +=$(if $(9), $(9))
+argv +=$(if $(10), $(error makeutils.mk::argv can only handle 9 arguments))
+argv +=)
+
+###########################################################################
+## Access function args as a simple list, inline within user functions.
+## Usage: $(info ** $(call banner,$(getargv)))
+## $(call banner,scalar)
+## $(call banner,list0 list1 list2)
+## $(call banner,ref) ; ref=foo bar tans
+## getarglist() would be a more accurate name but is longer to type
+getargv = $(if $(call isvar,$(1)),$($(1)),$(argv))
+
+###########################################################################
+# Strip [n] leading options from an argument list. This will allow passing
+# extra args to user functions that will not propogate to sub-$(call )'s
+# Usage: $(call subargv,2)
+subargv =$(wordlist $(1),$(words $(getargv)),$(getargv))
+
+###########################################################################
+# Intent: Display a distinct banner heading in the output stream
+# Usage: $(call banner,BUILDING: foo bar tans)
+# Debug:
+# target-preqs = \
+# $(call banner,target-preqs-BEGIN) \
+# foo bar tans \
+# $(call banner,target-preqs-END) \
+# $(NULL)
+# target: $(target-preqs)
+
+banner = \
+$(info ) \
+$(info ***************************************************************************) \
+$(info ** $(getargv)) \
+$(info ***************************************************************************) \
+$(NULL)
+
+#####################################################################
+# Intent: Determine if a string or pattern is contained in a list
+# Usage: strcmp - $(call if_XinY,clean,$(MAKECMDGOALS))
+# : pattern - $(call if_XinY,clean%,$(MAKECMDGOALS))
+is_XinY =$(filter $(1),$(call subargv,3,$(getargv)))
+
+#####################################################################
+# Provide an alternate var to support testing
+ifdef MAKEUTILS_UNIT_TEST
+ mcg_goals=TEST_MAKECMDGOALS
+else
+ mcg_goals=MAKECMDGOALS
+endif
+
+# Intent: Conditionals for detecting common/tier target use
+isTargetStem = $(sort \
+ $(foreach var,$(getargv),\
+ $(foreach pat,$(var)% %$(var),\
+ $(call is_XinY,$(pat),${$(mcg_goals)})\
+ )))
+isTargetStemClean = $(call isTargetStem,clean)
+isTargetStemExport = $(call isTargetStem,export)
+isTargetStemLibs = $(call isTargetStem,libs)
+isTargetStemTools = $(call isTargetStem,tools)
+
+##################################################
+# Intent: Validation functions / unit test helpers
+
+errorifneq =$(if $(subst $(strip $(1)),$(NULL),$(strip $(2))),$(error expected [$(1)] but found [$(2)]))
+
+# Intent: verify function declaration exists
+requiredfunction =$(foreach func,$(1) $(2) $(3) $(4) $(5) $(6) $(7) $(8) $(9),$(if $(value $(func)),$(NULL),$(error required function [$(func)] is unavailable)))
+
+
+
+## http://www.gnu.org/software/make/manual/make.html#Call-Function
+## Usage: o = $(call map,origin,o map $(MAKE))
+map = $(foreach val,$(2),$(call $(1),$(val)))
+
+
+## Disable checking for clean targets
+ifeq (,$(filter %clean clean%,$(MAKECMDGOALS))) #{
+
+# Usage: $(call checkIfEmpty,[error|warning] foo NULL bar)
+checkIfEmpty =$(foreach var,$(wordlist 2,100,$(argv)),$(if $(strip $($(var))),$(NOP),$(call $(1),Variable $(var) does not contain a value)))
+
+# Usage: $(call errorIfEmpty,foo NULL bar)
+errorIfEmpty =$(call checkIfEmpty,error $(argv))
+warnIfEmpty =$(call checkIfEmpty,warning $(argv))
+
+endif #}
+
+###########################################################################
+## Common makefile library loader
+###########################################################################
+ifdef MOZILLA_DIR
+topORerr = $(MOZILLA_DIR)
+else
+topORerr = $(if $(topsrcdir),$(topsrcdir),$(error topsrcdir is not defined))
+endif
+
+ifdef USE_AUTOTARGETS_MK # mkdir_deps
+ include $(topORerr)/config/makefiles/autotargets.mk
+endif
+
+## copy(src, dst): recursive copy
+copy_dir = (cd $(1)/. && $(TAR) $(TAR_CREATE_FLAGS) - .) | (cd $(2)/. && tar -xf -)
diff --git a/config/makefiles/nonrecursive.mk b/config/makefiles/nonrecursive.mk
new file mode 100644
index 0000000000..498de568e7
--- /dev/null
+++ b/config/makefiles/nonrecursive.mk
@@ -0,0 +1,68 @@
+# -*- makefile -*-
+# vim:set ts=8 sw=8 sts=8 noet:
+#
+# 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/.
+
+# The purpose of this file is to pull in non-recursive targets when performing
+# a partial tree (not top-level) build. This will allow people to continue to
+# build individual directories while some of the targets may not be normally
+# defined in that make file.
+#
+# Non-recursive targets are attached to existing make targets. The
+# NONRECURSIVE_TARGETS variable lists the make targets that modified. For
+# each target in this list, the NONRECURSIVE_TARGET_<target> variable will
+# contain a list of partial variable names. We will then look in variables
+# named NONRECURSIVE_TARGETS_<target>_<fragment>_* for information describing
+# how to evaluate non-recursive make targets.
+#
+# Targets are defined by the following variables:
+#
+# FILE - The make file to evaluate. This is equivalent to
+# |make -f <FILE>|
+# DIRECTORY - The directory whose Makefile to evaluate. This is
+# equivalent to |make -C <DIRECTORY>|.
+# TARGETS - Targets to evaluate in that make file.
+#
+# Only 1 of FILE or DIRECTORY may be defined.
+#
+# For example:
+#
+# NONRECURSIVE_TARGETS = export libs
+# NONRECURSIVE_TARGETS_export = headers
+# NONRECURSIVE_TARGETS_export_headers_FILE = /path/to/exports.mk
+# NONRECURSIVE_TARGETS_export_headers_TARGETS = $(DIST)/include/foo.h $(DIST)/include/bar.h
+# NONRECURSIVE_TARGETS_libs = cppsrcs
+# NONRECURSIVE_TARGETS_libs_cppsrcs_DIRECTORY = $(DEPTH)/foo
+# NONRECURSIVE_TARGETS_libs_cppsrcs_TARGETS = /path/to/foo.o /path/to/bar.o
+#
+# Will get turned into the following:
+#
+# exports::
+# $(MAKE) -C $(DEPTH) -f /path/to/exports.mk $(DIST)/include/foo.h $(DIST)/include/bar.h
+#
+# libs::
+# $(MAKE) -C $(DEPTH)/foo /path/to/foo.o /path/to/bar.o
+
+ifndef INCLUDED_NONRECURSIVE_MK
+
+define define_nonrecursive_target
+$(1)::
+ $$(MAKE) -C $(or $(4),$$(DEPTH)) $(addprefix -f ,$(3)) $(2)
+endef
+
+$(foreach target,$(NONRECURSIVE_TARGETS), \
+ $(foreach entry,$(NONRECURSIVE_TARGETS_$(target)), \
+ $(eval $(call define_nonrecursive_target, \
+ $(target), \
+ $(NONRECURSIVE_TARGETS_$(target)_$(entry)_TARGETS), \
+ $(NONRECURSIVE_TARGETS_$(target)_$(entry)_FILE), \
+ $(NONRECURSIVE_TARGETS_$(target)_$(entry)_DIRECTORY), \
+ )) \
+ ) \
+)
+
+INCLUDED_NONRECURSIVE_MK := 1
+endif
+
diff --git a/config/makefiles/rust.mk b/config/makefiles/rust.mk
new file mode 100644
index 0000000000..9e3d5256b9
--- /dev/null
+++ b/config/makefiles/rust.mk
@@ -0,0 +1,613 @@
+# 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/.
+
+# /!\ In this file, we export multiple variables globally via make rather than
+# in recipes via the `env` command to avoid round-trips to msys on Windows, which
+# tend to break environment variable values in interesting ways.
+
+# /!\ Avoid the use of double-quotes in this file, so that the cargo
+# commands can be executed directly by make, without doing a round-trip
+# through a shell.
+
+cargo_host_flag := --target=$(RUST_HOST_TARGET)
+cargo_target_flag := --target=$(RUST_TARGET)
+
+# Permit users to pass flags to cargo from their mozconfigs (e.g. --color=always).
+cargo_build_flags = $(CARGOFLAGS)
+ifndef MOZ_DEBUG_RUST
+cargo_build_flags += --release
+endif
+
+# The Spidermonkey library can be built from a package tarball outside the
+# tree, so we want to let Cargo create lock files in this case. When built
+# within a tree, the Rust dependencies have been vendored in so Cargo won't
+# touch the lock file.
+ifndef JS_STANDALONE
+cargo_build_flags += --frozen
+endif
+
+cargo_build_flags += --manifest-path $(CARGO_FILE)
+ifdef BUILD_VERBOSE_LOG
+cargo_build_flags += -vv
+endif
+
+ifneq (,$(USE_CARGO_JSON_MESSAGE_FORMAT))
+cargo_build_flags += --message-format=json
+endif
+
+# Enable color output if original stdout was a TTY and color settings
+# aren't already present. This essentially restores the default behavior
+# of cargo when running via `mach`.
+ifdef MACH_STDOUT_ISATTY
+ifeq (,$(findstring --color,$(cargo_build_flags)))
+ifdef NO_ANSI
+cargo_build_flags += --color=never
+else
+cargo_build_flags += --color=always
+endif
+endif
+endif
+
+# Without -j > 1, make will not pass jobserver info down to cargo. Force
+# one job when requested as a special case.
+cargo_build_flags += $(filter -j1,$(MAKEFLAGS))
+
+# We also need to rebuild the rust stdlib so that it's instrumented. Because
+# build-std is still pretty experimental, we need to explicitly request
+# the panic_abort crate for `panic = "abort"` support.
+ifdef MOZ_TSAN
+cargo_build_flags += -Zbuild-std=std,panic_abort
+RUSTFLAGS += -Zsanitizer=thread
+endif
+
+rustflags_sancov =
+ifdef LIBFUZZER
+ifndef MOZ_TSAN
+ifndef FUZZING_JS_FUZZILLI
+# These options should match what is implicitly enabled for `clang -fsanitize=fuzzer`
+# here: https://github.com/llvm/llvm-project/blob/release/13.x/clang/lib/Driver/SanitizerArgs.cpp#L422
+#
+# -sanitizer-coverage-inline-8bit-counters Increments 8-bit counter for every edge.
+# -sanitizer-coverage-level=4 Enable coverage for all blocks, critical edges, and indirect calls.
+# -sanitizer-coverage-trace-compares Tracing of CMP and similar instructions.
+# -sanitizer-coverage-pc-table Create a static PC table.
+#
+# In TSan builds, we must not pass any of these, because sanitizer coverage is incompatible with TSan.
+rustflags_sancov += -Cpasses=sancov-module -Cllvm-args=-sanitizer-coverage-inline-8bit-counters -Cllvm-args=-sanitizer-coverage-level=4 -Cllvm-args=-sanitizer-coverage-trace-compares -Cllvm-args=-sanitizer-coverage-pc-table
+endif
+endif
+endif
+
+# These flags are passed via `cargo rustc` and only apply to the final rustc
+# invocation (i.e., only the top-level crate, not its dependencies).
+cargo_rustc_flags = $(CARGO_RUSTCFLAGS)
+ifndef DEVELOPER_OPTIONS
+ifndef MOZ_DEBUG_RUST
+# Enable link-time optimization for release builds, but not when linking
+# gkrust_gtest. And not when doing cross-language LTO.
+ifndef MOZ_LTO_RUST_CROSS
+# Never enable when sancov is enabled to work around https://github.com/rust-lang/rust/issues/90300.
+ifndef rustflags_sancov
+# Never enable when coverage is enabled to work around https://github.com/rust-lang/rust/issues/90045.
+ifndef MOZ_CODE_COVERAGE
+ifeq (,$(findstring gkrust_gtest,$(RUST_LIBRARY_FILE)))
+cargo_rustc_flags += -Clto$(if $(filter full,$(MOZ_LTO_RUST_CROSS)),=fat)
+endif
+# We need -Cembed-bitcode=yes for all crates when using -Clto.
+RUSTFLAGS += -Cembed-bitcode=yes
+endif
+endif
+endif
+endif
+endif
+
+ifdef CARGO_INCREMENTAL
+export CARGO_INCREMENTAL
+endif
+
+rustflags_neon =
+ifeq (neon,$(MOZ_FPU))
+ifneq (,$(filter thumbv7neon-,$(RUST_TARGET)))
+# Enable neon and disable restriction to 16 FPU registers when neon is enabled
+# but we're not using a thumbv7neon target, where it's already the default.
+# (CPUs with neon have 32 FPU registers available)
+rustflags_neon += -C target_feature=+neon,-d16
+endif
+endif
+
+rustflags_override = $(MOZ_RUST_DEFAULT_FLAGS) $(rustflags_neon)
+
+ifdef DEVELOPER_OPTIONS
+# By default the Rust compiler will perform a limited kind of ThinLTO on each
+# crate. For local builds this additional optimization is not worth the
+# increase in compile time so we opt out of it.
+rustflags_override += -Clto=off
+endif
+
+ifdef MOZ_USING_SCCACHE
+export RUSTC_WRAPPER=$(CCACHE)
+endif
+
+ifndef CROSS_COMPILE
+ifdef MOZ_TSAN
+PASS_ONLY_BASE_CFLAGS_TO_RUST=1
+else
+ifneq (,$(MOZ_ASAN)$(MOZ_UBSAN))
+ifneq ($(OS_ARCH), Linux)
+PASS_ONLY_BASE_CFLAGS_TO_RUST=1
+endif # !Linux
+endif # MOZ_ASAN || MOZ_UBSAN
+endif # MOZ_TSAN
+endif # !CROSS_COMPILE
+
+ifeq (WINNT,$(HOST_OS_ARCH))
+ifdef MOZ_CODE_COVERAGE
+PASS_ONLY_BASE_CFLAGS_TO_RUST=1
+endif # MOZ_CODE_COVERAGE
+endif # WINNT
+
+ifeq (WINNT,$(HOST_OS_ARCH))
+normalize_sep = $(subst \,/,$(1))
+else
+normalize_sep = $(1)
+endif
+
+# We start with host variables because the rust host and the rust target might be the same,
+# in which case we want the latter to take priority.
+
+# We're passing these for consumption by the `cc` crate, which doesn't use the same
+# convention as cargo itself:
+# https://github.com/alexcrichton/cc-rs/blob/baa71c0e298d9ad7ac30f0ad78f20b4b3b3a8fb2/src/lib.rs#L1715
+rust_host_cc_env_name := $(subst -,_,$(RUST_HOST_TARGET))
+
+# HOST_CC/HOST_CXX/CC/CXX usually contain base flags for e.g. the build target.
+# We want to pass those through CFLAGS_*/CXXFLAGS_* instead, so that they end up
+# after whatever cc-rs adds to the compiler command line, so that they win.
+# Ideally, we'd use CRATE_CC_NO_DEFAULTS=1, but that causes other problems at the
+# moment.
+export CC_$(rust_host_cc_env_name)=$(filter-out $(HOST_CC_BASE_FLAGS),$(HOST_CC))
+export CXX_$(rust_host_cc_env_name)=$(filter-out $(HOST_CXX_BASE_FLAGS),$(HOST_CXX))
+export AR_$(rust_host_cc_env_name)=$(HOST_AR)
+
+rust_cc_env_name := $(subst -,_,$(RUST_TARGET))
+
+export CC_$(rust_cc_env_name)=$(filter-out $(CC_BASE_FLAGS),$(CC))
+export CXX_$(rust_cc_env_name)=$(filter-out $(CXX_BASE_FLAGS),$(CXX))
+export AR_$(rust_cc_env_name)=$(AR)
+
+ifeq (WINNT,$(HOST_OS_ARCH))
+HOST_CC_BASE_FLAGS += -DUNICODE
+HOST_CXX_BASE_FLAGS += -DUNICODE
+endif
+ifeq (WINNT,$(OS_ARCH))
+CC_BASE_FLAGS += -DUNICODE
+CXX_BASE_FLAGS += -DUNICODE
+endif
+
+ifneq (1,$(PASS_ONLY_BASE_CFLAGS_TO_RUST))
+# -DMOZILLA_CONFIG_H is added to prevent mozilla-config.h from injecting anything
+# in C/C++ compiles from rust. That's not needed in the other branch because the
+# base flags don't force-include mozilla-config.h.
+export CFLAGS_$(rust_host_cc_env_name)=$(HOST_CC_BASE_FLAGS) $(COMPUTED_HOST_CFLAGS) -DMOZILLA_CONFIG_H
+export CXXFLAGS_$(rust_host_cc_env_name)=$(HOST_CXX_BASE_FLAGS) $(COMPUTED_HOST_CXXFLAGS) -DMOZILLA_CONFIG_H
+export CFLAGS_$(rust_cc_env_name)=$(CC_BASE_FLAGS) $(COMPUTED_CFLAGS) -DMOZILLA_CONFIG_H
+export CXXFLAGS_$(rust_cc_env_name)=$(CXX_BASE_FLAGS) $(COMPUTED_CXXFLAGS) -DMOZILLA_CONFIG_H
+else
+# Because cargo doesn't allow to distinguish builds happening for build
+# scripts/procedural macros vs. those happening for the rust target,
+# we can't blindly pass all our flags down for cc-rs to use them, because of the
+# side effects they can have on what otherwise should be host builds.
+# So for sanitizer and coverage builds, we only pass the base compiler flags.
+# This means C code built by rust is not going to be covered by sanitizers
+# and coverage. But at least we control what compiler is being used,
+# rather than relying on cc-rs guesses, which, sometimes fail us.
+export CFLAGS_$(rust_host_cc_env_name)=$(HOST_CC_BASE_FLAGS)
+export CXXFLAGS_$(rust_host_cc_env_name)=$(HOST_CXX_BASE_FLAGS)
+export CFLAGS_$(rust_cc_env_name)=$(CC_BASE_FLAGS)
+export CXXFLAGS_$(rust_cc_env_name)=$(CXX_BASE_FLAGS)
+endif
+
+# When host == target, cargo will compile build scripts with sanitizers enabled
+# if sanitizers are enabled, which may randomly fail when they execute
+# because of https://github.com/google/sanitizers/issues/1322.
+# Work around by disabling __tls_get_addr interception (bug 1635327).
+ifeq ($(RUST_TARGET),$(RUST_HOST_TARGET))
+define sanitizer_options
+ifdef MOZ_$1
+export $1_OPTIONS:=$$($1_OPTIONS:%=%:)intercept_tls_get_addr=0
+endif
+endef
+$(foreach san,ASAN TSAN UBSAN,$(eval $(call sanitizer_options,$(san))))
+endif
+
+# Force the target down to all bindgen callers, even those that may not
+# read BINDGEN_SYSTEM_FLAGS some way or another.
+export BINDGEN_EXTRA_CLANG_ARGS:=$(filter --target=%,$(BINDGEN_SYSTEM_FLAGS))
+export CARGO_TARGET_DIR
+export RUSTFLAGS
+export RUSTC
+export RUSTDOC
+export RUSTFMT
+export LIBCLANG_PATH=$(MOZ_LIBCLANG_PATH)
+export CLANG_PATH=$(MOZ_CLANG_PATH)
+export PKG_CONFIG
+export PKG_CONFIG_ALLOW_CROSS=1
+export PKG_CONFIG_PATH
+ifneq (,$(PKG_CONFIG_SYSROOT_DIR))
+export PKG_CONFIG_SYSROOT_DIR
+endif
+ifneq (,$(PKG_CONFIG_LIBDIR))
+export PKG_CONFIG_LIBDIR
+endif
+export RUST_BACKTRACE=full
+export MOZ_TOPOBJDIR=$(topobjdir)
+export MOZ_FOLD_LIBS
+export PYTHON3
+export CARGO_PROFILE_RELEASE_OPT_LEVEL
+export CARGO_PROFILE_DEV_OPT_LEVEL
+
+# Set COREAUDIO_SDK_PATH for third_party/rust/coreaudio-sys/build.rs
+ifeq ($(OS_ARCH), Darwin)
+ifdef MACOS_SDK_DIR
+export COREAUDIO_SDK_PATH=$(MACOS_SDK_DIR)
+endif
+endif
+
+ifndef RUSTC_BOOTSTRAP
+RUSTC_BOOTSTRAP := mozglue_static,qcms
+ifdef MOZ_RUST_SIMD
+RUSTC_BOOTSTRAP := $(RUSTC_BOOTSTRAP),encoding_rs,packed_simd
+endif
+export RUSTC_BOOTSTRAP
+endif
+
+target_rust_ltoable := force-cargo-library-build $(ADD_RUST_LTOABLE)
+target_rust_nonltoable := force-cargo-test-run force-cargo-program-build
+
+ifdef MOZ_PGO_RUST
+ifdef MOZ_PROFILE_GENERATE
+rust_pgo_flags := -C profile-generate=$(topobjdir)
+ifeq (1,$(words $(filter 5.% 6.% 7.% 8.% 9.% 10.% 11.%,$(CC_VERSION) $(RUSTC_LLVM_VERSION))))
+# Disable value profiling when:
+# (RUSTC_LLVM_VERSION < 12 and CC_VERSION >= 12) or (RUSTC_LLVM_VERSION >= 12 and CC_VERSION < 12)
+rust_pgo_flags += -C llvm-args=--disable-vp=true
+endif
+# The C compiler may be passed extra llvm flags for PGO that we also want to pass to rust as well.
+# In PROFILE_GEN_CFLAGS, they look like "-mllvm foo", and we want "-C llvm-args=foo", so first turn
+# "-mllvm foo" into "-mllvm:foo" so that it becomes a unique argument, that we can then filter for,
+# excluding other flags, and then turn into the right string.
+rust_pgo_flags += $(patsubst -mllvm:%,-C llvm-args=%,$(filter -mllvm:%,$(subst -mllvm ,-mllvm:,$(PROFILE_GEN_CFLAGS))))
+else # MOZ_PROFILE_USE
+rust_pgo_flags := -C profile-use=$(PGO_PROFILE_PATH)
+endif
+endif
+
+# Work around https://github.com/rust-lang/rust/issues/112480
+ifdef MOZ_DEBUG_RUST
+ifneq (,$(filter i686-pc-windows-%,$(RUST_TARGET)))
+RUSTFLAGS += -Zmir-enable-passes=-CheckAlignment
+RUSTC_BOOTSTRAP := 1
+endif
+endif
+
+$(target_rust_ltoable): RUSTFLAGS:=$(rustflags_override) $(rustflags_sancov) $(RUSTFLAGS) $(rust_pgo_flags) \
+ $(if $(MOZ_LTO_RUST_CROSS),\
+ -Clinker-plugin-lto \
+ ,)
+$(target_rust_nonltoable): RUSTFLAGS:=$(rustflags_override) $(rustflags_sancov) $(RUSTFLAGS)
+
+TARGET_RECIPES := $(target_rust_ltoable) $(target_rust_nonltoable)
+
+HOST_RECIPES := \
+ $(foreach a,library program,$(foreach b,build check udeps clippy,force-cargo-host-$(a)-$(b)))
+
+$(HOST_RECIPES): RUSTFLAGS:=$(rustflags_override)
+
+# If this is a release build we want rustc to generate one codegen unit per
+# crate. This results in better optimization and less code duplication at the
+# cost of longer compile times.
+ifndef DEVELOPER_OPTIONS
+$(TARGET_RECIPES) $(HOST_RECIPES): RUSTFLAGS += -C codegen-units=1
+endif
+
+# We use the + prefix to pass down the jobserver fds to cargo, but we
+# don't use the prefix when make -n is used, so that cargo doesn't run
+# in that case)
+define RUN_CARGO_INNER
+$(if $(findstring n,$(filter-out --%, $(MAKEFLAGS))),,+)$(CARGO) $(1) $(cargo_build_flags) $(CARGO_EXTRA_FLAGS) $(cargo_extra_cli_flags)
+endef
+
+ifdef CARGO_CONTINUE_ON_ERROR
+define RUN_CARGO
+-$(RUN_CARGO_INNER)
+endef
+else
+define RUN_CARGO
+$(RUN_CARGO_INNER)
+endef
+endif
+
+# This function is intended to be called by:
+#
+# $(call CARGO_BUILD,EXTRA_ENV_VAR1=X EXTRA_ENV_VAR2=Y ...)
+#
+# but, given the idiosyncracies of make, can also be called without arguments:
+#
+# $(call CARGO_BUILD)
+define CARGO_BUILD
+$(call RUN_CARGO,rustc$(if $(BUILDSTATUS), --timings))
+endef
+
+cargo_host_linker_env_var := CARGO_TARGET_$(call varize,$(RUST_HOST_TARGET))_LINKER
+cargo_linker_env_var := CARGO_TARGET_$(call varize,$(RUST_TARGET))_LINKER
+
+export MOZ_CLANG_NEWER_THAN_RUSTC_LLVM
+export MOZ_CARGO_WRAP_LDFLAGS
+export MOZ_CARGO_WRAP_LD
+export MOZ_CARGO_WRAP_LD_CXX
+export MOZ_CARGO_WRAP_HOST_LDFLAGS
+export MOZ_CARGO_WRAP_HOST_LD
+export MOZ_CARGO_WRAP_HOST_LD_CXX
+# Exporting from make always exports a value. Setting a value per-recipe
+# would export an empty value for the host recipes. When not doing a
+# cross-compile, the --target for those is the same, and cargo will use
+# CARGO_TARGET_*_LINKER for its linker, so we always pass the
+# cargo-linker wrapper, and fill MOZ_CARGO_WRAP_{HOST_,}LD* more or less
+# appropriately for all recipes.
+ifeq (WINNT,$(HOST_OS_ARCH))
+# Use .bat wrapping on Windows hosts, and shell wrapping on other hosts.
+# Like for CC/C*FLAGS, we want the target values to trump the host values when
+# both variables are the same.
+export $(cargo_host_linker_env_var):=$(topsrcdir)/build/cargo-host-linker.bat
+export $(cargo_linker_env_var):=$(topsrcdir)/build/cargo-linker.bat
+WRAP_HOST_LINKER_LIBPATHS:=$(HOST_LINKER_LIBPATHS_BAT)
+else
+export $(cargo_host_linker_env_var):=$(topsrcdir)/build/cargo-host-linker
+export $(cargo_linker_env_var):=$(topsrcdir)/build/cargo-linker
+WRAP_HOST_LINKER_LIBPATHS:=$(HOST_LINKER_LIBPATHS)
+endif
+
+# Cargo needs the same linker flags as the C/C++ compiler,
+# but not the final libraries. Filter those out because they
+# cause problems on macOS 10.7; see bug 1365993 for details.
+# Also, we don't want to pass PGO flags until cargo supports them.
+# Finally, we also remove the -Wl,--build-id=uuid flag when it's in
+# the LDFLAGS. The flag was chosen over the default (build-id=sha1)
+# in developer builds, because for libxul, it's faster. But it's also
+# non-deterministic. So when the rust compiler produces procedural
+# macros as libraries, they're not reproducible. Those procedural
+# macros then end up as dependencies of other crates, and their
+# non-reproducibility leads to sccache transitively having cache
+# misses.
+$(TARGET_RECIPES): MOZ_CARGO_WRAP_LDFLAGS:=$(filter-out -fsanitize=cfi% -framework Cocoa -lobjc AudioToolbox ExceptionHandling -fprofile-% -Wl$(COMMA)--build-id=uuid,$(LDFLAGS))
+
+# When building with sanitizer, rustc links its own runtime, which conflicts
+# with the one that passing -fsanitize=* to the linker would add.
+# Ideally, we'd always do this filtering, but because the flags may also apply
+# to build scripts because cargo doesn't allow the distinction, we only filter
+# when building programs, except when using thread sanitizer where we filter
+# everywhere.
+ifneq (,$(filter -Zsanitizer=%,$(RUSTFLAGS)))
+$(if $(filter -Zsanitizer=thread,$(RUSTFLAGS)),$(TARGET_RECIPES),force-cargo-program-build): MOZ_CARGO_WRAP_LDFLAGS:=$(filter-out -fsanitize=%,$(MOZ_CARGO_WRAP_LDFLAGS))
+endif
+
+# Rustc assumes that *-windows-gnu targets build with mingw-gcc and manually
+# add runtime libraries that don't exist with mingw-clang. We created dummy
+# libraries in $(topobjdir)/build/win32, but that's not enough, because some
+# of the wanted symbols that come from these libraries are available in a
+# different library, that we add manually. We also need to avoid rustc
+# passing -nodefaultlibs to clang so that it adds clang_rt.
+ifeq (WINNT_clang,$(OS_ARCH)_$(CC_TYPE))
+force-cargo-program-build: MOZ_CARGO_WRAP_LDFLAGS+=-L$(topobjdir)/build/win32 -lunwind
+force-cargo-program-build: CARGO_RUSTCFLAGS += -C default-linker-libraries=yes
+endif
+
+# Rustc passes -nodefaultlibs to the linker (clang) on mac, which prevents
+# clang from adding the necessary sanitizer runtimes when building with
+# C/C++ sanitizer but without rust sanitizer.
+ifeq (Darwin,$(OS_ARCH))
+ifeq (,$(filter -Zsanitizer=%,$(RUSTFLAGS)))
+ifneq (,$(filter -fsanitize=%,$(LDFLAGS)))
+force-cargo-program-build: CARGO_RUSTCFLAGS += -C default-linker-libraries=yes
+endif
+endif
+endif
+
+$(HOST_RECIPES): MOZ_CARGO_WRAP_LDFLAGS:=$(HOST_LDFLAGS) $(WRAP_HOST_LINKER_LIBPATHS)
+$(TARGET_RECIPES) $(HOST_RECIPES): MOZ_CARGO_WRAP_HOST_LDFLAGS:=$(HOST_LDFLAGS) $(WRAP_HOST_LINKER_LIBPATHS)
+
+ifeq (,$(filter clang-cl,$(CC_TYPE)))
+$(TARGET_RECIPES): MOZ_CARGO_WRAP_LD:=$(CC)
+$(TARGET_RECIPES): MOZ_CARGO_WRAP_LD_CXX:=$(CXX)
+else
+$(TARGET_RECIPES): MOZ_CARGO_WRAP_LD:=$(LINKER)
+$(TARGET_RECIPES): MOZ_CARGO_WRAP_LD_CXX:=$(LINKER)
+endif
+
+ifeq (,$(filter clang-cl,$(HOST_CC_TYPE)))
+$(HOST_RECIPES): MOZ_CARGO_WRAP_LD:=$(HOST_CC)
+$(HOST_RECIPES): MOZ_CARGO_WRAP_LD_CXX:=$(HOST_CXX)
+$(TARGET_RECIPES) $(HOST_RECIPES): MOZ_CARGO_WRAP_HOST_LD:=$(HOST_CC)
+$(TARGET_RECIPES) $(HOST_RECIPES): MOZ_CARGO_WRAP_HOST_LD_CXX:=$(HOST_CXX)
+else
+$(HOST_RECIPES): MOZ_CARGO_WRAP_LD:=$(HOST_LINKER)
+$(HOST_RECIPES): MOZ_CARGO_WRAP_LD_CXX:=$(HOST_LINKER)
+$(TARGET_RECIPES) $(HOST_RECIPES): MOZ_CARGO_WRAP_HOST_LD:=$(HOST_LINKER)
+$(TARGET_RECIPES) $(HOST_RECIPES): MOZ_CARGO_WRAP_HOST_LD_CXX:=$(HOST_LINKER)
+endif
+
+define make_default_rule
+$(1):
+
+endef
+
+# make_cargo_rule(target, real-target [, extra-deps])
+# Generates a rule suitable to rebuild $(target) only if its dependencies are
+# obsolete.
+# It relies on the fact that upon build, cargo generates a dependency file named
+# `$(target).d'. Unfortunately the lhs of the rule has an absolute path,
+# so we extract it under the name $(target)_deps below.
+#
+# If the dependencies are empty, the file was not created so we force a rebuild.
+# Otherwise we add it to the dependency list.
+#
+# The actual rule is a bit tricky. The `+' prefix allow for recursive parallel
+# make, and it's skipped (`:') if we already triggered a rebuild as part of the
+# dependency chain.
+#
+# Another tricky thing: some dependencies may contain escaped spaces, and they
+# need to be preserved, but $(foreach) splits on spaces, so we replace escaped
+# spaces with some unlikely string for the foreach, and replace them back in the
+# loop itself.
+define make_cargo_rule
+$(notdir $(1))_deps := $$(wordlist 2, 10000000, $$(if $$(wildcard $(basename $(1)).d),$$(shell cat $(basename $(1)).d)))
+$(1): $(CARGO_FILE) $(3) $(topsrcdir)/Cargo.lock $$(if $$($(notdir $(1))_deps),$$($(notdir $(1))_deps),$(2))
+ $$(REPORT_BUILD)
+ $$(if $$($(notdir $(1))_deps),+$(MAKE) $(2),:)
+
+$$(foreach dep, $$(call normalize_sep,$$(subst \ ,_^_^_^_,$$($(notdir $(1))_deps))),$$(eval $$(call make_default_rule,$$(subst _^_^_^_,\ ,$$(dep)))))
+endef
+
+ifdef RUST_LIBRARY_FILE
+
+rust_features_flag := --features '$(if $(RUST_LIBRARY_FEATURES),$(RUST_LIBRARY_FEATURES) )mozilla-central-workspace-hack'
+
+ifeq (WASI,$(OS_ARCH))
+# The rust wasi target defaults to statically link the wasi crt, but when we
+# build static libraries from rust and link them with C/C++ code, we also link
+# a wasi crt, which may conflict with rust's.
+force-cargo-library-build: CARGO_RUSTCFLAGS += -C target-feature=-crt-static
+endif
+
+# Assume any system libraries rustc links against are already in the target's LIBS.
+#
+# We need to run cargo unconditionally, because cargo is the only thing that
+# has full visibility into how changes in Rust sources might affect the final
+# build.
+force-cargo-library-build:
+ $(call BUILDSTATUS,START_Rust $(notdir $(RUST_LIBRARY_FILE)))
+ $(call CARGO_BUILD) --lib $(cargo_target_flag) $(rust_features_flag) -- $(cargo_rustc_flags)
+ $(call BUILDSTATUS,END_Rust $(notdir $(RUST_LIBRARY_FILE)))
+# When we are building in --enable-release mode; we add an additional check to confirm
+# that we are not importing any networking-related functions in rust code. This reduces
+# the chance of proxy bypasses originating from rust code.
+# The check only works when rust code is built with -Clto but without MOZ_LTO_RUST_CROSS.
+# Sanitizers and sancov also fail because compiler-rt hooks network functions.
+ifndef MOZ_PROFILE_GENERATE
+ifeq ($(OS_ARCH), Linux)
+ifeq (,$(rustflags_sancov)$(MOZ_ASAN)$(MOZ_TSAN)$(MOZ_UBSAN))
+ifndef MOZ_LTO_RUST_CROSS
+ifneq (,$(filter -Clto,$(cargo_rustc_flags)))
+ $(call py_action,check_binary $(@F),--networking $(RUST_LIBRARY_FILE))
+endif
+endif
+endif
+endif
+endif
+
+$(eval $(call make_cargo_rule,$(RUST_LIBRARY_FILE),force-cargo-library-build))
+
+SUGGEST_INSTALL_ON_FAILURE = (ret=$$?; if [ $$ret = 101 ]; then echo If $1 is not installed, install it using: cargo install $1; fi; exit $$ret)
+
+ifndef CARGO_NO_AUTO_ARG
+force-cargo-library-%:
+ $(call RUN_CARGO,$*) --lib $(cargo_target_flag) $(rust_features_flag) || $(call SUGGEST_INSTALL_ON_FAILURE,cargo-$*)
+else
+force-cargo-library-%:
+ $(call RUN_CARGO,$*) || $(call SUGGEST_INSTALL_ON_FAILURE,cargo-$*)
+endif
+
+else
+force-cargo-library-%:
+ @true
+
+endif # RUST_LIBRARY_FILE
+
+ifdef RUST_TESTS
+
+rust_test_options := $(foreach test,$(RUST_TESTS),-p $(test))
+
+rust_test_features_flag := --features '$(if $(RUST_TEST_FEATURES),$(RUST_TEST_FEATURES) )mozilla-central-workspace-hack'
+
+# Don't stop at the first failure. We want to list all failures together.
+rust_test_flag := --no-fail-fast
+
+force-cargo-test-run:
+ $(call RUN_CARGO,test $(cargo_target_flag) $(rust_test_flag) $(rust_test_options) $(rust_test_features_flag))
+
+endif # RUST_TESTS
+
+ifdef HOST_RUST_LIBRARY_FILE
+
+host_rust_features_flag := --features '$(if $(HOST_RUST_LIBRARY_FEATURES),$(HOST_RUST_LIBRARY_FEATURES) )mozilla-central-workspace-hack'
+
+force-cargo-host-library-build:
+ $(call BUILDSTATUS,START_Rust $(notdir $(HOST_RUST_LIBRARY_FILE)))
+ $(call CARGO_BUILD) --lib $(cargo_host_flag) $(host_rust_features_flag)
+ $(call BUILDSTATUS,END_Rust $(notdir $(HOST_RUST_LIBRARY_FILE)))
+
+$(eval $(call make_cargo_rule,$(HOST_RUST_LIBRARY_FILE),force-cargo-host-library-build))
+
+ifndef CARGO_NO_AUTO_ARG
+force-cargo-host-library-%:
+ $(call RUN_CARGO,$*) --lib $(cargo_host_flag) $(host_rust_features_flag)
+else
+force-cargo-host-library-%:
+ $(call RUN_CARGO,$*) --lib $(filter-out --release $(cargo_host_flag)) $(host_rust_features_flag)
+endif
+
+else
+force-cargo-host-library-%:
+ @true
+endif # HOST_RUST_LIBRARY_FILE
+
+ifdef RUST_PROGRAMS
+
+program_features_flag := --features mozilla-central-workspace-hack
+
+force-cargo-program-build: $(call resfile,module)
+ $(call BUILDSTATUS,START_Rust $(RUST_CARGO_PROGRAMS))
+ $(call CARGO_BUILD) $(addprefix --bin ,$(RUST_CARGO_PROGRAMS)) $(cargo_target_flag) $(program_features_flag) -- $(addprefix -C link-arg=$(CURDIR)/,$(call resfile,module)) $(CARGO_RUSTCFLAGS)
+ $(call BUILDSTATUS,END_Rust $(RUST_CARGO_PROGRAMS))
+
+$(foreach RUST_PROGRAM,$(RUST_PROGRAMS), $(eval $(call make_cargo_rule,$(RUST_PROGRAM),force-cargo-program-build,$(call resfile,module))))
+
+ifndef CARGO_NO_AUTO_ARG
+force-cargo-program-%:
+ $(call RUN_CARGO,$*) $(addprefix --bin ,$(RUST_CARGO_PROGRAMS)) $(cargo_target_flag) $(program_features_flag)
+else
+force-cargo-program-%:
+ $(call RUN_CARGO,$*)
+endif
+
+else
+force-cargo-program-%:
+ @true
+endif # RUST_PROGRAMS
+ifdef HOST_RUST_PROGRAMS
+
+host_program_features_flag := --features mozilla-central-workspace-hack
+
+force-cargo-host-program-build:
+ $(call BUILDSTATUS,START_Rust $(HOST_RUST_CARGO_PROGRAMS))
+ $(call CARGO_BUILD) $(addprefix --bin ,$(HOST_RUST_CARGO_PROGRAMS)) $(cargo_host_flag) $(host_program_features_flag)
+ $(call BUILDSTATUS,END_Rust $(HOST_RUST_CARGO_PROGRAMS))
+
+$(foreach HOST_RUST_PROGRAM,$(HOST_RUST_PROGRAMS), $(eval $(call make_cargo_rule,$(HOST_RUST_PROGRAM),force-cargo-host-program-build)))
+
+ifndef CARGO_NO_AUTO_ARG
+force-cargo-host-program-%:
+ $(call BUILDSTATUS,START_Rust $(HOST_RUST_CARGO_PROGRAMS))
+ $(call RUN_CARGO,$*) $(addprefix --bin ,$(HOST_RUST_CARGO_PROGRAMS)) $(cargo_host_flag) $(host_program_features_flag)
+ $(call BUILDSTATUS,END_Rust $(HOST_RUST_CARGO_PROGRAMS))
+else
+force-cargo-host-program-%:
+ $(call RUN_CARGO,$*) $(addprefix --bin ,$(HOST_RUST_CARGO_PROGRAMS)) $(filter-out --release $(cargo_target_flag))
+endif
+
+else
+force-cargo-host-program-%:
+ @true
+
+endif # HOST_RUST_PROGRAMS
diff --git a/config/makefiles/target_binaries.mk b/config/makefiles/target_binaries.mk
new file mode 100644
index 0000000000..31b2c4367e
--- /dev/null
+++ b/config/makefiles/target_binaries.mk
@@ -0,0 +1,43 @@
+# -*- makefile -*-
+# vim:set ts=8 sw=8 sts=8 noet:
+#
+# 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/.
+
+ifndef NO_DIST_INSTALL
+
+ifneq (,$(strip $(SIMPLE_PROGRAMS)$(RUST_PROGRAMS)))
+PROGRAMS_EXECUTABLES = $(SIMPLE_PROGRAMS) $(RUST_PROGRAMS)
+PROGRAMS_DEST ?= $(FINAL_TARGET)
+PROGRAMS_TARGET := target
+INSTALL_TARGETS += PROGRAMS
+endif
+
+
+ifdef SHARED_LIBRARY
+SHARED_LIBRARY_FILES = $(SHARED_LIBRARY)
+SHARED_LIBRARY_DEST ?= $(FINAL_TARGET)
+ifndef SHARED_LIBRARY_TARGET
+SHARED_LIBRARY_TARGET = target
+endif
+INSTALL_TARGETS += SHARED_LIBRARY
+endif # SHARED_LIBRARY
+
+ifdef WASM_LIBRARY
+WASM_LIBRARY_FILES = $(WASM_LIBRARY)
+WASM_LIBRARY_DEST ?= $(FINAL_TARGET)
+WASM_LIBRARY_TARGET = target
+INSTALL_TARGETS += WASM_LIBRARY
+endif
+
+ifneq (,$(strip $(HOST_SIMPLE_PROGRAMS)))
+HOST_PROGRAMS_EXECUTABLES = $(HOST_SIMPLE_PROGRAMS) $(HOST_RUST_PROGRAMS)
+HOST_PROGRAMS_DEST ?= $(DIST)/host/bin
+HOST_PROGRAMS_TARGET = host
+INSTALL_TARGETS += HOST_PROGRAMS
+endif
+
+endif # !NO_DIST_INSTALL
+
+# EOF
diff --git a/config/makefiles/xpidl/Makefile.in b/config/makefiles/xpidl/Makefile.in
new file mode 100644
index 0000000000..96601d6cb9
--- /dev/null
+++ b/config/makefiles/xpidl/Makefile.in
@@ -0,0 +1,94 @@
+# 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/.
+
+STANDALONE_MAKEFILE := 1
+
+include $(topsrcdir)/config/rules.mk
+
+# Building XPIDLs effectively consists of two steps:
+#
+# 1) Staging all .idl files to a common directory.
+# 2) Doing everything with the .idl files.
+#
+# Each .idl file is processed into a .h file and typelib information.
+# The .h file shares the same stem as the input file and is installed
+# in the common headers include directory.
+#
+# XPIDL files are logically grouped together by modules. The typelib
+# information for all XPIDLs in the same module is linked together into
+# an .xpt file having the name of the module.
+#
+# As an optimization to reduce overall CPU usage, we process all .idl
+# belonging to a module with a single command invocation. This prevents
+# redundant parsing of .idl files and significantly reduces CPU cycles.
+
+# For dependency files.
+idl_deps_dir := .deps
+
+dist_idl_dir := $(DIST)/idl
+dist_include_dir := $(DIST)/include
+dist_xpcrs_dir := $(DIST)/xpcrs
+stub_file := xptdata.stub
+process_py := $(topsrcdir)/python/mozbuild/mozbuild/action/xpidl-process.py
+target_file := $(topobjdir)/xpcom/reflect/xptinfo/xptdata.cpp
+xptdata_h := $(dist_include_dir)/xptdata.h
+generated_files := $(target_file) $(xptdata_h)
+code_gen_py := $(topsrcdir)/xpcom/reflect/xptinfo/xptcodegen.py
+code_gen_deps := $(topsrcdir)/xpcom/ds/tools/perfecthash.py
+
+# TODO we should use py_action, but that would require extra directories to be
+# in the virtualenv.
+%.xpt:
+ $(REPORT_BUILD)
+ $(call BUILDSTATUS,START_xpt $@)
+ $(PYTHON3) $(process_py) --depsdir $(idl_deps_dir) \
+ --bindings-conf $(topsrcdir)/dom/bindings/Bindings.conf \
+ $(foreach dir,$(all_idl_dirs),-I $(dir)) \
+ $(dist_include_dir) $(dist_xpcrs_dir) $(@D) \
+ $(basename $(notdir $@)) $($(basename $(notdir $@))_deps)
+# When some IDL is added or removed, if the actual IDL file was already, or
+# still is, in the tree, simple dependencies can't detect that the XPT needs
+# to be rebuilt.
+# Add the current value of $($(xpidl_module)_deps) in the depend file, such that
+# we can later check if the value has changed since last build, which will
+# indicate whether IDLs were added or removed.
+# Note that removing previously built files is not covered.
+ @echo $(basename $(notdir $@))_deps_built = $($(basename $(notdir $@))_deps) >> $(idl_deps_dir)/$(basename $(notdir $@)).pp
+ $(call BUILDSTATUS,END_xpt $@)
+
+xpidl_modules := @xpidl_modules@
+xpt_files := $(addsuffix .xpt,$(xpidl_modules))
+
+@xpidl_rules@
+
+depends_files := $(foreach root,$(xpidl_modules),$(idl_deps_dir)/$(root).pp)
+
+ifdef COMPILE_ENVIRONMENT
+xpidl:: $(generated_files)
+endif
+
+# See bug 1420119 for why we need the semicolon.
+$(target_file) $(xptdata_h) : $(stub_file) ;
+
+$(xpt_files): $(process_py) $(call mkdir_deps,$(idl_deps_dir) $(dist_include_dir) $(dist_xpcrs_dir))
+
+$(stub_file) : $(xpt_files) $(code_gen_py) $(code_gen_deps)
+ $(REPORT_BUILD)
+ $(call BUILDSTATUS,START_xpt $(notdir $(generated_files)))
+ $(PYTHON3) $(code_gen_py) $(generated_files) $(xpt_files)
+ @touch $@
+ $(call BUILDSTATUS,END_xpt $(notdir $(generated_files)))
+
+-include $(depends_files)
+
+define xpt_deps
+$(1): $(call mkdir_deps,$(dir $(1)))
+ifneq ($($(basename $(notdir $(1)))_deps),$($(basename $(notdir $(1)))_deps_built))
+$(1): FORCE
+endif
+endef
+
+$(foreach xpt,$(xpt_files),$(eval $(call xpt_deps,$(xpt))))
+
+.PHONY: xpidl
diff --git a/config/milestone.txt b/config/milestone.txt
new file mode 100644
index 0000000000..0809f53609
--- /dev/null
+++ b/config/milestone.txt
@@ -0,0 +1,13 @@
+# Holds the current milestone.
+# Should be in the format of
+#
+# x.x.x
+# x.x.x.x
+# x.x.x+
+#
+# Referenced by build/moz.configure/init.configure.
+# Hopefully I'll be able to automate replacement of *all*
+# hardcoded milestones in the tree from these two files.
+#--------------------------------------------------------
+
+124.0.1
diff --git a/config/moz.build b/config/moz.build
new file mode 100644
index 0000000000..3280aac27e
--- /dev/null
+++ b/config/moz.build
@@ -0,0 +1,116 @@
+# -*- 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/.
+
+with Files("**"):
+ BUG_COMPONENT = ("Firefox Build System", "General")
+
+with Files("mozunit/**"):
+ BUG_COMPONENT = ("Testing", "Python Test")
+
+DIST_INSTALL = False
+# For sanity's sake, we compile nsinstall without the wrapped system
+# headers, so that we can use it to set up the wrapped system headers.
+NoVisibilityFlags()
+
+CONFIGURE_SUBST_FILES += [
+ "tests/src-simple/Makefile",
+]
+
+if CONFIG["HOST_OS_ARCH"] != "WINNT":
+ HOST_SOURCES += [
+ "nsinstall.c",
+ "pathsub.c",
+ ]
+ HostProgram("nsinstall_real")
+
+PYTHON_UNITTEST_MANIFESTS += [
+ "tests/python.toml",
+]
+
+if CONFIG["CC_TYPE"] in ("clang", "gcc") and CONFIG["MOZ_OPTIMIZE"]:
+ CFLAGS += ["-O3"]
+
+HOST_DEFINES["UNICODE"] = True
+HOST_DEFINES["_UNICODE"] = True
+
+include("stl-headers.mozbuild")
+if CONFIG["WRAP_STL_INCLUDES"]:
+ stl_compiler = None
+ if CONFIG["OS_TARGET"] == "WINNT":
+ stl_compiler = "msvc"
+ else:
+ stl_compiler = "gcc"
+
+ if stl_compiler:
+ # Note that the 'stl_wrappers' folder is known to the build system as
+ # containing generated files; if this is changed here then the code in
+ # GeneratedFile.__init__ in python/mozbuild/mozbuild/frontend/data.py
+ # might need to be updated accordingly as well.
+ template_file = "%s-stl-wrapper.template.h" % stl_compiler
+ output_dir = "/dist/stl_wrappers"
+ # We have to use a sentinel file as the first file because the
+ # file_generate action will create it for us, but we want to create all
+ # the files in gen_wrappers()
+ outputs = tuple(
+ ["stl.sentinel"] + ["%s/%s" % (output_dir, h) for h in stl_headers]
+ )
+ GeneratedFile(
+ *outputs,
+ script="make-stl-wrappers.py",
+ entry_point="gen_wrappers",
+ inputs=[template_file],
+ flags=[TOPOBJDIR + output_dir, stl_compiler] + stl_headers
+ )
+
+ # Wrap <windows.h> to make it easier to use correctly
+ # NOTE: If we aren't wrapping STL includes, we're building part of the browser
+ # which won't need this wrapper, such as L10N. Just don't try to generate the
+ # wrapper in that case.
+ if CONFIG["OS_TARGET"] == "WINNT":
+ GeneratedFile(
+ "/dist/stl_wrappers/windows.h",
+ script="make-windows-h-wrapper.py",
+ entry_point="generate",
+ inputs=[
+ "windows-h-constant.decls.h",
+ "windows-h-unicode.decls.h",
+ "windows-h-wrapper.template.h",
+ ],
+ flags=[stl_compiler],
+ )
+ GeneratedFile(
+ "/dist/stl_wrappers/shlwapi.h",
+ script="make-windows-h-wrapper.py",
+ entry_point="generate",
+ inputs=[
+ "shlwapi-h-constant.decls.h",
+ "shlwapi-h-unicode.decls.h",
+ "shlwapi-h-wrapper.template.h",
+ ],
+ flags=[stl_compiler],
+ )
+
+if CONFIG["WRAP_SYSTEM_INCLUDES"]:
+ include("system-headers.mozbuild")
+ output_dir = "/dist/system_wrappers"
+ outputs = tuple(
+ ["system-header.sentinel"]
+ + ["%s/%s" % (output_dir, h) for h in stl_headers + system_headers]
+ )
+ GeneratedFile(
+ *outputs,
+ script="make-system-wrappers.py",
+ entry_point="gen_wrappers",
+ flags=[TOPOBJDIR + output_dir] + stl_headers + system_headers
+ )
+
+if CONFIG["COMPILE_ENVIRONMENT"] and CONFIG["CBINDGEN"]:
+ GeneratedFile(
+ "cbindgen-metadata.json",
+ script="/build/RunCbindgen.py",
+ entry_point="generate_metadata",
+ inputs=["!/.cargo/config"],
+ )
diff --git a/config/mozunit/mozunit/__init__.py b/config/mozunit/mozunit/__init__.py
new file mode 100644
index 0000000000..51f02c874e
--- /dev/null
+++ b/config/mozunit/mozunit/__init__.py
@@ -0,0 +1,6 @@
+# flake8: noqa
+# 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/.
+
+from .mozunit import *
diff --git a/config/mozunit/mozunit/mozunit.py b/config/mozunit/mozunit/mozunit.py
new file mode 100644
index 0000000000..28009425b6
--- /dev/null
+++ b/config/mozunit/mozunit/mozunit.py
@@ -0,0 +1,336 @@
+# 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/.
+
+import inspect
+import io
+import os
+import sys
+import unittest
+from unittest import TestResult as _TestResult
+from unittest import TextTestRunner as _TestRunner
+
+import pytest
+import six
+from six import BytesIO, StringIO
+
+here = os.path.abspath(os.path.dirname(__file__))
+
+try:
+ # buildconfig doesn't yet support Python 3, so we can use pathlib to
+ # resolve the topsrcdir relative to our current location.
+ from pathlib import Path
+
+ topsrcdir = Path(here).parents[2]
+except ImportError:
+ from mozbuild.base import MozbuildObject
+
+ build = MozbuildObject.from_environment(cwd=here)
+ topsrcdir = build.topsrcdir
+
+"""Helper to make python unit tests report the way that the Mozilla
+unit test infrastructure expects tests to report.
+
+Usage:
+
+import mozunit
+
+if __name__ == '__main__':
+ mozunit.main()
+"""
+
+
+class _MozTestResult(_TestResult):
+ def __init__(self, stream, descriptions):
+ _TestResult.__init__(self)
+ self.stream = stream
+ self.descriptions = descriptions
+
+ def getDescription(self, test):
+ if self.descriptions:
+ return test.shortDescription() or str(test)
+ else:
+ return str(test)
+
+ def printStatus(self, status, test, message=""):
+ line = "{status} | {file} | {klass}.{test}{sep}{message}".format(
+ status=status,
+ file=inspect.getfile(test.__class__),
+ klass=test.__class__.__name__,
+ test=test._testMethodName,
+ sep=", " if message else "",
+ message=message,
+ )
+ self.stream.writeln(line)
+
+ def addSuccess(self, test):
+ _TestResult.addSuccess(self, test)
+ self.printStatus("TEST-PASS", test)
+
+ def addSkip(self, test, reason):
+ _TestResult.addSkip(self, test, reason)
+ self.printStatus("TEST-SKIP", test)
+
+ def addExpectedFailure(self, test, err):
+ _TestResult.addExpectedFailure(self, test, err)
+ self.printStatus("TEST-KNOWN-FAIL", test)
+
+ def addUnexpectedSuccess(self, test):
+ _TestResult.addUnexpectedSuccess(self, test)
+ self.printStatus("TEST-UNEXPECTED-PASS", test)
+
+ def addError(self, test, err):
+ _TestResult.addError(self, test, err)
+ self.printFail(test, err)
+ self.stream.writeln("ERROR: {0}".format(self.getDescription(test)))
+ self.stream.writeln(self.errors[-1][1])
+
+ def addFailure(self, test, err):
+ _TestResult.addFailure(self, test, err)
+ self.printFail(test, err)
+ self.stream.writeln("FAIL: {0}".format(self.getDescription(test)))
+ self.stream.writeln(self.failures[-1][1])
+
+ def printFail(self, test, err):
+ exctype, value, tb = err
+ message = value or "NO MESSAGE"
+ if hasattr(value, "message"):
+ message = value.message.splitlines()[0]
+ # Skip test runner traceback levels
+ while tb and self._is_relevant_tb_level(tb):
+ tb = tb.tb_next
+ if tb:
+ _, ln, _ = inspect.getframeinfo(tb)[:3]
+ message = "line {0}: {1}".format(ln, message)
+ self.printStatus("TEST-UNEXPECTED-FAIL", test, message)
+
+
+class MozTestRunner(_TestRunner):
+ def _makeResult(self):
+ return _MozTestResult(self.stream, self.descriptions)
+
+ def run(self, test):
+ result = self._makeResult()
+ test(result)
+ return result
+
+
+def _mocked_file(cls):
+ """Create a mocked file class that inherits from the given class."""
+
+ class MockedFile(cls):
+ def __init__(self, context, filename, content):
+ self.context = context
+ self.name = filename
+ cls.__init__(self, content)
+
+ def close(self):
+ self.context.files[self.name] = self.getvalue()
+ cls.close(self)
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, type, value, traceback):
+ self.close()
+
+ return MockedFile
+
+
+MockedStringFile = _mocked_file(StringIO)
+MockedBytesFile = _mocked_file(BytesIO)
+
+
+def normcase(path):
+ """
+ Normalize the case of `path`.
+
+ Don't use `os.path.normcase` because that also normalizes forward slashes
+ to backslashes on Windows.
+ """
+ if sys.platform.startswith("win"):
+ return path.lower()
+ return path
+
+
+class _MockBaseOpen(object):
+ """Callable that acts like the open() function; see MockedOpen for more
+ info.
+ """
+
+ def __init__(self, open, files):
+ self.open = open
+ self.files = files
+
+ def __call__(
+ self,
+ name,
+ mode="r",
+ buffering=None,
+ encoding=None,
+ newline=None,
+ errors=None,
+ opener=None,
+ ):
+ # open() can be called with an integer "name" (i.e. a file descriptor).
+ # We don't generally do this in our codebase, but internal Python
+ # libraries sometimes do and we want to handle that cleanly.
+ if isinstance(name, int):
+ return self.open(
+ name,
+ mode=mode,
+ buffering=buffering,
+ encoding=encoding,
+ newline=newline,
+ errors=errors,
+ opener=opener,
+ )
+ # buffering is ignored.
+ absname = normcase(os.path.abspath(name))
+ if "w" in mode:
+ file = self._mocked_file(absname, mode)
+ elif absname in self.files:
+ content = self.files[absname]
+ if content is None:
+ raise IOError(2, "No such file or directory")
+ file = self._mocked_file(absname, mode, content)
+ elif "a" in mode:
+ read_mode = "rb" if "b" in mode else "r"
+ file = self._mocked_file(absname, mode, self.open(name, read_mode).read())
+ else:
+ file = self.open(name, mode)
+ if "a" in mode:
+ file.seek(0, os.SEEK_END)
+ return file
+
+ def _mocked_file(self, name, mode, content=None):
+ raise NotImplementedError("subclass must implement")
+
+
+class _MockPy2Open(_MockBaseOpen):
+ def _mocked_file(self, name, mode, content=None):
+ content = six.ensure_binary(content or b"")
+ return MockedBytesFile(self, name, content)
+
+
+class _MockOpen(_MockBaseOpen):
+ def _mocked_file(self, name, mode, content=None):
+ if "b" in mode:
+ content = six.ensure_binary(content or b"")
+ return MockedBytesFile(self, name, content)
+ else:
+ content = six.ensure_text(content or "")
+ return MockedStringFile(self, name, content)
+
+
+class MockedOpen(object):
+ """
+ Context manager diverting the open builtin such that opening files
+ can open "virtual" file instances given when creating a MockedOpen.
+
+ with MockedOpen({'foo': 'foo', 'bar': 'bar'}):
+ f = open('foo', 'r')
+
+ will thus open the virtual file instance for the file 'foo' to f.
+
+ If the content of a file is given as None, then that file will be
+ represented as not existing (even if it does, actually, exist).
+
+ MockedOpen also masks writes, so that creating or replacing files
+ doesn't touch the file system, while subsequently opening the file
+ will return the recorded content.
+
+ with MockedOpen():
+ f = open('foo', 'w')
+ f.write('foo')
+ self.assertRaises(Exception,f.open('foo', 'r'))
+ """
+
+ def __init__(self, files={}):
+ self.files = {}
+ for name, content in files.items():
+ self.files[normcase(os.path.abspath(name))] = content
+
+ def __enter__(self):
+ import six.moves.builtins
+
+ self.open = six.moves.builtins.open
+ self.io_open = io.open
+ self._orig_path_exists = os.path.exists
+ self._orig_path_isdir = os.path.isdir
+ self._orig_path_isfile = os.path.isfile
+ builtin_cls = _MockPy2Open if six.PY2 else _MockOpen
+ six.moves.builtins.open = builtin_cls(self.open, self.files)
+ io.open = _MockOpen(self.io_open, self.files)
+ os.path.exists = self._wrapped_exists
+ os.path.isdir = self._wrapped_isdir
+ os.path.isfile = self._wrapped_isfile
+
+ def __exit__(self, type, value, traceback):
+ import six.moves.builtins
+
+ six.moves.builtins.open = self.open
+ io.open = self.io_open
+ os.path.exists = self._orig_path_exists
+ os.path.isdir = self._orig_path_isdir
+ os.path.isfile = self._orig_path_isfile
+
+ def _wrapped_exists(self, p):
+ return self._wrapped_isfile(p) or self._wrapped_isdir(p)
+
+ def _wrapped_isfile(self, p):
+ p = normcase(p)
+ if p in self.files:
+ return self.files[p] is not None
+
+ abspath = normcase(os.path.abspath(p))
+ if abspath in self.files:
+ return self.files[abspath] is not None
+
+ return self._orig_path_isfile(p)
+
+ def _wrapped_isdir(self, p):
+ p = normcase(p)
+ p = p if p.endswith(("/", "\\")) else p + os.sep
+ if any(f.startswith(p) for f in self.files):
+ return True
+
+ abspath = normcase(os.path.abspath(p) + os.sep)
+ if any(f.startswith(abspath) for f in self.files):
+ return True
+
+ return self._orig_path_isdir(p)
+
+
+def main(*args, **kwargs):
+ runwith = kwargs.pop("runwith", "pytest")
+
+ if runwith == "unittest":
+ unittest.main(testRunner=MozTestRunner(), *args, **kwargs)
+ else:
+ args = list(args)
+ if os.environ.get("MACH_STDOUT_ISATTY") and not any(
+ a.startswith("--color") for a in args
+ ):
+ args.append("--color=yes")
+
+ module = __import__("__main__")
+ args.extend(
+ [
+ "--rootdir",
+ str(topsrcdir),
+ "-c",
+ os.path.join(here, "pytest.ini"),
+ "-vv",
+ "--tb=short",
+ "-p",
+ "mozlog.pytest_mozlog.plugin",
+ "-p",
+ "mozunit.pytest_plugin",
+ "-p",
+ "no:cacheprovider",
+ "-rsx", # show reasons for skip / xfail
+ module.__file__,
+ ]
+ )
+ sys.exit(pytest.main(args))
diff --git a/config/mozunit/mozunit/pytest.ini b/config/mozunit/mozunit/pytest.ini
new file mode 100644
index 0000000000..db7632389c
--- /dev/null
+++ b/config/mozunit/mozunit/pytest.ini
@@ -0,0 +1,4 @@
+[pytest]
+console_output_style=classic
+python_classes=PyTest
+xfail_strict=true
diff --git a/config/mozunit/mozunit/pytest_plugin.py b/config/mozunit/mozunit/pytest_plugin.py
new file mode 100644
index 0000000000..e05fc579e4
--- /dev/null
+++ b/config/mozunit/mozunit/pytest_plugin.py
@@ -0,0 +1,26 @@
+# 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/.
+
+import pytest
+
+
+def pytest_addoption(parser):
+ group = parser.getgroup("mozunit")
+ group.addoption(
+ "--run-slow", action="store_true", default=False, help="run slow tests"
+ )
+
+
+def pytest_configure(config):
+ config.addinivalue_line("markers", "slow: mark test as slow to run")
+
+
+def pytest_collection_modifyitems(config, items):
+ if config.getoption("--run-slow"):
+ # --run-slow given in cli: do not skip slow tests
+ return
+ skip_slow = pytest.mark.skip(reason="need --run-slow option to run")
+ for item in items:
+ if "slow" in item.keywords:
+ item.add_marker(skip_slow)
diff --git a/config/mozunit/setup.py b/config/mozunit/setup.py
new file mode 100644
index 0000000000..c2771b9053
--- /dev/null
+++ b/config/mozunit/setup.py
@@ -0,0 +1,19 @@
+# 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/.
+
+from setuptools import setup
+
+setup(
+ name="mozunit",
+ version="1.0",
+ description="Make unit tests report the way Mozilla infrastructure expects",
+ classifiers=["Programming Language :: Python :: 2.7"],
+ keywords="mozilla",
+ author="Mozilla Automation and Tools team",
+ author_email="tools@lists.mozilla.org",
+ license="MPL",
+ packages=["mozunit"],
+ include_package_data=True,
+ zip_safe=False,
+)
diff --git a/config/msvc-stl-wrapper.template.h b/config/msvc-stl-wrapper.template.h
new file mode 100644
index 0000000000..fe9be05011
--- /dev/null
+++ b/config/msvc-stl-wrapper.template.h
@@ -0,0 +1,72 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=8 et :
+ */
+/* 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/. */
+
+#ifndef mozilla_${HEADER}_h
+#define mozilla_${HEADER}_h
+
+#if _HAS_EXCEPTIONS
+# error "STL code can only be used with -fno-exceptions"
+#endif
+
+#if defined(__clang__)
+// Silence "warning: #include_next is a language extension [-Wgnu-include-next]"
+#pragma clang system_header
+#endif
+
+// Include mozalloc after the STL header and all other headers it includes
+// have been preprocessed.
+#if !defined(MOZ_INCLUDE_MOZALLOC_H)
+# define MOZ_INCLUDE_MOZALLOC_H
+# define MOZ_INCLUDE_MOZALLOC_H_FROM_${HEADER}
+#endif
+
+#ifdef _DEBUG
+// From
+// http://msdn.microsoft.com/en-us/library/aa985982%28VS.80%29.aspx
+// and
+// http://msdn.microsoft.com/en-us/library/aa985965%28VS.80%29.aspx
+// there appear to be two types of STL container checking. The
+// former is enabled by -D_DEBUG (which is implied by -MDd or -MTd), and
+// looks to be full generation/mutation checked iterators as done by
+// _GLIBCXX_DEBUG. The latter appears to just be bounds checking, and
+// is enabled by the following macros. It appears that the _DEBUG
+// iterators subsume _SECURE_SCL, and the following settings are
+// default anyway, so we'll just leave this commented out.
+//# define _SECURE_SCL 1
+//# define _SECURE_SCL_THROWS 0
+#else
+// Note: _SECURE_SCL iterators are on by default in opt builds. We
+// could leave them on, but since gcc doesn't, we might as well
+// preserve that behavior for perf reasons. nsTArray is in the same
+// camp as gcc. Can revisit later.
+//
+// FIXME/bug 551254: because we're not wrapping all the STL headers we
+// use, undefining this here can cause some headers to be built with
+// iterator checking and others not. Turning this off until we have a
+// better plan.
+//# undef _SECURE_SCL
+#endif
+
+#include_next <${HEADER}>
+
+#ifdef MOZ_INCLUDE_MOZALLOC_H_FROM_${HEADER}
+// See if we're in code that can use mozalloc.
+# if !defined(NS_NO_XPCOM) && !defined(MOZ_NO_MOZALLOC)
+// In recent versions of MSVC, <new>, which mozalloc.h includes, uses
+// <type_traits> without including it. Before MSVC 17.7, this worked
+// fine because <new> included <exception>, which includes <type_traits>.
+// That is still the case, but it now also includes <cstdlib> before
+// <type_traits>, so when something includes <exception> before <new>,
+// we get here before <type_traits> is included, which ends up not working.
+# include <type_traits>
+# include "mozilla/mozalloc.h"
+# else
+# error "STL code can only be used with infallible ::operator new()"
+# endif
+#endif
+
+#endif // if mozilla_${HEADER}_h
diff --git a/config/nsinstall.c b/config/nsinstall.c
new file mode 100644
index 0000000000..363ae3eefd
--- /dev/null
+++ b/config/nsinstall.c
@@ -0,0 +1,411 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+/*
+** Netscape portable install command.
+**
+** Brendan Eich, 7/20/95
+*/
+#include <stdio.h> /* OSF/1 requires this before grp.h, so put it first */
+#include <assert.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <dirent.h>
+#include <limits.h>
+#include <grp.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <utime.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "pathsub.h"
+
+#ifdef HAVE_GETOPT_H
+# include <getopt.h>
+#endif
+
+#ifdef SUNOS4
+# include "sunos4.h"
+#endif
+
+#ifdef NEXTSTEP
+# include <bsd/libc.h>
+#endif
+
+#ifdef __QNX__
+# include <unix.h>
+#endif
+
+#ifdef NEED_S_ISLNK
+# if !defined(S_ISLNK) && defined(S_IFLNK)
+# define S_ISLNK(a) (((a) & S_IFMT) == S_IFLNK)
+# endif
+#endif
+
+#ifndef _DIRECTORY_SEPARATOR
+# define _DIRECTORY_SEPARATOR "/"
+#endif /* _DIRECTORY_SEPARATOR */
+
+#ifdef NEED_FCHMOD_PROTO
+extern int fchmod(int fildes, mode_t mode);
+#endif
+
+static void usage(void) {
+ fprintf(stderr,
+ "usage: %s [-C cwd] [-L linkprefix] [-m mode] [-o owner] [-g group]\n"
+ " %*s [-DdltR] file [file ...] directory\n",
+ program, (int)strlen(program), "");
+ exit(2);
+}
+
+static int mkdirs(char* path, mode_t mode) {
+ char* cp;
+ struct stat sb;
+ int res;
+ int l;
+
+ /* strip trailing "/." */
+ l = strlen(path);
+ if (l > 1 && path[l - 1] == '.' && path[l - 2] == '/') path[l - 2] = 0;
+
+ while (*path == '/' && path[1] == '/') path++;
+ for (cp = strrchr(path, '/'); cp && cp != path && *(cp - 1) == '/'; cp--)
+ ;
+ if (cp && cp != path) {
+ *cp = '\0';
+ if ((lstat(path, &sb) < 0 || !S_ISDIR(sb.st_mode)) &&
+ mkdirs(path, mode) < 0) {
+ return -1;
+ }
+ *cp = '/';
+ }
+
+ res = mkdir(path, mode);
+ if ((res != 0) && (errno == EEXIST))
+ return 0;
+ else
+ return res;
+}
+
+static uid_t touid(char* owner) {
+ struct passwd* pw;
+ uid_t uid;
+ char* cp;
+
+ pw = getpwnam(owner);
+ if (pw) return pw->pw_uid;
+ uid = strtol(owner, &cp, 0);
+ if (uid == 0 && cp == owner) fail("cannot find uid for %s", owner);
+ return uid;
+}
+
+static gid_t togid(char* group) {
+ struct group* gr;
+ gid_t gid;
+ char* cp;
+
+ gr = getgrnam(group);
+ if (gr) return gr->gr_gid;
+ gid = strtol(group, &cp, 0);
+ if (gid == 0 && cp == group) fail("cannot find gid for %s", group);
+ return gid;
+}
+
+static void copyfile(char* name, char* toname, mode_t mode, char* group,
+ char* owner, int dotimes, uid_t uid, gid_t gid) {
+ int fromfd, tofd = -1, cc, wc, exists;
+ char buf[BUFSIZ], *bp;
+ struct stat sb, tosb;
+ struct utimbuf utb;
+
+ exists = (lstat(toname, &tosb) == 0);
+
+ fromfd = open(name, O_RDONLY);
+ if (fromfd < 0 || fstat(fromfd, &sb) < 0) fail("cannot access %s", name);
+ if (exists) {
+ if (S_ISREG(tosb.st_mode)) {
+ /* See if we can open it. This is more reliable than 'access'. */
+ tofd = open(toname, O_CREAT | O_WRONLY, 0666);
+ }
+ if (tofd < 0) {
+ (void)(S_ISDIR(tosb.st_mode) ? rmdir : unlink)(toname);
+ }
+ }
+ if (tofd < 0) {
+ tofd = open(toname, O_CREAT | O_WRONLY, 0666);
+ if (tofd < 0) fail("cannot create %s", toname);
+ }
+
+ bp = buf;
+ while ((cc = read(fromfd, bp, sizeof buf)) > 0) {
+ while ((wc = write(tofd, bp, (unsigned int)cc)) > 0) {
+ if ((cc -= wc) == 0) break;
+ bp += wc;
+ }
+ if (wc < 0) fail("cannot write to %s", toname);
+ }
+ if (cc < 0) fail("cannot read from %s", name);
+
+ if (ftruncate(tofd, sb.st_size) < 0) fail("cannot truncate %s", toname);
+#if !defined(VMS)
+ if (dotimes) {
+ utb.actime = sb.st_atime;
+ utb.modtime = sb.st_mtime;
+ if (utime(toname, &utb) < 0) fail("cannot set times of %s", toname);
+ }
+# ifdef HAVE_FCHMOD
+ if (fchmod(tofd, mode) < 0)
+# else
+ if (chmod(toname, mode) < 0)
+# endif
+ fail("cannot change mode of %s", toname);
+#endif
+ if ((owner || group) && fchown(tofd, uid, gid) < 0)
+ fail("cannot change owner of %s", toname);
+
+ /* Must check for delayed (NFS) write errors on close. */
+ if (close(tofd) < 0) fail("cannot write to %s", toname);
+ close(fromfd);
+#if defined(VMS)
+ if (chmod(toname, (mode & (S_IREAD | S_IWRITE))) < 0)
+ fail("cannot change mode of %s", toname);
+ if (dotimes) {
+ utb.actime = sb.st_atime;
+ utb.modtime = sb.st_mtime;
+ if (utime(toname, &utb) < 0) fail("cannot set times of %s", toname);
+ }
+#endif
+}
+
+static void copydir(char* from, char* to, mode_t mode, char* group, char* owner,
+ int dotimes, uid_t uid, gid_t gid) {
+ DIR* dir;
+ struct dirent* ep;
+ struct stat sb;
+ char *base, *destdir, *direntry, *destentry;
+
+ base = xbasename(from);
+
+ /* create destination directory */
+ destdir = xmalloc((unsigned int)(strlen(to) + 1 + strlen(base) + 1));
+ sprintf(destdir, "%s%s%s", to, _DIRECTORY_SEPARATOR, base);
+ if (mkdirs(destdir, mode) != 0) {
+ fail("cannot make directory %s\n", destdir);
+ free(destdir);
+ return;
+ }
+
+ if (!(dir = opendir(from))) {
+ fail("cannot open directory %s\n", from);
+ free(destdir);
+ return;
+ }
+
+ direntry = xmalloc((unsigned int)PATH_MAX);
+ destentry = xmalloc((unsigned int)PATH_MAX);
+
+ while ((ep = readdir(dir))) {
+ if (strcmp(ep->d_name, ".") == 0 || strcmp(ep->d_name, "..") == 0) continue;
+
+ sprintf(direntry, "%s/%s", from, ep->d_name);
+ sprintf(destentry, "%s%s%s", destdir, _DIRECTORY_SEPARATOR, ep->d_name);
+
+ if (stat(direntry, &sb) == 0 && S_ISDIR(sb.st_mode))
+ copydir(direntry, destdir, mode, group, owner, dotimes, uid, gid);
+ else
+ copyfile(direntry, destentry, mode, group, owner, dotimes, uid, gid);
+ }
+
+ free(destdir);
+ free(direntry);
+ free(destentry);
+ closedir(dir);
+}
+
+int main(int argc, char** argv) {
+ int onlydir, dodir, dolink, dorelsymlink, dotimes, opt, len, lplen, tdlen,
+ bnlen, exists;
+ mode_t mode = 0755;
+ char *linkprefix, *owner, *group, *cp, *cwd, *todir, *toname, *name, *base,
+ *linkname, buf[BUFSIZ];
+ uid_t uid;
+ gid_t gid;
+ struct stat sb, tosb, fromsb;
+
+ program = argv[0];
+ cwd = linkname = linkprefix = owner = group = 0;
+ onlydir = dodir = dolink = dorelsymlink = dotimes = lplen = 0;
+
+ while ((opt = getopt(argc, argv, "C:DdlL:Rm:o:g:t")) != EOF) {
+ switch (opt) {
+ case 'C':
+ cwd = optarg;
+ break;
+ case 'D':
+ onlydir = 1;
+ break;
+ case 'd':
+ dodir = 1;
+ break;
+ case 'L':
+ linkprefix = optarg;
+ lplen = strlen(linkprefix);
+ dolink = 1;
+ break;
+ case 'R':
+ dolink = dorelsymlink = 1;
+ break;
+ case 'm':
+ mode = strtoul(optarg, &cp, 8);
+ if (mode == 0 && cp == optarg) usage();
+ break;
+ case 'o':
+ owner = optarg;
+ break;
+ case 'g':
+ group = optarg;
+ break;
+ case 't':
+ dotimes = 1;
+ break;
+ default:
+ usage();
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+ if (argc < 2 - onlydir) usage();
+
+ todir = argv[argc - 1];
+ if ((stat(todir, &sb) < 0 || !S_ISDIR(sb.st_mode)) &&
+ mkdirs(todir, 0777) < 0) {
+ fail("cannot make directory %s", todir);
+ }
+ if (onlydir) return 0;
+
+ if (!cwd) {
+#ifndef NEEDS_GETCWD
+# ifndef GETCWD_CANT_MALLOC
+ cwd = getcwd(0, PATH_MAX);
+# else
+ cwd = malloc(PATH_MAX + 1);
+ cwd = getcwd(cwd, PATH_MAX);
+# endif
+#else
+ cwd = malloc(PATH_MAX + 1);
+ cwd = getwd(cwd);
+#endif
+ }
+
+ xchdir(todir);
+#ifndef NEEDS_GETCWD
+# ifndef GETCWD_CANT_MALLOC
+ todir = getcwd(0, PATH_MAX);
+# else
+ todir = malloc(PATH_MAX + 1);
+ todir = getcwd(todir, PATH_MAX);
+# endif
+#else
+ todir = malloc(PATH_MAX + 1);
+ todir = getwd(todir);
+#endif
+ tdlen = strlen(todir);
+ xchdir(cwd);
+ tdlen = strlen(todir);
+
+ uid = owner ? touid(owner) : (uid_t)(-1);
+ gid = group ? togid(group) : (gid_t)(-1);
+
+ while (--argc > 0) {
+ name = *argv++;
+ len = strlen(name);
+ base = xbasename(name);
+ bnlen = strlen(base);
+ toname = xmalloc((unsigned int)(tdlen + 1 + bnlen + 1));
+ sprintf(toname, "%s%s%s", todir, _DIRECTORY_SEPARATOR, base);
+ exists = (lstat(toname, &tosb) == 0);
+
+ if (dodir) {
+ /* -d means create a directory, always */
+ if (exists && !S_ISDIR(tosb.st_mode)) {
+ (void)unlink(toname);
+ exists = 0;
+ }
+ if (!exists && mkdir(toname, mode) < 0)
+ fail("cannot make directory %s", toname);
+ if ((owner || group) && chown(toname, uid, gid) < 0)
+ fail("cannot change owner of %s", toname);
+ } else if (dolink) {
+ if (access(name, R_OK) != 0) {
+ fail("cannot access %s", name);
+ }
+ if (*name == '/') {
+ /* source is absolute pathname, link to it directly */
+ linkname = 0;
+ } else {
+ if (linkprefix) {
+ /* -L prefixes names with a $cwd arg. */
+ len += lplen + 1;
+ linkname = xmalloc((unsigned int)(len + 1));
+ sprintf(linkname, "%s/%s", linkprefix, name);
+ } else if (dorelsymlink) {
+ /* Symlink the relative path from todir to source name. */
+ linkname = xmalloc(PATH_MAX);
+
+ if (*todir == '/') {
+ /* todir is absolute: skip over common prefix. */
+ lplen = relatepaths(todir, cwd, linkname);
+ strcpy(linkname + lplen, name);
+ } else {
+ /* todir is named by a relative path: reverse it. */
+ reversepath(todir, name, len, linkname);
+ xchdir(cwd);
+ }
+
+ len = strlen(linkname);
+ }
+ name = linkname;
+ }
+
+ /* Check for a pre-existing symlink with identical content. */
+ if (exists &&
+ (!S_ISLNK(tosb.st_mode) || readlink(toname, buf, sizeof buf) != len ||
+ strncmp(buf, name, (unsigned int)len) != 0 ||
+ ((stat(name, &fromsb) == 0) && (fromsb.st_mtime > tosb.st_mtime)))) {
+ (void)(S_ISDIR(tosb.st_mode) ? rmdir : unlink)(toname);
+ exists = 0;
+ }
+ if (!exists && symlink(name, toname) < 0)
+ fail("cannot make symbolic link %s", toname);
+#ifdef HAVE_LCHOWN
+ if ((owner || group) && lchown(toname, uid, gid) < 0)
+ fail("cannot change owner of %s", toname);
+#endif
+
+ if (linkname) {
+ free(linkname);
+ linkname = 0;
+ }
+ } else {
+ /* Copy from name to toname, which might be the same file. */
+ if (stat(name, &sb) == 0 && S_IFDIR & sb.st_mode) {
+ /* then is directory: must explicitly create destination dir */
+ /* and manually copy files over */
+ copydir(name, todir, mode, group, owner, dotimes, uid, gid);
+ } else {
+ copyfile(name, toname, mode, group, owner, dotimes, uid, gid);
+ }
+ }
+
+ free(toname);
+ }
+
+ free(cwd);
+ free(todir);
+ return 0;
+}
diff --git a/config/nsinstall.py b/config/nsinstall.py
new file mode 100644
index 0000000000..200a7ee19c
--- /dev/null
+++ b/config/nsinstall.py
@@ -0,0 +1,172 @@
+# 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/.
+
+# This is a partial python port of nsinstall.
+# It's intended to be used when there's no natively compile nsinstall
+# available, and doesn't intend to be fully equivalent.
+# Its major use is for l10n repackaging on systems that don't have
+# a full build environment set up.
+# The basic limitation is, it doesn't even try to link and ignores
+# all related options.
+import os
+import os.path
+import shutil
+import sys
+from optparse import OptionParser
+
+import mozfile
+import six
+
+
+def _nsinstall_internal(argv):
+ usage = "usage: %prog [options] arg1 [arg2 ...] target-directory"
+ p = OptionParser(usage=usage)
+
+ p.add_option("-D", action="store_true", help="Create a single directory only")
+ p.add_option("-t", action="store_true", help="Preserve time stamp")
+ p.add_option("-m", action="store", help="Set mode", metavar="mode")
+ p.add_option("-d", action="store_true", help="Create directories in target")
+ p.add_option(
+ "-R", action="store_true", help="Use relative symbolic links (ignored)"
+ )
+ p.add_option(
+ "-L", action="store", metavar="linkprefix", help="Link prefix (ignored)"
+ )
+ p.add_option(
+ "-X",
+ action="append",
+ metavar="file",
+ help="Ignore a file when installing a directory recursively.",
+ )
+
+ # The remaining arguments are not used in our tree, thus they're not
+ # implented.
+ def BadArg(option, opt, value, parser):
+ parser.error("option not supported: {0}".format(opt))
+
+ p.add_option(
+ "-C", action="callback", metavar="CWD", callback=BadArg, help="NOT SUPPORTED"
+ )
+ p.add_option(
+ "-o",
+ action="callback",
+ callback=BadArg,
+ help="Set owner (NOT SUPPORTED)",
+ metavar="owner",
+ )
+ p.add_option(
+ "-g",
+ action="callback",
+ callback=BadArg,
+ help="Set group (NOT SUPPORTED)",
+ metavar="group",
+ )
+
+ (options, args) = p.parse_args(argv)
+
+ if options.m:
+ # mode is specified
+ try:
+ options.m = int(options.m, 8)
+ except Exception:
+ sys.stderr.write("nsinstall: {0} is not a valid mode\n".format(options.m))
+ return 1
+
+ # just create one directory?
+ def maybe_create_dir(dir, mode, try_again):
+ dir = os.path.abspath(dir)
+ if os.path.exists(dir):
+ if not os.path.isdir(dir):
+ print("nsinstall: {0} is not a directory".format(dir), file=sys.stderr)
+ return 1
+ if mode:
+ os.chmod(dir, mode)
+ return 0
+
+ try:
+ if mode:
+ os.makedirs(dir, mode)
+ else:
+ os.makedirs(dir)
+ except Exception as e:
+ # We might have hit EEXIST due to a race condition (see bug 463411) -- try again once
+ if try_again:
+ return maybe_create_dir(dir, mode, False)
+ print("nsinstall: failed to create directory {0}: {1}".format(dir, e))
+ return 1
+ else:
+ return 0
+
+ if options.X:
+ options.X = [os.path.abspath(path) for path in options.X]
+
+ if options.D:
+ return maybe_create_dir(args[0], options.m, True)
+
+ # nsinstall arg1 [...] directory
+ if len(args) < 2:
+ p.error("not enough arguments")
+
+ def copy_all_entries(entries, target):
+ for e in entries:
+ e = os.path.abspath(e)
+ if options.X and e in options.X:
+ continue
+
+ dest = os.path.join(target, os.path.basename(e))
+ dest = os.path.abspath(dest)
+ handleTarget(e, dest)
+ if options.m:
+ os.chmod(dest, options.m)
+
+ # set up handler
+ if options.d:
+ # we're supposed to create directories
+ def handleTarget(srcpath, targetpath):
+ # target directory was already created, just use mkdir
+ os.mkdir(targetpath)
+
+ else:
+ # we're supposed to copy files
+ def handleTarget(srcpath, targetpath):
+ if os.path.isdir(srcpath):
+ if not os.path.exists(targetpath):
+ os.mkdir(targetpath)
+ entries = [os.path.join(srcpath, e) for e in os.listdir(srcpath)]
+ copy_all_entries(entries, targetpath)
+ # options.t is not relevant for directories
+ if options.m:
+ os.chmod(targetpath, options.m)
+ else:
+ if os.path.exists(targetpath):
+ if sys.platform == "win32":
+ mozfile.remove(targetpath)
+ else:
+ os.remove(targetpath)
+ if options.t:
+ shutil.copy2(srcpath, targetpath)
+ else:
+ shutil.copy(srcpath, targetpath)
+
+ # the last argument is the target directory
+ target = args.pop()
+ # ensure target directory (importantly, we do not apply a mode to the directory
+ # because we want to copy files into it and the mode might be read-only)
+ rv = maybe_create_dir(target, None, True)
+ if rv != 0:
+ return rv
+
+ copy_all_entries(args, target)
+ return 0
+
+
+# nsinstall as a native command is always UTF-8
+
+
+def nsinstall(argv):
+ return _nsinstall_internal([six.ensure_text(arg, "utf-8") for arg in argv])
+
+
+if __name__ == "__main__":
+ sys.exit(_nsinstall_internal(sys.argv[1:]))
diff --git a/config/pathsub.c b/config/pathsub.c
new file mode 100644
index 0000000000..cac00d95fe
--- /dev/null
+++ b/config/pathsub.c
@@ -0,0 +1,177 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+/*
+** Pathname subroutines.
+**
+** Brendan Eich, 8/29/95
+*/
+#include <assert.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include "pathsub.h"
+
+#ifdef USE_REENTRANT_LIBC
+# include <libc_r.h>
+#endif
+
+#ifdef SUNOS4
+# include "sunos4.h"
+#endif
+
+char* program;
+
+void fail(const char* format, ...) {
+ int error;
+ va_list ap;
+
+#ifdef USE_REENTRANT_LIBC
+ R_STRERROR_INIT_R();
+#endif
+
+ error = errno;
+ fprintf(stderr, "%s: ", program);
+ va_start(ap, format);
+ vfprintf(stderr, format, ap);
+ va_end(ap);
+ if (error) {
+#ifdef USE_REENTRANT_LIBC
+ R_STRERROR_R(errno);
+ fprintf(stderr, ": %s", r_strerror_r);
+#else
+ fprintf(stderr, ": %s", strerror(errno));
+#endif
+ }
+
+ putc('\n', stderr);
+ exit(1);
+}
+
+char* getcomponent(char* path, char* name) {
+ if (*path == '\0') return 0;
+ if (*path == '/') {
+ *name++ = '/';
+ } else {
+ do {
+ *name++ = *path++;
+ } while (*path != '/' && *path != '\0');
+ }
+ *name = '\0';
+ while (*path == '/') path++;
+ return path;
+}
+
+#ifdef LAME_READDIR
+# include <sys/param.h>
+/*
+** The static buffer in Unixware's readdir is too small.
+*/
+struct dirent* readdir(DIR* d) {
+ static struct dirent* buf = NULL;
+
+ if (buf == NULL)
+ buf = (struct dirent*)malloc(sizeof(struct dirent) + MAXPATHLEN);
+ return (readdir_r(d, buf));
+}
+#endif
+
+char* ino2name(ino_t ino) {
+ DIR* dp;
+ struct dirent* ep;
+ char* name;
+
+ dp = opendir("..");
+ if (!dp) fail("cannot read parent directory");
+ for (;;) {
+ if (!(ep = readdir(dp))) fail("cannot find current directory");
+ if (ep->d_ino == ino) break;
+ }
+ name = xstrdup(ep->d_name);
+ closedir(dp);
+ return name;
+}
+
+void* xmalloc(size_t size) {
+ void* p = malloc(size);
+ if (!p) fail("cannot allocate %u bytes", size);
+ return p;
+}
+
+char* xstrdup(char* s) { return strcpy(xmalloc(strlen(s) + 1), s); }
+
+char* xbasename(char* path) {
+ char* cp;
+
+ while ((cp = strrchr(path, '/')) && cp[1] == '\0') *cp = '\0';
+ if (!cp) return path;
+ return cp + 1;
+}
+
+void xchdir(const char* dir) {
+ if (chdir(dir) < 0) fail("cannot change directory to %s", dir);
+}
+
+int relatepaths(char* from, char* to, char* outpath) {
+ char *cp, *cp2;
+ int len;
+ char buf[NAME_MAX];
+
+ assert(*from == '/' && *to == '/');
+ for (cp = to, cp2 = from; *cp == *cp2; cp++, cp2++)
+ if (*cp == '\0') break;
+ while (cp[-1] != '/') cp--, cp2--;
+ if (cp - 1 == to) {
+ /* closest common ancestor is /, so use full pathname */
+ len = strlen(strcpy(outpath, to));
+ if (outpath[len] != '/') {
+ outpath[len++] = '/';
+ outpath[len] = '\0';
+ }
+ } else {
+ len = 0;
+ while ((cp2 = getcomponent(cp2, buf)) != 0) {
+ strcpy(outpath + len, "../");
+ len += 3;
+ }
+ while ((cp = getcomponent(cp, buf)) != 0) {
+ sprintf(outpath + len, "%s/", buf);
+ len += strlen(outpath + len);
+ }
+ }
+ return len;
+}
+
+void reversepath(char* inpath, char* name, int len, char* outpath) {
+ char *cp, *cp2;
+ char buf[NAME_MAX];
+ struct stat sb;
+
+ cp = strcpy(outpath + PATH_MAX - (len + 1), name);
+ cp2 = inpath;
+ while ((cp2 = getcomponent(cp2, buf)) != 0) {
+ if (strcmp(buf, ".") == 0) continue;
+ if (strcmp(buf, "..") == 0) {
+ if (stat(".", &sb) < 0) fail("cannot stat current directory");
+ name = ino2name(sb.st_ino);
+ len = strlen(name);
+ cp -= len + 1;
+ strcpy(cp, name);
+ cp[len] = '/';
+ free(name);
+ xchdir("..");
+ } else {
+ cp -= 3;
+ strncpy(cp, "../", 3);
+ xchdir(buf);
+ }
+ }
+ strcpy(outpath, cp);
+}
diff --git a/config/pathsub.h b/config/pathsub.h
new file mode 100644
index 0000000000..e01bc63d86
--- /dev/null
+++ b/config/pathsub.h
@@ -0,0 +1,42 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#ifndef pathsub_h___
+#define pathsub_h___
+/*
+** Pathname subroutines.
+**
+** Brendan Eich, 8/29/95
+*/
+#include <limits.h>
+#include <sys/types.h>
+
+#ifndef PATH_MAX
+# define PATH_MAX 1024
+#endif
+
+/*
+ * Just prevent stupidity
+ */
+#undef NAME_MAX
+#define NAME_MAX 256
+
+extern char* program;
+
+extern void fail(const char* format, ...);
+extern char* getcomponent(char* path, char* name);
+extern char* ino2name(ino_t ino);
+extern void* xmalloc(size_t size);
+extern char* xstrdup(char* s);
+extern char* xbasename(char* path);
+extern void xchdir(const char* dir);
+
+/* Relate absolute pathnames from and to returning the result in outpath. */
+extern int relatepaths(char* from, char* to, char* outpath);
+
+/* XXX changes current working directory -- caveat emptor */
+extern void reversepath(char* inpath, char* name, int len, char* outpath);
+
+#endif /* pathsub_h___ */
diff --git a/config/printconfigsetting.py b/config/printconfigsetting.py
new file mode 100644
index 0000000000..e2b7487760
--- /dev/null
+++ b/config/printconfigsetting.py
@@ -0,0 +1,24 @@
+# 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/.
+
+import sys
+from configparser import ConfigParser, NoOptionError, NoSectionError
+
+try:
+ (filename, section, key) = sys.argv[1:]
+except ValueError:
+ print("Usage: printconfigsetting.py <filename> <section> <setting>")
+ sys.exit(1)
+
+cfg = ConfigParser()
+cfg.read(filename)
+
+try:
+ print(cfg.get(section, key))
+except NoOptionError:
+ print("Key %s not found." % key, file=sys.stderr)
+ sys.exit(1)
+except NoSectionError:
+ print("Section [%s] not found." % section, file=sys.stderr)
+ sys.exit(1)
diff --git a/config/printprereleasesuffix.py b/config/printprereleasesuffix.py
new file mode 100644
index 0000000000..a3403e3d2a
--- /dev/null
+++ b/config/printprereleasesuffix.py
@@ -0,0 +1,35 @@
+# 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/.
+
+# Prints the pre-release version suffix based on the version string
+#
+# Examples:
+# 2.1a3 > " 2.1 Alpha 3"
+# 2.1a3pre > ""
+# 3.2b4 > " 3.2 Beta 4"
+# 3.2b4pre > ""
+import re
+import sys
+
+
+def get_prerelease_suffix(version):
+ """Returns the prerelease suffix from the version string argument"""
+
+ def mfunc(m):
+ return " {0} {1} {2}".format(
+ m.group("prefix"),
+ {"a": "Alpha", "b": "Beta"}[m.group("c")],
+ m.group("suffix"),
+ )
+
+ result, c = re.subn(
+ r"^(?P<prefix>(\d+\.)*\d+)(?P<c>[ab])(?P<suffix>\d+)$", mfunc, version
+ )
+ if c != 1:
+ return ""
+ return result
+
+
+if len(sys.argv) == 2:
+ print(get_prerelease_suffix(sys.argv[1]))
diff --git a/config/rebuild_check.py b/config/rebuild_check.py
new file mode 100644
index 0000000000..a906fdc304
--- /dev/null
+++ b/config/rebuild_check.py
@@ -0,0 +1,68 @@
+# 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/.
+
+import errno
+import os
+
+
+def mtime(path):
+ try:
+ return os.stat(path).st_mtime
+ except OSError as e:
+ if e.errno == errno.ENOENT:
+ return -1
+ raise
+
+
+def rebuild_check(args):
+ target = args[0]
+ deps = args[1:]
+ t = mtime(target)
+ if t < 0:
+ print(target)
+ return
+
+ newer = []
+ removed = []
+ for dep in deps:
+ deptime = mtime(dep)
+ if deptime < 0:
+ removed.append(dep)
+ elif deptime > t:
+ newer.append(dep)
+
+ def format_filelist(filelist):
+ if not filelist:
+ return None
+
+ limit = 5
+ length = len(filelist)
+ if length < limit:
+ return ", ".join(filelist)
+
+ truncated = filelist[:limit]
+ remaining = length - limit
+
+ return "%s (and %d other files)" % (", ".join(truncated), remaining)
+
+ newer = format_filelist(newer)
+ removed = format_filelist(removed)
+
+ if newer and removed:
+ print(
+ "Rebuilding %s because %s changed and %s was removed"
+ % (target, newer, removed)
+ )
+ elif newer:
+ print("Rebuilding %s because %s changed" % (target, newer))
+ elif removed:
+ print("Rebuilding %s because %s was removed" % (target, removed))
+ else:
+ print("Rebuilding %s for an unknown reason" % target)
+
+
+if __name__ == "__main__":
+ import sys
+
+ rebuild_check(sys.argv[1:])
diff --git a/config/recurse.mk b/config/recurse.mk
new file mode 100644
index 0000000000..a2e10e6a18
--- /dev/null
+++ b/config/recurse.mk
@@ -0,0 +1,216 @@
+# 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/.
+
+ifndef INCLUDED_RULES_MK
+include $(topsrcdir)/config/rules.mk
+endif
+
+# The traditional model of directory traversal with make is as follows:
+# make -C foo
+# Entering foo
+# make -C bar
+# Entering foo/bar
+# make -C baz
+# Entering foo/baz
+# make -C qux
+# Entering qux
+#
+# Pseudo derecurse transforms the above into:
+# make -C foo
+# make -C foo/bar
+# make -C foo/baz
+# make -C qux
+
+ifeq (.,$(DEPTH))
+
+include root.mk
+
+# Main rules (export, compile, libs and tools) call recurse_* rules.
+# This wrapping is only really useful for build status.
+$(RUNNABLE_TIERS)::
+ $(if $(filter $@,$(MAKECMDGOALS)),$(call BUILDSTATUS,TIERS $@),)
+ $(call BUILDSTATUS,TIER_START $@)
+ +$(MAKE) recurse_$@
+ $(call BUILDSTATUS,TIER_FINISH $@)
+
+# Special rule that does install-manifests (cf. Makefile.in) + compile
+binaries::
+ +$(MAKE) recurse_compile
+
+# Get current tier and corresponding subtiers from the data in root.mk.
+CURRENT_TIER := $(filter $(foreach tier,$(RUNNABLE_TIERS) $(non_default_tiers),recurse_$(tier) $(tier)-deps),$(MAKECMDGOALS))
+ifneq (,$(filter-out 0 1,$(words $(CURRENT_TIER))))
+$(error $(CURRENT_TIER) not supported on the same make command line)
+endif
+CURRENT_TIER := $(subst recurse_,,$(CURRENT_TIER:-deps=))
+
+# The rules here are doing directory traversal, so we don't want further
+# recursion to happen when running make -C subdir $tier. But some make files
+# further call make -C something else, and sometimes expect recursion to
+# happen in that case.
+# Conveniently, every invocation of make increases MAKELEVEL, so only stop
+# recursion from happening at current MAKELEVEL + 1.
+ifdef CURRENT_TIER
+ifeq (0,$(MAKELEVEL))
+export NO_RECURSE_MAKELEVEL=1
+else
+export NO_RECURSE_MAKELEVEL=$(word $(MAKELEVEL),2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20)
+endif
+endif
+
+RECURSE = $(if $(RECURSE_TRACE_ONLY),@echo $2/$1,$(call SUBMAKE,$1,$2))
+
+# Use the $(*_dirs) variables available in root.mk
+CURRENT_DIRS := $($(CURRENT_TIER)_dirs)
+
+# Need a list of compile targets because we can't use pattern rules:
+# https://savannah.gnu.org/bugs/index.php?42833
+# Only recurse the paths starting with RECURSE_BASE_DIR when provided.
+.PHONY: $(pre_compile_targets) $(compile_targets) $(syms_targets)
+$(pre_compile_targets) $(compile_targets) $(syms_targets):
+ $(if $(filter $(RECURSE_BASE_DIR)%,$@),$(call RECURSE,$(@F),$(@D)))
+
+$(syms_targets): %/syms: %/target
+
+# Only hook symbols targets into the main compile graph in automation.
+ifdef MOZ_AUTOMATION
+ifeq (1,$(MOZ_AUTOMATION_BUILD_SYMBOLS))
+recurse_compile: $(syms_targets)
+endif
+endif
+
+# Create a separate rule that depends on every 'syms' target so that
+# symbols can be dumped on demand locally.
+.PHONY: recurse_syms
+recurse_syms: $(syms_targets)
+
+# The compile tier has different rules from other tiers.
+ifneq ($(CURRENT_TIER),compile)
+
+# Recursion rule for all directories traversed for all subtiers in the
+# current tier.
+$(addsuffix /$(CURRENT_TIER),$(CURRENT_DIRS)): %/$(CURRENT_TIER):
+ $(call RECURSE,$(CURRENT_TIER),$*)
+
+.PHONY: $(addsuffix /$(CURRENT_TIER),$(CURRENT_DIRS))
+
+# Dummy rules for possibly inexisting dependencies for the above tier targets
+$(addsuffix /Makefile,$(CURRENT_DIRS)) $(addsuffix /backend.mk,$(CURRENT_DIRS)):
+
+ifeq ($(CURRENT_TIER),export)
+# At least build/export requires config/export for buildid, but who knows what
+# else, so keep this global dependency to make config/export first for now.
+$(addsuffix /$(CURRENT_TIER),$(filter-out config,$(CURRENT_DIRS))): config/$(CURRENT_TIER)
+
+# The export tier requires nsinstall, which is built from config. So every
+# subdirectory traversal needs to happen after building nsinstall in config, which
+# is done with the config/host target. Note the config/host target only exists if
+# nsinstall is actually built, which it is not on Windows, because we use
+# nsinstall.py there.
+ifdef COMPILE_ENVIRONMENT
+ifneq (,$(filter config/host, $(compile_targets)))
+$(addsuffix /$(CURRENT_TIER),$(CURRENT_DIRS)): config/host
+endif
+endif
+endif
+
+endif # ifeq ($(CURRENT_TIER),compile)
+
+else
+
+# Don't recurse if MAKELEVEL is NO_RECURSE_MAKELEVEL as defined above
+ifeq ($(NO_RECURSE_MAKELEVEL),$(MAKELEVEL))
+
+$(RUNNABLE_TIERS)::
+
+else
+#########################
+# Tier traversal handling
+#########################
+
+define CREATE_SUBTIER_TRAVERSAL_RULE
+.PHONY: $(1)
+
+$(1):: $$(SUBMAKEFILES)
+ $$(LOOP_OVER_DIRS)
+
+endef
+
+$(foreach subtier,$(filter-out compile,$(RUNNABLE_TIERS)),$(eval $(call CREATE_SUBTIER_TRAVERSAL_RULE,$(subtier))))
+
+ifndef TOPLEVEL_BUILD
+ifdef COMPILE_ENVIRONMENT
+compile::
+ @$(MAKE) -C $(DEPTH) compile RECURSE_BASE_DIR=$(relativesrcdir)/
+endif # COMPILE_ENVIRONMENT
+endif
+
+endif # ifeq ($(NO_RECURSE_MAKELEVEL),$(MAKELEVEL))
+
+endif # ifeq (.,$(DEPTH))
+
+recurse:
+ @$(RECURSED_COMMAND)
+ $(LOOP_OVER_DIRS)
+
+ifeq (.,$(DEPTH))
+
+# This is required so that the pre-export tier sees the rules in
+# mobile/android
+ifeq ($(MOZ_WIDGET_TOOLKIT),android)
+recurse_pre-export: mobile/android/pre-export
+endif
+
+# CSS2Properties.webidl needs ServoCSSPropList.py from layout/style
+dom/bindings/export: layout/style/ServoCSSPropList.py
+
+# Various telemetry histogram files need ServoCSSPropList.py from layout/style
+toolkit/components/telemetry/export: layout/style/ServoCSSPropList.py
+
+ifeq ($(TARGET_ENDIANNESS),big)
+config/external/icu/data/target-objects: config/external/icu/data/$(MDDEPDIR)/icudt$(MOZ_ICU_VERSION)b.dat.stub
+config/external/icu/data/$(MDDEPDIR)/icudt$(MOZ_ICU_VERSION)b.dat.stub: config/external/icu/icupkg/host
+endif
+
+ifdef ENABLE_CLANG_PLUGIN
+# Only target rules use the clang plugin.
+$(filter %/target %/target-objects,$(filter-out config/export config/host build/unix/stdc++compat/% build/clang-plugin/%,$(compile_targets))) security/rlbox/pre-compile media/libsoundtouch/src/pre-compile: build/clang-plugin/host build/clang-plugin/tests/target-objects
+build/clang-plugin/tests/target-objects: build/clang-plugin/host
+# clang-plugin tests require js-confdefs.h on js standalone builds and mozilla-config.h on
+# other builds, because they are -include'd.
+ifdef JS_STANDALONE
+# The js/src/export target only exists when CURRENT_TIER is export. If we're in a later tier,
+# we can assume js/src/export has happened anyways.
+ifeq ($(CURRENT_TIER),export)
+build/clang-plugin/tests/target-objects: js/src/export
+endif
+else
+build/clang-plugin/tests/target-objects: mozilla-config.h
+endif
+endif
+
+# Interdependencies that moz.build world don't know about yet for compilation.
+# Note some others are hardcoded or "guessed" in recursivemake.py and emitter.py
+ifdef MOZ_USING_WASM_SANDBOXING
+dom/media/ogg/target-objects extensions/spellcheck/hunspell/glue/target-objects gfx/thebes/target-objects parser/expat/target-objects parser/htmlparser/target-objects gfx/ots/src/target-objects: security/rlbox/pre-compile
+dom/media/target-objects dom/media/mediasink/target-objects: media/libsoundtouch/src/pre-compile
+endif
+
+# Most things are built during compile (target/host), but some things happen during export
+# Those need to depend on config/export for system wrappers.
+$(addprefix build/unix/stdc++compat/,target host) build/clang-plugin/host: config/export
+
+# Rust targets, and export targets that run cbindgen need
+# $topobjdir/.cargo/config to be preprocessed first. Ideally, we'd only set it
+# as a dependency of the rust targets, but unfortunately, that pushes Make to
+# execute them much later than we'd like them to be when the file doesn't exist
+# prior to Make running. So we also set it as a dependency of pre-export, which
+# ensures it exists before recursing the rust targets and the export targets
+# that run cbindgen, tricking Make into keeping them early.
+$(rust_targets): $(DEPTH)/.cargo/config
+ifndef TEST_MOZBUILD
+recurse_pre-export: $(DEPTH)/.cargo/config
+endif
+
+endif
diff --git a/config/rules.mk b/config/rules.mk
new file mode 100644
index 0000000000..ff721eabd4
--- /dev/null
+++ b/config/rules.mk
@@ -0,0 +1,1177 @@
+# -*- makefile -*-
+# vim:set ts=8 sw=8 sts=8 noet:
+#
+# 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/.
+#
+
+ifndef topsrcdir
+$(error topsrcdir was not set))
+endif
+
+# Define an include-at-most-once flag
+ifdef INCLUDED_RULES_MK
+$(error Do not include rules.mk twice!)
+endif
+INCLUDED_RULES_MK = 1
+
+ifndef INCLUDED_CONFIG_MK
+include $(topsrcdir)/config/config.mk
+endif
+
+USE_AUTOTARGETS_MK = 1
+include $(MOZILLA_DIR)/config/makefiles/makeutils.mk
+
+ifdef REBUILD_CHECK
+REPORT_BUILD = $(info $(shell $(PYTHON3) $(MOZILLA_DIR)/config/rebuild_check.py $@ $?))
+REPORT_BUILD_VERBOSE = $(REPORT_BUILD)
+else
+REPORT_BUILD = $(info $(relativesrcdir)/$(notdir $@))
+
+ifdef BUILD_VERBOSE_LOG
+REPORT_BUILD_VERBOSE = $(REPORT_BUILD)
+else
+REPORT_BUILD_VERBOSE = $(call BUILDSTATUS,BUILD_VERBOSE $(relativesrcdir))
+endif
+
+endif
+
+EXEC = exec
+
+################################################################################
+# Testing frameworks support
+################################################################################
+
+testxpcobjdir = $(DEPTH)/_tests/xpcshell
+
+ifdef ENABLE_TESTS
+ifdef CPP_UNIT_TESTS
+ifdef COMPILE_ENVIRONMENT
+
+# Compile the tests to $(DIST)/bin. Make lots of niceties available by default
+# through TestHarness.h, by modifying the list of includes and the libs against
+# which stuff links.
+SIMPLE_PROGRAMS += $(CPP_UNIT_TESTS)
+
+ifndef MOZ_PROFILE_GENERATE
+CPP_UNIT_TESTS_FILES = $(CPP_UNIT_TESTS)
+CPP_UNIT_TESTS_DEST = $(DIST)/cppunittests
+CPP_UNIT_TESTS_TARGET = target
+INSTALL_TARGETS += CPP_UNIT_TESTS
+endif
+
+run-cppunittests::
+ @$(PYTHON3) $(MOZILLA_DIR)/testing/runcppunittests.py --xre-path=$(DIST)/bin --symbols-path=$(DIST)/crashreporter-symbols $(CPP_UNIT_TESTS)
+
+cppunittests-remote:
+ $(PYTHON3) -u $(MOZILLA_DIR)/testing/remotecppunittests.py \
+ --xre-path=$(DEPTH)/dist/bin \
+ --localLib=$(DEPTH)/dist/$(MOZ_APP_NAME) \
+ --deviceIP=${TEST_DEVICE} \
+ $(CPP_UNIT_TESTS) $(EXTRA_TEST_ARGS); \
+
+endif # COMPILE_ENVIRONMENT
+endif # CPP_UNIT_TESTS
+endif # ENABLE_TESTS
+
+
+#
+# Library rules
+#
+# If FORCE_STATIC_LIB is set, build a static library.
+# Otherwise, build a shared library.
+#
+
+ifndef LIBRARY
+ifdef REAL_LIBRARY
+ifdef NO_EXPAND_LIBS
+# Only build actual library if it is requested.
+LIBRARY := $(REAL_LIBRARY)
+endif
+endif
+endif
+
+ifdef FORCE_SHARED_LIB
+ifdef MKSHLIB
+
+ifdef LIB_IS_C_ONLY
+MKSHLIB = $(MKCSHLIB)
+endif
+
+endif # MKSHLIB
+endif # FORCE_SHARED_LIB
+
+ifeq ($(OS_ARCH),WINNT)
+
+#
+# This next line captures both the default (non-MOZ_COPY_PDBS)
+# case as well as the MOZ_COPY_PDBS-for-mingwclang case.
+#
+# For the default case, placing the pdb in the build
+# directory is needed.
+#
+# For the MOZ_COPY_PDBS, non-mingwclang case - we need to
+# build the pdb next to the executable (handled in the if
+# statement immediately below.)
+#
+# For the MOZ_COPY_PDBS, mingwclang case - we also need to
+# build the pdb next to the executable, but this macro doesn't
+# work for jsapi-tests which is a little special, so we specify
+# the output directory below with MOZ_PROGRAM_LDFLAGS.
+#
+LINK_PDBFILE ?= $(basename $(@F)).pdb
+
+ifdef MOZ_COPY_PDBS
+ifneq ($(CC_TYPE),clang)
+LINK_PDBFILE = $(basename $@).pdb
+endif
+endif
+
+ifndef GNU_CC
+
+ifdef SIMPLE_PROGRAMS
+COMPILE_PDB_FLAG ?= -Fd$(basename $(@F)).pdb
+COMPILE_CFLAGS += $(COMPILE_PDB_FLAG)
+COMPILE_CXXFLAGS += $(COMPILE_PDB_FLAG)
+endif
+
+ifdef MOZ_DEBUG
+CODFILE=$(basename $(@F)).cod
+endif
+
+endif # !GNU_CC
+endif # WINNT
+
+ifeq (arm-Darwin,$(TARGET_CPU)-$(OS_TARGET))
+ifdef PROGRAM
+MOZ_PROGRAM_LDFLAGS += -Wl,-rpath -Wl,@executable_path/Frameworks
+endif
+endif
+
+# For Mac executables, set the @rpath to be @executable_path by default so that
+# shared libraries built with an @rpath install name in the same directory
+# as the executable can be resolved. Executables not in the same directory
+# should override the @rpath with a relative path such as @executable_path/../
+# depending on their install location.
+ifeq ($(OS_ARCH),Darwin)
+MOZ_PROGRAM_LDFLAGS += -Wl,-rpath,@executable_path
+endif
+
+ifeq ($(OS_ARCH),WINNT)
+ifeq ($(CC_TYPE),clang)
+MOZ_PROGRAM_LDFLAGS += -Wl,-pdb,$(dir $@)/$(LINK_PDBFILE)
+endif
+endif
+
+ifeq ($(HOST_OS_ARCH),WINNT)
+HOST_PDBFILE=$(basename $(@F)).pdb
+HOST_PDB_FLAG ?= -PDB:$(HOST_PDBFILE)
+HOST_C_LDFLAGS += -DEBUG $(HOST_PDB_FLAG)
+HOST_CXX_LDFLAGS += -DEBUG $(HOST_PDB_FLAG)
+endif
+
+# Don't build SIMPLE_PROGRAMS during the MOZ_PROFILE_GENERATE pass, and do not
+# attempt to install them
+ifdef MOZ_PROFILE_GENERATE
+$(foreach category,$(INSTALL_TARGETS),\
+ $(eval $(category)_FILES := $(foreach file,$($(category)_FILES),$(if $(filter $(SIMPLE_PROGRAMS),$(notdir $(file))),,$(file)))))
+SIMPLE_PROGRAMS :=
+endif
+
+ifdef COMPILE_ENVIRONMENT
+ifndef TARGETS
+TARGETS = $(LIBRARY) $(SHARED_LIBRARY) $(PROGRAM) $(SIMPLE_PROGRAMS) $(HOST_PROGRAM) $(HOST_SIMPLE_PROGRAMS) $(HOST_SHARED_LIBRARY)
+endif
+
+COBJS = $(notdir $(CSRCS:.c=.$(OBJ_SUFFIX)))
+CWASMOBJS = $(notdir $(WASM_CSRCS:.c=.$(WASM_OBJ_SUFFIX)))
+SOBJS = $(notdir $(SSRCS:.S=.$(OBJ_SUFFIX)))
+# CPPSRCS can have different extensions (eg: .cpp, .cc)
+CPPOBJS = $(notdir $(addsuffix .$(OBJ_SUFFIX),$(basename $(CPPSRCS))))
+CPPWASMOBJS = $(notdir $(addsuffix .$(WASM_OBJ_SUFFIX),$(basename $(WASM_CPPSRCS))))
+CMOBJS = $(notdir $(CMSRCS:.m=.$(OBJ_SUFFIX)))
+CMMOBJS = $(notdir $(CMMSRCS:.mm=.$(OBJ_SUFFIX)))
+# ASFILES can have different extensions (.s, .asm)
+ASOBJS = $(notdir $(addsuffix .$(OBJ_SUFFIX),$(basename $(ASFILES))))
+RS_STATICLIB_CRATE_OBJ = $(addprefix lib,$(notdir $(RS_STATICLIB_CRATE_SRC:.rs=.$(LIB_SUFFIX))))
+ifndef OBJS
+_OBJS = $(COBJS) $(SOBJS) $(CPPOBJS) $(CMOBJS) $(CMMOBJS) $(ASOBJS) $(CWASMOBJS) $(CPPWASMOBJS)
+OBJS = $(strip $(_OBJS))
+endif
+
+HOST_COBJS = $(addprefix host_,$(notdir $(HOST_CSRCS:.c=.$(OBJ_SUFFIX))))
+# HOST_CPPOBJS can have different extensions (eg: .cpp, .cc)
+HOST_CPPOBJS = $(addprefix host_,$(notdir $(addsuffix .$(OBJ_SUFFIX),$(basename $(HOST_CPPSRCS)))))
+HOST_CMOBJS = $(addprefix host_,$(notdir $(HOST_CMSRCS:.m=.$(OBJ_SUFFIX))))
+HOST_CMMOBJS = $(addprefix host_,$(notdir $(HOST_CMMSRCS:.mm=.$(OBJ_SUFFIX))))
+ifndef HOST_OBJS
+_HOST_OBJS = $(HOST_COBJS) $(HOST_CPPOBJS) $(HOST_CMOBJS) $(HOST_CMMOBJS)
+HOST_OBJS = $(strip $(_HOST_OBJS))
+endif
+else
+LIBRARY :=
+SHARED_LIBRARY :=
+IMPORT_LIBRARY :=
+REAL_LIBRARY :=
+PROGRAM :=
+SIMPLE_PROGRAMS :=
+HOST_SHARED_LIBRARY :=
+HOST_PROGRAM :=
+HOST_SIMPLE_PROGRAMS :=
+endif
+
+ifdef MACH
+ifndef NO_BUILDSTATUS_MESSAGES
+define BUILDSTATUS
+@echo 'BUILDSTATUS@$(relativesrcdir) $1'
+
+endef
+endif
+endif
+
+define SUBMAKE # $(call SUBMAKE,target,directory,static)
++@$(MAKE) $(if $(2),-C $(2)) $(1)
+
+endef # The extra line is important here! don't delete it
+
+define TIER_DIR_SUBMAKE
+$(call SUBMAKE,$(4),$(3),$(5))
+
+endef # Ths empty line is important.
+
+ifneq (,$(strip $(DIRS)))
+LOOP_OVER_DIRS = \
+ $(foreach dir,$(DIRS),$(call SUBMAKE,$@,$(dir)))
+endif
+
+#
+# Now we can differentiate between objects used to build a library, and
+# objects used to build an executable in the same directory.
+#
+ifndef PROGOBJS
+PROGOBJS = $(OBJS)
+endif
+
+ifndef HOST_PROGOBJS
+HOST_PROGOBJS = $(HOST_OBJS)
+endif
+
+#
+# Tags: emacs (etags), vi (ctags)
+# TAG_PROGRAM := ctags -L -
+#
+TAG_PROGRAM = xargs etags -a
+
+#
+# Turn on C++ linking if we have any .cpp or .mm files
+# (moved this from config.mk so that config.mk can be included
+# before the CPPSRCS are defined)
+#
+ifneq ($(HOST_CPPSRCS)$(HOST_CMMSRCS),)
+HOST_CPP_PROG_LINK = 1
+endif
+
+#
+# MacOS X specific stuff
+#
+
+ifeq ($(OS_ARCH),Darwin)
+ifneq (,$(SHARED_LIBRARY))
+_LOADER_PATH := @rpath
+EXTRA_DSO_LDOPTS += -dynamiclib -install_name $(_LOADER_PATH)/$@ -compatibility_version 1 -current_version 1
+endif
+endif
+
+#
+# GNU doesn't have path length limitation
+#
+
+ifeq ($(OS_ARCH),GNU)
+OS_CPPFLAGS += -DPATH_MAX=1024 -DMAXPATHLEN=1024
+endif
+
+#
+# MINGW32
+#
+ifeq ($(OS_ARCH),WINNT)
+ifdef GNU_CC
+DSO_LDOPTS += -Wl,--out-implib -Wl,$(IMPORT_LIBRARY)
+endif
+endif
+
+ifeq ($(USE_TVFS),1)
+IFLAGS1 = -rb
+IFLAGS2 = -rb
+else
+IFLAGS1 = -m 644
+IFLAGS2 = -m 755
+endif
+
+ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH))
+OUTOPTION = -Fo# eol
+else
+OUTOPTION = -o # eol
+endif # WINNT && !GNU_CC
+
+ifeq (,$(CROSS_COMPILE))
+HOST_OUTOPTION = $(OUTOPTION)
+else
+# Windows-to-Windows cross compiles should always use MSVC-style options for
+# host compiles.
+ifeq (WINNT_WINNT,$(HOST_OS_ARCH)_$(OS_ARCH))
+ifneq (,$(filter-out clang-cl,$(HOST_CC_TYPE)))
+$(error MSVC-style compilers should be used for host compilations!)
+endif
+HOST_OUTOPTION = -Fo# eol
+else
+HOST_OUTOPTION = -o # eol
+endif
+endif
+################################################################################
+
+# Ensure the build config is up to date. This is done automatically when builds
+# are performed through |mach build|. The check here is to catch people not
+# using mach. If we ever enforce builds through mach, this code can be removed.
+ifndef MOZBUILD_BACKEND_CHECKED
+ifndef MACH
+ifndef TOPLEVEL_BUILD
+BUILD_BACKEND_FILES := $(addprefix $(DEPTH)/backend.,$(addsuffix Backend,$(BUILD_BACKENDS)))
+$(DEPTH)/backend.%Backend:
+ $(error Build configuration changed. Build with |mach build| or run |mach build-backend| to regenerate build config)
+
+define build_backend_rule
+$(1): $$(shell cat $(1).in)
+
+endef
+$(foreach file,$(BUILD_BACKEND_FILES),$(eval $(call build_backend_rule,$(file))))
+
+default:: $(BUILD_BACKEND_FILES)
+
+export MOZBUILD_BACKEND_CHECKED=1
+endif
+endif
+endif
+
+# The root makefile doesn't want to do a plain export/libs, because
+# of the tiers and because of libxul. Suppress the default rules in favor
+# of something else. Makefiles which use this var *must* provide a sensible
+# default rule before including rules.mk
+default all::
+ $(foreach tier,$(TIERS),$(call SUBMAKE,$(tier)))
+
+ifdef BUILD_VERBOSE_LOG
+ECHO := echo
+QUIET :=
+else
+ECHO := true
+QUIET := -q
+endif
+
+# Dependencies which, if modified, should cause everything to rebuild
+GLOBAL_DEPS += Makefile $(addprefix $(DEPTH)/config/,$(INCLUDED_AUTOCONF_MK)) $(MOZILLA_DIR)/config/config.mk
+
+ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
+# We always build .res files for programs and shared libraries
+resfile = $(notdir $1).res
+# We also build .res files for simple programs if a corresponding manifest
+# exists. We'll generate a .rc file that includes the manifest.
+resfile_for_manifest = $(if $(wildcard $(srcdir)/$(notdir $1).manifest),$(call resfile,$1))
+else
+resfile =
+resfile_for_manifest =
+endif
+
+##############################################
+ifdef COMPILE_ENVIRONMENT
+compile:: host target
+
+host:: $(HOST_OBJS) $(HOST_PROGRAM) $(HOST_SIMPLE_PROGRAMS) $(HOST_RUST_PROGRAMS) $(HOST_SHARED_LIBRARY)
+
+target:: $(filter-out $(MOZBUILD_NON_DEFAULT_TARGETS),$(LIBRARY) $(SHARED_LIBRARY) $(PROGRAM) $(SIMPLE_PROGRAMS) $(RUST_PROGRAMS))
+
+ifndef LIBRARY
+ifdef OBJS
+target:: $(OBJS)
+endif
+endif
+
+target-objects: $(OBJS) $(PROGOBJS) $(filter-out $(MOZBUILD_NON_DEFAULT_TARGETS),$(RUST_LIBRARY_FILE))
+host-objects: $(HOST_OBJS) $(HOST_PROGOBJS) $(HOST_RUST_LIBRARY_FILE)
+
+syms::
+
+include $(MOZILLA_DIR)/config/makefiles/target_binaries.mk
+endif
+
+alltags:
+ $(RM) TAGS
+ find $(topsrcdir) -name dist -prune -o \( -name '*.[hc]' -o -name '*.cp' -o -name '*.cpp' -o -name '*.idl' \) -print | $(TAG_PROGRAM)
+
+define EXPAND_CC_OR_CXX
+$(if $(PROG_IS_C_ONLY_$(notdir $(1))),$(CC),$(CCC))
+endef
+
+#
+# PROGRAM = Foo
+# creates OBJS, links with LIBS to create Foo
+#
+$(PROGRAM): $(PROGOBJS) $(STATIC_LIBS) $(EXTRA_DEPS) $(call resfile,$(PROGRAM)) $(GLOBAL_DEPS) $(call mkdir_deps,$(FINAL_TARGET))
+ $(REPORT_BUILD)
+ $(call BUILDSTATUS,START_Program $(@F))
+ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH))
+ $(LINKER) -OUT:$@ -PDB:$(LINK_PDBFILE) -IMPLIB:$(basename $(@F)).lib $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(MOZ_PROGRAM_LDFLAGS) $($(notdir $@)_OBJS) $(filter %.res,$^) $(STATIC_LIBS) $(SHARED_LIBS) $(OS_LIBS)
+else # !WINNT || GNU_CC
+ $(call EXPAND_CC_OR_CXX,$@) -o $@ $(COMPUTED_CXX_LDFLAGS) $($(notdir $@)_OBJS) $(filter %.res,$^) $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(STATIC_LIBS) $(MOZ_PROGRAM_LDFLAGS) $(SHARED_LIBS) $(OS_LIBS)
+ $(call py_action,check_binary $(@F),$@)
+endif # WINNT && !GNU_CC
+
+ifdef ENABLE_STRIP
+ $(STRIP) $(STRIP_FLAGS) $@
+endif
+ifdef MOZ_POST_PROGRAM_COMMAND
+ $(MOZ_POST_PROGRAM_COMMAND) $@
+endif
+ $(call BUILDSTATUS,END_Program $(@F))
+
+$(HOST_PROGRAM): $(HOST_PROGOBJS) $(HOST_LIBS) $(HOST_EXTRA_DEPS) $(GLOBAL_DEPS) $(call mkdir_deps,$(DEPTH)/dist/host/bin)
+ $(REPORT_BUILD)
+ $(call BUILDSTATUS,START_Program $(@F))
+ifeq (_WINNT,$(GNU_CC)_$(HOST_OS_ARCH))
+ $(HOST_LINKER) -OUT:$@ -PDB:$(HOST_PDBFILE) $($(notdir $@)_OBJS) $(WIN32_EXE_LDFLAGS) $(HOST_LDFLAGS) $(HOST_LINKER_LIBPATHS) $(HOST_LIBS) $(HOST_EXTRA_LIBS)
+else
+ifeq ($(HOST_CPP_PROG_LINK),1)
+ $(HOST_CXX) -o $@ $(HOST_CXX_LDFLAGS) $(HOST_LDFLAGS) $($(notdir $@)_OBJS) $(HOST_LIBS) $(HOST_EXTRA_LIBS)
+else
+ $(HOST_CC) -o $@ $(HOST_C_LDFLAGS) $(HOST_LDFLAGS) $($(notdir $@)_OBJS) $(HOST_LIBS) $(HOST_EXTRA_LIBS)
+endif # HOST_CPP_PROG_LINK
+endif
+ $(call BUILDSTATUS,END_Program $(@F))
+
+#
+# This is an attempt to support generation of multiple binaries
+# in one directory, it assumes everything to compile Foo is in
+# Foo.o (from either Foo.c or Foo.cpp).
+#
+# SIMPLE_PROGRAMS = Foo Bar
+# creates Foo.o Bar.o, links with LIBS to create Foo, Bar.
+#
+define simple_program_deps
+$1: $(1:$(BIN_SUFFIX)=.$(OBJ_SUFFIX)) $(STATIC_LIBS) $(EXTRA_DEPS) $(call resfile_for_manifest,$1) $(GLOBAL_DEPS)
+endef
+$(foreach p,$(SIMPLE_PROGRAMS),$(eval $(call simple_program_deps,$(p))))
+
+$(SIMPLE_PROGRAMS):
+ $(REPORT_BUILD)
+ $(call BUILDSTATUS,START_Program $(@F))
+ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH))
+ $(LINKER) -out:$@ -pdb:$(LINK_PDBFILE) $($@_OBJS) $(filter %.res,$^) $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(MOZ_PROGRAM_LDFLAGS) $(STATIC_LIBS) $(SHARED_LIBS) $(OS_LIBS)
+else
+ $(call EXPAND_CC_OR_CXX,$@) $(COMPUTED_CXX_LDFLAGS) -o $@ $($@_OBJS) $(filter %.res,$^) $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(STATIC_LIBS) $(MOZ_PROGRAM_LDFLAGS) $(SHARED_LIBS) $(OS_LIBS)
+ $(call py_action,check_binary $(@F),$@)
+endif # WINNT && !GNU_CC
+
+ifdef ENABLE_STRIP
+ $(STRIP) $(STRIP_FLAGS) $@
+endif
+ifdef MOZ_POST_PROGRAM_COMMAND
+ $(MOZ_POST_PROGRAM_COMMAND) $@
+endif
+ $(call BUILDSTATUS,END_Program $(@F))
+
+$(HOST_SIMPLE_PROGRAMS): host_%$(HOST_BIN_SUFFIX): $(HOST_LIBS) $(HOST_EXTRA_DEPS) $(GLOBAL_DEPS)
+ $(REPORT_BUILD)
+ $(call BUILDSTATUS,START_Program $(@F))
+ifeq (WINNT_,$(HOST_OS_ARCH)_$(GNU_CC))
+ $(HOST_LINKER) -OUT:$@ -PDB:$(HOST_PDBFILE) $($(notdir $@)_OBJS) $(WIN32_EXE_LDFLAGS) $(HOST_LDFLAGS) $(HOST_LINKER_LIBPATHS) $(HOST_LIBS) $(HOST_EXTRA_LIBS)
+else
+ifneq (,$(HOST_CPPSRCS)$(USE_HOST_CXX))
+ $(HOST_CXX) $(HOST_OUTOPTION)$@ $(HOST_CXX_LDFLAGS) $(HOST_LDFLAGS) $($(notdir $@)_OBJS) $(HOST_LIBS) $(HOST_EXTRA_LIBS)
+else
+ $(HOST_CC) $(HOST_OUTOPTION)$@ $(HOST_C_LDFLAGS) $(HOST_LDFLAGS) $($(notdir $@)_OBJS) $(HOST_LIBS) $(HOST_EXTRA_LIBS)
+endif
+endif
+ $(call BUILDSTATUS,END_Program $(@F))
+
+$(LIBRARY): $(OBJS) $(STATIC_LIBS) $(EXTRA_DEPS) $(GLOBAL_DEPS)
+ $(REPORT_BUILD)
+ $(call BUILDSTATUS,START_StaticLib $@)
+ $(RM) $(REAL_LIBRARY)
+ $(AR) $(AR_FLAGS) $($@_OBJS)
+ $(call BUILDSTATUS,END_StaticLib $@)
+
+$(WASM_ARCHIVE): $(CWASMOBJS) $(CPPWASMOBJS) $(STATIC_LIBS) $(EXTRA_DEPS) $(GLOBAL_DEPS)
+ $(REPORT_BUILD_VERBOSE)
+ $(call BUILDSTATUS,START_WasmLib $@)
+ $(RM) $(WASM_ARCHIVE)
+ $(WASM_CXX) -o $@ -Wl,--export-all -Wl,--stack-first -Wl,-z,stack-size=$(if $(MOZ_OPTIMIZE),262144,1048576) -Wl,--no-entry -Wl,--import-memory -Wl,--import-table $(CWASMOBJS) $(CPPWASMOBJS) $(addprefix -l,$(WASM_LIBS))
+ $(call BUILDSTATUS,END_WasmLib $@)
+
+ifeq ($(OS_ARCH),WINNT)
+# Import libraries are created by the rules creating shared libraries.
+# The rules to copy them to $(DIST)/lib depend on $(IMPORT_LIBRARY),
+# but make will happily consider the import library before it is refreshed
+# when rebuilding the corresponding shared library. Defining an empty recipe
+# for import libraries forces make to wait for the shared library recipe to
+# have run before considering other targets that depend on the import library.
+# See bug 795204.
+$(IMPORT_LIBRARY): $(SHARED_LIBRARY) ;
+endif
+
+$(HOST_SHARED_LIBRARY): Makefile
+ $(REPORT_BUILD)
+ $(call BUILDSTATUS,START_SharedLib $@)
+ $(RM) $@
+ifneq (,$(filter clang-cl,$(HOST_CC_TYPE)))
+ $(HOST_LINKER) -DLL -OUT:$@ $($(notdir $@)_OBJS) $(HOST_CXX_LDFLAGS) $(HOST_LDFLAGS) $(HOST_LINKER_LIBPATHS) $(HOST_LIBS) $(HOST_EXTRA_LIBS)
+else
+ $(HOST_CXX) $(HOST_OUTOPTION)$@ $($(notdir $@)_OBJS) $(HOST_CXX_LDFLAGS) $(HOST_LDFLAGS) $(HOST_LIBS) $(HOST_EXTRA_LIBS)
+endif
+ $(call BUILDSTATUS,END_SharedLib $@)
+
+# On Darwin (Mac OS X), dwarf2 debugging uses debug info left in .o files,
+# so instead of deleting .o files after repacking them into a dylib, we make
+# symlinks back to the originals. The symlinks are a no-op for stabs debugging,
+# so no need to conditionalize on OS version or debugging format.
+
+$(SHARED_LIBRARY): $(OBJS) $(call resfile,$(SHARED_LIBRARY)) $(STATIC_LIBS) $(EXTRA_DEPS) $(GLOBAL_DEPS)
+ $(REPORT_BUILD)
+ $(call BUILDSTATUS,START_SharedLib $@)
+ $(RM) $@
+ $(MKSHLIB) $($@_OBJS) $(filter %.res,$^) $(RELRHACK_LDFLAGS) $(LDFLAGS) $(STATIC_LIBS) $(SHARED_LIBS) $(EXTRA_DSO_LDOPTS) $(MOZ_GLUE_LDFLAGS) $(OS_LIBS)
+ $(call py_action,check_binary,$@)
+
+ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH))
+endif # WINNT && !GCC
+ chmod +x $@
+ifdef ENABLE_STRIP
+ $(STRIP) $(STRIP_FLAGS) $@
+endif
+ $(call BUILDSTATUS,END_SharedLib $@)
+
+# The object file is in the current directory, and the source file can be any
+# relative path. This macro adds the dependency obj: src for each source file.
+# This dependency must be first for the $< flag to work correctly, and the
+# rules that have commands for these targets must not list any other
+# prerequisites, or they will override the $< variable.
+define src_objdep
+$(basename $3$(notdir $1)).$2: $1 $$(call mkdir_deps,$$(MDDEPDIR))
+endef
+$(foreach f,$(CSRCS) $(SSRCS) $(CPPSRCS) $(CMSRCS) $(CMMSRCS) $(ASFILES),$(eval $(call src_objdep,$(f),$(OBJ_SUFFIX))))
+$(foreach f,$(HOST_CSRCS) $(HOST_CPPSRCS) $(HOST_CMSRCS) $(HOST_CMMSRCS),$(eval $(call src_objdep,$(f),$(OBJ_SUFFIX),host_)))
+$(foreach f,$(WASM_CSRCS) $(WASM_CPPSRCS),$(eval $(call src_objdep,$(f),wasm)))
+
+# The Rust compiler only outputs library objects, and so we need different
+# mangling to generate dependency rules for it.
+mk_global_crate_libname = $(basename lib$(notdir $1)).$(LIB_SUFFIX)
+crate_src_libdep = $(call mk_global_crate_libname,$1): $1 $$(call mkdir_deps,$$(MDDEPDIR))
+$(foreach f,$(RS_STATICLIB_CRATE_SRC),$(eval $(call crate_src_libdep,$(f))))
+
+$(OBJS) $(HOST_OBJS) $(PROGOBJS) $(HOST_PROGOBJS): $(GLOBAL_DEPS)
+
+# Rules for building native targets must come first because of the host_ prefix
+$(HOST_COBJS):
+ $(REPORT_BUILD_VERBOSE)
+ $(call BUILDSTATUS,OBJECT_FILE $@)
+ $(HOST_CC) $(HOST_OUTOPTION)$@ -c $(HOST_CPPFLAGS) $(HOST_CFLAGS) $(NSPR_CFLAGS) $<
+ $(call BUILDSTATUS,END_Object $@)
+
+$(HOST_CPPOBJS):
+ $(REPORT_BUILD_VERBOSE)
+ $(call BUILDSTATUS,OBJECT_FILE $@)
+ $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CPPFLAGS) $(HOST_CXXFLAGS) $(NSPR_CFLAGS) $<
+ $(call BUILDSTATUS,END_Object $@)
+
+$(HOST_CMOBJS):
+ $(REPORT_BUILD_VERBOSE)
+ $(call BUILDSTATUS,OBJECT_FILE $@)
+ $(HOST_CC) $(HOST_OUTOPTION)$@ -c $(HOST_CPPFLAGS) $(HOST_CFLAGS) $(HOST_CMFLAGS) $(NSPR_CFLAGS) $<
+ $(call BUILDSTATUS,END_Object $@)
+
+$(HOST_CMMOBJS):
+ $(REPORT_BUILD_VERBOSE)
+ $(call BUILDSTATUS,OBJECT_FILE $@)
+ $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CPPFLAGS) $(HOST_CXXFLAGS) $(HOST_CMMFLAGS) $(NSPR_CFLAGS) $<
+ $(call BUILDSTATUS,END_Object $@)
+
+$(COBJS):
+ $(REPORT_BUILD_VERBOSE)
+ $(call BUILDSTATUS,OBJECT_FILE $@)
+ $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $($(notdir $<)_FLAGS) $<
+ $(call BUILDSTATUS,END_Object $@)
+
+$(CWASMOBJS):
+ $(REPORT_BUILD_VERBOSE)
+ $(call BUILDSTATUS,OBJECT_FILE $@)
+ $(WASM_CC) -o $@ -c $(WASM_CFLAGS) $($(notdir $<)_FLAGS) $<
+ $(call BUILDSTATUS,END_Object $@)
+
+WINEWRAP = $(if $(and $(filter %.exe,$1),$(WINE)),$(WINE) $1,$1)
+
+# Windows program run via Wine don't like Unix absolute paths (they look
+# like command line arguments). So when needed, create relative paths
+# from absolute paths. We start with $(DEPTH), which gets us to topobjdir,
+# then add "/.." for each component of topobjdir, which gets us to /.
+# then we can add the absolute path after that and we have a relative path,
+# albeit longer than it could be.
+ifdef WINE
+relativize = $(if $(filter /%,$1),$(DEPTH)$(subst $(space),,$(foreach d,$(subst /, ,$(topobjdir)),/..))$1,$1)
+else
+relativize = $1
+endif
+
+ifdef WINE
+# asmarm64 needs a library that can be found in $PATH but for some reason,
+# wine wants its path in $WINEPATH, so fill that to make it happy.
+$(ASOBJS) $(SOBJS): export WINEPATH=$(subst :,;,$(PATH))
+endif
+
+ifdef ASFILES
+# The AS_DASH_C_FLAG is needed cause not all assemblers (Solaris) accept
+# a '-c' flag.
+$(ASOBJS):
+ $(REPORT_BUILD_VERBOSE)
+ $(call BUILDSTATUS,OBJECT_FILE $@)
+ $(call WINEWRAP,$(AS)) $(ASOUTOPTION)$@ $(ASFLAGS) $($(notdir $<)_FLAGS) $(AS_DASH_C_FLAG) $(call relativize,$<)
+ $(call BUILDSTATUS,END_Object $@)
+endif
+
+define syms_template
+$(2): $(1)
+ifdef MOZ_CRASHREPORTER
+ $$(call py_action,dumpsymbols $$@,$$(abspath $$<) $$(abspath $$@) $$(DUMP_SYMBOLS_FLAGS))
+ifeq ($(OS_ARCH),WINNT)
+ifdef WINCHECKSEC
+ $$(PYTHON3) $$(topsrcdir)/build/win32/autowinchecksec.py $$<
+endif # WINCHECKSEC
+endif # WINNT
+endif
+endef
+
+ifneq (,$(filter $(DIST)/bin%,$(FINAL_TARGET)))
+DUMP_SYMS_TARGETS := $(SHARED_LIBRARY) $(PROGRAM) $(SIMPLE_PROGRAMS)
+endif
+
+ifdef MOZ_AUTOMATION
+ifeq (,$(filter 1,$(MOZ_AUTOMATION_BUILD_SYMBOLS)))
+DUMP_SYMS_TARGETS :=
+endif
+endif
+
+ifdef MOZ_COPY_PDBS
+MAIN_PDB_FILES = $(addsuffix .pdb,$(basename $(DUMP_SYMS_TARGETS)))
+MAIN_PDB_DEST ?= $(FINAL_TARGET)
+MAIN_PDB_TARGET = syms
+INSTALL_TARGETS += MAIN_PDB
+
+ifdef CPP_UNIT_TESTS
+CPP_UNIT_TESTS_PDB_FILES = $(addsuffix .pdb,$(basename $(CPP_UNIT_TESTS)))
+CPP_UNIT_TESTS_PDB_DEST = $(DIST)/cppunittests
+CPP_UNIT_TESTS_PDB_TARGET = syms
+INSTALL_TARGETS += CPP_UNIT_TESTS_PDB
+endif
+
+else ifdef MOZ_CRASHREPORTER
+$(foreach file,$(DUMP_SYMS_TARGETS),$(eval $(call syms_template,$(file),$(notdir $(file))_syms.track)))
+syms:: $(foreach file,$(DUMP_SYMS_TARGETS),$(notdir $(file))_syms.track)
+endif
+
+ifneq (,$(RUST_TESTS)$(RUST_LIBRARY_FILE)$(HOST_RUST_LIBRARY_FILE)$(RUST_PROGRAMS)$(HOST_RUST_PROGRAMS))
+include $(MOZILLA_DIR)/config/makefiles/rust.mk
+endif
+
+$(SOBJS):
+ $(REPORT_BUILD)
+ $(call WINEWRAP,$(AS)) $(ASOUTOPTION)$@ $(SFLAGS) $($(notdir $<)_FLAGS) -c $(call relativize,$<)
+
+$(CPPOBJS):
+ $(REPORT_BUILD_VERBOSE)
+ $(call BUILDSTATUS,OBJECT_FILE $@)
+ $(CCC) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS) $($(notdir $<)_FLAGS) $<
+ $(call BUILDSTATUS,END_Object $@)
+
+$(CPPWASMOBJS):
+ $(REPORT_BUILD_VERBOSE)
+ $(call BUILDSTATUS,OBJECT_FILE $@)
+ $(WASM_CXX) -o $@ -c $(WASM_CXXFLAGS) $($(notdir $<)_FLAGS) $<
+ $(call BUILDSTATUS,END_Object $@)
+
+$(CMMOBJS):
+ $(REPORT_BUILD_VERBOSE)
+ $(call BUILDSTATUS,OBJECT_FILE $@)
+ $(CCC) -o $@ -c $(COMPILE_CXXFLAGS) $(COMPILE_CMMFLAGS) $($(notdir $<)_FLAGS) $<
+ $(call BUILDSTATUS,END_Object $@)
+
+$(CMOBJS):
+ $(REPORT_BUILD_VERBOSE)
+ $(call BUILDSTATUS,OBJECT_FILE $@)
+ $(CC) -o $@ -c $(COMPILE_CFLAGS) $(COMPILE_CMFLAGS) $($(notdir $<)_FLAGS) $<
+ $(call BUILDSTATUS,END_Object $@)
+
+$(filter %.s,$(CPPSRCS:%.cpp=%.s)): %.s: %.cpp $(call mkdir_deps,$(MDDEPDIR))
+ $(REPORT_BUILD_VERBOSE)
+ $(CCC) -S $(COMPILE_CXXFLAGS) $($(notdir $<)_FLAGS) $<
+
+$(filter %.s,$(CPPSRCS:%.cc=%.s)): %.s: %.cc $(call mkdir_deps,$(MDDEPDIR))
+ $(REPORT_BUILD_VERBOSE)
+ $(CCC) -S $(COMPILE_CXXFLAGS) $($(notdir $<)_FLAGS) $<
+
+$(filter %.s,$(CPPSRCS:%.cxx=%.s)): %.s: %.cpp $(call mkdir_deps,$(MDDEPDIR))
+ $(REPORT_BUILD_VERBOSE)
+ $(CCC) -S $(COMPILE_CXXFLAGS) $($(notdir $<)_FLAGS) $<
+
+$(filter %.s,$(CSRCS:%.c=%.s)): %.s: %.c $(call mkdir_deps,$(MDDEPDIR))
+ $(REPORT_BUILD_VERBOSE)
+ $(CC) -S $(COMPILE_CFLAGS) $($(notdir $<)_FLAGS) $<
+
+ifneq (,$(filter %.i,$(MAKECMDGOALS)))
+# Call as $(call _group_srcs,extension,$(SRCS)) - this will create a list
+# of the full sources, as well as the $(notdir) version. So:
+# foo.cpp sub/bar.cpp
+# becomes:
+# foo.cpp sub/bar.cpp bar.cpp
+#
+# This way we can match both 'make sub/bar.i' and 'make bar.i'
+_group_srcs = $(sort $(patsubst %.$1,%.i,$(filter %.$1,$2 $(notdir $2))))
+
+define PREPROCESS_RULES
+_PREPROCESSED_$1_FILES := $$(call _group_srcs,$1,$$($2))
+# Make preprocessed files PHONY so they are always executed, since they are
+# manual targets and we don't necessarily write to $@.
+.PHONY: $$(_PREPROCESSED_$1_FILES)
+
+# Hack up VPATH so we can reach the sources. Eg: 'make Parser.i' may need to
+# reach $(srcdir)/frontend/Parser.i
+vpath %.$1 $$(addprefix $$(srcdir)/,$$(sort $$(dir $$($2))))
+vpath %.$1 $$(addprefix $$(CURDIR)/,$$(sort $$(dir $$($2))))
+
+$$(_PREPROCESSED_$1_FILES): _DEPEND_CFLAGS=
+$$(_PREPROCESSED_$1_FILES): %.i: %.$1
+ $$(REPORT_BUILD_VERBOSE)
+ $$(addprefix $$(MKDIR) -p ,$$(filter-out .,$$(@D)))
+ $$($3) -C $$(PREPROCESS_OPTION)$$@ $(foreach var,$4,$$($(var))) $$($$(notdir $$<)_FLAGS) $$<
+
+endef
+
+$(eval $(call PREPROCESS_RULES,cpp,CPPSRCS,CCC,COMPILE_CXXFLAGS))
+$(eval $(call PREPROCESS_RULES,cc,CPPSRCS,CCC,COMPILE_CXXFLAGS))
+$(eval $(call PREPROCESS_RULES,cxx,CPPSRCS,CCC,COMPILE_CXXFLAGS))
+$(eval $(call PREPROCESS_RULES,c,CSRCS,CC,COMPILE_CFLAGS))
+$(eval $(call PREPROCESS_RULES,mm,CMMSRCS,CCC,COMPILE_CXXFLAGS COMPILE_CMMFLAGS))
+
+# Default to pre-processing the actual unified file. This can be overridden
+# at the command-line to pre-process only the individual source file.
+PP_UNIFIED ?= 1
+
+# PP_REINVOKE gets set on the sub-make to prevent us from going in an
+# infinite loop if the filename doesn't exist in the unified source files.
+ifndef PP_REINVOKE
+
+MATCH_cpp = \(cpp\|cc|cxx\)
+UPPER_c = C
+UPPER_cpp = CPP
+UPPER_mm = CMM
+
+# When building with PP_UNIFIED=0, we also have to look in the Unified files to
+# find a matching pathname.
+_get_all_sources = $1 $(if $(filter Unified%,$1),$(shell sed -n 's/\#include "\(.*\)"$$/\1/p' $(filter Unified%,$1)))
+all_cpp_sources := $(call _get_all_sources,$(CPPSRCS))
+all_mm_sources := $(call _get_all_sources,$(CMMSRCS))
+all_c_sources := $(call _get_all_sources,$(CSRCS))
+all_sources := $(all_cpp_sources) $(all_cmm_sources) $(all_c_sources)
+
+# The catch-all %.i rule runs when we pass in a .i filename that doesn't match
+# one of the *SRCS variables. The two code paths depend on whether or not
+# we are requesting a unified file (PP_UNIFIED=1, the default) or not:
+#
+# PP_UNIFIED=1:
+# - Look for it in any of the Unified files, and re-exec make with
+# Unified_foo0.i as the target. This gets us the full unified preprocessed
+# file.
+#
+# PP_UNIFIED=0:
+# - If the .i filename is in *SRCS, or in a Unified filename, then we re-exec
+# make with that filename as the target. The *SRCS variables are modified
+# to have the Unified sources appended to them so that the static pattern
+# rules will match.
+%.i: FORCE
+ifeq ($(PP_UNIFIED),1)
+ @$(MAKE) PP_REINVOKE=1 \
+ $(or $(addsuffix .i, \
+ $(foreach type,c cpp mm, \
+ $(if $(filter Unified%,$($(UPPER_$(type))SRCS)), \
+ $(shell grep -l '#include "\(.*/\)\?$(basename $@).$(or $(MATCH_$(type)),$(type))"' Unified*.$(type) | sed 's/\.$(type)$$//') \
+ ))),$(error "File not found for preprocessing: $@"))
+else
+ @$(MAKE) PP_REINVOKE=1 $@ \
+ $(foreach type,c cpp mm,$(UPPER_$(type))SRCS="$(all_$(type)_sources)")
+endif
+
+endif
+
+endif
+
+# EXTRA_DEPS contains manifests (manually added in Makefile.in ; bug 1498414)
+%.res: $(or $(RCFILE),%.rc) $(MOZILLA_DIR)/config/create_res.py $(EXTRA_DEPS)
+ $(REPORT_BUILD)
+ $(call BUILDSTATUS,START_Res $@)
+ $(PYTHON3) $(MOZILLA_DIR)/config/create_res.py $(DEFINES) $(INCLUDES) -o $@ $<
+ $(call BUILDSTATUS,END_Res $@)
+
+$(notdir $(addsuffix .rc,$(PROGRAM) $(SHARED_LIBRARY) $(SIMPLE_PROGRAMS) module)): %.rc: $(RCINCLUDE) $(MOZILLA_DIR)/config/create_rc.py
+ $(call BUILDSTATUS,START_Rc $@)
+ $(PYTHON3) $(MOZILLA_DIR)/config/create_rc.py '$(if $(filter module,$*),,$*)' '$(RCINCLUDE)'
+ $(call BUILDSTATUS,END_Rc $@)
+
+# Cancel GNU make built-in implicit rules
+MAKEFLAGS += -r
+
+ifneq (,$(filter WINNT,$(OS_ARCH)))
+SEP := ;
+else
+SEP := :
+endif
+
+EMPTY :=
+SPACE := $(EMPTY) $(EMPTY)
+
+###############################################################################
+# Bunch of things that extend the 'export' rule (in order):
+###############################################################################
+
+ifneq ($(XPI_NAME),)
+$(FINAL_TARGET):
+ $(NSINSTALL) -D $@
+
+export:: $(FINAL_TARGET)
+endif
+
+################################################################################
+# The default location for prefs is the gre prefs directory.
+# PREF_DIR is used for L10N_PREF_JS_EXPORTS in various locales/ directories.
+PREF_DIR = defaults/pref
+
+# If DIST_SUBDIR is defined it indicates that app and gre dirs are
+# different and that we are building app related resources. Hence,
+# PREF_DIR should point to the app prefs location.
+ifneq (,$(DIST_SUBDIR)$(XPI_NAME))
+PREF_DIR = defaults/preferences
+endif
+
+################################################################################
+# CHROME PACKAGING
+
+chrome::
+ $(MAKE) realchrome
+ $(LOOP_OVER_DIRS)
+
+$(FINAL_TARGET)/chrome: $(call mkdir_deps,$(FINAL_TARGET)/chrome)
+
+ifneq (,$(JAR_MANIFEST))
+ifndef NO_DIST_INSTALL
+
+ifdef XPI_NAME
+ifdef XPI_ROOT_APPID
+# For add-on packaging we may specify that an application
+# sub-dir should be added to the root chrome manifest with
+# a specific application id.
+MAKE_JARS_FLAGS += --root-manifest-entry-appid='$(XPI_ROOT_APPID)'
+endif
+
+# if DIST_SUBDIR is defined but XPI_ROOT_APPID is not there's
+# no way langpacks will get packaged right, so error out.
+ifneq (,$(DIST_SUBDIR))
+ifndef XPI_ROOT_APPID
+$(error XPI_ROOT_APPID is not defined - langpacks will break.)
+endif
+endif
+endif
+
+misc realchrome:: $(FINAL_TARGET)/chrome
+ $(call py_action,jar_maker $(subst $(topsrcdir)/,,$(JAR_MANIFEST)),\
+ $(QUIET) -d $(FINAL_TARGET) \
+ $(MAKE_JARS_FLAGS) $(DEFINES) $(ACDEFINES) \
+ $(JAR_MANIFEST))
+
+ifdef AB_CD
+.PHONY: l10n
+l10n: misc ;
+endif
+endif
+
+endif
+
+# When you move this out of the tools tier, please remove the corresponding
+# hacks in recursivemake.py that check if Makefile.in sets the variable.
+ifneq ($(XPI_PKGNAME),)
+tools realchrome::
+ @echo 'Packaging $(XPI_PKGNAME).xpi...'
+ $(call py_action,zip $(XPI_PKGNAME).xpi,-C $(FINAL_TARGET) ../$(XPI_PKGNAME).xpi '*')
+endif
+
+#############################################################################
+# MDDEPDIR is the subdirectory where all the dependency files are placed.
+# This uses a make rule (instead of a macro) to support parallel
+# builds (-jN). If this were done in the LOOP_OVER_DIRS macro, two
+# processes could simultaneously try to create the same directory.
+#
+# We use $(CURDIR) in the rule's target to ensure that we don't find
+# a dependency directory in the source tree via VPATH (perhaps from
+# a previous build in the source tree) and thus neglect to create a
+# dependency directory in the object directory, where we really need
+# it.
+
+_MDDEPEND_FILES :=
+
+ifneq (,$(filter target-objects target all default,$(MAKECMDGOALS)))
+_MDDEPEND_FILES += $(addsuffix .pp,$(notdir $(sort $(OBJS) $(PROGOBJS))))
+endif
+
+ifneq (,$(filter host-objects host all default,$(MAKECMDGOALS)))
+_MDDEPEND_FILES += $(addsuffix .pp,$(notdir $(sort $(HOST_OBJS) $(HOST_PROGOBJS))))
+endif
+
+MDDEPEND_FILES := $(strip $(wildcard $(addprefix $(MDDEPDIR)/,$(_MDDEPEND_FILES))))
+MDDEPEND_FILES += $(EXTRA_MDDEPEND_FILES)
+
+ifneq (,$(MDDEPEND_FILES))
+-include $(MDDEPEND_FILES)
+endif
+
+################################################################################
+# Install/copy rules
+#
+# The INSTALL_TARGETS variable contains a list of all install target
+# categories. Each category defines a list of files and executables, and an
+# install destination,
+#
+# FOO_FILES := foo bar
+# FOO_EXECUTABLES := baz
+# FOO_DEST := target_path
+# INSTALL_TARGETS += FOO
+#
+# Additionally, a FOO_TARGET variable may be added to indicate the target for
+# which the files and executables are installed. Default is "libs".
+#
+# Finally, a FOO_KEEP_PATH variable may be set to 1 to indicate the paths given
+# in FOO_FILES/FOO_EXECUTABLES are to be kept at the destination. That is,
+# if FOO_FILES is bar/baz/qux.h, and FOO_DEST is $(DIST)/include, the installed
+# file would be $(DIST)/include/bar/baz/qux.h instead of $(DIST)/include/qux.h
+
+# If we're using binary nsinstall and it's not built yet, fallback to python nsinstall.
+ifneq (,$(filter $(DEPTH)/config/nsinstall$(HOST_BIN_SUFFIX),$(install_cmd)))
+ifeq (,$(wildcard $(DEPTH)/config/nsinstall$(HOST_BIN_SUFFIX)))
+nsinstall_is_usable = $(if $(wildcard $(DEPTH)/config/nsinstall$(HOST_BIN_SUFFIX)),yes)
+
+define install_cmd_override
+$(1): install_cmd = $$(if $$(nsinstall_is_usable),$$(INSTALL),$$(NSINSTALL_PY) -t) $$(1)
+endef
+endif
+endif
+
+install_target_tier = $(or $($(1)_TARGET),libs)
+INSTALL_TARGETS_TIERS := $(sort $(foreach category,$(INSTALL_TARGETS),$(call install_target_tier,$(category))))
+
+install_target_result = $($(1)_DEST:%/=%)/$(if $($(1)_KEEP_PATH),$(2),$(notdir $(2)))
+install_target_files = $(foreach file,$($(1)_FILES),$(call install_target_result,$(category),$(file)))
+install_target_executables = $(foreach file,$($(1)_EXECUTABLES),$(call install_target_result,$(category),$(file)))
+
+# Work around a GNU make 3.81 bug where it gives $< the wrong value.
+# See details in bug 934864.
+define create_dependency
+$(1): $(2)
+$(1): $(2)
+endef
+
+define install_target_template
+$(call install_cmd_override,$(2))
+$(call create_dependency,$(2),$(1))
+endef
+
+$(foreach category,$(INSTALL_TARGETS),\
+ $(if $($(category)_DEST),,$(error Missing $(category)_DEST)) \
+ $(foreach tier,$(call install_target_tier,$(category)),\
+ $(eval INSTALL_TARGETS_FILES_$(tier) += $(call install_target_files,$(category))) \
+ $(eval INSTALL_TARGETS_EXECUTABLES_$(tier) += $(call install_target_executables,$(category))) \
+ ) \
+ $(foreach file,$($(category)_FILES) $($(category)_EXECUTABLES), \
+ $(eval $(call install_target_template,$(file),$(call install_target_result,$(category),$(file)))) \
+ ) \
+)
+
+$(foreach tier,$(INSTALL_TARGETS_TIERS), \
+ $(eval $(if $(filter .,$(DEPTH)),recurse_$(tier):,$(tier)::) $(INSTALL_TARGETS_FILES_$(tier)) $(INSTALL_TARGETS_EXECUTABLES_$(tier))) \
+)
+
+install_targets_sanity = $(if $(filter-out $(notdir $@),$(notdir $(<))),$(error Looks like $@ has an unexpected dependency on $< which breaks INSTALL_TARGETS))
+
+$(sort $(foreach tier,$(INSTALL_TARGETS_TIERS),$(INSTALL_TARGETS_FILES_$(tier)))):
+ $(install_targets_sanity)
+ $(call BUILDSTATUS,START_Install $@)
+ $(call install_cmd,$(IFLAGS1) '$<' '$(@D)')
+ $(call BUILDSTATUS,END_Install $@)
+
+$(sort $(foreach tier,$(INSTALL_TARGETS_TIERS),$(INSTALL_TARGETS_EXECUTABLES_$(tier)))):
+ $(install_targets_sanity)
+ $(call BUILDSTATUS,START_Install $@)
+ $(call install_cmd,$(IFLAGS2) '$<' '$(@D)')
+ $(call BUILDSTATUS,END_Install $@)
+
+################################################################################
+# Preprocessing rules
+#
+# The PP_TARGETS variable contains a list of all preprocessing target
+# categories. Each category has associated variables listing input files, the
+# output directory, extra preprocessor flags, and so on. For example:
+#
+# FOO := input-file
+# FOO_PATH := target-directory
+# FOO_FLAGS := -Dsome_flag
+# PP_TARGETS += FOO
+#
+# If PP_TARGETS lists a category name <C> (like FOO, above), then we consult the
+# following make variables to see what to do:
+#
+# - <C> lists input files to be preprocessed with mozbuild.action.preprocessor.
+# We search VPATH for the names given here. If an input file name ends in
+# '.in', that suffix is omitted from the output file name.
+#
+# - <C>_PATH names the directory in which to place the preprocessed output
+# files. We create this directory if it does not already exist. Setting
+# this variable is optional; if unset, we install the files in $(CURDIR).
+#
+# - <C>_FLAGS lists flags to pass to mozbuild.action.preprocessor, in addition
+# to the usual bunch. Setting this variable is optional.
+#
+# - <C>_TARGET names the 'make' target that should depend on creating the output
+# files. Setting this variable is optional; if unset, we preprocess the
+# files for the 'libs' target.
+#
+# - <C>_KEEP_PATH may be set to 1 to indicate the paths given in <C> are to be
+# kept under <C>_PATH. That is, if <C> is bar/baz/qux.h.in and <C>_PATH is
+# $(DIST)/include, the preprocessed file would be $(DIST)/include/bar/baz/qux.h
+# instead of $(DIST)/include/qux.h.
+
+pp_target_tier = $(or $($(1)_TARGET),libs)
+PP_TARGETS_TIERS := $(sort $(foreach category,$(PP_TARGETS),$(call pp_target_tier,$(category))))
+
+pp_target_result = $(or $($(1)_PATH:%/=%),$(CURDIR))/$(if $($(1)_KEEP_PATH),$(2:.in=),$(notdir $(2:.in=)))
+pp_target_results = $(foreach file,$($(1)),$(call pp_target_result,$(category),$(file)))
+
+$(foreach category,$(PP_TARGETS), \
+ $(foreach tier,$(call pp_target_tier,$(category)), \
+ $(eval PP_TARGETS_RESULTS_$(tier) += $(call pp_target_results,$(category))) \
+ ) \
+ $(foreach file,$($(category)), \
+ $(eval $(call create_dependency,$(call pp_target_result,$(category),$(file)), \
+ $(file) $(GLOBAL_DEPS))) \
+ ) \
+ $(eval $(call pp_target_results,$(category)): PP_TARGET_FLAGS=$($(category)_FLAGS)) \
+)
+
+$(foreach tier,$(PP_TARGETS_TIERS), \
+ $(eval $(if $(filter .,$(DEPTH)),recurse_$(tier):,$(tier)::) $(PP_TARGETS_RESULTS_$(tier))) \
+)
+
+PP_TARGETS_ALL_RESULTS := $(sort $(foreach tier,$(PP_TARGETS_TIERS),$(PP_TARGETS_RESULTS_$(tier))))
+$(PP_TARGETS_ALL_RESULTS):
+ $(if $(filter-out $(notdir $@),$(notdir $(<:.in=))),$(error Looks like $@ has an unexpected dependency on $< which breaks PP_TARGETS))
+ $(RM) '$@'
+ $(call py_action,preprocessor $(@F),--depend $(MDDEPDIR)/$(@F).pp $(PP_TARGET_FLAGS) $(DEFINES) $(ACDEFINES) '$<' -o '$@')
+
+$(filter %.css,$(PP_TARGETS_ALL_RESULTS)): PP_TARGET_FLAGS+=--marker %
+
+# The depfile is based on the filename, and we don't want conflicts. So check
+# there's only one occurrence of any given filename in PP_TARGETS_ALL_RESULTS.
+PP_TARGETS_ALL_RESULT_NAMES := $(notdir $(PP_TARGETS_ALL_RESULTS))
+$(foreach file,$(sort $(PP_TARGETS_ALL_RESULT_NAMES)), \
+ $(if $(filter-out 1,$(words $(filter $(file),$(PP_TARGETS_ALL_RESULT_NAMES)))), \
+ $(error Multiple preprocessing rules are creating a $(file) file) \
+ ) \
+)
+
+ifneq (,$(filter $(PP_TARGETS_TIERS) $(PP_TARGETS_ALL_RESULTS),$(MAKECMDGOALS)))
+# If the depfile for a preprocessed file doesn't exist, add a dep to force
+# re-preprocessing.
+$(foreach file,$(PP_TARGETS_ALL_RESULTS), \
+ $(if $(wildcard $(MDDEPDIR)/$(notdir $(file)).pp), \
+ , \
+ $(eval $(file): FORCE) \
+ ) \
+)
+
+MDDEPEND_FILES := $(strip $(wildcard $(addprefix $(MDDEPDIR)/,$(addsuffix .pp,$(notdir $(PP_TARGETS_ALL_RESULTS))))))
+
+ifneq (,$(MDDEPEND_FILES))
+-include $(MDDEPEND_FILES)
+endif
+
+endif
+
+# Pull in non-recursive targets if this is a partial tree build.
+ifndef TOPLEVEL_BUILD
+include $(MOZILLA_DIR)/config/makefiles/nonrecursive.mk
+endif
+
+################################################################################
+# Special gmake rules.
+################################################################################
+
+
+#
+# Re-define the list of default suffixes, so gmake won't have to churn through
+# hundreds of built-in suffix rules for stuff we don't need.
+#
+.SUFFIXES:
+
+#
+# Fake targets. Always run these rules, even if a file/directory with that
+# name already exists.
+#
+.PHONY: all alltags boot chrome realchrome export install libs makefiles run_apprunner tools $(DIRS) FORCE
+
+# Used as a dependency to force targets to rebuild
+FORCE:
+
+# Delete target if error occurs when building target
+.DELETE_ON_ERROR:
+
+tags: TAGS
+
+TAGS: $(CSRCS) $(CPPSRCS) $(wildcard *.h)
+ -etags $(CSRCS) $(CPPSRCS) $(wildcard *.h)
+ $(LOOP_OVER_DIRS)
+
+ifndef INCLUDED_DEBUGMAKE_MK #{
+ ## Only parse when an echo* or show* target is requested
+ ifneq (,$(call isTargetStem,echo,show))
+ include $(MOZILLA_DIR)/config/makefiles/debugmake.mk
+ endif #}
+endif #}
+
+FREEZE_VARIABLES = \
+ CSRCS \
+ CPPSRCS \
+ EXPORTS \
+ DIRS \
+ LIBRARY \
+ MODULE \
+ $(NULL)
+
+$(foreach var,$(FREEZE_VARIABLES),$(eval $(var)_FROZEN := '$($(var))'))
+
+CHECK_FROZEN_VARIABLES = $(foreach var,$(FREEZE_VARIABLES), \
+ $(if $(subst $($(var)_FROZEN),,'$($(var))'),$(error Makefile variable '$(var)' changed value after including rules.mk. Was $($(var)_FROZEN), now $($(var)).)))
+
+libs export::
+ $(CHECK_FROZEN_VARIABLES)
+
+.DEFAULT_GOAL := $(or $(OVERRIDE_DEFAULT_GOAL),default)
+
+#############################################################################
+# Derived targets and dependencies
+
+include $(MOZILLA_DIR)/config/makefiles/autotargets.mk
+ifneq ($(NULL),$(AUTO_DEPS))
+ default all libs tools export:: $(AUTO_DEPS)
+endif
diff --git a/config/run-and-prefix.py b/config/run-and-prefix.py
new file mode 100644
index 0000000000..af27e6743b
--- /dev/null
+++ b/config/run-and-prefix.py
@@ -0,0 +1,36 @@
+#!/usr/bin/env 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/.
+
+# This script runs a process and prefixes its output with.
+# Usage: run-and-prefix.py prefix command arg0 argv1...
+
+import os
+import subprocess
+import sys
+
+sys.stdout = os.fdopen(sys.stdout.fileno(), "wb", 0)
+sys.stderr = os.fdopen(sys.stderr.fileno(), "wb", 0)
+
+prefix = sys.argv[1].encode("utf-8")
+args = sys.argv[2:]
+
+p = subprocess.Popen(
+ args,
+ bufsize=0,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ stdin=sys.stdin.fileno(),
+ close_fds=False,
+)
+
+while True:
+ data = p.stdout.readline()
+
+ if data == b"":
+ break
+
+ sys.stdout.write(b"%s> %s" % (prefix, data))
+
+sys.exit(p.wait())
diff --git a/config/run_spidermonkey_checks.py b/config/run_spidermonkey_checks.py
new file mode 100644
index 0000000000..1d7ed98af3
--- /dev/null
+++ b/config/run_spidermonkey_checks.py
@@ -0,0 +1,15 @@
+# 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/.
+
+import subprocess
+import sys
+
+import buildconfig
+
+
+def main(output, lib_file, *scripts):
+ for script in scripts:
+ retcode = subprocess.call([sys.executable, script], cwd=buildconfig.topsrcdir)
+ if retcode != 0:
+ raise Exception(script + " failed")
diff --git a/config/shlwapi-h-constant.decls.h b/config/shlwapi-h-constant.decls.h
new file mode 100644
index 0000000000..494a5a7dd7
--- /dev/null
+++ b/config/shlwapi-h-constant.decls.h
@@ -0,0 +1,23 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* 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/. */
+
+/*
+ * This file contains a series of C-style declarations for constants defined in
+ * shlwapi.h using #define. Adding a new constant should be a simple as adding
+ * its name (and optionally type) to this file.
+ *
+ * This file is processed by make-windows-h-wrapper.py to generate a wrapper for
+ * the header which removes the defines usually implementing these constants.
+ *
+ * Wrappers defined in this file will be declared as `constexpr` values,
+ * and will have their value derived from the windows.h define.
+ *
+ * NOTE: This is *NOT* a real C header, but rather an input to the avove script.
+ * Only basic declarations in the form found here are allowed.
+ */
+
+// XXX(glandium): We don't have any here, because they don't look like they
+// could cause problems.
diff --git a/config/shlwapi-h-unicode.decls.h b/config/shlwapi-h-unicode.decls.h
new file mode 100644
index 0000000000..17c2ab6eac
--- /dev/null
+++ b/config/shlwapi-h-unicode.decls.h
@@ -0,0 +1,24 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* 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/. */
+
+/*
+ * This file contains a series of C-style function prototypes for A/W-suffixed
+ * Win32 APIs defined by shlwapi.h.
+ *
+ * This file is processed by make-windows-h-wrapper.py to generate a wrapper for
+ * the header which removes the defines usually implementing these aliases.
+ *
+ * Wrappers defined in this file will have the 'stdcall' calling convention,
+ * will be defined as 'inline', and will only be defined if the corresponding
+ * #define directive has not been #undef-ed.
+ *
+ * NOTE: This is *NOT* a real C header, but rather an input to the avove script.
+ * Only basic declarations in the form found here are allowed.
+ */
+
+// XXX(glandium): there are a ton more, but this is the one that is causing
+// immediate problems.
+HRESULT GetAcceptLanguages(LPTSTR, DWORD*);
diff --git a/config/shlwapi-h-wrapper.template.h b/config/shlwapi-h-wrapper.template.h
new file mode 100644
index 0000000000..289a755549
--- /dev/null
+++ b/config/shlwapi-h-wrapper.template.h
@@ -0,0 +1,43 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* 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/. */
+
+#ifndef mozilla_shlwapi_h
+#define mozilla_shlwapi_h
+
+// Include the "real" shlwapi.h header.
+//
+// Also turn off deprecation warnings, as we may be wrapping deprecated fns.
+
+#pragma GCC system_header
+#include_next <shlwapi.h>
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+
+// Check if the header should be disabled
+#if defined(MOZ_DISABLE_WINDOWS_WRAPPER)
+# define MOZ_WINDOWS_WRAPPER_DISABLED_REASON "explicitly disabled"
+
+#elif !defined(__cplusplus)
+# define MOZ_WINDOWS_WRAPPER_DISABLED_REASON "non-C++ source file"
+
+#else
+// We're allowed to wrap in the current context. Define `MOZ_WRAPPED_SHLWAPI_H`
+// to note that fact, and perform the wrapping.
+# define MOZ_WRAPPED_SHLWAPI_H
+extern "C++" {
+
+// clang-format off
+${decls}
+// clang-format on
+
+} // extern "C++"
+
+#endif // enabled
+
+#pragma GCC diagnostic pop
+
+#endif // !defined(mozilla_shlwapi_h)
diff --git a/config/static-checking-config.mk b/config/static-checking-config.mk
new file mode 100644
index 0000000000..95884d5979
--- /dev/null
+++ b/config/static-checking-config.mk
@@ -0,0 +1,21 @@
+# 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/.
+
+# The entire tree should be subject to static analysis using the XPCOM
+# script. Additional scripts may be added by specific subdirectories.
+
+ifdef ENABLE_CLANG_PLUGIN
+# Replace "clang-cl.exe" to "clang.exe --driver-mode=cl" to avoid loading the
+# module clang.exe again when load the plugin dll, which links to the import
+# library of clang.exe.
+# Likewise with "clang++.exe", replacing it with "clang.exe --driver-mode=g++",
+# when building .wasm files from source (we do need to keep clang++ when
+# building $(WASM_ARCHIVE)). Note we'd normally use $(CPPWASMOBJS), but it's
+# not defined yet when this file is included.
+ifeq ($(OS_ARCH),WINNT)
+CC := $(subst clang-cl.exe,clang.exe --driver-mode=cl,$(CC:.EXE=.exe))
+CXX := $(subst clang-cl.exe,clang.exe --driver-mode=cl,$(CXX:.EXE=.exe))
+$(notdir $(addsuffix .$(WASM_OBJ_SUFFIX),$(basename $(WASM_CPPSRCS)))): WASM_CXX := $(subst clang++.exe,clang.exe --driver-mode=g++,$(WASM_CXX:.EXE=.exe))
+endif
+endif
diff --git a/config/stl-headers.mozbuild b/config/stl-headers.mozbuild
new file mode 100644
index 0000000000..ffa8a8cc32
--- /dev/null
+++ b/config/stl-headers.mozbuild
@@ -0,0 +1,60 @@
+# -*- 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/.
+
+# This list contains the of STL headers that have been reviewed for exception
+# safety and approved. See
+#
+# https://bugzilla.mozilla.org/show_bug.cgi?id=551254
+#
+# At build time, each header listed here is converted into a "wrapper
+# header" that is installed into dist/stl_includes.
+#
+# If you would like to request a new STL header <foo> be added, please
+# file a Core:XPCOM bug with a title like "STL: Review exception
+# safety of <foo> for gcc and MSVC".
+stl_headers = [
+ "new",
+ # FIXME: these headers haven't been reviewed yet, but we use them
+ # unsafely in Gecko, so we might as well prevent them from
+ # throwing exceptions
+ "algorithm",
+ "atomic",
+ "cassert",
+ "climits",
+ "cmath",
+ "condition_variable",
+ "cstdarg",
+ "cstdio",
+ "cstdlib",
+ "cstring",
+ "cwchar",
+ "deque",
+ "functional",
+ "ios",
+ "iosfwd",
+ "iostream",
+ "istream",
+ "iterator",
+ "limits",
+ "list",
+ "map",
+ "memory",
+ "mutex",
+ "ostream",
+ "regex",
+ "set",
+ "shared_mutex",
+ "stack",
+ "string",
+ "thread",
+ "tuple",
+ "type_traits",
+ "unordered_map",
+ "unordered_set",
+ "utility",
+ "vector",
+ "xutility",
+]
diff --git a/config/system-headers.mozbuild b/config/system-headers.mozbuild
new file mode 100644
index 0000000000..0c06f581b3
--- /dev/null
+++ b/config/system-headers.mozbuild
@@ -0,0 +1,1373 @@
+# -*- 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/.
+
+system_headers = [
+ "A4Stuff.h",
+ "activscp.h",
+ "AEDataModel.h",
+ "AEObjects.h",
+ "AEPackObject.h",
+ "AERegistry.h",
+ "AEUtils.h",
+ "afxcmn.h",
+ "afxcoll.h",
+ "afxcview.h",
+ "afxdisp.h",
+ "afxdtctl.h",
+ "afxext.h",
+ "afxmt.h",
+ "afxpriv.h",
+ "afxtempl.h",
+ "afxwin.h",
+ "Aliases.h",
+ "all.h",
+ "alloca.h",
+ "alloc.h",
+ "alsa/asoundlib.h",
+ "ansi_parms.h",
+ "a.out.h",
+ "app/Cursor.h",
+ "Appearance.h",
+ "AppFileInfo.h",
+ "AppKit.h",
+ "AppleEvents.h",
+ "Application.h",
+ "app/Message.h",
+ "app/MessageRunner.h",
+ "arpa/inet.h",
+ "arpa/nameser.h",
+ "array",
+ "asm/page.h",
+ "asm/sigcontext.h",
+ "asm/signal.h",
+ "ASRegistry.h",
+ "assert.h",
+ "atk/atk.h",
+ "atlcom.h",
+ "atlconv.h",
+ "atlctl.cpp",
+ "atlctl.h",
+ "ATLCTL.H",
+ "atlhost.h",
+ "atlimpl.cpp",
+ "atlwin.cpp",
+ "atomic.h",
+ "ATSTypes.h",
+ "ATSUnicode.h",
+ "Balloons.h",
+ "base64.h",
+ "base/pblock.h",
+ "base/PCR_Base.h",
+ "base/session.h",
+ "basetyps.h",
+ "be/app/Application.h",
+ "Beep.h",
+ "be/kernel/image.h",
+ "be/kernel/OS.h",
+ "bfd.h",
+ "Bitmap.h",
+ "bitset",
+ "blapi.h",
+ "blapit.h",
+ "bsd/libc.h",
+ "bsd/syscall.h",
+ "bstring.h",
+ "builtin.h",
+ "Button.h",
+ "byteswap.h",
+ "cairo-atsui.h",
+ "cairo-beos.h",
+ "cairo-directfb.h",
+ "cairo-ft.h",
+ "cairo-glitz.h",
+ "cairo-gobject.h",
+ "cairo.h",
+ "cairo-pdf.h",
+ "cairo-ps.h",
+ "cairo-qpainter.h",
+ "cairo-qt.h",
+ "cairo-quartz.h",
+ "cairo-tee.h",
+ "cairo-win32.h",
+ "cairo-xlib.h",
+ "cairo-xlib-xrender.h",
+ "callconv.h",
+ "Carbon/Carbon.h",
+ "CarbonEvents.h",
+ "Carbon.h",
+ "c_asm.h",
+ "cctype",
+ "cderr.h",
+ "cerrno",
+ "certdb.h",
+ "cert.h",
+ "certt.h",
+ "CFBase.h",
+ "CFBundle.h",
+ "CFData.h",
+ "CFDictionary.h",
+ "cf.h",
+ "CFNumber.h",
+ "CFPlugIn.h",
+ "CFPreferences.h",
+ "CFString.h",
+ "CFURL.h",
+ "CGAffineTransform.h",
+ "CheckBox.h",
+ "ciferfam.h",
+ "Clipboard.h",
+ "cmmf.h",
+ "cmmft.h",
+ "cmplrs/stsupport.h",
+ "cms.h",
+ "cmsreclist.h",
+ "cmst.h",
+ "Cocoa/Cocoa.h",
+ "CodeFragments.h",
+ "comdef.h",
+ "commctrl.h",
+ "COMMCTRL.H",
+ "commdlg.h",
+ "compat.h",
+ "complex",
+ "condapi.h",
+ "ConditionalMacros.h",
+ "conio.h",
+ "console.h",
+ "ControlDefinitions.h",
+ "Controls.h",
+ "CoreFoundation/CoreFoundation.h",
+ "CoreServices/CoreServices.h",
+ "CPalmRec.cpp",
+ "Cpalmrec.h",
+ "CPCatgry.cpp",
+ "CPDbBMgr.h",
+ "CPString.cpp",
+ "CPString.h",
+ "crtdbg.h",
+ "crt_externs.h",
+ "crypt.h",
+ "cryptohi.h",
+ "cryptoht.h",
+ "cstddef",
+ "ctime",
+ "ctype.h",
+ "curl/curl.h",
+ "curl/easy.h",
+ "curses.h",
+ "cxxabi.h",
+ "DateTimeUtils.h",
+ "dbus/dbus.h",
+ "ddeml.h",
+ "Debug.h",
+ "dem.h",
+ "descrip.h",
+ "Devices.h",
+ "dfb_types.h",
+ "dfiff.h",
+ "dgiff.h",
+ "Dialogs.h",
+ "direct/build.h",
+ "direct/clock.h",
+ "direct/conf.h",
+ "direct/debug.h",
+ "direct/direct.h",
+ "directfb_keyboard.h",
+ "directfb_strings.h",
+ "direct.h",
+ "direct/hash.h",
+ "direct/interface.h",
+ "direct/interface_implementation.h",
+ "direct/list.h",
+ "direct/log.h",
+ "direct/memcpy.h",
+ "direct/mem.h",
+ "direct/messages.h",
+ "direct/modules.h",
+ "direct/serial.h",
+ "direct/signals.h",
+ "direct/stream.h",
+ "direct/system.h",
+ "direct/thread.h",
+ "direct/trace.h",
+ "direct/tree.h",
+ "direct/types.h",
+ "direct/utf8.h",
+ "direct/util.h",
+ "dirent.h",
+ "DiskInit.h",
+ "dlfcn.h",
+ "dlgs.h",
+ "dl.h",
+ "docobj.h",
+ "dos/dosextens.h",
+ "dos.h",
+ "Drag.h",
+ "DriverServices.h",
+ "DriverSynchronization.h",
+ "DropInPanel.h",
+ "dvidef.h",
+ "ecl-exp.h",
+ "elf.h",
+ "endian.h",
+ "Entry.h",
+ "err.h",
+ "errno.h",
+ "Errors.h",
+ "Events.h",
+ "exception",
+ "exdisp.h",
+ "ExDisp.h",
+ "exe386.h",
+ "execinfo.h",
+ "extras.h",
+ "fcntl.h",
+ "features.h",
+ "fenv.h",
+ "ffi.h",
+ "fibdef.h",
+ "File.h",
+ "filehdr.h",
+ "files.h",
+ "Files.h",
+ "FindDirectory.h",
+ "Finder.h",
+ "FinderRegistry.h",
+ "FixMath.h",
+ "float.h",
+ "fnmatch.h",
+ "Folders.h",
+ "fontconfig/fcfreetype.h",
+ "fontconfig/fontconfig.h",
+ "Font.h",
+ "Fonts.h",
+ "fp.h",
+ "fpieee.h",
+ "frame/log.h",
+ "frame/req.h",
+ "freetype/freetype.h",
+ "freetype/ftadvanc.h",
+ "freetype/ftbitmap.h",
+ "freetype/ftcache.h",
+ "freetype/ftfntfmt.h",
+ "freetype/ftglyph.h",
+ "freetype/ftlcdfil.h",
+ "freetype/ftoutln.h",
+ "freetype/ftsizes.h",
+ "freetype/ftsynth.h",
+ "freetype/ftxf86.h",
+ "freetype.h",
+ "freetype/t1tables.h",
+ "freetype/ttnameid.h",
+ "freetype/tttables.h",
+ "fribidi/fribidi.h",
+ "FSp_fopen.h",
+ "fstream",
+ "fstream.h",
+ "ft2build.h",
+ "ftadvanc.h",
+ "ftbitmap.h",
+ "ftcache.h",
+ "ftfntfmt.h",
+ "ftglyph.h",
+ "ftlcdfil.h",
+ "ftoutln.h",
+ "fts.h",
+ "ftsizes.h",
+ "ftsynth.h",
+ "ftxf86.h",
+ "fusion/arena.h",
+ "fusion/build.h",
+ "fusion/call.h",
+ "fusion/conf.h",
+ "fusion/fusion.h",
+ "fusion/fusion_internal.h",
+ "fusion/hash.h",
+ "fusion/lock.h",
+ "fusion/object.h",
+ "fusion/property.h",
+ "fusion/protocol.h",
+ "fusion/reactor.h",
+ "fusion/ref.h",
+ "fusion/shmalloc.h",
+ "fusion/shm/pool.h",
+ "fusion/shm/shm.h",
+ "fusion/shm/shm_internal.h",
+ "fusion/types.h",
+ "fusion/vector.h",
+ "gconf/gconf-client.h",
+ "Gdiplus.h",
+ "gdk/gdkdirectfb.h",
+ "gdk/gdk.h",
+ "gdk/gdkkeysyms.h",
+ "gdk/gdkprivate.h",
+ "gdk/gdkwayland.h",
+ "gdk-pixbuf/gdk-pixbuf.h",
+ "Gestalt.h",
+ "getopt.h",
+ "gio/gio.h",
+ "glibconfig.h",
+ "glib.h",
+ "glib-object.h",
+ "glob.h",
+ "gmodule.h",
+ "gnome.h",
+ "gnu/libc-version.h",
+ "gps.h",
+ "grp.h",
+ "gssapi_generic.h",
+ "gssapi/gssapi_generic.h",
+ "gssapi/gssapi.h",
+ "gssapi.h",
+ "gst/app/gstappsink.h",
+ "gst/app/gstappsrc.h",
+ "gst/gst.h",
+ "gst/video/video.h",
+ "gtk/gtk.h",
+ "gtk/gtkunixprint.h",
+ "hasht.h",
+ "HIToolbox/HIToolbox.h",
+ "hlink.h",
+ "ia64/sys/inline.h",
+ "Icons.h",
+ "iconv.h",
+ "ieeefp.h",
+ "ifaddrs.h",
+ "image.h",
+ "imagehlp.h",
+ "imm.h",
+ "initguid.h",
+ "initializer_list",
+ "InterfaceDefs.h",
+ "InternetConfig.h",
+ "IntlResources.h",
+ "ints.h",
+ "intshcut.h",
+ "inttypes.h",
+ "iodef.h",
+ "io.h",
+ "IOKit/IOKitLib.h",
+ "IOKit/IOMessage.h",
+ "IOKit/pwr_mgt/IOPMLib.h",
+ "iomanip",
+ "iostream.h",
+ "jar-ds.h",
+ "jarfile.h",
+ "jar.h",
+ "JavaControl.h",
+ "JavaEmbedding/JavaControl.h",
+ "JavaVM/jni.h",
+ "JManager.h",
+ "JNIEnvTests.h",
+ "jni.h",
+ "JVMManagerTests.h",
+ "Kerberos/Kerberos.h",
+ "kernel/image.h",
+ "kernel/OS.h",
+ "key.h",
+ "keyhi.h",
+ "keyt.h",
+ "keythi.h",
+ "kvm.h",
+ "LAction.h",
+ "langinfo.h",
+ "LApplication.h",
+ "LArray.h",
+ "LArrayIterator.h",
+ "LAttachable.h",
+ "LAttachment.h",
+ "LaunchServices.h",
+ "lber.h",
+ "LBroadcaster.h",
+ "LButton.h",
+ "lcache.h",
+ "LCaption.h",
+ "LCheckBox.h",
+ "LCicnButton.h",
+ "LClipboard.h",
+ "LCommander.h",
+ "LComparator.h",
+ "LControl.h",
+ "ldap.h",
+ "ldaplog.h",
+ "ldappr.h",
+ "ldap_ssl.h",
+ "LDataStream.h",
+ "ldfcn.h",
+ "LDialogBox.h",
+ "ldif.h",
+ "LDocApplication.h",
+ "LDocument.h",
+ "LDragAndDrop.h",
+ "LDragTask.h",
+ "LEditField.h",
+ "LEditText.h",
+ "LEventDispatcher.h",
+ "LFile.h",
+ "LFileStream.h",
+ "LFileTypeList.h",
+ "LFocusBox.h",
+ "LGrafPortView.h",
+ "LHandleStream.h",
+ "libc_r.h",
+ "libelf.h",
+ "libelf/libelf.h",
+ "libgen.h",
+ "libgnome/gnome-url.h",
+ "libgnome/libgnome.h",
+ "libgnomeui/gnome-icon-lookup.h",
+ "libgnomeui/gnome-icon-theme.h",
+ "libgnomeui/gnome-ui-init.h",
+ "libutil.h",
+ "limits.h",
+ "link.h",
+ "linux/ioprio.h",
+ "linux/kernel.h",
+ "linux/limits.h",
+ "linux/rtc.h",
+ "linux/version.h",
+ "List.h",
+ "Lists.h",
+ "LListBox.h",
+ "LListener.h",
+ "LMenuBar.h",
+ "LMenu.h",
+ "LModelDirector.h",
+ "LModelObject.h",
+ "LModelProperty.h",
+ "loader.h",
+ "locale",
+ "locale.h",
+ "LOffscreenView.h",
+ "logkeys.h",
+ "logstrng.h",
+ "Looper.h",
+ "LowMem.h",
+ "LPane.h",
+ "LPeriodical.h",
+ "LPicture.h",
+ "LPlaceHolder.h",
+ "LPrintout.h",
+ "LProgressBar.h",
+ "LPushButton.h",
+ "LRadioGroup.h",
+ "LRadioGroupView.h",
+ "LRunArray.h",
+ "LScroller.h",
+ "LSharable.h",
+ "LSingleDoc.h",
+ "LStaticText.h",
+ "LStdControl.h",
+ "LStream.h",
+ "LString.h",
+ "LTabGroup.h",
+ "LTabGroupView.h",
+ "LTableArrayStorage.h",
+ "LTableMonoGeometry.h",
+ "LTableSingleSelector.h",
+ "LTableView.h",
+ "LTextEditView.h",
+ "LTextTableView.h",
+ "LUndoer.h",
+ "LVariableArray.h",
+ "LView.h",
+ "LWindow.h",
+ "m68881.h",
+ "MacErrors.h",
+ "MacHeadersCarbon.h",
+ "machine/ansi.h",
+ "machine/builtins.h",
+ "machine/clock.h",
+ "machine/endian.h",
+ "machine/frame.h",
+ "machine/inline.h",
+ "machine/limits.h",
+ "machine/signal.h",
+ "machine/trap.h",
+ "mach/mach_host.h",
+ "mach/mach_init.h",
+ "mach/mach_interface.h",
+ "mach/mach_port.h",
+ "mach-o/dyld.h",
+ "MacLocales.h",
+ "MacMemory.h",
+ "MacTCP.h",
+ "MacTypes.h",
+ "MacWindows.h",
+ "malloc.h",
+ "malloc_np.h",
+ "mapicode.h",
+ "mapidefs.h",
+ "mapiguid.h",
+ "mapi.h",
+ "mapitags.h",
+ "mapiutil.h",
+ "mapix.h",
+ "Math64.h",
+ "math.h",
+ "mbstring.h",
+ "mem.h",
+ "memory.h",
+ "Memory.h",
+ "MenuBar.h",
+ "Menu.h",
+ "Menus.h",
+ "Message.h",
+ "Mime.h",
+ "MixedMode.h",
+ "mlang.h",
+ "mmsystem.h",
+ "model.h",
+ "Movies.h",
+ "mpw/errno.h",
+ "mshtmhst.h",
+ "mshtml.h",
+ "mswsock.h",
+ "Multiprocessing.h",
+ "mutex.h",
+ "Navigation.h",
+ "ncompat.h",
+ "ncurses.h",
+ "netCore.h",
+ "netdb.h",
+ "net/if.h",
+ "netinet/in.h",
+ "netinet/in_systm.h",
+ "netinet/tcp.h",
+ "newexe.h",
+ "new.h",
+ "nl_types.h",
+ "NodeInfo.h",
+ "nspr.h",
+ "nssb64.h",
+ "nssb64t.h",
+ "nssbase.h",
+ "nssbaset.h",
+ "nssck.api",
+ "nssckbi.h",
+ "nssckepv.h",
+ "nssckft.h",
+ "nssckfwc.h",
+ "nssckfw.h",
+ "nssckfwt.h",
+ "nssckg.h",
+ "nssckmdt.h",
+ "nssckt.h",
+ "nss.h",
+ "nssilckt.h",
+ "nssilock.h",
+ "nsslocks.h",
+ "nssrwlk.h",
+ "nssrwlkt.h",
+ "nssutil.h",
+ "nsswitch.h",
+ "objbase.h",
+ "objidl.h",
+ "Objsafe.h",
+ "ocsp.h",
+ "ocspt.h",
+ "ojiapitests.h",
+ "ole2.h",
+ "oleidl.h",
+ "OpenGL/OpenGL.h",
+ "OpenTptInternet.h",
+ "OpenTransport.h",
+ "OS.h",
+ "osreldate.h",
+ "OSUtils.h",
+ "p12.h",
+ "p12plcy.h",
+ "p12t.h",
+ "Packages.h",
+ "Palettes.h",
+ "PALM_CMN.H",
+ "pango/pango-break.h",
+ "pango/pangofc-decoder.h",
+ "pango/pangofc-font.h",
+ "pango/pangofc-fontmap.h",
+ "pango/pango-fontmap.h",
+ "pango/pango.h",
+ "pango/pango-modules.h",
+ "pango/pango-utils.h",
+ "pango/pangoxft.h",
+ "pascal.h",
+ "Patches.h",
+ "Path.h",
+ "pcfs/pc_dir.h",
+ "Pgenerr.h",
+ "PGenErr.h",
+ "Ph.h",
+ "pixman.h",
+ "pk11func.h",
+ "pk11pqg.h",
+ "pk11priv.h",
+ "pk11pub.h",
+ "pk11sdr.h",
+ "pkcs11f.h",
+ "pkcs11.h",
+ "pkcs11n.h",
+ "pkcs11p.h",
+ "pkcs11t.h",
+ "pkcs11u.h",
+ "pkcs12.h",
+ "pkcs12t.h",
+ "pkcs7t.h",
+ "plarena.h",
+ "plarenas.h",
+ "plbase64.h",
+ "plerror.h",
+ "plgetopt.h",
+ "plhash.h",
+ "plstr.h",
+ "PLStringFuncs.h",
+ "PMApplication.h",
+ "pmddim.h",
+ "poll.h",
+ "Polygon.h",
+ "portable.h",
+ "port.h",
+ "portreg.h",
+ "Power.h",
+ "PP_ClassHeaders.cp",
+ "PP_Constants.h",
+ "PPCToolbox.h",
+ "PP_DebugHeaders.cp",
+ "PP_KeyCodes.h",
+ "PP_Macros.h",
+ "PP_Messages.h",
+ "PP_Prefix.h",
+ "PP_Resources.h",
+ "PP_Types.h",
+ "pratom.h",
+ "prbit.h",
+ "prclist.h",
+ "prcmon.h",
+ "prcountr.h",
+ "prcpucfg.h",
+ "prcvar.h",
+ "prdtoa.h",
+ "preenc.h",
+ "prenv.h",
+ "prerr.h",
+ "prerror.h",
+ "prinet.h",
+ "prinit.h",
+ "prinrval.h",
+ "Printing.h",
+ "Print/PMPrintingDialogExtensions.h",
+ "prio.h",
+ "pripcsem.h",
+ "private",
+ "prlink.h",
+ "prlock.h",
+ "prlog.h",
+ "prlong.h",
+ "prmem.h",
+ "prmon.h",
+ "prmwait.h",
+ "prnetdb.h",
+ "Processes.h",
+ "process.h",
+ "Process.h",
+ "prolock.h",
+ "proto/dos.h",
+ "proto/exec.h",
+ "prpdce.h",
+ "prprf.h",
+ "prproces.h",
+ "prrng.h",
+ "prrwlock.h",
+ "prshma.h",
+ "prshm.h",
+ "prsystem.h",
+ "prthread.h",
+ "prtime.h",
+ "prtpool.h",
+ "prtrace.h",
+ "prtypes.h",
+ "prvrsion.h",
+ "prwin16.h",
+ "psap.h",
+ "Pt.h",
+ "pthread.h",
+ "pthread_np.h",
+ "pulse/pulseaudio.h",
+ "pwd.h",
+ "Python.h",
+ "QDOffscreen.h",
+ "queue",
+ "Quickdraw.h",
+ "QuickDraw.h",
+ "QuickTimeComponents.h",
+ "quipu/attr.h",
+ "regex.h",
+ "Region.h",
+ "resolv.h",
+ "Resources.h",
+ "Retrace.h",
+ "rld_interface.h",
+ "Roster.h",
+ "rpc.h",
+ "rpcproxy.h",
+ "rpc/types.h",
+ "sane/sane.h",
+ "sane/sanei.h",
+ "sane/saneopts.h",
+ "sanitizer/asan_interface.h",
+ "sanitizer/common_interface_defs.h",
+ "sched.h",
+ "Scrap.h",
+ "Screen.h",
+ "Script.h",
+ "ScrollBar.h",
+ "secasn1.h",
+ "secasn1t.h",
+ "seccomon.h",
+ "secder.h",
+ "secdert.h",
+ "secdig.h",
+ "secdigt.h",
+ "secerr.h",
+ "sec.h",
+ "sechash.h",
+ "secitem.h",
+ "secmime.h",
+ "secmod.h",
+ "secmodt.h",
+ "secoid.h",
+ "secoidt.h",
+ "secpkcs5.h",
+ "secpkcs7.h",
+ "secport.h",
+ "secrng.h",
+ "security.h",
+ "secutil.h",
+ "semaphore.h",
+ "servprov.h",
+ "setjmp.h",
+ "SFNTLayoutTypes.h",
+ "SFNTTypes.h",
+ "sha1.h",
+ "share.h",
+ "shellapi.h",
+ "shlguid.h",
+ "shlobj.h",
+ "shsign.h",
+ "sigcontext.h",
+ "signal.h",
+ "SimpleGameSound.h",
+ "SIOUX.h",
+ "size_t.h",
+ "smime.h",
+ "someincludefile.h",
+ "soundcard.h",
+ "Sound.h",
+ "soundtouch/SoundTouchFactory.h",
+ "soundtouch/SoundTouch.h",
+ "spawn.h",
+ "sqlite3.h",
+ "sslerr.h",
+ "ssl.h",
+ "sslproto.h",
+ "sslt.h",
+ "sstream",
+ "StandardFile.h",
+ "starlet.h",
+ "stat.h",
+ "statreg.cpp",
+ "statreg.h",
+ "stdarg.h",
+ "stdbool.h",
+ "stddef.h",
+ "stdint.h",
+ "stdio.h",
+ "stdlib.h",
+ "storage/FindDirectory.h",
+ "StorageKit.h",
+ "StringCompare.h",
+ "string.h",
+ "String.h",
+ "strings.h",
+ "Strings.h",
+ "StringView.h",
+ "stropts.h",
+ "strstrea.h",
+ "structs.h",
+ "stsdef.h",
+ "SupportDefs.h",
+ "support/String.h",
+ "support/SupportDefs.h",
+ "support/TLS.h",
+ "svrcore.h",
+ "symconst.h",
+ "sym.h",
+ "synch.h",
+ "syncmgr.h",
+ "sys/atomic_op.h",
+ "sys/bitypes.h",
+ "sys/byteorder.h",
+ "syscall.h",
+ "sys/cdefs.h",
+ "sys/cfgodm.h",
+ "sys/elf.h",
+ "sys/endian.h",
+ "sys/epoll.h",
+ "sys/errno.h",
+ "sys/eventfd.h",
+ "sys/fault.h",
+ "sys/fcntl.h",
+ "sys/file.h",
+ "sys/filio.h",
+ "sys/frame.h",
+ "sys/immu.h",
+ "sys/inotify.h",
+ "sys/inttypes.h",
+ "sys/ioccom.h",
+ "sys/ioctl.h",
+ "sys/ipc.h",
+ "sys/klog.h",
+ "sys/ldr.h",
+ "sys/link.h",
+ "sys/locking.h",
+ "syslog.h",
+ "sys/lwp.h",
+ "sys/machine.h",
+ "sys/mman.h",
+ "sys/mmu.h",
+ "sys/mount.h",
+ "sys/mpctl.h",
+ "sys/msg.h",
+ "sys/param.h",
+ "sys/pda.h",
+ "sys/poll.h",
+ "sys/ppc.h",
+ "sys/prctl.h",
+ "sys/priv.h",
+ "sys/procfs.h",
+ "sys/pstat.h",
+ "sys/ptrace.h",
+ "sys/queue.h",
+ "sys/quota.h",
+ "sys/reboot.h",
+ "sys/reg.h",
+ "sys/regset.h",
+ "sys/resource.h",
+ "sys/sched.h",
+ "sys/select.h",
+ "sys/sem.h",
+ "sys/sendfile.h",
+ "sys/shm.h",
+ "sys/siginfo.h",
+ "sys/signal.h",
+ "sys/socket.h",
+ "sys/sockio.h",
+ "sys/sparc/frame.h",
+ "sys/stack.h",
+ "sys/statfs.h",
+ "sys/stat.h",
+ "sys/statvfs.h",
+ "sys/syscall.h",
+ "sys/sysctl.h",
+ "sys/sysinfo.h",
+ "sys/sysmacros.h",
+ "sys/sysmp.h",
+ "sys/syssgi.h",
+ "sys/systeminfo.h",
+ "sys/system_properties.h",
+ "sys/thr.h",
+ "sys/timeb.h",
+ "sys/time.h",
+ "sys/times.h",
+ "sys/ttycom.h",
+ "sys/types.h",
+ "sys/ucontext.h",
+ "sys/uio.h",
+ "sys/un.h",
+ "sys/unistd.h",
+ "sys/user.h",
+ "sys/utsname.h",
+ "sys/vfs.h",
+ "sys/wait.h",
+ "t1tables.h",
+ "tables.h",
+ "TArray.h",
+ "TArrayIterator.h",
+ "task.h",
+ "tchar.h",
+ "TCHAR.H",
+ "termios.h",
+ "TextCommon.h",
+ "TextEdit.h",
+ "TextEncodingConverter.h",
+ "TextServices.h",
+ "TextUtils.h",
+ "TextView.h",
+ "th/PCR_Th.h",
+ "thread.h",
+ "ThreadManagerTests.h",
+ "Threads.h",
+ "time.h",
+ "Timer.h",
+ "tlhelp32.h",
+ "ToolUtils.h",
+ "tr1/functional",
+ "trace.h",
+ "Traps.h",
+ "ttnameid.h",
+ "tttables.h",
+ "typeinfo",
+ "types.h",
+ "Types.h",
+ "UAppleEventsMgr.h",
+ "UAttachments.h",
+ "ucontext.h",
+ "uconv.h",
+ "UCursor.h",
+ "UDebugging.h",
+ "UDesktop.h",
+ "UDrawingState.h",
+ "UDrawingUtils.h",
+ "UEnvironment.h",
+ "UEventMgr.h",
+ "UException.h",
+ "UExtractFromAEDesc.h",
+ "UGWorld.h",
+ "UKeyFilters.h",
+ "ulocks.h",
+ "ulserrno.h",
+ "UMemoryMgr.h",
+ "UModalDialogs.h",
+ "UNavServicesDialogs.h",
+ "UnicodeBlockObjects.h",
+ "UnicodeConverter.h",
+ "UnicodeUtilities.h",
+ "unidef.h",
+ "unikbd.h",
+ "unistd.h",
+ "unix.h",
+ "unixio.h",
+ "unknwn.h",
+ "unwind.h",
+ "UPrinting.h",
+ "UQuickTime.h",
+ "UReanimator.h",
+ "URegions.h",
+ "URegistrar.h",
+ "UResourceMgr.h",
+ "urlhist.h",
+ "urlmon.h",
+ "UScrap.h",
+ "UScreenPort.h",
+ "UTCUtils.h",
+ "UTETextAction.h",
+ "UTEViewTextAction.h",
+ "UTextEdit.h",
+ "UTextTraits.h",
+ "utilmodt.h",
+ "utilpars.h",
+ "utilparst.h",
+ "utilrename.h",
+ "utime.h",
+ "UWindows.h",
+ "values.h",
+ "varargs.h",
+ "vcclr.h",
+ "View.h",
+ "Volume.h",
+ "wab.h",
+ "wait.h",
+ "wchar.h",
+ "wctype.h",
+ "winbase.h",
+ "win/compobj.h",
+ "windef.h",
+ "Window.h",
+ "windows.h",
+ "Windows.h",
+ "windowsx.h",
+ "Wininet.h",
+ "winnls.h",
+ "winperf.h",
+ "winreg.h",
+ "Winreg.h",
+ "winsock2.h",
+ "winsock.h",
+ "winspool.h",
+ "winsvc.h",
+ "winuser.h",
+ "winver.h",
+ "wmem.h",
+ "workbench/startup.h",
+ "wtypes.h",
+ "wx/image.h",
+ "wx/listctrl.h",
+ "wx/log.h",
+ "wx/toolbar.h",
+ "wx/wx.h",
+ "wx/xrc/xmlres.h",
+ "xlocale.h",
+ "zmouse.h",
+ "vorbis/codec.h",
+ "opus/opus.h",
+ "opus/opus_multistream.h",
+ "ogg/ogg.h",
+ "theora/theoradec.h",
+ "vpx/svc_context.h",
+ "vpx/vp8.h",
+ "vpx/vp8cx.h",
+ "vpx/vp8dx.h",
+ "vpx/vpx_codec.h",
+ "vpx/vpx_decoder.h",
+ "vpx/vpx_encoder.h",
+ "vpx/vpx_frame_buffer.h",
+ "vpx/vpx_image.h",
+ "vpx_mem/vpx_mem.h",
+ "aom/aom_image.h",
+ "aom/aomdx.h",
+ "aom/aom_decoder.h",
+]
+
+if CONFIG["MOZ_X11"]:
+ system_headers += [
+ "gdk/gdkx.h",
+ "gtk/gtkx.h",
+ "X11/cursorfont.h",
+ "X11/extensions/Print.h",
+ "X11/extensions/scrnsaver.h",
+ "X11/extensions/shape.h",
+ "X11/extensions/Xcomposite.h",
+ "X11/extensions/Xdamage.h",
+ "X11/extensions/Xfixes.h",
+ "X11/extensions/Xrandr.h",
+ "X11/extensions/XShm.h",
+ "X11/extensions/XTest.h",
+ "X11/ImUtil.h",
+ "X11/Intrinsic.h",
+ "X11/keysymdef.h",
+ "X11/keysym.h",
+ "X11/Shell.h",
+ "X11/StringDefs.h",
+ "X11/Xatom.h",
+ "X11/Xft/Xft.h",
+ "X11/Xfuncproto.h",
+ "X11/X.h",
+ "X11/XKBlib.h",
+ "X11/Xlib.h",
+ "X11/Xlibint.h",
+ "X11/Xlib-xcb.h",
+ "X11/Xlocale.h",
+ "X11/Xos.h",
+ "X11/Xutil.h",
+ "xcb/shm.h",
+ "xcb/xcb.h",
+ ]
+
+if CONFIG["OS_TARGET"] == "Android":
+ system_headers += [
+ "android/api-level.h",
+ "android/ashmem.h",
+ "android_audio/AudioSystem.h",
+ "android/log.h",
+ "android/looper.h",
+ "android/native_window.h",
+ "android/native_window_jni.h",
+ "audio_effects/effect_aec.h",
+ "audio_effects/effect_ns.h",
+ "AudioParameter.h",
+ "AudioSystem.h",
+ "AudioTrack.h",
+ "avc_utils.h",
+ "binder/Binder.h",
+ "binder/BinderService.h",
+ "binder/IBinder.h",
+ "binder/IInterface.h",
+ "binder/IMemory.h",
+ "binder/IPCThreadState.h",
+ "binder/IPermissionController.h",
+ "binder/IServiceManager.h",
+ "binder/Parcel.h",
+ "binder/ProcessState.h",
+ "camera/Camera.h",
+ "camera/CameraParameters.h",
+ "ColorConverter.h",
+ "cutils/android_reboot.h",
+ "cutils/atomic.h",
+ "cutils/compiler.h",
+ "cutils/log.h",
+ "cutils/native_handle.h",
+ "cutils/properties.h",
+ "cutils/sockets.h",
+ "foundation/ABase.h",
+ "foundation/ABitReader.h",
+ "foundation/ABuffer.h",
+ "foundation/ADebug.h",
+ "foundation/AHandler.h",
+ "foundation/AHandlerReflector.h",
+ "foundation/ALooper.h",
+ "foundation/AMessage.h",
+ "foundation/AString.h",
+ "foundation/base64.h",
+ "foundation/hexdump.h",
+ "gui/BufferQueue.h",
+ "gui/ConsumerBase.h",
+ "gui/GraphicBufferAlloc.h",
+ "gui/IConsumerListener.h",
+ "gui/IGraphicBufferAlloc.h",
+ "gui/IGraphicBufferProducer.h",
+ "gui/ISurfaceComposerClient.h",
+ "gui/ISurfaceComposer.h",
+ "gui/ISurfaceTexture.h",
+ "gui/SurfaceComposerClient.h",
+ "gui/Surface.h",
+ "gui/SurfaceTextureClient.h",
+ "hardware/audio.h",
+ "hardware/gralloc.h",
+ "hardware/hardware.h",
+ "hardware/hwcomposer.h",
+ "hardware_legacy/power.h",
+ "hardware_legacy/uevent.h",
+ "hardware_legacy/vibrator.h",
+ "hardware/lights.h",
+ "hardware/power.h",
+ "HTTPBase.h",
+ "linux/android_alarm.h",
+ "linux/ashmem.h",
+ "media/AudioEffect.h",
+ "media/AudioSystem.h",
+ "media/ICrypto.h",
+ "media/IOMX.h",
+ "media/MediaProfiles.h",
+ "media/MediaRecorderBase.h",
+ "media/openmax/OMX_Audio.h",
+ "media/stagefright/AACWriter.h",
+ "media/stagefright/AMRWriter.h",
+ "media/stagefright/AudioSource.h",
+ "media/stagefright/DataSource.h",
+ "media/stagefright/foundation/ABase.h",
+ "media/stagefright/foundation/ABitReader.h",
+ "media/stagefright/foundation/ABuffer.h",
+ "media/stagefright/foundation/ADebug.h",
+ "media/stagefright/foundation/AHandler.h",
+ "media/stagefright/foundation/AHandlerReflector.h",
+ "media/stagefright/foundation/ALooper.h",
+ "media/stagefright/foundation/AMessage.h",
+ "media/stagefright/foundation/AString.h",
+ "media/stagefright/foundation/base64.h",
+ "media/stagefright/foundation/hexdump.h",
+ "media/stagefright/MediaBufferGroup.h",
+ "media/stagefright/MediaBuffer.h",
+ "media/stagefright/MediaCodec.h",
+ "media/stagefright/MediaCodecList.h",
+ "media/stagefright/MediaCodecSource.h",
+ "media/stagefright/MediaDefs.h",
+ "media/stagefright/MediaErrors.h",
+ "media/stagefright/MediaExtractor.h",
+ "media/stagefright/MediaSource.h",
+ "media/stagefright/MediaWriter.h",
+ "media/stagefright/MetaData.h",
+ "media/stagefright/MPEG2TSWriter.h",
+ "media/stagefright/MPEG4Writer.h",
+ "media/stagefright/OMXClient.h",
+ "media/stagefright/OMXCodec.h",
+ "media/stagefright/openmax/OMX_Core.h",
+ "media/stagefright/openmax/OMX_Index.h",
+ "media/stagefright/openmax/OMX_IVCommon.h",
+ "media/stagefright/openmax/OMX_Types.h",
+ "media/stagefright/openmax/OMX_Video.h",
+ "media/stagefright/Utils.h",
+ "OMX_Component.h",
+ "OMX.h",
+ "stagefright/AACWriter.h",
+ "stagefright/AMRWriter.h",
+ "stagefright/AudioSource.h",
+ "stagefright/DataSource.h",
+ "stagefright/foundation/ABase.h",
+ "stagefright/foundation/ABitReader.h",
+ "stagefright/foundation/ABuffer.h",
+ "stagefright/foundation/ADebug.h",
+ "stagefright/foundation/AHandler.h",
+ "stagefright/foundation/AHandlerReflector.h",
+ "stagefright/foundation/ALooper.h",
+ "stagefright/foundation/AMessage.h",
+ "stagefright/foundation/AString.h",
+ "stagefright/foundation/base64.h",
+ "stagefright/foundation/hexdump.h",
+ "stagefright/MediaBufferGroup.h",
+ "stagefright/MediaBuffer.h",
+ "stagefright/MediaCodec.h",
+ "stagefright/MediaDefs.h",
+ "stagefright/MediaErrors.h",
+ "stagefright/MediaExtractor.h",
+ "stagefright/MediaSource.h",
+ "stagefright/MediaWriter.h",
+ "stagefright/MetaData.h",
+ "stagefright/MPEG2TSWriter.h",
+ "stagefright/MPEG4Writer.h",
+ "stagefright/OMXClient.h",
+ "stagefright/OMXCodec.h",
+ "stagefright/openmax/OMX_Component.h",
+ "stagefright/openmax/OMX_Core.h",
+ "stagefright/openmax/OMX_Index.h",
+ "stagefright/openmax/OMX_IVCommon.h",
+ "stagefright/openmax/OMX_Types.h",
+ "stagefright/openmax/OMX_Video.h",
+ "stagefright/Utils.h",
+ "suspend/autosuspend.h",
+ "system/audio.h",
+ "system/graphics.h",
+ "system/window.h",
+ "sysutils/NetlinkEvent.h",
+ "ui/ANativeObjectBase.h",
+ "ui/egl/android_natives.h",
+ "ui/Fence.h",
+ "ui/FramebufferNativeWindow.h",
+ "ui/GraphicBuffer.h",
+ "ui/Rect.h",
+ "ui/Region.h",
+ "utils/BitSet.h",
+ "utils/CallStack.h",
+ "utils/Errors.h",
+ "utils/FileMap.h",
+ "utils/KeyedVector.h",
+ "utils/List.h",
+ "utils/Log.h",
+ "utils/Looper.h",
+ "utils/PropertyMap.h",
+ "utils/RefBase.h",
+ "utils/String16.h",
+ "utils/String8.h",
+ "utils/TextOutput.h",
+ "utils/threads.h",
+ "utils/Timers.h",
+ "utils/Trace.h",
+ "utils/TypeHelpers.h",
+ "utils/Unicode.h",
+ "utils/Vector.h",
+ "utils/VectorImpl.h",
+ "vr/gvr/capi/include/gvr_controller.h",
+ "vr/gvr/capi/include/gvr.h",
+ ]
+
+if CONFIG["MOZ_JACK"]:
+ system_headers += [
+ "jack/jack.h",
+ "jack/statistics.h",
+ ]
+
+if CONFIG["MOZ_SNDIO"]:
+ system_headers += [
+ "sndio.h",
+ ]
+
+if CONFIG["MOZ_SYSTEM_JPEG"]:
+ system_headers += [
+ "jpeglib.h",
+ ]
+
+if CONFIG["MOZ_LIBAV_FFT"]:
+ system_headers += [
+ "libavcodec/avfft.h",
+ ]
+
+if CONFIG["MOZ_SYSTEM_PNG"]:
+ system_headers += [
+ "png.h",
+ ]
+
+if CONFIG["MOZ_SYSTEM_WEBP"]:
+ system_headers += [
+ "webp/decode.h",
+ "webp/demux.h",
+ "webp/mux_types.h",
+ "webp/types.h",
+ ]
+
+if CONFIG["MOZ_SYSTEM_ZLIB"]:
+ system_headers += [
+ "zlib.h",
+ ]
+
+if CONFIG["MOZ_SYSTEM_LIBEVENT"]:
+ system_headers += [
+ "event2/event_compat.h",
+ "event2/event.h",
+ "event2/event_struct.h",
+ "event.h",
+ ]
+else:
+ system_headers += [
+ "sys/event.h",
+ ]
+
+if CONFIG["MOZ_ENABLE_LIBPROXY"]:
+ system_headers += [
+ "proxy.h",
+ ]
+
+if CONFIG["MOZ_SYSTEM_ICU"]:
+ system_headers += [
+ "unicode/calendar.h",
+ "unicode/datefmt.h",
+ "unicode/dtfmtsym.h",
+ "unicode/locid.h",
+ "unicode/numberformatter.h",
+ "unicode/numsys.h",
+ "unicode/plurrule.h",
+ "unicode/putil.h",
+ "unicode/timezone.h",
+ "unicode/ucal.h",
+ "unicode/uchar.h",
+ "unicode/uclean.h",
+ "unicode/ucol.h",
+ "unicode/ucurr.h",
+ "unicode/udat.h",
+ "unicode/udata.h",
+ "unicode/udateintervalformat.h",
+ "unicode/udatpg.h",
+ "unicode/udisplaycontext.h",
+ "unicode/uldnames.h",
+ "unicode/ulistformatter.h",
+ "unicode/uenum.h",
+ "unicode/uformattedvalue.h",
+ "unicode/umachine.h",
+ "unicode/uniset.h",
+ "unicode/unistr.h",
+ "unicode/unorm.h",
+ "unicode/unum.h",
+ "unicode/unumberformatter.h",
+ "unicode/uobject.h",
+ "unicode/upluralrules.h",
+ "unicode/ureldatefmt.h",
+ "unicode/ures.h",
+ "unicode/ustring.h",
+ "unicode/utypes.h",
+ ]
+
+if CONFIG["MOZ_WAYLAND"]:
+ system_headers += [
+ "xkbcommon/xkbcommon.h",
+ "wayland-client.h",
+ "wayland-egl.h",
+ "wayland-util.h",
+ ]
+
+if CONFIG["OS_TARGET"] in ("Android", "Linux", "FreeBSD"):
+ system_headers += [
+ "sys/auxv.h",
+ ]
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"].startswith("mips"):
+ system_headers += [
+ "sys/cachectl.h",
+ ]
+
+if CONFIG["OS_TARGET"] == "FreeBSD":
+ system_headers += [
+ "sys/capsicum.h",
+ ]
+
+if CONFIG["MOZ_APP_SYSTEM_HEADERS"]:
+ include("../" + CONFIG["MOZ_BUILD_APP"] + "/app-system-headers.mozbuild")
diff --git a/config/tests/chrome.manifest.flat b/config/tests/chrome.manifest.flat
new file mode 100644
index 0000000000..6c0a7e5362
--- /dev/null
+++ b/config/tests/chrome.manifest.flat
@@ -0,0 +1,4 @@
+content test chrome/test/one
+locale ab-X-stuff chrome/test/three
+overlay chrome://one/file.xml chrome://two/otherfile.xml
+skin test classic chrome/test/one
diff --git a/config/tests/python.toml b/config/tests/python.toml
new file mode 100644
index 0000000000..ed6cb41f40
--- /dev/null
+++ b/config/tests/python.toml
@@ -0,0 +1,10 @@
+[DEFAULT]
+subsuite = "mozbuild"
+
+["test_mozbuild_reading.py"]
+
+["unit-mozunit.py"]
+
+["unit-nsinstall.py"]
+
+["unit-printprereleasesuffix.py"]
diff --git a/config/tests/ref-simple/one/file.xml b/config/tests/ref-simple/one/file.xml
new file mode 100644
index 0000000000..21aacb9bd6
--- /dev/null
+++ b/config/tests/ref-simple/one/file.xml
@@ -0,0 +1 @@
+<?xml version="1.0"><doc/>
diff --git a/config/tests/ref-simple/one/preproc b/config/tests/ref-simple/one/preproc
new file mode 100644
index 0000000000..3e04d6329d
--- /dev/null
+++ b/config/tests/ref-simple/one/preproc
@@ -0,0 +1,2 @@
+
+This is ab-X-stuff.
diff --git a/config/tests/ref-simple/one/some.css b/config/tests/ref-simple/one/some.css
new file mode 100644
index 0000000000..a8a3ee47cc
--- /dev/null
+++ b/config/tests/ref-simple/one/some.css
@@ -0,0 +1,6 @@
+#div: {
+/* this is a ID rule, and should stay intact */
+}
+[lang=ab-X-stuff] {
+/* this selector should match content with lang="ab-X-stuff" */
+}
diff --git a/config/tests/ref-simple/three/l10nfile.txt b/config/tests/ref-simple/three/l10nfile.txt
new file mode 100644
index 0000000000..7ce7909abf
--- /dev/null
+++ b/config/tests/ref-simple/three/l10nfile.txt
@@ -0,0 +1 @@
+localized content
diff --git a/config/tests/ref-simple/two/otherfile.xml b/config/tests/ref-simple/two/otherfile.xml
new file mode 100644
index 0000000000..6c50abf6fc
--- /dev/null
+++ b/config/tests/ref-simple/two/otherfile.xml
@@ -0,0 +1 @@
+<?xml version="1.0"><otherdoc/>
diff --git a/config/tests/src-simple/Makefile.in b/config/tests/src-simple/Makefile.in
new file mode 100644
index 0000000000..7d3065a17a
--- /dev/null
+++ b/config/tests/src-simple/Makefile.in
@@ -0,0 +1,38 @@
+#
+# 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/.
+
+LOCALE_SRCDIR = $(srcdir)/l10n
+
+EXTERNALLY_MANAGED_MAKE_FILE := 1
+STANDALONE_MAKEFILE := 1
+JAR_MANIFEST := $(srcdir)/jar.mn
+
+include $(topsrcdir)/config/config.mk
+
+XPI_NAME = test_jar_mn
+
+ACDEFINES += \
+ -DAB_CD=ab-X-stuff \
+ $(NULL)
+
+MY_MANIFEST = $(if $(USE_EXTENSION_MANIFEST), $(FINAL_TARGET)/chrome.manifest, $(FINAL_TARGET)/chrome/test.manifest)
+REF_MANIFEST = $(if $(USE_EXTENSION_MANIFEST),chrome.manifest,test.manifest)
+
+check-%::
+ if test -d $(FINAL_TARGET); then rm -rf $(FINAL_TARGET); fi;
+ $(MAKE) realchrome MOZ_JAR_MAKER_FILE_FORMAT=$*
+ @echo 'Comparing manifests...'
+ @if ! diff --text -U 0 $(MY_MANIFEST) $(srcdir)/../$(REF_MANIFEST).$* ; then \
+ echo 'TEST-UNEXPECTED-FAIL | config/tests/$(REF_MANIFEST).$* | differing content in manifest!' ; \
+ false; \
+ fi
+ @if [ $* = 'jar' ]; then \
+ $(UNZIP) -d $(FINAL_TARGET)/chrome/test $(FINAL_TARGET)/chrome/test.jar; \
+ fi
+ @echo 'Comparing packages...'
+ @if ! diff -ur $(srcdir)/../ref-simple $(FINAL_TARGET)/chrome/test ; then\
+ echo 'TEST-UNEXPECTED-FAIL | config/tests/ref-simple | different content in jar' ; \
+ false; \
+ fi
diff --git a/config/tests/src-simple/jar.mn b/config/tests/src-simple/jar.mn
new file mode 100644
index 0000000000..12ed607b66
--- /dev/null
+++ b/config/tests/src-simple/jar.mn
@@ -0,0 +1,22 @@
+#filter substitution
+
+test.jar:
+# test chrome with flags and path expansion
+% content test %one
+# test locale with variable substitution and path expansion
+% locale @AB_CD@ %three
+# test overlays
+% overlay chrome://one/file.xml chrome://two/otherfile.xml
+# test regular file, preprocessed file, preprocessed css
+ one/file.xml (thesrcdir/file.xml)
+* one/preproc (thesrcdir/preproc.in)
+* one/some.css (thesrcdir/some.css)
+# test reference against topsrcdir
+ two/otherfile.xml (/config/tests/src-simple/thetopsrcdir/otherfile.xml)
+# test reference against localesrcdir
+ three/l10nfile.txt (%l10nfile.txt)
+
+test.jar:
+# test manifest update the locale one was already added above, add skin
+% locale @AB_CD@ %three
+% skin test classic %one
diff --git a/config/tests/src-simple/l10n/l10nfile.txt b/config/tests/src-simple/l10n/l10nfile.txt
new file mode 100644
index 0000000000..7ce7909abf
--- /dev/null
+++ b/config/tests/src-simple/l10n/l10nfile.txt
@@ -0,0 +1 @@
+localized content
diff --git a/config/tests/src-simple/moz.build b/config/tests/src-simple/moz.build
new file mode 100644
index 0000000000..d988c0ff9b
--- /dev/null
+++ b/config/tests/src-simple/moz.build
@@ -0,0 +1,7 @@
+# -*- 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/.
+
+JAR_MANIFESTS += ["jar.mn"]
diff --git a/config/tests/src-simple/thesrcdir/file.xml b/config/tests/src-simple/thesrcdir/file.xml
new file mode 100644
index 0000000000..21aacb9bd6
--- /dev/null
+++ b/config/tests/src-simple/thesrcdir/file.xml
@@ -0,0 +1 @@
+<?xml version="1.0"><doc/>
diff --git a/config/tests/src-simple/thesrcdir/preproc.in b/config/tests/src-simple/thesrcdir/preproc.in
new file mode 100644
index 0000000000..16d5024182
--- /dev/null
+++ b/config/tests/src-simple/thesrcdir/preproc.in
@@ -0,0 +1,6 @@
+# This would be an processed out
+# pretty lengthy
+# license header.
+# For example.
+
+#expand This is __AB_CD__.
diff --git a/config/tests/src-simple/thesrcdir/some.css b/config/tests/src-simple/thesrcdir/some.css
new file mode 100644
index 0000000000..36171b4bba
--- /dev/null
+++ b/config/tests/src-simple/thesrcdir/some.css
@@ -0,0 +1,6 @@
+#div: {
+/* this is a ID rule, and should stay intact */
+}
+%expand [lang=__AB_CD__] {
+/* this selector should match content with lang="ab-X-stuff" */
+}
diff --git a/config/tests/src-simple/thetopsrcdir/otherfile.xml b/config/tests/src-simple/thetopsrcdir/otherfile.xml
new file mode 100644
index 0000000000..6c50abf6fc
--- /dev/null
+++ b/config/tests/src-simple/thetopsrcdir/otherfile.xml
@@ -0,0 +1 @@
+<?xml version="1.0"><otherdoc/>
diff --git a/config/tests/test.manifest.flat b/config/tests/test.manifest.flat
new file mode 100644
index 0000000000..0cf9dbf3ab
--- /dev/null
+++ b/config/tests/test.manifest.flat
@@ -0,0 +1,4 @@
+content test test/one
+locale ab-X-stuff test/three
+overlay chrome://one/file.xml chrome://two/otherfile.xml
+skin test classic test/one
diff --git a/config/tests/test.manifest.jar b/config/tests/test.manifest.jar
new file mode 100644
index 0000000000..e2700dfbe1
--- /dev/null
+++ b/config/tests/test.manifest.jar
@@ -0,0 +1,4 @@
+content test jar:test.jar!/one
+locale ab-X-stuff jar:test.jar!/three
+overlay chrome://one/file.xml chrome://two/otherfile.xml
+skin test classic jar:test.jar!/one
diff --git a/config/tests/test.manifest.symlink b/config/tests/test.manifest.symlink
new file mode 100644
index 0000000000..0cf9dbf3ab
--- /dev/null
+++ b/config/tests/test.manifest.symlink
@@ -0,0 +1,4 @@
+content test test/one
+locale ab-X-stuff test/three
+overlay chrome://one/file.xml chrome://two/otherfile.xml
+skin test classic test/one
diff --git a/config/tests/test_mozbuild_reading.py b/config/tests/test_mozbuild_reading.py
new file mode 100644
index 0000000000..17fecf1452
--- /dev/null
+++ b/config/tests/test_mozbuild_reading.py
@@ -0,0 +1,104 @@
+# 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/.
+
+import os
+import sys
+import unittest
+
+from mozbuild.base import MozbuildObject
+from mozbuild.frontend.context import Files
+from mozbuild.frontend.reader import BuildReader, EmptyConfig
+from mozpack.files import FileFinder
+from mozunit import main
+
+
+class TestMozbuildReading(unittest.TestCase):
+ # This hack is needed to appease running in automation.
+ def setUp(self):
+ self._old_env = dict(os.environ)
+ os.environ.pop("MOZCONFIG", None)
+ os.environ.pop("MOZ_OBJDIR", None)
+
+ def tearDown(self):
+ os.environ.clear()
+ os.environ.update(self._old_env)
+
+ def _mozbuilds(self, reader):
+ if not hasattr(self, "_mozbuild_paths"):
+ self._mozbuild_paths = set(reader.all_mozbuild_paths())
+
+ return self._mozbuild_paths
+
+ @unittest.skip("failing in SpiderMonkey builds")
+ def test_filesystem_traversal_reading(self):
+ """Reading moz.build according to filesystem traversal works.
+
+ We attempt to read every known moz.build file via filesystem traversal.
+
+ If this test fails, it means that metadata extraction will fail.
+ """
+ mb = MozbuildObject.from_environment(detect_virtualenv_mozinfo=False)
+ config = mb.config_environment
+ reader = BuildReader(config)
+ all_paths = self._mozbuilds(reader)
+ paths, contexts = reader.read_relevant_mozbuilds(all_paths)
+ self.assertEqual(set(paths), all_paths)
+ self.assertGreaterEqual(len(contexts), len(paths))
+
+ def test_filesystem_traversal_no_config(self):
+ """Reading moz.build files via filesystem traversal mode with no build config.
+
+ This is similar to the above test except no build config is applied.
+ This will likely fail in more scenarios than the above test because a
+ lot of moz.build files assumes certain variables are present.
+ """
+ here = os.path.abspath(os.path.dirname(__file__))
+ root = os.path.normpath(os.path.join(here, "..", ".."))
+ config = EmptyConfig(root)
+ reader = BuildReader(config)
+ all_paths = self._mozbuilds(reader)
+ paths, contexts = reader.read_relevant_mozbuilds(all_paths)
+ self.assertEqual(set(paths.keys()), all_paths)
+ self.assertGreaterEqual(len(contexts), len(paths))
+
+ def test_orphan_file_patterns(self):
+ if sys.platform == "win32":
+ raise unittest.SkipTest("failing on windows builds")
+
+ mb = MozbuildObject.from_environment(detect_virtualenv_mozinfo=False)
+
+ try:
+ config = mb.config_environment
+ except Exception as e:
+ if str(e) == "config.status not available. Run configure.":
+ raise unittest.SkipTest("failing without config.status")
+ raise
+
+ if config.substs["MOZ_BUILD_APP"] == "js":
+ raise unittest.SkipTest("failing in Spidermonkey builds")
+
+ reader = BuildReader(config)
+ all_paths = self._mozbuilds(reader)
+ _, contexts = reader.read_relevant_mozbuilds(all_paths)
+
+ finder = FileFinder(config.topsrcdir, ignore=["obj*"])
+
+ def pattern_exists(pat):
+ return [p for p in finder.find(pat)] != []
+
+ for ctx in contexts:
+ if not isinstance(ctx, Files):
+ continue
+ relsrcdir = ctx.relsrcdir
+ for p in ctx.patterns:
+ if not pattern_exists(os.path.join(relsrcdir, p)):
+ self.fail(
+ "The pattern '%s' in a Files() entry in "
+ "'%s' corresponds to no files in the tree.\n"
+ "Please update this entry." % (p, ctx.main_path)
+ )
+
+
+if __name__ == "__main__":
+ main()
diff --git a/config/tests/unit-mozunit.py b/config/tests/unit-mozunit.py
new file mode 100644
index 0000000000..6915d86718
--- /dev/null
+++ b/config/tests/unit-mozunit.py
@@ -0,0 +1,87 @@
+# 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/.
+
+import os
+import unittest
+from tempfile import mkstemp
+
+from mozunit import MockedOpen, main
+
+
+class TestMozUnit(unittest.TestCase):
+ def test_mocked_open(self):
+ # Create a temporary file on the file system.
+ (fd, path) = mkstemp()
+ with os.fdopen(fd, "w") as file:
+ file.write("foobar")
+
+ self.assertFalse(os.path.exists("file1"))
+ self.assertFalse(os.path.exists("file2"))
+
+ with MockedOpen({"file1": "content1", "file2": "content2"}):
+ self.assertTrue(os.path.exists("file1"))
+ self.assertTrue(os.path.exists("file2"))
+ self.assertFalse(os.path.exists("foo/file1"))
+
+ # Check the contents of the files given at MockedOpen creation.
+ self.assertEqual(open("file1", "r").read(), "content1")
+ self.assertEqual(open("file2", "r").read(), "content2")
+
+ # Check that overwriting these files alters their content.
+ with open("file1", "w") as file:
+ file.write("foo")
+ self.assertTrue(os.path.exists("file1"))
+ self.assertEqual(open("file1", "r").read(), "foo")
+
+ # ... but not until the file is closed.
+ file = open("file2", "w")
+ file.write("bar")
+ self.assertEqual(open("file2", "r").read(), "content2")
+ file.close()
+ self.assertEqual(open("file2", "r").read(), "bar")
+
+ # Check that appending to a file does append
+ with open("file1", "a") as file:
+ file.write("bar")
+ self.assertEqual(open("file1", "r").read(), "foobar")
+
+ self.assertFalse(os.path.exists("file3"))
+
+ # Opening a non-existing file ought to fail.
+ self.assertRaises(IOError, open, "file3", "r")
+ self.assertFalse(os.path.exists("file3"))
+
+ # Check that writing a new file does create the file.
+ with open("file3", "w") as file:
+ file.write("baz")
+ self.assertEqual(open("file3", "r").read(), "baz")
+ self.assertTrue(os.path.exists("file3"))
+
+ # Check the content of the file created outside MockedOpen.
+ self.assertEqual(open(path, "r").read(), "foobar")
+
+ # Check that overwriting a file existing on the file system
+ # does modify its content.
+ with open(path, "w") as file:
+ file.write("bazqux")
+ self.assertEqual(open(path, "r").read(), "bazqux")
+
+ with MockedOpen():
+ # Check that appending to a file existing on the file system
+ # does modify its content.
+ with open(path, "a") as file:
+ file.write("bazqux")
+ self.assertEqual(open(path, "r").read(), "foobarbazqux")
+
+ # Check that the file was not actually modified on the file system.
+ self.assertEqual(open(path, "r").read(), "foobar")
+ os.remove(path)
+
+ # Check that the file created inside MockedOpen wasn't actually
+ # created.
+ self.assertRaises(IOError, open, "file3", "r")
+
+
+if __name__ == "__main__":
+ main()
diff --git a/config/tests/unit-nsinstall.py b/config/tests/unit-nsinstall.py
new file mode 100644
index 0000000000..e9990f928c
--- /dev/null
+++ b/config/tests/unit-nsinstall.py
@@ -0,0 +1,179 @@
+import os
+import os.path
+import subprocess
+import sys
+import time
+import unittest
+from shutil import rmtree
+from tempfile import mkdtemp
+
+import mozunit
+import nsinstall as nsinstall_module
+import six
+from nsinstall import nsinstall
+
+NSINSTALL_PATH = nsinstall_module.__file__
+
+# Run the non-ASCII tests on (a) Windows, or (b) any platform with
+# sys.stdin.encoding set to UTF-8
+import codecs
+
+RUN_NON_ASCII_TESTS = sys.platform == "win32" or (
+ sys.stdin.encoding is not None
+ and codecs.lookup(sys.stdin.encoding) == codecs.lookup("utf-8")
+)
+
+
+class TestNsinstall(unittest.TestCase):
+ """
+ Unit tests for nsinstall.py
+ """
+
+ def setUp(self):
+ self.tmpdir = mkdtemp()
+
+ def tearDown(self):
+ # Unicode strings means non-ASCII children can be deleted properly on
+ # Windows
+ if sys.stdin.encoding is None:
+ tmpdir = six.ensure_text(self.tmpdir)
+ else:
+ tmpdir = six.ensure_text(self.tmpdir, sys.stdin.encoding)
+ rmtree(tmpdir)
+
+ # utility methods for tests
+ def touch(self, file, dir=None):
+ if dir is None:
+ dir = self.tmpdir
+ f = os.path.join(dir, file)
+ open(f, "w").close()
+ return f
+
+ def mkdirs(self, dir):
+ d = os.path.join(self.tmpdir, dir)
+ os.makedirs(d)
+ return d
+
+ def test_nsinstall_D(self):
+ "Test nsinstall -D <dir>"
+ testdir = os.path.join(self.tmpdir, "test")
+ self.assertEqual(nsinstall(["-D", testdir]), 0)
+ self.assert_(os.path.isdir(testdir))
+
+ def test_nsinstall_basic(self):
+ "Test nsinstall <file> <dir>"
+ testfile = self.touch("testfile")
+ testdir = self.mkdirs("testdir")
+ self.assertEqual(nsinstall([testfile, testdir]), 0)
+ self.assert_(os.path.isfile(os.path.join(testdir, "testfile")))
+
+ def test_nsinstall_basic_recursive(self):
+ "Test nsinstall <dir> <dest dir>"
+ sourcedir = self.mkdirs("sourcedir")
+ self.touch("testfile", sourcedir)
+ Xfile = self.touch("Xfile", sourcedir)
+ copieddir = self.mkdirs("sourcedir/copieddir")
+ self.touch("testfile2", copieddir)
+ Xdir = self.mkdirs("sourcedir/Xdir")
+ self.touch("testfile3", Xdir)
+
+ destdir = self.mkdirs("destdir")
+
+ self.assertEqual(nsinstall([sourcedir, destdir, "-X", Xfile, "-X", Xdir]), 0)
+
+ testdir = os.path.join(destdir, "sourcedir")
+ self.assert_(os.path.isdir(testdir))
+ self.assert_(os.path.isfile(os.path.join(testdir, "testfile")))
+ self.assert_(not os.path.exists(os.path.join(testdir, "Xfile")))
+ self.assert_(os.path.isdir(os.path.join(testdir, "copieddir")))
+ self.assert_(os.path.isfile(os.path.join(testdir, "copieddir", "testfile2")))
+ self.assert_(not os.path.exists(os.path.join(testdir, "Xdir")))
+
+ def test_nsinstall_multiple(self):
+ "Test nsinstall <three files> <dest dir>"
+ testfiles = [
+ self.touch("testfile1"),
+ self.touch("testfile2"),
+ self.touch("testfile3"),
+ ]
+ testdir = self.mkdirs("testdir")
+ self.assertEqual(nsinstall(testfiles + [testdir]), 0)
+ for f in testfiles:
+ self.assert_(os.path.isfile(os.path.join(testdir, os.path.basename(f))))
+
+ def test_nsinstall_dir_exists(self):
+ "Test nsinstall <dir> <dest dir>, where <dest dir>/<dir> already exists"
+ srcdir = self.mkdirs("test")
+ destdir = self.mkdirs("testdir/test")
+ self.assertEqual(nsinstall([srcdir, os.path.dirname(destdir)]), 0)
+ self.assert_(os.path.isdir(destdir))
+
+ def test_nsinstall_t(self):
+ "Test that nsinstall -t works (preserve timestamp)"
+ testfile = self.touch("testfile")
+ testdir = self.mkdirs("testdir")
+ # set mtime to now - 30 seconds
+ t = int(time.time()) - 30
+ os.utime(testfile, (t, t))
+ self.assertEqual(nsinstall(["-t", testfile, testdir]), 0)
+ destfile = os.path.join(testdir, "testfile")
+ self.assert_(os.path.isfile(destfile))
+ self.assertEqual(os.stat(testfile).st_mtime, os.stat(destfile).st_mtime)
+
+ @unittest.skipIf(sys.platform == "win32", "Windows doesn't have real file modes")
+ def test_nsinstall_m(self):
+ "Test that nsinstall -m works (set mode)"
+ testfile = self.touch("testfile")
+ mode = 0o600
+ os.chmod(testfile, mode)
+ testdir = self.mkdirs("testdir")
+ self.assertEqual(
+ nsinstall(["-m", "{0:04o}".format(mode), testfile, testdir]), 0
+ )
+ destfile = os.path.join(testdir, "testfile")
+ self.assert_(os.path.isfile(destfile))
+ self.assertEqual(os.stat(testfile).st_mode, os.stat(destfile).st_mode)
+
+ def test_nsinstall_d(self):
+ "Test that nsinstall -d works (create directories in target)"
+ # -d makes no sense to me, but ok!
+ testfile = self.touch("testfile")
+ testdir = self.mkdirs("testdir")
+ destdir = os.path.join(testdir, "subdir")
+ self.assertEqual(nsinstall(["-d", testfile, destdir]), 0)
+ self.assert_(os.path.isdir(os.path.join(destdir, "testfile")))
+
+ @unittest.skipIf(not RUN_NON_ASCII_TESTS, "Skipping non ascii tests")
+ def test_nsinstall_non_ascii(self):
+ "Test that nsinstall handles non-ASCII files"
+ filename = "\u2325\u3452\u2415\u5081"
+ testfile = self.touch(filename)
+ testdir = self.mkdirs("\u4241\u1D04\u1414")
+ self.assertEqual(
+ nsinstall([testfile.encode("utf-8"), testdir.encode("utf-8")]), 0
+ )
+
+ destfile = os.path.join(testdir, filename)
+ self.assert_(os.path.isfile(destfile))
+
+ # Executing nsinstall.py with python 2 is not supported.
+ @unittest.skipIf(
+ not RUN_NON_ASCII_TESTS or sys.version_info[0] == 2, "Skipping non ascii tests"
+ )
+ def test_nsinstall_non_ascii_subprocess(self):
+ "Test that nsinstall as a subprocess handles non-ASCII files"
+ filename = "\u2325\u3452\u2415\u5081"
+ testfile = self.touch(filename)
+ testdir = self.mkdirs("\u4241\u1D04\u1414")
+ p = subprocess.Popen([sys.executable, NSINSTALL_PATH, testfile, testdir])
+ rv = p.wait()
+
+ self.assertEqual(rv, 0)
+ destfile = os.path.join(testdir, filename)
+ self.assert_(os.path.isfile(destfile))
+
+ # TODO: implement -R, -l, -L and test them!
+
+
+if __name__ == "__main__":
+ mozunit.main()
diff --git a/config/tests/unit-printprereleasesuffix.py b/config/tests/unit-printprereleasesuffix.py
new file mode 100644
index 0000000000..cebf48883c
--- /dev/null
+++ b/config/tests/unit-printprereleasesuffix.py
@@ -0,0 +1,79 @@
+import unittest
+
+import mozunit
+from printprereleasesuffix import get_prerelease_suffix
+
+
+class TestGetPreReleaseSuffix(unittest.TestCase):
+ """
+ Unit tests for the get_prerelease_suffix function
+ """
+
+ def test_alpha_1(self):
+ """test 1a1 version string"""
+ self.c = get_prerelease_suffix("1a1")
+ self.assertEqual(self.c, " 1 Alpha 1")
+
+ def test_alpha_10(self):
+ """test 1.2a10 version string"""
+ self.c = get_prerelease_suffix("1.2a10")
+ self.assertEqual(self.c, " 1.2 Alpha 10")
+
+ def test_beta_3(self):
+ """test 1.2.3b3 version string"""
+ self.c = get_prerelease_suffix("1.2.3b3")
+ self.assertEqual(self.c, " 1.2.3 Beta 3")
+
+ def test_beta_30(self):
+ """test 1.2.3.4b30 version string"""
+ self.c = get_prerelease_suffix("1.2.3.4b30")
+ self.assertEqual(self.c, " 1.2.3.4 Beta 30")
+
+ def test_release_1(self):
+ """test 1.2.3.4 version string"""
+ self.c = get_prerelease_suffix("1.2.3.4")
+ self.assertEqual(self.c, "")
+
+ def test_alpha_1_pre(self):
+ """test 1.2a1pre version string"""
+ self.c = get_prerelease_suffix("1.2a1pre")
+ self.assertEqual(self.c, "")
+
+ def test_beta_10_pre(self):
+ """test 3.4b10pre version string"""
+ self.c = get_prerelease_suffix("3.4b10pre")
+ self.assertEqual(self.c, "")
+
+ def test_pre_0(self):
+ """test 1.2pre0 version string"""
+ self.c = get_prerelease_suffix("1.2pre0")
+ self.assertEqual(self.c, "")
+
+ def test_pre_1_b(self):
+ """test 1.2pre1b version string"""
+ self.c = get_prerelease_suffix("1.2pre1b")
+ self.assertEqual(self.c, "")
+
+ def test_a_a(self):
+ """test 1.2aa version string"""
+ self.c = get_prerelease_suffix("1.2aa")
+ self.assertEqual(self.c, "")
+
+ def test_b_b(self):
+ """test 1.2bb version string"""
+ self.c = get_prerelease_suffix("1.2bb")
+ self.assertEqual(self.c, "")
+
+ def test_a_b(self):
+ """test 1.2ab version string"""
+ self.c = get_prerelease_suffix("1.2ab")
+ self.assertEqual(self.c, "")
+
+ def test_plus(self):
+ """test 1.2+ version string"""
+ self.c = get_prerelease_suffix("1.2+")
+ self.assertEqual(self.c, "")
+
+
+if __name__ == "__main__":
+ mozunit.main()
diff --git a/config/tests/unitMozZipFile.py b/config/tests/unitMozZipFile.py
new file mode 100644
index 0000000000..4965dc1df3
--- /dev/null
+++ b/config/tests/unitMozZipFile.py
@@ -0,0 +1,214 @@
+# 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/.
+
+import copy
+import os
+import random
+import shutil
+import sys
+import unittest
+from string import letters
+
+"""
+Test case infrastructure for MozZipFile.
+
+This isn't really a unit test, but a test case generator and runner.
+For a given set of files, lengths, and number of writes, we create
+a testcase for every combination of the three. There are some
+symmetries used to reduce the number of test cases, the first file
+written is always the first file, the second is either the first or
+the second, the third is one of the first three. That is, if we
+had 4 files, but only three writes, the fourth file would never even
+get tried.
+
+The content written to the jars is pseudorandom with a fixed seed.
+"""
+
+if not __file__:
+ __file__ = sys.argv[0]
+sys.path.append(os.path.join(os.path.dirname(__file__), ".."))
+
+import zipfile
+
+from MozZipFile import ZipFile
+
+leafs = ("firstdir/oneleaf", "seconddir/twoleaf", "thirddir/with/sub/threeleaf")
+_lengths = map(lambda n: n * 64, [16, 64, 80])
+lengths = 3
+writes = 5
+
+
+def givenlength(i):
+ """Return a length given in the _lengths array to allow manual
+ tuning of which lengths of zip entries to use.
+ """
+ return _lengths[i]
+
+
+def prod(*iterables):
+ """'Tensor product of a list of iterables.
+
+ This generator returns lists of items, one of each given
+ iterable. It iterates over all possible combinations.
+ """
+ for item in iterables[0]:
+ if len(iterables) == 1:
+ yield [item]
+ else:
+ for others in prod(*iterables[1:]):
+ yield [item] + others
+
+
+def getid(descs):
+ "Convert a list of ints to a string."
+ return reduce(lambda x, y: x + "{0}{1}".format(*tuple(y)), descs, "")
+
+
+def getContent(length):
+ "Get pseudo random content of given length."
+ rv = [None] * length
+ for i in xrange(length):
+ rv[i] = random.choice(letters)
+ return "".join(rv)
+
+
+def createWriter(sizer, *items):
+ "Helper method to fill in tests, one set of writes, one for each item"
+ locitems = copy.deepcopy(items)
+ for item in locitems:
+ item["length"] = sizer(item.pop("length", 0))
+
+ def helper(self):
+ mode = "w"
+ if os.path.isfile(self.f):
+ mode = "a"
+ zf = ZipFile(self.f, mode, self.compression)
+ for item in locitems:
+ self._write(zf, **item)
+ zf = None
+ pass
+
+ return helper
+
+
+def createTester(name, *writes):
+ """Helper method to fill in tests, calls into a list of write
+ helper methods.
+ """
+ _writes = copy.copy(writes)
+
+ def tester(self):
+ for w in _writes:
+ getattr(self, w)()
+ self._verifyZip()
+ pass
+
+ # unit tests get confused if the method name isn't test...
+ tester.__name__ = name
+ return tester
+
+
+class TestExtensiveStored(unittest.TestCase):
+ """Unit tests for MozZipFile
+
+ The testcase are actually populated by code following the class
+ definition.
+ """
+
+ stage = "mozzipfilestage"
+ compression = zipfile.ZIP_STORED
+
+ def leaf(self, *leafs):
+ return os.path.join(self.stage, *leafs)
+
+ def setUp(self):
+ if os.path.exists(self.stage):
+ shutil.rmtree(self.stage)
+ os.mkdir(self.stage)
+ self.f = self.leaf("test.jar")
+ self.ref = {}
+ self.seed = 0
+
+ def tearDown(self):
+ self.f = None
+ self.ref = None
+
+ def _verifyZip(self):
+ zf = zipfile.ZipFile(self.f)
+ badEntry = zf.testzip()
+ self.failIf(badEntry, badEntry)
+ zlist = zf.namelist()
+ zlist.sort()
+ vlist = self.ref.keys()
+ vlist.sort()
+ self.assertEqual(zlist, vlist)
+ for leaf, content in self.ref.iteritems():
+ zcontent = zf.read(leaf)
+ self.assertEqual(content, zcontent)
+
+ def _write(self, zf, seed=None, leaf=0, length=0):
+ if seed is None:
+ seed = self.seed
+ self.seed += 1
+ random.seed(seed)
+ leaf = leafs[leaf]
+ content = getContent(length)
+ self.ref[leaf] = content
+ zf.writestr(leaf, content)
+ dir = os.path.dirname(self.leaf("stage", leaf))
+ if not os.path.isdir(dir):
+ os.makedirs(dir)
+ open(self.leaf("stage", leaf), "w").write(content)
+
+
+# all leafs in all lengths
+atomics = list(prod(xrange(len(leafs)), xrange(lengths)))
+
+# populate TestExtensiveStore with testcases
+for w in xrange(writes):
+ # Don't iterate over all files for the the first n passes,
+ # those are redundant as long as w < lengths.
+ # There are symmetries in the trailing end, too, but I don't know
+ # how to reduce those out right now.
+ nonatomics = [
+ list(prod(range(min(i, len(leafs))), xrange(lengths))) for i in xrange(1, w + 1)
+ ] + [atomics]
+ for descs in prod(*nonatomics):
+ suffix = getid(descs)
+ dicts = [dict(leaf=leaf, length=length) for leaf, length in descs]
+ setattr(
+ TestExtensiveStored, "_write" + suffix, createWriter(givenlength, *dicts)
+ )
+ setattr(
+ TestExtensiveStored,
+ "test" + suffix,
+ createTester("test" + suffix, "_write" + suffix),
+ )
+
+# now create another round of tests, with two writing passes
+# first, write all file combinations into the jar, close it,
+# and then write all atomics again.
+# This should catch more or less all artifacts generated
+# by the final ordering step when closing the jar.
+files = [list(prod([i], xrange(lengths))) for i in xrange(len(leafs))]
+allfiles = reduce(
+ lambda l, r: l + r, [list(prod(*files[: (i + 1)])) for i in xrange(len(leafs))]
+)
+
+for first in allfiles:
+ testbasename = "test{0}_".format(getid(first))
+ test = [None, "_write" + getid(first), None]
+ for second in atomics:
+ test[0] = testbasename + getid([second])
+ test[2] = "_write" + getid([second])
+ setattr(TestExtensiveStored, test[0], createTester(*test))
+
+
+class TestExtensiveDeflated(TestExtensiveStored):
+ "Test all that has been tested with ZIP_STORED with DEFLATED, too."
+ compression = zipfile.ZIP_DEFLATED
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/config/wasm2c.py b/config/wasm2c.py
new file mode 100644
index 0000000000..572e015ada
--- /dev/null
+++ b/config/wasm2c.py
@@ -0,0 +1,14 @@
+# 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/.
+
+import os
+import subprocess
+
+
+def wasm2c(output, wasm2c_bin, wasm_lib):
+ output.close()
+ module_name = os.path.basename(os.path.splitext(wasm_lib)[0])
+ return subprocess.run(
+ [wasm2c_bin, "-n", module_name, "-o", output.name, wasm_lib]
+ ).returncode
diff --git a/config/windows-h-constant.decls.h b/config/windows-h-constant.decls.h
new file mode 100644
index 0000000000..4fe0e8bd30
--- /dev/null
+++ b/config/windows-h-constant.decls.h
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* 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/. */
+
+/*
+ * This file contains a series of C-style declarations for constants defined in
+ * windows.h using #define. Adding a new constant should be a simple as adding
+ * its name (and optionally type) to this file.
+ *
+ * This file is processed by make-windows-h-wrapper.py to generate a wrapper for
+ * the header which removes the defines usually implementing these constants.
+ *
+ * Wrappers defined in this file will be declared as `constexpr` values,
+ * and will have their value derived from the windows.h define.
+ *
+ * NOTE: This is *NOT* a real C header, but rather an input to the avove script.
+ * Only basic declarations in the form found here are allowed.
+ */
+
+// XXX(nika): There are a lot of these (>30k)!
+// This is just a set of ones I saw in a quick scan which looked problematic.
+
+auto CREATE_NEW;
+auto CREATE_ALWAYS;
+auto OPEN_EXISTING;
+auto OPEN_ALWAYS;
+auto TRUNCATE_EXISTING;
+auto INVALID_FILE_SIZE;
+auto INVALID_SET_FILE_POINTER;
+auto INVALID_FILE_ATTRIBUTES;
+
+auto ANSI_NULL;
+auto UNICODE_NULL;
+
+auto MINCHAR;
+auto MAXCHAR;
+auto MINSHORT;
+auto MAXSHORT;
+auto MINLONG;
+auto MAXLONG;
+auto MAXBYTE;
+auto MAXWORD;
+auto MAXDWORD;
+
+auto ERROR;
+
+auto DELETE;
+auto READ_CONTROL;
+auto WRITE_DAC;
+auto WRITE_OWNER;
+auto SYNCHRONIZE;
+auto TRANSPARENT;
+
+auto MAXIMUM_ALLOWED;
+auto GENERIC_READ;
+auto GENERIC_WRITE;
+auto GENERIC_EXECUTE;
+auto GENERIC_ALL;
+
+auto NO_ERROR;
+auto WAIT_FAILED;
+auto WAIT_ABANDONED;
+auto WAIT_TIMEOUT;
diff --git a/config/windows-h-unicode.decls.h b/config/windows-h-unicode.decls.h
new file mode 100644
index 0000000000..9274bcca9d
--- /dev/null
+++ b/config/windows-h-unicode.decls.h
@@ -0,0 +1,1130 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* 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/. */
+
+/*
+ * This file contains a series of C-style function prototypes for A/W-suffixed
+ * Win32 APIs defined by windows.h.
+ *
+ * This file is processed by make-windows-h-wrapper.py to generate a wrapper for
+ * the header which removes the defines usually implementing these aliases.
+ *
+ * Wrappers defined in this file will have the 'stdcall' calling convention,
+ * will be defined as 'inline', and will only be defined if the corresponding
+ * #define directive has not been #undef-ed.
+ *
+ * NOTE: This is *NOT* a real C header, but rather an input to the avove script.
+ * Only basic declarations in the form found here are allowed.
+ */
+
+LPTSTR GetCommandLine();
+
+BOOL FreeEnvironmentStrings(LPTCH);
+
+DWORD GetEnvironmentVariable(LPCTSTR, LPTSTR, DWORD);
+
+BOOL SetEnvironmentVariable(LPCTSTR, LPCTSTR);
+
+DWORD ExpandEnvironmentStrings(LPCTSTR, LPTSTR, DWORD);
+
+BOOL SetCurrentDirectory(LPCTSTR);
+
+DWORD GetCurrentDirectory(DWORD, LPTSTR);
+
+DWORD SearchPath(LPCTSTR, LPCTSTR, LPCTSTR, DWORD, LPTSTR, LPTSTR*);
+
+BOOL NeedCurrentDirectoryForExePath(LPCTSTR);
+
+BOOL CreateDirectory(LPCTSTR, LPSECURITY_ATTRIBUTES);
+
+HANDLE CreateFile(LPCTSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD,
+ HANDLE);
+
+BOOL DeleteFile(LPCTSTR);
+
+HANDLE FindFirstChangeNotification(LPCTSTR, BOOL, DWORD);
+
+HANDLE FindFirstFile(LPCTSTR, LPWIN32_FIND_DATA);
+
+HANDLE FindFirstFileEx(LPCTSTR, FINDEX_INFO_LEVELS, LPVOID, FINDEX_SEARCH_OPS,
+ LPVOID, DWORD);
+
+BOOL FindNextFile(HANDLE, LPWIN32_FIND_DATA);
+
+BOOL GetDiskFreeSpace(LPCTSTR, LPDWORD, LPDWORD, LPDWORD, LPDWORD);
+
+BOOL GetDiskFreeSpaceEx(LPCTSTR, PULARGE_INTEGER, PULARGE_INTEGER,
+ PULARGE_INTEGER);
+
+UINT GetDriveType(LPCTSTR);
+
+DWORD GetFileAttributes(LPCTSTR);
+
+BOOL GetFileAttributesEx(LPCTSTR, GET_FILEEX_INFO_LEVELS, LPVOID);
+
+DWORD GetFinalPathNameByHandle(HANDLE, LPTSTR, DWORD, DWORD);
+
+DWORD GetFullPathName(LPCTSTR, DWORD, LPTSTR, LPTSTR*);
+
+DWORD GetLongPathName(LPCTSTR, LPTSTR, DWORD);
+
+BOOL RemoveDirectory(LPCTSTR);
+
+BOOL SetFileAttributes(LPCTSTR, DWORD);
+
+DWORD GetCompressedFileSize(LPCTSTR, LPDWORD);
+
+DWORD GetTempPath(DWORD, LPTSTR);
+
+BOOL GetVolumeInformation(LPCTSTR, LPTSTR, DWORD, LPDWORD, LPDWORD, LPDWORD,
+ LPTSTR, DWORD);
+
+UINT GetTempFileName(LPCTSTR, LPCTSTR, UINT, LPTSTR);
+
+void OutputDebugString(LPCTSTR);
+
+void FatalAppExit(UINT, LPCTSTR);
+
+HANDLE CreateMutex(LPSECURITY_ATTRIBUTES, BOOL, LPCTSTR);
+
+HANDLE CreateEvent(LPSECURITY_ATTRIBUTES, BOOL, BOOL, LPCTSTR);
+
+HANDLE OpenEvent(DWORD, BOOL, LPCTSTR);
+
+HANDLE CreateMutexEx(LPSECURITY_ATTRIBUTES, LPCTSTR, DWORD, DWORD);
+
+HANDLE CreateEventEx(LPSECURITY_ATTRIBUTES, LPCTSTR, DWORD, DWORD);
+
+BOOL CreateProcess(LPCTSTR, LPTSTR, LPSECURITY_ATTRIBUTES,
+ LPSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID, LPCTSTR,
+ LPSTARTUPINFO, LPPROCESS_INFORMATION);
+
+BOOL CreateProcessAsUser(HANDLE, LPCTSTR, LPTSTR, LPSECURITY_ATTRIBUTES,
+ LPSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID, LPCTSTR,
+ LPSTARTUPINFO, LPPROCESS_INFORMATION);
+
+UINT GetSystemDirectory(LPTSTR, UINT);
+
+UINT GetWindowsDirectory(LPTSTR, UINT);
+
+UINT GetSystemWindowsDirectory(LPTSTR, UINT);
+
+BOOL GetComputerNameEx(COMPUTER_NAME_FORMAT, LPTSTR, LPDWORD);
+
+BOOL GetVersionEx(LPOSVERSIONINFO);
+
+BOOL SetComputerName(LPCTSTR);
+
+BOOL SetComputerNameEx(COMPUTER_NAME_FORMAT, LPCTSTR);
+
+BOOL LoadEnclaveImage(LPVOID, LPCTSTR);
+
+UINT GetSystemWow64Directory(LPTSTR, UINT);
+
+DWORD GetModuleFileName(HMODULE, LPTSTR, DWORD);
+
+HMODULE GetModuleHandle(LPCTSTR);
+
+BOOL GetModuleHandleEx(DWORD, LPCTSTR, HMODULE*);
+
+HMODULE LoadLibraryEx(LPCTSTR, HANDLE, DWORD);
+
+int LoadString(HINSTANCE, UINT, LPTSTR, int);
+
+BOOL EnumResourceLanguagesEx(HMODULE, LPCTSTR, LPCTSTR, ENUMRESLANGPROC,
+ LONG_PTR, DWORD, LANGID);
+
+BOOL EnumResourceNamesEx(HMODULE, LPCTSTR, ENUMRESNAMEPROC, LONG_PTR, DWORD,
+ LANGID);
+
+BOOL EnumResourceTypesEx(HMODULE, ENUMRESTYPEPROC, LONG_PTR, DWORD, LANGID);
+
+HMODULE LoadLibrary(LPCTSTR);
+
+BOOL GetBinaryType(LPCTSTR, LPDWORD);
+
+DWORD GetShortPathName(LPCTSTR, LPTSTR, DWORD);
+
+DWORD GetLongPathNameTransacted(LPCTSTR, LPTSTR, DWORD, HANDLE);
+
+BOOL SetEnvironmentStrings(LPTCH);
+
+BOOL SetFileShortName(HANDLE, LPCTSTR);
+
+DWORD FormatMessage(DWORD, LPCVOID, DWORD, DWORD, LPTSTR, DWORD, va_list*);
+
+HANDLE CreateMailslot(LPCTSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES);
+
+BOOL EncryptFile(LPCTSTR);
+
+BOOL DecryptFile(LPCTSTR, DWORD);
+
+BOOL FileEncryptionStatus(LPCTSTR, LPDWORD);
+
+DWORD OpenEncryptedFileRaw(LPCTSTR, ULONG, PVOID*);
+
+HANDLE OpenMutex(DWORD, BOOL, LPCTSTR);
+
+HANDLE CreateSemaphore(LPSECURITY_ATTRIBUTES, LONG, LONG, LPCTSTR);
+
+HANDLE OpenSemaphore(DWORD, BOOL, LPCTSTR);
+
+HANDLE CreateWaitableTimer(LPSECURITY_ATTRIBUTES, BOOL, LPCTSTR);
+
+HANDLE OpenWaitableTimer(DWORD, BOOL, LPCTSTR);
+
+HANDLE CreateSemaphoreEx(LPSECURITY_ATTRIBUTES, LONG, LONG, LPCTSTR, DWORD,
+ DWORD);
+
+HANDLE CreateWaitableTimerEx(LPSECURITY_ATTRIBUTES, LPCTSTR, DWORD, DWORD);
+
+HANDLE CreateFileMapping(HANDLE, LPSECURITY_ATTRIBUTES, DWORD, DWORD, DWORD,
+ LPCTSTR);
+
+HANDLE CreateFileMappingNuma(HANDLE, LPSECURITY_ATTRIBUTES, DWORD, DWORD, DWORD,
+ LPCTSTR, DWORD);
+
+HANDLE OpenFileMapping(DWORD, BOOL, LPCTSTR);
+
+DWORD GetLogicalDriveStrings(DWORD, LPTSTR);
+
+void GetStartupInfo(LPSTARTUPINFO);
+
+DWORD GetFirmwareEnvironmentVariable(LPCTSTR, LPCTSTR, PVOID, DWORD);
+
+BOOL SetFirmwareEnvironmentVariable(LPCTSTR, LPCTSTR, PVOID, DWORD);
+
+HRSRC FindResource(HMODULE, LPCTSTR, LPCTSTR);
+
+HRSRC FindResourceEx(HMODULE, LPCTSTR, LPCTSTR, WORD);
+
+BOOL EnumResourceTypes(HMODULE, ENUMRESTYPEPROC, LONG_PTR);
+
+BOOL EnumResourceNames(HMODULE, LPCTSTR, ENUMRESNAMEPROC, LONG_PTR);
+
+BOOL EnumResourceLanguages(HMODULE, LPCTSTR, LPCTSTR, ENUMRESLANGPROC,
+ LONG_PTR);
+
+HANDLE BeginUpdateResource(LPCTSTR, BOOL);
+
+BOOL UpdateResource(HANDLE, LPCTSTR, LPCTSTR, WORD, LPVOID, DWORD);
+
+BOOL EndUpdateResource(HANDLE, BOOL);
+
+ATOM GlobalAddAtom(LPCTSTR);
+
+ATOM GlobalAddAtomEx(LPCTSTR, DWORD);
+
+ATOM GlobalFindAtom(LPCTSTR);
+
+UINT GlobalGetAtomName(ATOM, LPTSTR, int);
+
+ATOM AddAtom(LPCTSTR);
+
+ATOM FindAtom(LPCTSTR);
+
+UINT GetAtomName(ATOM, LPTSTR, int);
+
+UINT GetProfileInt(LPCTSTR, LPCTSTR, INT);
+
+DWORD GetProfileString(LPCTSTR, LPCTSTR, LPCTSTR, LPTSTR, DWORD);
+
+BOOL WriteProfileString(LPCTSTR, LPCTSTR, LPCTSTR);
+
+DWORD GetProfileSection(LPCTSTR, LPTSTR, DWORD);
+
+BOOL WriteProfileSection(LPCTSTR, LPCTSTR);
+
+UINT GetPrivateProfileInt(LPCTSTR, LPCTSTR, INT, LPCTSTR);
+
+DWORD GetPrivateProfileString(LPCTSTR, LPCTSTR, LPCTSTR, LPTSTR, DWORD,
+ LPCTSTR);
+
+BOOL WritePrivateProfileString(LPCTSTR, LPCTSTR, LPCTSTR, LPCTSTR);
+
+DWORD GetPrivateProfileSection(LPCTSTR, LPTSTR, DWORD, LPCTSTR);
+
+BOOL WritePrivateProfileSection(LPCTSTR, LPCTSTR, LPCTSTR);
+
+DWORD GetPrivateProfileSectionNames(LPTSTR, DWORD, LPCTSTR);
+
+BOOL GetPrivateProfileStruct(LPCTSTR, LPCTSTR, LPVOID, UINT, LPCTSTR);
+
+BOOL WritePrivateProfileStruct(LPCTSTR, LPCTSTR, LPVOID, UINT, LPCTSTR);
+
+BOOL SetDllDirectory(LPCTSTR);
+
+DWORD GetDllDirectory(DWORD, LPTSTR);
+
+BOOL CreateDirectoryEx(LPCTSTR, LPCTSTR, LPSECURITY_ATTRIBUTES);
+
+BOOL CreateDirectoryTransacted(LPCTSTR, LPCTSTR, LPSECURITY_ATTRIBUTES, HANDLE);
+
+BOOL RemoveDirectoryTransacted(LPCTSTR, HANDLE);
+
+DWORD GetFullPathNameTransacted(LPCTSTR, DWORD, LPTSTR, LPTSTR*, HANDLE);
+
+BOOL DefineDosDevice(DWORD, LPCTSTR, LPCTSTR);
+
+DWORD QueryDosDevice(LPCTSTR, LPTSTR, DWORD);
+
+HANDLE CreateFileTransacted(LPCTSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD,
+ DWORD, HANDLE, HANDLE, PUSHORT, PVOID);
+
+BOOL SetFileAttributesTransacted(LPCTSTR, DWORD, HANDLE);
+
+BOOL GetFileAttributesTransacted(LPCTSTR, GET_FILEEX_INFO_LEVELS, LPVOID,
+ HANDLE);
+
+DWORD GetCompressedFileSizeTransacted(LPCTSTR, LPDWORD, HANDLE);
+
+BOOL DeleteFileTransacted(LPCTSTR, HANDLE);
+
+BOOL CheckNameLegalDOS8Dot3(LPCTSTR, LPSTR, DWORD, PBOOL, PBOOL);
+
+HANDLE FindFirstFileTransacted(LPCTSTR, FINDEX_INFO_LEVELS, LPVOID,
+ FINDEX_SEARCH_OPS, LPVOID, DWORD, HANDLE);
+
+BOOL CopyFile(LPCTSTR, LPCTSTR, BOOL);
+
+BOOL CopyFileEx(LPCTSTR, LPCTSTR, LPPROGRESS_ROUTINE, LPVOID, LPBOOL, DWORD);
+
+BOOL CopyFileTransacted(LPCTSTR, LPCTSTR, LPPROGRESS_ROUTINE, LPVOID, LPBOOL,
+ DWORD, HANDLE);
+
+BOOL MoveFile(LPCTSTR, LPCTSTR);
+
+BOOL MoveFileEx(LPCTSTR, LPCTSTR, DWORD);
+
+BOOL MoveFileWithProgress(LPCTSTR, LPCTSTR, LPPROGRESS_ROUTINE, LPVOID, DWORD);
+
+BOOL MoveFileTransacted(LPCTSTR, LPCTSTR, LPPROGRESS_ROUTINE, LPVOID, DWORD,
+ HANDLE);
+
+BOOL ReplaceFile(LPCTSTR, LPCTSTR, LPCTSTR, DWORD, LPVOID, LPVOID);
+
+BOOL CreateHardLink(LPCTSTR, LPCTSTR, LPSECURITY_ATTRIBUTES);
+
+BOOL CreateHardLinkTransacted(LPCTSTR, LPCTSTR, LPSECURITY_ATTRIBUTES, HANDLE);
+
+HANDLE CreateNamedPipe(LPCTSTR, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD,
+ LPSECURITY_ATTRIBUTES);
+
+BOOL GetNamedPipeHandleState(HANDLE, LPDWORD, LPDWORD, LPDWORD, LPDWORD, LPTSTR,
+ DWORD);
+
+BOOL CallNamedPipe(LPCTSTR, LPVOID, DWORD, LPVOID, DWORD, LPDWORD, DWORD);
+
+BOOL WaitNamedPipe(LPCTSTR, DWORD);
+
+BOOL GetNamedPipeClientComputerName(HANDLE, LPTSTR, ULONG);
+
+BOOL SetVolumeLabel(LPCTSTR, LPCTSTR);
+
+BOOL ClearEventLog(HANDLE, LPCTSTR);
+
+BOOL BackupEventLog(HANDLE, LPCTSTR);
+
+HANDLE OpenEventLog(LPCTSTR, LPCTSTR);
+
+HANDLE RegisterEventSource(LPCTSTR, LPCTSTR);
+
+HANDLE OpenBackupEventLog(LPCTSTR, LPCTSTR);
+
+BOOL ReadEventLog(HANDLE, DWORD, DWORD, LPVOID, DWORD, DWORD*, DWORD*);
+
+BOOL ReportEvent(HANDLE, WORD, WORD, DWORD, PSID, WORD, DWORD, LPCTSTR*,
+ LPVOID);
+
+BOOL AccessCheckAndAuditAlarm(LPCTSTR, LPVOID, LPTSTR, LPTSTR,
+ PSECURITY_DESCRIPTOR, DWORD, PGENERIC_MAPPING,
+ BOOL, LPDWORD, LPBOOL, LPBOOL);
+
+BOOL AccessCheckByTypeAndAuditAlarm(LPCTSTR, LPVOID, LPCTSTR, LPCTSTR,
+ PSECURITY_DESCRIPTOR, PSID, DWORD,
+ AUDIT_EVENT_TYPE, DWORD, POBJECT_TYPE_LIST,
+ DWORD, PGENERIC_MAPPING, BOOL, LPDWORD,
+ LPBOOL, LPBOOL);
+
+BOOL AccessCheckByTypeResultListAndAuditAlarm(LPCTSTR, LPVOID, LPCTSTR, LPCTSTR,
+ PSECURITY_DESCRIPTOR, PSID, DWORD,
+ AUDIT_EVENT_TYPE, DWORD,
+ POBJECT_TYPE_LIST, DWORD,
+ PGENERIC_MAPPING, BOOL, LPDWORD,
+ LPDWORD, LPBOOL);
+
+BOOL AccessCheckByTypeResultListAndAuditAlarmByHandle(
+ LPCTSTR, LPVOID, HANDLE, LPCTSTR, LPCTSTR, PSECURITY_DESCRIPTOR, PSID,
+ DWORD, AUDIT_EVENT_TYPE, DWORD, POBJECT_TYPE_LIST, DWORD, PGENERIC_MAPPING,
+ BOOL, LPDWORD, LPDWORD, LPBOOL);
+
+BOOL ObjectOpenAuditAlarm(LPCTSTR, LPVOID, LPTSTR, LPTSTR, PSECURITY_DESCRIPTOR,
+ HANDLE, DWORD, DWORD, PPRIVILEGE_SET, BOOL, BOOL,
+ LPBOOL);
+
+BOOL ObjectPrivilegeAuditAlarm(LPCTSTR, LPVOID, HANDLE, DWORD, PPRIVILEGE_SET,
+ BOOL);
+
+BOOL ObjectCloseAuditAlarm(LPCTSTR, LPVOID, BOOL);
+
+BOOL ObjectDeleteAuditAlarm(LPCTSTR, LPVOID, BOOL);
+
+BOOL PrivilegedServiceAuditAlarm(LPCTSTR, LPCTSTR, HANDLE, PPRIVILEGE_SET,
+ BOOL);
+
+BOOL SetFileSecurity(LPCTSTR, SECURITY_INFORMATION, PSECURITY_DESCRIPTOR);
+
+BOOL GetFileSecurity(LPCTSTR, SECURITY_INFORMATION, PSECURITY_DESCRIPTOR, DWORD,
+ LPDWORD);
+
+BOOL IsBadStringPtr(LPCTSTR, UINT_PTR);
+
+BOOL LookupAccountSid(LPCTSTR, PSID, LPTSTR, LPDWORD, LPTSTR, LPDWORD,
+ PSID_NAME_USE);
+
+BOOL LookupAccountName(LPCTSTR, LPCTSTR, PSID, LPDWORD, LPTSTR, LPDWORD,
+ PSID_NAME_USE);
+
+BOOL LookupAccountNameLocal(LPCTSTR, PSID, LPDWORD, LPTSTR, LPDWORD,
+ PSID_NAME_USE);
+
+BOOL LookupAccountSidLocal(PSID, LPTSTR, LPDWORD, LPTSTR, LPDWORD,
+ PSID_NAME_USE);
+
+BOOL LookupPrivilegeValue(LPCTSTR, LPCTSTR, PLUID);
+
+BOOL LookupPrivilegeName(LPCTSTR, PLUID, LPTSTR, LPDWORD);
+
+BOOL LookupPrivilegeDisplayName(LPCTSTR, LPCTSTR, LPTSTR, LPDWORD, LPDWORD);
+
+BOOL BuildCommDCB(LPCTSTR, LPDCB);
+
+BOOL BuildCommDCBAndTimeouts(LPCTSTR, LPDCB, LPCOMMTIMEOUTS);
+
+BOOL CommConfigDialog(LPCTSTR, HWND, LPCOMMCONFIG);
+
+BOOL GetDefaultCommConfig(LPCTSTR, LPCOMMCONFIG, LPDWORD);
+
+BOOL SetDefaultCommConfig(LPCTSTR, LPCOMMCONFIG, DWORD);
+
+BOOL GetComputerName(LPTSTR, LPDWORD);
+
+BOOL DnsHostnameToComputerName(LPCTSTR, LPTSTR, LPDWORD);
+
+BOOL GetUserName(LPTSTR, LPDWORD);
+
+BOOL LogonUser(LPCTSTR, LPCTSTR, LPCTSTR, DWORD, DWORD, PHANDLE);
+
+BOOL LogonUserEx(LPCTSTR, LPCTSTR, LPCTSTR, DWORD, DWORD, PHANDLE, PSID*,
+ PVOID*, LPDWORD, PQUOTA_LIMITS);
+
+HANDLE CreatePrivateNamespace(LPSECURITY_ATTRIBUTES, LPVOID, LPCTSTR);
+
+HANDLE OpenPrivateNamespace(LPVOID, LPCTSTR);
+
+HANDLE CreateBoundaryDescriptor(LPCTSTR, ULONG);
+
+BOOL GetCurrentHwProfile(LPHW_PROFILE_INFO);
+
+BOOL VerifyVersionInfo(LPOSVERSIONINFOEX, DWORD, DWORDLONG);
+
+HANDLE CreateJobObject(LPSECURITY_ATTRIBUTES, LPCTSTR);
+
+HANDLE OpenJobObject(DWORD, BOOL, LPCTSTR);
+
+HANDLE FindFirstVolume(LPTSTR, DWORD);
+
+BOOL FindNextVolume(HANDLE, LPTSTR, DWORD);
+
+HANDLE FindFirstVolumeMountPoint(LPCTSTR, LPTSTR, DWORD);
+
+BOOL FindNextVolumeMountPoint(HANDLE, LPTSTR, DWORD);
+
+BOOL SetVolumeMountPoint(LPCTSTR, LPCTSTR);
+
+BOOL DeleteVolumeMountPoint(LPCTSTR);
+
+BOOL GetVolumeNameForVolumeMountPoint(LPCTSTR, LPTSTR, DWORD);
+
+BOOL GetVolumePathName(LPCTSTR, LPTSTR, DWORD);
+
+BOOL GetVolumePathNamesForVolumeName(LPCTSTR, LPTCH, DWORD, PDWORD);
+
+HANDLE CreateActCtx(PCACTCTX);
+
+BOOL FindActCtxSectionString(DWORD, const GUID*, ULONG, LPCTSTR,
+ PACTCTX_SECTION_KEYED_DATA);
+
+BOOLEAN CreateSymbolicLink(LPCTSTR, LPCTSTR, DWORD);
+
+BOOLEAN CreateSymbolicLinkTransacted(LPCTSTR, LPCTSTR, DWORD, HANDLE);
+
+int AddFontResource(LPCTSTR);
+
+HMETAFILE CopyMetaFile(HMETAFILE, LPCTSTR);
+
+HDC CreateDC(LPCTSTR, LPCTSTR, LPCTSTR, const DEVMODE*);
+
+HFONT CreateFontIndirect(const LOGFONT*);
+
+HFONT CreateFont(int, int, int, int, int, DWORD, DWORD, DWORD, DWORD, DWORD,
+ DWORD, DWORD, DWORD, LPCTSTR);
+
+HDC CreateIC(LPCTSTR, LPCTSTR, LPCTSTR, const DEVMODE*);
+
+HDC CreateMetaFile(LPCTSTR);
+
+BOOL CreateScalableFontResource(DWORD, LPCTSTR, LPCTSTR, LPCTSTR);
+
+int DeviceCapabilities(LPCTSTR, LPCTSTR, WORD, LPTSTR, const DEVMODE*);
+
+int EnumFontFamiliesEx(HDC, LPLOGFONT, FONTENUMPROC, LPARAM, DWORD);
+
+int EnumFontFamilies(HDC, LPCTSTR, FONTENUMPROC, LPARAM);
+
+int EnumFonts(HDC, LPCTSTR, FONTENUMPROC, LPARAM);
+
+BOOL GetCharWidth(HDC, UINT, UINT, LPINT);
+
+BOOL GetCharWidth32(HDC, UINT, UINT, LPINT);
+
+BOOL GetCharWidthFloat(HDC, UINT, UINT, PFLOAT);
+
+BOOL GetCharABCWidths(HDC, UINT, UINT, LPABC);
+
+BOOL GetCharABCWidthsFloat(HDC, UINT, UINT, LPABCFLOAT);
+
+DWORD GetGlyphOutline(HDC, UINT, UINT, LPGLYPHMETRICS, DWORD, LPVOID,
+ const MAT2*);
+
+HMETAFILE GetMetaFile(LPCTSTR);
+
+UINT GetOutlineTextMetrics(HDC, UINT, LPOUTLINETEXTMETRIC);
+
+BOOL GetTextExtentPoint(HDC, LPCTSTR, int, LPSIZE);
+
+BOOL GetTextExtentPoint32(HDC, LPCTSTR, int, LPSIZE);
+
+BOOL GetTextExtentExPoint(HDC, LPCTSTR, int, int, LPINT, LPINT, LPSIZE);
+
+DWORD GetCharacterPlacement(HDC, LPCTSTR, int, int, LPGCP_RESULTS, DWORD);
+
+DWORD GetGlyphIndices(HDC, LPCTSTR, int, LPWORD, DWORD);
+
+int AddFontResourceEx(LPCTSTR, DWORD, PVOID);
+
+BOOL RemoveFontResourceEx(LPCTSTR, DWORD, PVOID);
+
+HFONT CreateFontIndirectEx(const ENUMLOGFONTEXDV*);
+
+HDC ResetDC(HDC, const DEVMODE*);
+
+BOOL RemoveFontResource(LPCTSTR);
+
+HENHMETAFILE CopyEnhMetaFile(HENHMETAFILE, LPCTSTR);
+
+HDC CreateEnhMetaFile(HDC, LPCTSTR, const RECT*, LPCTSTR);
+
+HENHMETAFILE GetEnhMetaFile(LPCTSTR);
+
+UINT GetEnhMetaFileDescription(HENHMETAFILE, UINT, LPTSTR);
+
+BOOL GetTextMetrics(HDC, LPTEXTMETRIC);
+
+int StartDoc(HDC, const DOCINFO*);
+
+int GetObject(HANDLE, int, LPVOID);
+
+BOOL TextOut(HDC, int, int, LPCTSTR, int);
+
+BOOL ExtTextOut(HDC, int, int, UINT, const RECT*, LPCTSTR, UINT, const INT*);
+
+BOOL PolyTextOut(HDC, const POLYTEXT*, int);
+
+int GetTextFace(HDC, int, LPTSTR);
+
+DWORD GetKerningPairs(HDC, DWORD, LPKERNINGPAIR);
+
+BOOL GetLogColorSpace(HCOLORSPACE, LPLOGCOLORSPACE, DWORD);
+
+HCOLORSPACE CreateColorSpace(LPLOGCOLORSPACE);
+
+BOOL GetICMProfile(HDC, LPDWORD, LPTSTR);
+
+BOOL SetICMProfile(HDC, LPTSTR);
+
+int EnumICMProfiles(HDC, ICMENUMPROC, LPARAM);
+
+BOOL UpdateICMRegKey(DWORD, LPTSTR, LPTSTR, UINT);
+
+HKL LoadKeyboardLayout(LPCTSTR, UINT);
+
+BOOL GetKeyboardLayoutName(LPTSTR);
+
+HDESK CreateDesktop(LPCTSTR, LPCTSTR, DEVMODE*, DWORD, ACCESS_MASK,
+ LPSECURITY_ATTRIBUTES);
+
+HDESK CreateDesktopEx(LPCTSTR, LPCTSTR, DEVMODE*, DWORD, ACCESS_MASK,
+ LPSECURITY_ATTRIBUTES, ULONG, PVOID);
+
+HDESK OpenDesktop(LPCTSTR, DWORD, BOOL, ACCESS_MASK);
+
+BOOL EnumDesktops(HWINSTA, DESKTOPENUMPROC, LPARAM);
+
+HWINSTA CreateWindowStation(LPCTSTR, DWORD, ACCESS_MASK, LPSECURITY_ATTRIBUTES);
+
+HWINSTA OpenWindowStation(LPCTSTR, BOOL, ACCESS_MASK);
+
+BOOL EnumWindowStations(WINSTAENUMPROC, LPARAM);
+
+BOOL GetUserObjectInformation(HANDLE, int, PVOID, DWORD, LPDWORD);
+
+BOOL SetUserObjectInformation(HANDLE, int, PVOID, DWORD);
+
+UINT RegisterWindowMessage(LPCTSTR);
+
+BOOL GetMessage(LPMSG, HWND, UINT, UINT);
+
+LRESULT DispatchMessage(const MSG*);
+
+BOOL PeekMessage(LPMSG, HWND, UINT, UINT, UINT);
+
+LRESULT SendMessage(HWND, UINT, WPARAM, LPARAM);
+
+LRESULT SendMessageTimeout(HWND, UINT, WPARAM, LPARAM, UINT, UINT, PDWORD_PTR);
+
+BOOL SendNotifyMessage(HWND, UINT, WPARAM, LPARAM);
+
+BOOL SendMessageCallback(HWND, UINT, WPARAM, LPARAM, SENDASYNCPROC, ULONG_PTR);
+
+long BroadcastSystemMessageEx(DWORD, LPDWORD, UINT, WPARAM, LPARAM, PBSMINFO);
+
+long BroadcastSystemMessage(DWORD, LPDWORD, UINT, WPARAM, LPARAM);
+
+HDEVNOTIFY RegisterDeviceNotification(HANDLE, LPVOID, DWORD);
+
+BOOL PostMessage(HWND, UINT, WPARAM, LPARAM);
+
+BOOL PostThreadMessage(DWORD, UINT, WPARAM, LPARAM);
+
+BOOL PostAppMessage(DWORD, UINT, WPARAM, LPARAM);
+
+LRESULT DefWindowProc(HWND, UINT, WPARAM, LPARAM);
+
+LRESULT CallWindowProc(WNDPROC, HWND, UINT, WPARAM, LPARAM);
+
+ATOM RegisterClass(const WNDCLASS*);
+
+BOOL UnregisterClass(LPCTSTR, HINSTANCE);
+
+BOOL GetClassInfo(HINSTANCE, LPCTSTR, LPWNDCLASS);
+
+ATOM RegisterClassEx(const WNDCLASSEX*);
+
+BOOL GetClassInfoEx(HINSTANCE, LPCTSTR, LPWNDCLASSEX);
+
+HWND CreateWindowEx(DWORD, LPCTSTR, LPCTSTR, DWORD, int, int, int, int, HWND,
+ HMENU, HINSTANCE, LPVOID);
+
+HWND CreateWindow(LPCTSTR, LPCTSTR, DWORD, int, int, int, int, HWND, HMENU,
+ HINSTANCE, LPVOID);
+
+HWND CreateDialogParam(HINSTANCE, LPCTSTR, HWND, DLGPROC, LPARAM);
+
+HWND CreateDialogIndirectParam(HINSTANCE, LPCDLGTEMPLATE, HWND, DLGPROC,
+ LPARAM);
+
+HWND CreateDialog(HINSTANCE, LPCTSTR, HWND, DLGPROC);
+
+HWND CreateDialogIndirect(HINSTANCE, LPCDLGTEMPLATE, HWND, DLGPROC);
+
+INT_PTR DialogBoxParam(HINSTANCE, LPCTSTR, HWND, DLGPROC, LPARAM);
+
+INT_PTR DialogBoxIndirectParam(HINSTANCE, LPCDLGTEMPLATE, HWND, DLGPROC,
+ LPARAM);
+
+INT_PTR DialogBox(HINSTANCE, LPCTSTR, HWND, DLGPROC);
+
+INT_PTR DialogBoxIndirect(HINSTANCE, LPCDLGTEMPLATE, HWND, DLGPROC);
+
+BOOL SetDlgItemText(HWND, int, LPCTSTR);
+
+UINT GetDlgItemText(HWND, int, LPTSTR, int);
+
+LRESULT SendDlgItemMessage(HWND, int, UINT, WPARAM, LPARAM);
+
+LRESULT DefDlgProc(HWND, UINT, WPARAM, LPARAM);
+
+BOOL CallMsgFilter(LPMSG, int);
+
+UINT RegisterClipboardFormat(LPCTSTR);
+
+int GetClipboardFormatName(UINT, LPTSTR, int);
+
+BOOL CharToOem(LPCTSTR, LPSTR);
+
+BOOL OemToChar(LPCSTR, LPTSTR);
+
+BOOL CharToOemBuff(LPCTSTR, LPSTR, DWORD);
+
+BOOL OemToCharBuff(LPCSTR, LPTSTR, DWORD);
+
+LPTSTR CharUpper(LPTSTR);
+
+DWORD CharUpperBuff(LPTSTR, DWORD);
+
+LPTSTR CharLower(LPTSTR);
+
+DWORD CharLowerBuff(LPTSTR, DWORD);
+
+LPTSTR CharNext(LPCTSTR);
+
+LPTSTR CharPrev(LPCTSTR, LPCTSTR);
+
+BOOL IsCharAlpha(CHAR);
+
+BOOL IsCharAlphaNumeric(CHAR);
+
+BOOL IsCharUpper(CHAR);
+
+BOOL IsCharLower(CHAR);
+
+int GetKeyNameText(LONG, LPTSTR, int);
+
+SHORT VkKeyScan(CHAR);
+
+SHORT VkKeyScanEx(CHAR, HKL);
+
+UINT MapVirtualKey(UINT, UINT);
+
+UINT MapVirtualKeyEx(UINT, UINT, HKL);
+
+HACCEL LoadAccelerators(HINSTANCE, LPCTSTR);
+
+HACCEL CreateAcceleratorTable(LPACCEL, int);
+
+int CopyAcceleratorTable(HACCEL, LPACCEL, int);
+
+int TranslateAccelerator(HWND, HACCEL, LPMSG);
+
+HMENU LoadMenu(HINSTANCE, LPCTSTR);
+
+HMENU LoadMenuIndirect(const MENUTEMPLATE*);
+
+BOOL ChangeMenu(HMENU, UINT, LPCTSTR, UINT, UINT);
+
+int GetMenuString(HMENU, UINT, LPTSTR, int, UINT);
+
+BOOL InsertMenu(HMENU, UINT, UINT, UINT_PTR, LPCTSTR);
+
+BOOL AppendMenu(HMENU, UINT, UINT_PTR, LPCTSTR);
+
+BOOL ModifyMenu(HMENU, UINT, UINT, UINT_PTR, LPCTSTR);
+
+BOOL InsertMenuItem(HMENU, UINT, BOOL, LPCMENUITEMINFO);
+
+BOOL GetMenuItemInfo(HMENU, UINT, BOOL, LPMENUITEMINFO);
+
+BOOL SetMenuItemInfo(HMENU, UINT, BOOL, LPCMENUITEMINFO);
+
+int DrawText(HDC, LPCTSTR, int, LPRECT, UINT);
+
+int DrawTextEx(HDC, LPTSTR, int, LPRECT, UINT, LPDRAWTEXTPARAMS);
+
+BOOL GrayString(HDC, HBRUSH, GRAYSTRINGPROC, LPARAM, int, int, int, int, int);
+
+BOOL DrawState(HDC, HBRUSH, DRAWSTATEPROC, LPARAM, WPARAM, int, int, int, int,
+ UINT);
+
+LONG TabbedTextOut(HDC, int, int, LPCTSTR, int, int, const INT*, int);
+
+DWORD GetTabbedTextExtent(HDC, LPCTSTR, int, int, const INT*);
+
+BOOL SetProp(HWND, LPCTSTR, HANDLE);
+
+HANDLE GetProp(HWND, LPCTSTR);
+
+HANDLE RemoveProp(HWND, LPCTSTR);
+
+int EnumPropsEx(HWND, PROPENUMPROCEX, LPARAM);
+
+int EnumProps(HWND, PROPENUMPROC);
+
+BOOL SetWindowText(HWND, LPCTSTR);
+
+int GetWindowText(HWND, LPTSTR, int);
+
+int GetWindowTextLength(HWND);
+
+int MessageBox(HWND, LPCTSTR, LPCTSTR, UINT);
+
+int MessageBoxEx(HWND, LPCTSTR, LPCTSTR, UINT, WORD);
+
+int MessageBoxIndirect(const MSGBOXPARAMS*);
+
+LONG GetWindowLong(HWND, int);
+
+LONG SetWindowLong(HWND, int, LONG);
+
+LONG_PTR GetWindowLongPtr(HWND, int);
+
+LONG_PTR SetWindowLongPtr(HWND, int, LONG_PTR);
+
+DWORD GetClassLong(HWND, int);
+
+DWORD SetClassLong(HWND, int, LONG);
+
+ULONG_PTR GetClassLongPtr(HWND, int);
+
+ULONG_PTR SetClassLongPtr(HWND, int, LONG_PTR);
+
+HWND FindWindow(LPCTSTR, LPCTSTR);
+
+HWND FindWindowEx(HWND, HWND, LPCTSTR, LPCTSTR);
+
+int GetClassName(HWND, LPTSTR, int);
+
+HHOOK SetWindowsHook(int, HOOKPROC);
+
+HHOOK SetWindowsHookEx(int, HOOKPROC, HINSTANCE, DWORD);
+
+HBITMAP LoadBitmap(HINSTANCE, LPCTSTR);
+
+HCURSOR LoadCursor(HINSTANCE, LPCTSTR);
+
+HCURSOR LoadCursorFromFile(LPCTSTR);
+
+HICON LoadIcon(HINSTANCE, LPCTSTR);
+
+UINT PrivateExtractIcons(LPCTSTR, int, int, int, HICON*, UINT*, UINT, UINT);
+
+HANDLE LoadImage(HINSTANCE, LPCTSTR, UINT, int, int, UINT);
+
+BOOL GetIconInfoEx(HICON, PICONINFOEX);
+
+BOOL IsDialogMessage(HWND, LPMSG);
+
+int DlgDirList(HWND, LPTSTR, int, int, UINT);
+
+BOOL DlgDirSelectEx(HWND, LPTSTR, int, int);
+
+int DlgDirListComboBox(HWND, LPTSTR, int, int, UINT);
+
+BOOL DlgDirSelectComboBoxEx(HWND, LPTSTR, int, int);
+
+LRESULT DefFrameProc(HWND, HWND, UINT, WPARAM, LPARAM);
+
+LRESULT DefMDIChildProc(HWND, UINT, WPARAM, LPARAM);
+
+HWND CreateMDIWindow(LPCTSTR, LPCTSTR, DWORD, int, int, int, int, HWND,
+ HINSTANCE, LPARAM);
+
+BOOL WinHelp(HWND, LPCTSTR, UINT, ULONG_PTR);
+
+LONG ChangeDisplaySettings(DEVMODE*, DWORD);
+
+LONG ChangeDisplaySettingsEx(LPCTSTR, DEVMODE*, HWND, DWORD, LPVOID);
+
+BOOL EnumDisplaySettings(LPCTSTR, DWORD, DEVMODE*);
+
+BOOL EnumDisplaySettingsEx(LPCTSTR, DWORD, DEVMODE*, DWORD);
+
+BOOL EnumDisplayDevices(LPCTSTR, DWORD, PDISPLAY_DEVICE, DWORD);
+
+BOOL SystemParametersInfo(UINT, UINT, PVOID, UINT);
+
+BOOL GetMonitorInfo(HMONITOR, LPMONITORINFO);
+
+UINT GetWindowModuleFileName(HWND, LPTSTR, UINT);
+
+UINT RealGetWindowClass(HWND, LPTSTR, UINT);
+
+BOOL GetAltTabInfo(HWND, int, PALTTABINFO, LPTSTR, UINT);
+
+UINT GetRawInputDeviceInfo(HANDLE, UINT, LPVOID, PUINT);
+
+int GetDateFormat(LCID, DWORD, const SYSTEMTIME*, LPCTSTR, LPTSTR, int);
+
+int GetTimeFormat(LCID, DWORD, const SYSTEMTIME*, LPCTSTR, LPTSTR, int);
+
+BOOL GetCPInfoEx(UINT, DWORD, LPCPINFOEX);
+
+int CompareString(LCID, DWORD, PCNZTCH, int, PCNZTCH, int);
+
+int GetLocaleInfo(LCID, LCTYPE, LPTSTR, int);
+
+BOOL SetLocaleInfo(LCID, LCTYPE, LPCTSTR);
+
+int GetCalendarInfo(LCID, CALID, CALTYPE, LPTSTR, int, LPDWORD);
+
+BOOL SetCalendarInfo(LCID, CALID, CALTYPE, LPCTSTR);
+
+int GetNumberFormat(LCID, DWORD, LPCTSTR, const NUMBERFMT*, LPTSTR, int);
+
+int GetCurrencyFormat(LCID, DWORD, LPCTSTR, const CURRENCYFMT*, LPTSTR, int);
+
+BOOL EnumCalendarInfo(CALINFO_ENUMPROC, LCID, CALID, CALTYPE);
+
+BOOL EnumCalendarInfoEx(CALINFO_ENUMPROCEX, LCID, CALID, CALTYPE);
+
+BOOL EnumTimeFormats(TIMEFMT_ENUMPROC, LCID, DWORD);
+
+BOOL EnumDateFormats(DATEFMT_ENUMPROC, LCID, DWORD);
+
+BOOL EnumDateFormatsEx(DATEFMT_ENUMPROCEX, LCID, DWORD);
+
+int GetGeoInfo(GEOID, GEOTYPE, LPTSTR, int, LANGID);
+
+BOOL GetStringTypeEx(LCID, DWORD, LPCTSTR, int, LPWORD);
+
+int FoldString(DWORD, LPCTSTR, int, LPTSTR, int);
+
+BOOL EnumSystemLocales(LOCALE_ENUMPROC, DWORD);
+
+BOOL EnumSystemLanguageGroups(LANGUAGEGROUP_ENUMPROC, DWORD, LONG_PTR);
+
+BOOL EnumLanguageGroupLocales(LANGGROUPLOCALE_ENUMPROC, LGRPID, DWORD,
+ LONG_PTR);
+
+BOOL EnumUILanguages(UILANGUAGE_ENUMPROC, DWORD, LONG_PTR);
+
+BOOL EnumSystemCodePages(CODEPAGE_ENUMPROC, DWORD);
+
+BOOL ReadConsoleInput(HANDLE, PINPUT_RECORD, DWORD, LPDWORD);
+
+BOOL PeekConsoleInput(HANDLE, PINPUT_RECORD, DWORD, LPDWORD);
+
+BOOL ReadConsole(HANDLE, LPVOID, DWORD, LPDWORD, PCONSOLE_READCONSOLE_CONTROL);
+
+BOOL WriteConsole(HANDLE, const void*, DWORD, LPDWORD, LPVOID);
+
+BOOL FillConsoleOutputCharacter(HANDLE, CHAR, DWORD, COORD, LPDWORD);
+
+BOOL WriteConsoleOutputCharacter(HANDLE, LPCTSTR, DWORD, COORD, LPDWORD);
+
+BOOL ReadConsoleOutputCharacter(HANDLE, LPTSTR, DWORD, COORD, LPDWORD);
+
+BOOL WriteConsoleInput(HANDLE, const INPUT_RECORD*, DWORD, LPDWORD);
+
+BOOL ScrollConsoleScreenBuffer(HANDLE, const SMALL_RECT*, const SMALL_RECT*,
+ COORD, const CHAR_INFO*);
+
+BOOL WriteConsoleOutput(HANDLE, const CHAR_INFO*, COORD, COORD, PSMALL_RECT);
+
+BOOL ReadConsoleOutput(HANDLE, PCHAR_INFO, COORD, COORD, PSMALL_RECT);
+
+DWORD GetConsoleTitle(LPTSTR, DWORD);
+
+DWORD GetConsoleOriginalTitle(LPTSTR, DWORD);
+
+BOOL SetConsoleTitle(LPCTSTR);
+
+BOOL AddConsoleAlias(LPTSTR, LPTSTR, LPTSTR);
+
+DWORD GetConsoleAlias(LPTSTR, LPTSTR, DWORD, LPTSTR);
+
+DWORD GetConsoleAliasesLength(LPTSTR);
+
+DWORD GetConsoleAliasExesLength();
+
+DWORD GetConsoleAliases(LPTSTR, DWORD, LPTSTR);
+
+DWORD GetConsoleAliasExes(LPTSTR, DWORD);
+
+void ExpungeConsoleCommandHistory(LPTSTR);
+
+BOOL SetConsoleNumberOfCommands(DWORD, LPTSTR);
+
+DWORD GetConsoleCommandHistoryLength(LPTSTR);
+
+DWORD GetConsoleCommandHistory(LPTSTR, DWORD, LPTSTR);
+
+DWORD VerFindFile(DWORD, LPTSTR, LPTSTR, LPTSTR, LPTSTR, PUINT, LPTSTR, PUINT);
+
+DWORD VerInstallFile(DWORD, LPTSTR, LPTSTR, LPTSTR, LPTSTR, LPTSTR, LPTSTR,
+ PUINT);
+
+DWORD GetFileVersionInfoSize(LPCTSTR, LPDWORD);
+
+BOOL GetFileVersionInfo(LPCTSTR, DWORD, DWORD, LPVOID);
+
+DWORD GetFileVersionInfoSizeEx(DWORD, LPCTSTR, LPDWORD);
+
+BOOL GetFileVersionInfoEx(DWORD, LPCTSTR, DWORD, DWORD, LPVOID);
+
+DWORD VerLanguageName(DWORD, LPTSTR, DWORD);
+
+BOOL VerQueryValue(LPCVOID, LPCTSTR, LPVOID*, PUINT);
+
+LSTATUS RegConnectRegistry(LPCTSTR, HKEY, PHKEY);
+
+LSTATUS RegConnectRegistryEx(LPCTSTR, HKEY, ULONG, PHKEY);
+
+LSTATUS RegCreateKey(HKEY, LPCTSTR, PHKEY);
+
+LSTATUS RegCreateKeyEx(HKEY, LPCTSTR, DWORD, LPTSTR, DWORD, REGSAM,
+ const LPSECURITY_ATTRIBUTES, PHKEY, LPDWORD);
+
+LSTATUS RegCreateKeyTransacted(HKEY, LPCTSTR, DWORD, LPTSTR, DWORD, REGSAM,
+ const LPSECURITY_ATTRIBUTES, PHKEY, LPDWORD,
+ HANDLE, PVOID);
+
+LSTATUS RegDeleteKey(HKEY, LPCTSTR);
+
+LSTATUS RegDeleteKeyEx(HKEY, LPCTSTR, REGSAM, DWORD);
+
+LSTATUS RegDeleteKeyTransacted(HKEY, LPCTSTR, REGSAM, DWORD, HANDLE, PVOID);
+
+LSTATUS RegDeleteValue(HKEY, LPCTSTR);
+
+LSTATUS RegEnumKey(HKEY, DWORD, LPTSTR, DWORD);
+
+LSTATUS RegEnumKeyEx(HKEY, DWORD, LPTSTR, LPDWORD, LPDWORD, LPTSTR, LPDWORD,
+ PFILETIME);
+
+LSTATUS RegEnumValue(HKEY, DWORD, LPTSTR, LPDWORD, LPDWORD, LPDWORD, LPBYTE,
+ LPDWORD);
+
+LSTATUS RegLoadKey(HKEY, LPCTSTR, LPCTSTR);
+
+LSTATUS RegOpenKey(HKEY, LPCTSTR, PHKEY);
+
+LSTATUS RegOpenKeyEx(HKEY, LPCTSTR, DWORD, REGSAM, PHKEY);
+
+LSTATUS RegOpenKeyTransacted(HKEY, LPCTSTR, DWORD, REGSAM, PHKEY, HANDLE,
+ PVOID);
+
+LSTATUS RegQueryInfoKey(HKEY, LPTSTR, LPDWORD, LPDWORD, LPDWORD, LPDWORD,
+ LPDWORD, LPDWORD, LPDWORD, LPDWORD, LPDWORD, PFILETIME);
+
+LSTATUS RegQueryValue(HKEY, LPCTSTR, LPTSTR, PLONG);
+
+LSTATUS RegQueryMultipleValues(HKEY, PVALENT, DWORD, LPTSTR, LPDWORD);
+
+LSTATUS RegQueryValueEx(HKEY, LPCTSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD);
+
+LSTATUS RegReplaceKey(HKEY, LPCTSTR, LPCTSTR, LPCTSTR);
+
+LSTATUS RegRestoreKey(HKEY, LPCTSTR, DWORD);
+
+LSTATUS RegSaveKey(HKEY, LPCTSTR, const LPSECURITY_ATTRIBUTES);
+
+LSTATUS RegSetValue(HKEY, LPCTSTR, DWORD, LPCTSTR, DWORD);
+
+LSTATUS RegSetValueEx(HKEY, LPCTSTR, DWORD, DWORD, const BYTE*, DWORD);
+
+LSTATUS RegUnLoadKey(HKEY, LPCTSTR);
+
+LSTATUS RegDeleteKeyValue(HKEY, LPCTSTR, LPCTSTR);
+
+LSTATUS RegSetKeyValue(HKEY, LPCTSTR, LPCTSTR, DWORD, LPCVOID, DWORD);
+
+LSTATUS RegDeleteTree(HKEY, LPCTSTR);
+
+LSTATUS RegCopyTree(HKEY, LPCTSTR, HKEY);
+
+LSTATUS RegGetValue(HKEY, LPCTSTR, LPCTSTR, DWORD, LPDWORD, PVOID, LPDWORD);
+
+LSTATUS RegLoadMUIString(HKEY, LPCTSTR, LPTSTR, DWORD, LPDWORD, DWORD, LPCTSTR);
+
+LSTATUS RegLoadAppKey(LPCTSTR, PHKEY, REGSAM, DWORD, DWORD);
+
+BOOL InitiateSystemShutdown(LPTSTR, LPTSTR, DWORD, BOOL, BOOL);
+
+BOOL AbortSystemShutdown(LPTSTR);
+
+BOOL InitiateSystemShutdownEx(LPTSTR, LPTSTR, DWORD, BOOL, BOOL, DWORD);
+
+DWORD InitiateShutdown(LPTSTR, LPTSTR, DWORD, DWORD, DWORD);
+
+LSTATUS RegSaveKeyEx(HKEY, LPCTSTR, const LPSECURITY_ATTRIBUTES, DWORD);
+
+DWORD MultinetGetConnectionPerformance(LPNETRESOURCE, LPNETCONNECTINFOSTRUCT);
+
+BOOL ChangeServiceConfig(SC_HANDLE, DWORD, DWORD, DWORD, LPCTSTR, LPCTSTR,
+ LPDWORD, LPCTSTR, LPCTSTR, LPCTSTR, LPCTSTR);
+
+BOOL ChangeServiceConfig2(SC_HANDLE, DWORD, LPVOID);
+
+SC_HANDLE CreateService(SC_HANDLE, LPCTSTR, LPCTSTR, DWORD, DWORD, DWORD, DWORD,
+ LPCTSTR, LPCTSTR, LPDWORD, LPCTSTR, LPCTSTR, LPCTSTR);
+
+BOOL EnumDependentServices(SC_HANDLE, DWORD, LPENUM_SERVICE_STATUS, DWORD,
+ LPDWORD, LPDWORD);
+
+BOOL EnumServicesStatus(SC_HANDLE, DWORD, DWORD, LPENUM_SERVICE_STATUS, DWORD,
+ LPDWORD, LPDWORD, LPDWORD);
+
+BOOL EnumServicesStatusEx(SC_HANDLE, SC_ENUM_TYPE, DWORD, DWORD, LPBYTE, DWORD,
+ LPDWORD, LPDWORD, LPDWORD, LPCTSTR);
+
+BOOL GetServiceKeyName(SC_HANDLE, LPCTSTR, LPTSTR, LPDWORD);
+
+BOOL GetServiceDisplayName(SC_HANDLE, LPCTSTR, LPTSTR, LPDWORD);
+
+SC_HANDLE OpenSCManager(LPCTSTR, LPCTSTR, DWORD);
+
+SC_HANDLE OpenService(SC_HANDLE, LPCTSTR, DWORD);
+
+BOOL QueryServiceConfig(SC_HANDLE, LPQUERY_SERVICE_CONFIG, DWORD, LPDWORD);
+
+BOOL QueryServiceConfig2(SC_HANDLE, DWORD, LPBYTE, DWORD, LPDWORD);
+
+BOOL QueryServiceLockStatus(SC_HANDLE, LPQUERY_SERVICE_LOCK_STATUS, DWORD,
+ LPDWORD);
+
+SERVICE_STATUS_HANDLE RegisterServiceCtrlHandler(LPCTSTR, LPHANDLER_FUNCTION);
+
+SERVICE_STATUS_HANDLE RegisterServiceCtrlHandlerEx(LPCTSTR,
+ LPHANDLER_FUNCTION_EX,
+ LPVOID);
+
+BOOL StartServiceCtrlDispatcher(const SERVICE_TABLE_ENTRY*);
+
+BOOL StartService(SC_HANDLE, DWORD, LPCTSTR*);
+
+DWORD NotifyServiceStatusChange(SC_HANDLE, DWORD, PSERVICE_NOTIFY);
+
+BOOL ControlServiceEx(SC_HANDLE, DWORD, DWORD, PVOID);
+
+HKL ImmInstallIME(LPCTSTR, LPCTSTR);
+
+UINT ImmGetDescription(HKL, LPTSTR, UINT);
+
+UINT ImmGetIMEFileName(HKL, LPTSTR, UINT);
+
+LONG ImmGetCompositionString(HIMC, DWORD, LPVOID, DWORD);
+
+BOOL ImmSetCompositionString(HIMC, DWORD, LPVOID, DWORD, LPVOID, DWORD);
+
+DWORD ImmGetCandidateListCount(HIMC, LPDWORD);
+
+DWORD ImmGetCandidateList(HIMC, DWORD, LPCANDIDATELIST, DWORD);
+
+DWORD ImmGetGuideLine(HIMC, DWORD, LPTSTR, DWORD);
+
+BOOL ImmGetCompositionFont(HIMC, LPLOGFONT);
+
+BOOL ImmSetCompositionFont(HIMC, LPLOGFONT);
+
+BOOL ImmConfigureIME(HKL, HWND, DWORD, LPVOID);
+
+LRESULT ImmEscape(HKL, HIMC, UINT, LPVOID);
+
+DWORD ImmGetConversionList(HKL, HIMC, LPCTSTR, LPCANDIDATELIST, DWORD, UINT);
+
+BOOL ImmIsUIMessage(HWND, UINT, WPARAM, LPARAM);
+
+BOOL ImmRegisterWord(HKL, LPCTSTR, DWORD, LPCTSTR);
+
+BOOL ImmUnregisterWord(HKL, LPCTSTR, DWORD, LPCTSTR);
+
+UINT ImmGetRegisterWordStyle(HKL, UINT, LPSTYLEBUF);
+
+UINT ImmEnumRegisterWord(HKL, REGISTERWORDENUMPROC, LPCTSTR, DWORD, LPCTSTR,
+ LPVOID);
+
+DWORD ImmGetImeMenuItems(HIMC, DWORD, DWORD, LPIMEMENUITEMINFO,
+ LPIMEMENUITEMINFO, DWORD);
diff --git a/config/windows-h-wrapper.template.h b/config/windows-h-wrapper.template.h
new file mode 100644
index 0000000000..75879d23cc
--- /dev/null
+++ b/config/windows-h-wrapper.template.h
@@ -0,0 +1,45 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* 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/. */
+
+#ifndef mozilla_windows_h
+#define mozilla_windows_h
+
+// Include the "real" windows.h header.
+//
+// Also turn off deprecation warnings, as we may be wrapping deprecated fns.
+
+#pragma GCC system_header
+#include_next <windows.h>
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+
+// Check if the header should be disabled
+#if defined(MOZ_DISABLE_WINDOWS_WRAPPER)
+# define MOZ_WINDOWS_WRAPPER_DISABLED_REASON "explicitly disabled"
+
+#elif !defined(__cplusplus)
+# define MOZ_WINDOWS_WRAPPER_DISABLED_REASON "non-C++ source file"
+
+#else
+// We're allowed to wrap in the current context. Define `MOZ_WRAPPED_WINDOWS_H`
+// to note that fact, and perform the wrapping.
+# define MOZ_WRAPPED_WINDOWS_H
+extern "C++" {
+
+// clang-format off
+${decls}
+// clang-format on
+
+} // extern "C++"
+
+# undef GetCurrentTime // Use GetTickCount() instead.
+
+#endif // enabled
+
+#pragma GCC diagnostic pop
+
+#endif // !defined(mozilla_windows_h)