summaryrefslogtreecommitdiffstats
path: root/config
diff options
context:
space:
mode:
Diffstat (limited to 'config')
-rw-r--r--config/Makefile.in103
-rw-r--r--config/Moz/Milestone.pm220
-rw-r--r--config/MozZipFile.py137
-rw-r--r--config/android-common.mk51
-rw-r--r--config/autoconf-js.mk.in6
-rw-r--r--config/autoconf.mk.in6
-rw-r--r--config/baseconfig.mk56
-rw-r--r--config/check_js_msg_encoding.py68
-rw-r--r--config/check_macroassembler_style.py283
-rwxr-xr-xconfig/check_source_count.py57
-rw-r--r--config/check_spidermonkey_style.py589
-rw-r--r--config/check_vanilla_allocations.py191
-rw-r--r--config/config.mk604
-rw-r--r--config/createprecomplete.py67
-rw-r--r--config/doxygen.cfg.in1364
-rw-r--r--config/emptyvars-js.mk.in1
-rw-r--r--config/emptyvars.mk.in1
-rw-r--r--config/expandlibs.py143
-rw-r--r--config/expandlibs_config.py27
-rw-r--r--config/expandlibs_exec.py354
-rw-r--r--config/expandlibs_gen.py41
-rw-r--r--config/external/fdlibm/moz.build12
-rw-r--r--config/external/ffi/Makefile.in12
-rw-r--r--config/external/ffi/moz.build107
-rw-r--r--config/external/ffi/subst_header.py25
-rw-r--r--config/external/freetype2/Makefile.in12
-rw-r--r--config/external/freetype2/moz.build14
-rw-r--r--config/external/icu/common/moz.build18
-rw-r--r--config/external/icu/common/sources.mozbuild281
-rw-r--r--config/external/icu/data/icudata.s31
-rw-r--r--config/external/icu/data/icudata_gas.S12
-rw-r--r--config/external/icu/data/icudt58l.datbin0 -> 10912128 bytes
-rw-r--r--config/external/icu/data/moz.build31
-rw-r--r--config/external/icu/defs.mozbuild49
-rw-r--r--config/external/icu/i18n/moz.build15
-rw-r--r--config/external/icu/i18n/sources.mozbuild280
-rw-r--r--config/external/icu/moz.build21
-rw-r--r--config/external/icu/stubdata/moz.build13
-rw-r--r--config/external/lgpllibs/lgpllibs.def10
-rw-r--r--config/external/lgpllibs/moz.build18
-rw-r--r--config/external/moz.build67
-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.build232
-rw-r--r--config/external/nspr/prcpucfg.h29
-rw-r--r--config/external/nss/Makefile.in488
-rw-r--r--config/external/nss/crmf/moz.build20
-rw-r--r--config/external/nss/moz.build42
-rw-r--r--config/external/nss/nss.mk27
-rw-r--r--config/external/nss/nss.symbols724
-rw-r--r--config/external/sqlite/moz.build22
-rw-r--r--config/external/zlib/moz.build21
-rw-r--r--config/faster/rules.mk110
-rw-r--r--config/find_OOM_errors.py352
-rw-r--r--config/gcc-stl-wrapper.template.h69
-rw-r--r--config/gcc_hidden.h6
-rw-r--r--config/install.bat10
-rw-r--r--config/link.py47
-rw-r--r--config/make-stl-wrappers.py52
-rw-r--r--config/makefiles/autotargets.mk94
-rw-r--r--config/makefiles/debugmake.mk119
-rw-r--r--config/makefiles/functions.mk30
-rw-r--r--config/makefiles/java-build.mk159
-rw-r--r--config/makefiles/makeutils.mk121
-rw-r--r--config/makefiles/nonrecursive.mk68
-rw-r--r--config/makefiles/target_binaries.mk42
-rw-r--r--config/makefiles/test/Makefile.in98
-rw-r--r--config/makefiles/test/check-arglist.mk100
-rw-r--r--config/makefiles/test/check-autotargets.mk84
-rw-r--r--config/makefiles/test/check_XinY.mk70
-rw-r--r--config/makefiles/test/moz.build6
-rw-r--r--config/makefiles/xpidl/Makefile.in93
-rw-r--r--config/milestone.txt13
-rw-r--r--config/moz.build49
-rw-r--r--config/mozunit.py207
-rw-r--r--config/msvc-stl-wrapper.template.h81
-rw-r--r--config/nsinstall.c451
-rwxr-xr-xconfig/nsinstall.py182
-rw-r--r--config/pathsub.c215
-rw-r--r--config/pathsub.h42
-rw-r--r--config/printconfigsetting.py31
-rw-r--r--config/printprereleasesuffix.py31
-rw-r--r--config/pythonpath.py56
-rw-r--r--config/rebuild_check.py44
-rw-r--r--config/recurse.mk180
-rw-r--r--config/rules.mk1541
-rw-r--r--config/static-checking-config.mk12
-rw-r--r--config/stl-headers49
-rw-r--r--config/string-format.js65
-rw-r--r--config/system-headers1337
-rw-r--r--config/tests/chrome.manifest.flat4
-rw-r--r--config/tests/makefiles/autodeps/Makefile.in36
-rw-r--r--config/tests/makefiles/autodeps/check_mkdir.tpy269
-rw-r--r--config/tests/makefiles/autodeps/moz.build6
-rw-r--r--config/tests/makefiles/autodeps/testor.tmpl64
-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.py116
-rw-r--r--config/tests/unit-expandlibs.py431
-rw-r--r--config/tests/unit-mozunit.py86
-rw-r--r--config/tests/unit-nsinstall.py174
-rw-r--r--config/tests/unit-printprereleasesuffix.py80
-rw-r--r--config/tests/unitMozZipFile.py201
-rw-r--r--config/version.mk51
-rwxr-xr-xconfig/version_win.pl374
122 files changed, 15434 insertions, 0 deletions
diff --git a/config/Makefile.in b/config/Makefile.in
new file mode 100644
index 000000000..10807cfb9
--- /dev/null
+++ b/config/Makefile.in
@@ -0,0 +1,103 @@
+# -*- 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
+
+ifdef WRAP_SYSTEM_INCLUDES
+export-preqs = \
+ $(call mkdir_deps,system_wrappers) \
+ $(NULL)
+
+export:: $(export-preqs)
+ $(PYTHON) -m mozbuild.action.preprocessor $(DEFINES) $(ACDEFINES) \
+ -DMOZ_TREE_CAIRO=$(MOZ_TREE_CAIRO) \
+ -DMOZ_TREE_PIXMAN=$(MOZ_TREE_PIXMAN) \
+ -DMOZ_SYSTEM_HUNSPELL=$(MOZ_SYSTEM_HUNSPELL) \
+ -DMOZ_SYSTEM_BZ2=$(MOZ_SYSTEM_BZ2) \
+ -DMOZ_SYSTEM_ZLIB=$(MOZ_SYSTEM_ZLIB) \
+ -DMOZ_SYSTEM_PNG=$(MOZ_SYSTEM_PNG) \
+ -DMOZ_SYSTEM_JPEG=$(MOZ_SYSTEM_JPEG) \
+ -DMOZ_SYSTEM_LIBEVENT=$(MOZ_SYSTEM_LIBEVENT) \
+ -DMOZ_SYSTEM_LIBVPX=$(MOZ_SYSTEM_LIBVPX) \
+ -DMOZ_SYSTEM_ICU=$(MOZ_SYSTEM_ICU) \
+ $(srcdir)/system-headers $(srcdir)/stl-headers | $(PERL) $(topsrcdir)/nsprpub/config/make-system-wrappers.pl system_wrappers
+ $(INSTALL) system_wrappers $(DIST)
+
+GARBAGE_DIRS += system_wrappers
+endif
+
+ifdef WRAP_STL_INCLUDES
+ifdef GNU_CXX
+stl_compiler = gcc
+else
+ifdef _MSC_VER
+stl_compiler = msvc
+endif
+endif
+endif
+
+ifdef stl_compiler
+STL_WRAPPERS_SENTINEL = $(DIST)/stl_wrappers/sentinel
+
+$(STL_WRAPPERS_SENTINEL): $(srcdir)/make-stl-wrappers.py $(srcdir)/$(stl_compiler)-stl-wrapper.template.h $(srcdir)/stl-headers $(GLOBAL_DEPS)
+ $(PYTHON) $(srcdir)/make-stl-wrappers.py stl_wrappers $(stl_compiler) $(srcdir)/$(stl_compiler)-stl-wrapper.template.h $(srcdir)/stl-headers
+ $(PYTHON) $(srcdir)/nsinstall.py -t stl_wrappers $(DIST)
+ touch $(STL_WRAPPERS_SENTINEL)
+
+export:: $(STL_WRAPPERS_SENTINEL)
+
+GARBAGE += $(STL_WRAPPERS_SENTINEL)
+GARBAGE_DIRS += stl_wrappers
+endif
+
+GARBAGE += \
+ $(FINAL_LINK_COMPS) $(FINAL_LINK_LIBS) $(FINAL_LINK_COMP_NAMES) $(srcdir)/*.pyc *.pyc
+
+FORCE:
+
+ifndef JS_STANDALONE
+check-preqs += check-jar-mn
+endif
+check-preqs += check-makefiles
+
+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
+
+check-makefiles:
+ $(MAKE) -C tests/makefiles/autodeps check
diff --git a/config/Moz/Milestone.pm b/config/Moz/Milestone.pm
new file mode 100644
index 000000000..722203298
--- /dev/null
+++ b/config/Moz/Milestone.pm
@@ -0,0 +1,220 @@
+#!/usr/bin/perl -w
+# 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/.
+
+package Moz::Milestone;
+use strict;
+
+use vars qw($officialMilestone
+ $milestone);
+
+local $Moz::Milestone::milestone;
+local $Moz::Milestone::officialMilestone;
+
+#
+# Usage: getOfficialMilestone($milestoneFile)
+# Returns full milestone (x.x.x.x[ab12pre+])
+#
+sub getOfficialMilestone($) {
+ my $mfile = $_[0];
+ open(FILE,"$mfile") ||
+ die ("Can't open $mfile for reading!");
+
+ my $num = <FILE>;
+ while($num =~ /^\s*#/ || $num !~ /^\d/) {
+ $num = <FILE>;
+ }
+
+ close(FILE);
+ if ($num !~ /^\d/) { return; }
+ chomp($num);
+ # Remove extra ^M caused by using dos-mode line-endings
+ chop $num if (substr($num, -1, 1) eq "\r");
+ $Moz::Milestone::officialMilestone = $num;
+ $Moz::Milestone::milestone = &getMilestoneNum;
+ return $num;
+}
+
+#
+# Usage: getMilestoneNum($num)
+# Returns: milestone without a + if it exists.
+#
+sub getMilestoneNum {
+ if (defined($Moz::Milestone::milestone)) {
+ return $Moz::Milestone::milestone;
+ }
+
+ if (defined($Moz::Milestone::officialMilestone)) {
+ $Moz::Milestone::milestone = $Moz::Milestone::officialMilestone;
+ } else {
+ $Moz::Milestone::milestone = $_[0];
+ }
+
+ if ($Moz::Milestone::milestone =~ /\+$/) { # for x.x.x+, strip off the +
+ $Moz::Milestone::milestone =~ s/\+$//;
+ }
+
+ return $Moz::Milestone::milestone;
+}
+
+#
+# Usage: getMilestoneQualifier($num)
+# Returns: + if it exists.
+#
+sub getMilestoneQualifier {
+ my $milestoneQualifier;
+ if (defined($Moz::Milestone::officialMilestone)) {
+ $milestoneQualifier = $Moz::Milestone::officialMilestone;
+ } else {
+ $milestoneQualifier = $_[0];
+ }
+
+ if ($milestoneQualifier =~ /\+$/) {
+ return "+";
+ }
+}
+
+sub getMilestoneMajor {
+ my $milestoneMajor;
+ if (defined($Moz::Milestone::milestone)) {
+ $milestoneMajor = $Moz::Milestone::milestone;
+ } else {
+ $milestoneMajor = $_[0];
+ }
+ my @parts = split(/\./,$milestoneMajor);
+ return $parts[0];
+}
+
+sub getMilestoneMinor {
+ my $milestoneMinor;
+ if (defined($Moz::Milestone::milestone)) {
+ $milestoneMinor = $Moz::Milestone::milestone;
+ } else {
+ $milestoneMinor = $_[0];
+ }
+ my @parts = split(/\./,$milestoneMinor);
+
+ if ($#parts < 1 ) { return 0; }
+ return $parts[1];
+}
+
+sub getMilestoneMini {
+ my $milestoneMini;
+ if (defined($Moz::Milestone::milestone)) {
+ $milestoneMini = $Moz::Milestone::milestone;
+ } else {
+ $milestoneMini = $_[0];
+ }
+ my @parts = split(/\./,$milestoneMini);
+
+ if ($#parts < 2 ) { return 0; }
+ return $parts[2];
+}
+
+sub getMilestoneMicro {
+ my $milestoneMicro;
+ if (defined($Moz::Milestone::milestone)) {
+ $milestoneMicro = $Moz::Milestone::milestone;
+ } else {
+ $milestoneMicro = $_[0];
+ }
+ my @parts = split(/\./,$milestoneMicro);
+
+ if ($#parts < 3 ) { return 0; }
+ return $parts[3];
+}
+
+sub getMilestoneAB {
+ my $milestoneAB;
+ if (defined($Moz::Milestone::milestone)) {
+ $milestoneAB = $Moz::Milestone::milestone;
+ } else {
+ $milestoneAB = $_[0];
+ }
+
+ if ($milestoneAB =~ /a/) { return "alpha"; }
+ if ($milestoneAB =~ /b/) { return "beta"; }
+ return "final";
+}
+
+#
+# Usage: getMilestoneABWithNum($milestoneFile)
+# Returns the alpha and beta tag with its number (a1, a2, b3, ...)
+#
+sub getMilestoneABWithNum {
+ my $milestoneABNum;
+ if (defined($Moz::Milestone::milestone)) {
+ $milestoneABNum = $Moz::Milestone::milestone;
+ } else {
+ $milestoneABNum = $_[0];
+ }
+
+ if ($milestoneABNum =~ /([ab]\d+)/) {
+ return $1;
+ } else {
+ return "";
+ }
+}
+
+#
+# build_file($template_file,$output_file)
+#
+sub build_file($$) {
+ my @FILE;
+ my @MILESTONE_PARTS;
+ my $MINI_VERSION = 0;
+ my $MICRO_VERSION = 0;
+ my $OFFICIAL = 0;
+ my $QUALIFIER = "";
+
+ if (!defined($Moz::Milestone::milestone)) { die("$0: no milestone file set!\n"); }
+ @MILESTONE_PARTS = split(/\./, &getMilestoneNum);
+ if ($#MILESTONE_PARTS >= 2) {
+ $MINI_VERSION = 1;
+ } else {
+ $MILESTONE_PARTS[2] = 0;
+ }
+ if ($#MILESTONE_PARTS >= 3) {
+ $MICRO_VERSION = 1;
+ } else {
+ $MILESTONE_PARTS[3] = 0;
+ }
+ if (! &getMilestoneQualifier) {
+ $OFFICIAL = 1;
+ } else {
+ $QUALIFIER = "+";
+ }
+
+ if (-e $_[0]) {
+ open(FILE, "$_[0]") || die("$0: Can't open $_[0] for reading!\n");
+ @FILE = <FILE>;
+ close(FILE);
+
+ open(FILE, ">$_[1]") || die("$0: Can't open $_[1] for writing!\n");
+
+ #
+ # There will be more of these based on what we need for files.
+ #
+ foreach(@FILE) {
+ s/__MOZ_MAJOR_VERSION__/$MILESTONE_PARTS[0]/g;
+ s/__MOZ_MINOR_VERSION__/$MILESTONE_PARTS[1]/g;
+ s/__MOZ_MINI_VERSION__/$MILESTONE_PARTS[2]/g;
+ s/__MOZ_MICRO_VERSION__/$MILESTONE_PARTS[3]/g;
+ if ($MINI_VERSION) {
+ s/__MOZ_OPTIONAL_MINI_VERSION__/.$MILESTONE_PARTS[2]/g;
+ }
+ if ($MICRO_VERSION) {
+ s/__MOZ_OPTIONAL_MICRO_VERSION__/.$MILESTONE_PARTS[3]/g;
+ }
+
+ print FILE $_;
+ }
+ close(FILE);
+ } else {
+ die("$0: $_[0] doesn't exist for autoversioning!\n");
+ }
+
+}
+
+1;
diff --git a/config/MozZipFile.py b/config/MozZipFile.py
new file mode 100644
index 000000000..337fe0521
--- /dev/null
+++ b/config/MozZipFile.py
@@ -0,0 +1,137 @@
+# 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
+
+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, basestring)
+ 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) << 16L
+ 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 self.NameToInfo.has_key(zinfo.filename):
+ # 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(lambda l, r: cmp(l.header_offset, r.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(lambda l, r: cmp(l[0].header_offset, r[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/android-common.mk b/config/android-common.mk
new file mode 100644
index 000000000..a54f20b88
--- /dev/null
+++ b/config/android-common.mk
@@ -0,0 +1,51 @@
+# 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/.
+
+# Ensure ANDROID_SDK is defined before including this file.
+# We use common android defaults for boot class path and java version.
+ifndef ANDROID_SDK
+ $(error ANDROID_SDK must be defined before including android-common.mk)
+endif
+
+# DEBUG_JARSIGNER always debug signs.
+DEBUG_JARSIGNER=$(PYTHON) $(abspath $(topsrcdir)/mobile/android/debug_sign_tool.py) \
+ --keytool=$(KEYTOOL) \
+ --jarsigner=$(JARSIGNER) \
+ $(NULL)
+
+# RELEASE_JARSIGNER release signs if possible.
+ifdef MOZ_SIGN_CMD
+RELEASE_JARSIGNER := $(MOZ_SIGN_CMD) -f jar
+else
+RELEASE_JARSIGNER := $(DEBUG_JARSIGNER)
+endif
+
+# $(1) is the full path to input: foo-debug-unsigned-unaligned.apk.
+# $(2) is the full path to output: foo.apk.
+# Use this like: $(call RELEASE_SIGN_ANDROID_APK,foo-debug-unsigned-unaligned.apk,foo.apk)
+#
+# The |zip -d| there to handle re-signing previously signed APKs. Gradle
+# produces signed, unaligned APK files, but this expects unsigned, unaligned
+# APK files. The |zip -d| discards any existing signature, turning a signed,
+# unaligned APK into an unsigned, unaligned APK. Sadly |zip -q| doesn't
+# silence a warning about "nothing to do" so we pipe to /dev/null.
+RELEASE_SIGN_ANDROID_APK = \
+ cp $(1) $(2)-unaligned.apk && \
+ ($(ZIP) -d $(2)-unaligned.apk 'META-INF/*' > /dev/null || true) && \
+ $(RELEASE_JARSIGNER) $(2)-unaligned.apk && \
+ $(ZIPALIGN) -f -v 4 $(2)-unaligned.apk $(2) && \
+ $(RM) $(2)-unaligned.apk
+
+# For Android, we default to 1.7
+ifndef JAVA_VERSION
+ JAVA_VERSION = 1.7
+endif
+
+JAVAC_FLAGS = \
+ -target $(JAVA_VERSION) \
+ -source $(JAVA_VERSION) \
+ -encoding UTF8 \
+ -g:source,lines \
+ -Werror \
+ $(NULL)
diff --git a/config/autoconf-js.mk.in b/config/autoconf-js.mk.in
new file mode 100644
index 000000000..ae4ad2c5e
--- /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 000000000..fb52bc197
--- /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 000000000..47a12b16e
--- /dev/null
+++ b/config/baseconfig.mk
@@ -0,0 +1,56 @@
+# 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.
+includedir := $(includedir)/$(MOZ_APP_NAME)-$(MOZ_APP_VERSION)
+idldir = $(datadir)/idl/$(MOZ_APP_NAME)-$(MOZ_APP_VERSION)
+installdir = $(libdir)/$(MOZ_APP_NAME)-$(MOZ_APP_VERSION)
+sdkdir = $(libdir)/$(MOZ_APP_NAME)-devel-$(MOZ_APP_VERSION)
+ifeq (.,$(DEPTH))
+DIST = dist
+else
+DIST = $(DEPTH)/dist
+endif
+ABS_DIST = $(topobjdir)/dist
+
+# We do magic with OBJ_SUFFIX in config.mk, the following ensures we don't
+# manually use it before config.mk inclusion
+_OBJ_SUFFIX := $(OBJ_SUFFIX)
+OBJ_SUFFIX = $(error config/config.mk needs to be included before using OBJ_SUFFIX)
+
+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
+TIERS := $(if $(MOZ_ARTIFACT_BUILDS),artifact )pre-export export $(if $(COMPILE_ENVIRONMENT),compile )misc libs tools
+endif
+
+# These defines are used to support the twin-topsrcdir model for comm-central.
+ifdef MOZILLA_SRCDIR
+ MOZILLA_DIR = $(MOZILLA_SRCDIR)
+else
+ MOZILLA_DIR = $(topsrcdir)
+endif
diff --git a/config/check_js_msg_encoding.py b/config/check_js_msg_encoding.py
new file mode 100644
index 000000000..295cd0855
--- /dev/null
+++ b/config/check_js_msg_encoding.py
@@ -0,0 +1,68 @@
+# 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.
+#----------------------------------------------------------------------------
+
+from __future__ import print_function
+
+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:
+ log_fail(filename, 'not in {} encoding'.format(expected_encoding))
+
+ log_pass(filename, 'ok')
+ return True
+
+def check_files():
+ result = True
+
+ repo = get_repository_from_env()
+ root = repo.path
+
+ for filename in repo.get_files_in_working_directory():
+ if filename.endswith('.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_macroassembler_style.py b/config/check_macroassembler_style.py
new file mode 100644
index 000000000..00be610db
--- /dev/null
+++ b/config/check_macroassembler_style.py
@@ -0,0 +1,283 @@
+# 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.
+#----------------------------------------------------------------------------
+
+from __future__ import print_function
+
+import difflib
+import os
+import re
+import sys
+
+from mozversioncontrol import get_repository_from_env
+
+
+architecture_independent = set([ 'generic' ])
+all_architecture_names = set([ 'x86', 'x64', 'arm', 'arm64', 'mips32', 'mips64' ])
+all_shared_architecture_names = set([ 'x86_shared', 'mips_shared', 'arm', 'arm64' ])
+
+reBeforeArg = "(?<=[(,\s])"
+reArgType = "(?P<type>[\w\s:*&]+)"
+reArgName = "(?P<name>\s\w+)"
+reArgDefault = "(?P<default>(?:\s=[^,)]+)?)"
+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()
+ # Match arguments, and keep only the type.
+ signature = reMatchArg.sub('\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>[^()]*)\).*', '\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)
+
+ 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)
+])
+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')]
+ 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:
+ return []
+
+ style_section = False
+ code_section = False
+ lines = ''
+ signatures = []
+ with open(filename) as f:
+ for line in f:
+ if '//{{{ check_macroassembler_style' in line:
+ style_section = True
+ elif '//}}} check_macroassembler_style' in line:
+ style_section = False
+ if not style_section:
+ continue
+
+ line = re.sub(r'//.*', '', line)
+ if line.startswith('{'):
+ if 'MacroAssembler::' in lines:
+ signatures.extend(get_normalized_signatures(lines, fileAnnot))
+ code_section = True
+ continue
+ if line.startswith('}'):
+ code_section = False
+ lines = ''
+ continue
+ if code_section:
+ continue
+
+ if len(line.strip()) == 0:
+ lines = ''
+ continue
+ lines = lines + line
+ # Continue until we have a complete declaration
+ if '{' not in lines:
+ continue
+ # Skip variable declarations
+ if ')' not in lines:
+ lines = ''
+ continue
+
+ return signatures
+
+def get_macroassembler_declaration(filename):
+ style_section = False
+ lines = ''
+ signatures = []
+ with open(filename) as f:
+ for line in f:
+ if '//{{{ check_macroassembler_style' in line:
+ style_section = True
+ elif '//}}} check_macroassembler_style' in line:
+ style_section = False
+ if not style_section:
+ continue
+
+ line = re.sub(r'//.*', '', line)
+ if len(line.strip()) == 0:
+ lines = ''
+ continue
+ lines = lines + line
+ # Continue until we have a complete declaration
+ if ';' not in lines:
+ continue
+ # Skip variable declarations
+ 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]))
+ if len(archs.symmetric_difference(architecture_independent)) == 0:
+ output.append(s + ';\n')
+ if s.startswith('inline'):
+ 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(archs) + ');\n')
+ for a in 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'])
+
+ repo = get_repository_from_env()
+
+ # Select the appropriate files.
+ for filename in repo.get_files_in_working_directory():
+ if not filename.startswith('js/src/jit/'):
+ continue
+ if 'MacroAssembler' not in filename:
+ continue
+
+ filename = os.path.join(repo.path, filename)
+
+ if filename.endswith('MacroAssembler.h'):
+ decls = append_signatures(decls, get_macroassembler_declaration(filename))
+ else:
+ defs = append_signatures(defs, get_macroassembler_definitions(filename))
+
+ # 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')
+
+ 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 000000000..e347e7a55
--- /dev/null
+++ b/config/check_source_count.py
@@ -0,0 +1,57 @@
+#!/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.
+from __future__ import print_function
+import sys
+import os
+import re
+
+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 000000000..647f403c4
--- /dev/null
+++ b/config/check_spidermonkey_style.py
@@ -0,0 +1,589 @@
+# 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.
+#----------------------------------------------------------------------------
+
+from __future__ import print_function
+
+import difflib
+import os
+import re
+import sys
+
+from mozversioncontrol import get_repository_from_env
+
+
+# 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
+]
+
+# 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/sharkctl.h', # we ignore devtools/ in general
+ 'devtools/Instruments.h', # we ignore devtools/ in general
+ 'double-conversion.h', # strange MFBT case
+ 'javascript-trace.h', # generated in $OBJDIR if HAVE_DTRACE is defined
+ 'jsautokw.h', # generated in $OBJDIR
+ 'jscustomallocator.h', # provided by embedders; allowed to be missing
+ 'js-config.h', # generated in $OBJDIR
+ 'fdlibm.h', # fdlibm
+ '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/timezone.h', # ICU
+ 'unicode/ucal.h', # ICU
+ 'unicode/uclean.h', # ICU
+ 'unicode/ucol.h', # ICU
+ 'unicode/udat.h', # ICU
+ 'unicode/udatpg.h', # ICU
+ 'unicode/uenum.h', # ICU
+ 'unicode/unorm.h', # ICU
+ 'unicode/unum.h', # ICU
+ 'unicode/unumsys.h', # ICU
+ 'unicode/ustring.h', # ICU
+ 'unicode/utypes.h', # ICU
+ 'vtune/VTuneWrapper.h' # VTune
+])
+
+# 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
+ 'jsautokw.h', # Included in the body of frontend/TokenStream.h
+ 'jswin.h', # Must be #included before <psapi.h>
+ 'machine/endian.h', # Must be included after <sys/types.h> on BSD
+ 'winbase.h', # Must precede other system headers(?)
+ 'windef.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/BadIncludes2.h:1: error:
+ vanilla header includes an inline-header file "tests/style/BadIncludes2-inl.h"
+
+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/BadIncludesOrder-inl.h:5:6: error:
+ "vm/Interpreter-inl.h" should be included after "jsscriptinlines.h"
+
+js/src/tests/style/BadIncludesOrder-inl.h:6:7: error:
+ "jsscriptinlines.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: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:27:28: error:
+ "jsobj.h" should be included after "jsfun.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():
+ # 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"
+ # - "mfbt/decimal/Decimal.h -> "mozilla/Decimal.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/') # type: tuple(str)
+ non_js_inclnames = set() # type: set(inclname)
+ js_names = dict() # type: dict(filename, inclname)
+
+ repo = get_repository_from_env()
+
+ # Select the appropriate files.
+ for filename in repo.get_files_in_working_directory():
+ for non_js_dir in non_js_dirnames:
+ if filename.startswith(non_js_dir) and filename.endswith('.h'):
+ inclname = 'mozilla/' + filename.split('/')[-1]
+ non_js_inclnames.add(inclname)
+
+ if filename.startswith('js/public/') and filename.endswith('.h'):
+ inclname = 'js/' + filename[len('js/public/'):]
+ js_names[filename] = inclname
+
+ if filename.startswith('js/src/') and \
+ not filename.startswith(tuple(ignored_js_src_dirs)) and \
+ filename.endswith(('.c', '.cpp', '.h', '.tbl', '.msg')):
+ inclname = filename[len('js/src/'):]
+ js_names[filename] = 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 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)
+
+ # This script is run in js/src/, so prepend '../../' to get to the root of the Mozilla
+ # source tree.
+ with open(os.path.join(repo.path, filename)) as f:
+ do_file(filename, inclname, file_kind, f, 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_spider_monkey_style.py expected output',
+ tofile='check_spider_monkey_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', '')
+
+
+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, e.g. module == "foo/Bar", header_inclname == "foo/Bar.h".
+ if module == module_name(header_inclname):
+ return True
+
+ # A public header, e.g. module == "foo/Bar", header_inclname == "js/Bar.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, inclname, linenum, is_system):
+ self.inclname = inclname
+ self.linenum = linenum
+ self.is_system = is_system
+
+ def isLeaf(self):
+ 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
+ '''
+
+ 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 + '"'
+
+
+class HashIfBlock(object):
+ '''Important information about a #if/#endif 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 leaf is either an Include (representing a #include), or another
+ nested HashIfBlock.'''
+ def __init__(self):
+ self.kids = []
+
+ def isLeaf(self):
+ return False
+
+
+def do_file(filename, inclname, file_kind, f, all_inclnames, included_h_inclnames):
+ block_stack = [HashIfBlock()]
+
+ # Extract the #include statements as a tree of IBlocks and IIncludes.
+ for linenum, line in enumerate(f, start=1):
+ # We're only interested in lines that contain a '#'.
+ if not '#' in line:
+ continue
+
+ # Look for a |#include "..."| line.
+ m = re.match(r'\s*#\s*include\s+"([^"]*)"', line)
+ if m is not None:
+ block_stack[-1].kids.append(Include(m.group(1), linenum, False))
+
+ # Look for a |#include <...>| line.
+ m = re.match(r'\s*#\s*include\s+<([^>]*)>', line)
+ if m is not None:
+ block_stack[-1].kids.append(Include(m.group(1), linenum, True))
+
+ # 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 = HashIfBlock()
+ block_stack[-1].kids.append(new_block)
+ block_stack.append(new_block)
+
+ # 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 = HashIfBlock()
+ block_stack[-1].kids.append(new_block)
+ block_stack.append(new_block)
+
+ # 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()
+
+ 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:
+ 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 this.isLeaf():
+ check_include_statement(this)
+ if prev is not None and prev.isLeaf():
+ check_includes_order(prev, this)
+ else:
+ for prev2, this2 in zip([None] + this.kids[0:-1], this.kids):
+ pair_traverse(prev2, this2)
+
+ pair_traverse(None, block_stack[-1])
+
+
+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():
+ ok = check_style()
+
+ 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')
+
+ 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 000000000..2a3be879e
--- /dev/null
+++ b/config/check_vanilla_allocations.py
@@ -0,0 +1,191 @@
+# 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
+# (e.g. malloc(), free()) is a bug.
+#
+# 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.
+#----------------------------------------------------------------------------
+
+from __future__ import print_function
+
+import argparse
+import re
+import subprocess
+import sys
+
+# 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 jsutil.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 jsutil.cpp,
+# *or* (b) fails to find them in jsutil.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:
+ # -u: show only undefined symbols
+ # -C: demangle symbol names
+ # -A: show an object filename for each undefined symbol
+ cmd = ['nm', '-u', '-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.
+
+ alloc_fns = [
+ # 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',
+
+ 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_unescaped = [fn.translate(None, r'\\') 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:jsutil.o: U malloc
+ #
+ alloc_fns_re = r'([^:/ ]+):\s+U (' + r'|'.join(alloc_fns) + r')'
+
+ # This tracks which allocation/free functions have been seen in jsutil.cpp.
+ jsutil_cpp = set([])
+
+ # Would it be helpful to emit detailed line number information after a failure?
+ emit_line_info = False
+
+ for line in lines:
+ m = re.search(alloc_fns_re, line)
+ if m is None:
+ continue
+
+ filename = m.group(1)
+ fn = m.group(2)
+ if filename == 'jsutil.o':
+ jsutil_cpp.add(fn)
+ else:
+ # 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 jsutil.cpp. (This will
+ # fail if the function-detection code breaks at any point.)
+ for fn in alloc_fns_unescaped:
+ if fn not in jsutil_cpp:
+ fail("'" + fn + "' isn't used as expected in jsutil.cpp")
+ else:
+ jsutil_cpp.remove(fn)
+
+ # This should never happen, but check just in case.
+ if jsutil_cpp:
+ fail('unexpected allocation fns used in jsutil.cpp: ' +
+ ', '.join(jsutil_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; jsutil.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 jsutil.cpp:117
+ #
+ alloc_lines_re = r'U ((' + r'|'.join(alloc_fns) + 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 000000000..4e3fd1a6c
--- /dev/null
+++ b/config/config.mk
@@ -0,0 +1,604 @@
+#
+# 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.
+#
+
+# 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
+
+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
+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 \
+ INSTALL_EXTENSION_ID \
+ 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
+
+# The VERSION_NUMBER is suffixed onto the end of the DLLs we ship.
+VERSION_NUMBER = 50
+
+ifeq ($(HOST_OS_ARCH),WINNT)
+ ifeq ($(MOZILLA_DIR),$(topsrcdir))
+ win_srcdir := $(subst $(topsrcdir),$(WIN_TOP_SRC),$(srcdir))
+ else
+ # This means we're in comm-central's topsrcdir, so we need to adjust
+ # WIN_TOP_SRC (which points to mozilla's topsrcdir) for the substitution
+ # to win_srcdir.
+ cc_WIN_TOP_SRC := $(WIN_TOP_SRC:%/mozilla=%)
+ win_srcdir := $(subst $(topsrcdir),$(cc_WIN_TOP_SRC),$(srcdir))
+ endif
+ BUILD_TOOLS = $(WIN_TOP_SRC)/build/unix
+else
+ win_srcdir := $(srcdir)
+ BUILD_TOOLS = $(MOZILLA_DIR)/build/unix
+endif
+
+CONFIG_TOOLS = $(MOZ_BUILD_ROOT)/config
+AUTOCONF_TOOLS = $(MOZILLA_DIR)/build/autoconf
+
+ifdef _MSC_VER
+CC_WRAPPER ?= $(call py_action,cl)
+CXX_WRAPPER ?= $(call py_action,cl)
+endif # _MSC_VER
+
+CC := $(CC_WRAPPER) $(CC)
+CXX := $(CXX_WRAPPER) $(CXX)
+MKDIR ?= mkdir
+SLEEP ?= sleep
+TOUCH ?= touch
+
+PYTHON_PATH = $(PYTHON) $(topsrcdir)/config/pythonpath.py
+
+# determine debug-related options
+_DEBUG_ASFLAGS :=
+_DEBUG_CFLAGS :=
+_DEBUG_LDFLAGS :=
+
+ifneq (,$(MOZ_DEBUG)$(MOZ_DEBUG_SYMBOLS))
+ ifeq ($(AS),$(YASM))
+ ifeq ($(OS_ARCH)_$(GNU_CC),WINNT_)
+ _DEBUG_ASFLAGS += -g cv8
+ else
+ ifneq ($(OS_ARCH),Darwin)
+ _DEBUG_ASFLAGS += -g dwarf2
+ endif
+ endif
+ else
+ _DEBUG_ASFLAGS += $(MOZ_DEBUG_FLAGS)
+ endif
+ _DEBUG_CFLAGS += $(MOZ_DEBUG_FLAGS)
+ _DEBUG_LDFLAGS += $(MOZ_DEBUG_LDFLAGS)
+endif
+
+ASFLAGS += $(_DEBUG_ASFLAGS)
+OS_CFLAGS += $(_DEBUG_CFLAGS)
+OS_CXXFLAGS += $(_DEBUG_CFLAGS)
+OS_LDFLAGS += $(_DEBUG_LDFLAGS)
+
+# XXX: What does this? Bug 482434 filed for better explanation.
+ifeq ($(OS_ARCH)_$(GNU_CC),WINNT_)
+ifndef MOZ_DEBUG
+
+# MOZ_DEBUG_SYMBOLS generates debug symbols in separate PDB files.
+# Used for generating an optimized build with debugging symbols.
+# Used in the Windows nightlies to generate symbols for crash reporting.
+ifdef MOZ_DEBUG_SYMBOLS
+ifdef HAVE_64BIT_BUILD
+OS_LDFLAGS += -DEBUG -OPT:REF,ICF
+else
+OS_LDFLAGS += -DEBUG -OPT:REF
+endif
+endif
+
+#
+# Handle DMD in optimized builds.
+#
+ifdef MOZ_DMD
+ifdef HAVE_64BIT_BUILD
+OS_LDFLAGS = -DEBUG -OPT:REF,ICF
+else
+OS_LDFLAGS = -DEBUG -OPT:REF
+endif
+endif # MOZ_DMD
+
+endif # MOZ_DEBUG
+
+endif # WINNT && !GNU_CC
+
+#
+# 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
+ifneq (1,$(NO_PROFILE_GUIDED_OPTIMIZE))
+ifdef MOZ_PROFILE_GENERATE
+OS_CFLAGS += $(if $(filter $(notdir $<),$(notdir $(NO_PROFILE_GUIDED_OPTIMIZE))),,$(PROFILE_GEN_CFLAGS))
+OS_CXXFLAGS += $(if $(filter $(notdir $<),$(notdir $(NO_PROFILE_GUIDED_OPTIMIZE))),,$(PROFILE_GEN_CFLAGS))
+OS_LDFLAGS += $(PROFILE_GEN_LDFLAGS)
+ifeq (WINNT,$(OS_ARCH))
+AR_FLAGS += -LTCG
+endif
+endif # MOZ_PROFILE_GENERATE
+
+ifdef MOZ_PROFILE_USE
+OS_CFLAGS += $(if $(filter $(notdir $<),$(notdir $(NO_PROFILE_GUIDED_OPTIMIZE))),,$(PROFILE_USE_CFLAGS))
+OS_CXXFLAGS += $(if $(filter $(notdir $<),$(notdir $(NO_PROFILE_GUIDED_OPTIMIZE))),,$(PROFILE_USE_CFLAGS))
+OS_LDFLAGS += $(PROFILE_USE_LDFLAGS)
+ifeq (WINNT,$(OS_ARCH))
+AR_FLAGS += -LTCG
+endif
+endif # MOZ_PROFILE_USE
+endif # NO_PROFILE_GUIDED_OPTIMIZE
+
+MAKE_JARS_FLAGS = \
+ -t $(topsrcdir) \
+ -f $(MOZ_JAR_MAKER_FILE_FORMAT) \
+ $(NULL)
+
+ifdef USE_EXTENSION_MANIFEST
+MAKE_JARS_FLAGS += -e
+endif
+
+TAR_CREATE_FLAGS = -chf
+
+#
+# Personal makefile customizations go in these optional make include files.
+#
+MY_CONFIG := $(DEPTH)/config/myconfig.mk
+MY_RULES := $(DEPTH)/config/myrules.mk
+
+#
+# Default command macros; can be overridden in <arch>.mk.
+#
+CCC = $(CXX)
+
+INCLUDES = \
+ -I$(srcdir) \
+ -I$(CURDIR) \
+ $(LOCAL_INCLUDES) \
+ -I$(ABS_DIST)/include \
+ $(NULL)
+
+ifndef IS_GYP_DIR
+# NSPR_CFLAGS and NSS_CFLAGS must appear ahead of the other flags to avoid Linux
+# builds wrongly picking up system NSPR/NSS header files.
+OS_INCLUDES := \
+ $(NSPR_CFLAGS) $(NSS_CFLAGS) \
+ $(MOZ_JPEG_CFLAGS) \
+ $(MOZ_PNG_CFLAGS) \
+ $(MOZ_ZLIB_CFLAGS) \
+ $(MOZ_PIXMAN_CFLAGS) \
+ $(NULL)
+endif
+
+include $(MOZILLA_DIR)/config/static-checking-config.mk
+
+CFLAGS = $(OS_CPPFLAGS) $(OS_CFLAGS)
+CXXFLAGS = $(OS_CPPFLAGS) $(OS_CXXFLAGS)
+LDFLAGS = $(OS_LDFLAGS) $(MOZBUILD_LDFLAGS) $(MOZ_FIX_LINK_PATHS)
+
+ifdef MOZ_OPTIMIZE
+ifeq (1,$(MOZ_OPTIMIZE))
+ifneq (,$(if $(MOZ_PROFILE_GENERATE)$(MOZ_PROFILE_USE),$(MOZ_PGO_OPTIMIZE_FLAGS)))
+CFLAGS += $(MOZ_PGO_OPTIMIZE_FLAGS)
+CXXFLAGS += $(MOZ_PGO_OPTIMIZE_FLAGS)
+else
+CFLAGS += $(MOZ_OPTIMIZE_FLAGS)
+CXXFLAGS += $(MOZ_OPTIMIZE_FLAGS)
+endif # neq (,$(MOZ_PROFILE_GENERATE)$(MOZ_PROFILE_USE))
+else
+CFLAGS += $(MOZ_OPTIMIZE_FLAGS)
+CXXFLAGS += $(MOZ_OPTIMIZE_FLAGS)
+endif # MOZ_OPTIMIZE == 1
+LDFLAGS += $(MOZ_OPTIMIZE_LDFLAGS)
+endif # MOZ_OPTIMIZE
+
+HOST_CFLAGS += $(_DEPEND_CFLAGS)
+HOST_CXXFLAGS += $(_DEPEND_CFLAGS)
+ifdef CROSS_COMPILE
+HOST_CFLAGS += $(HOST_OPTIMIZE_FLAGS)
+else
+ifdef MOZ_OPTIMIZE
+ifeq (1,$(MOZ_OPTIMIZE))
+HOST_CFLAGS += $(MOZ_OPTIMIZE_FLAGS)
+else
+HOST_CFLAGS += $(MOZ_OPTIMIZE_FLAGS)
+endif # MOZ_OPTIMIZE == 1
+endif # MOZ_OPTIMIZE
+endif # CROSS_COMPILE
+
+CFLAGS += $(MOZ_FRAMEPTR_FLAGS)
+CXXFLAGS += $(MOZ_FRAMEPTR_FLAGS)
+
+# Check for ALLOW_COMPILER_WARNINGS (shorthand for Makefiles to request that we
+# *don't* use the warnings-as-errors compile flags)
+
+# Don't use warnings-as-errors in Windows PGO builds because it is suspected of
+# causing problems in that situation. (See bug 437002.)
+ifeq (WINNT_1,$(OS_ARCH)_$(MOZ_PROFILE_GENERATE)$(MOZ_PROFILE_USE))
+ALLOW_COMPILER_WARNINGS=1
+endif # WINNT && (MOS_PROFILE_GENERATE ^ MOZ_PROFILE_USE)
+
+# Don't use warnings-as-errors in clang-cl because it warns about many more
+# things than MSVC does.
+ifdef CLANG_CL
+ALLOW_COMPILER_WARNINGS=1
+endif # CLANG_CL
+
+# Use warnings-as-errors if ALLOW_COMPILER_WARNINGS is not set to 1 (which
+# includes the case where it's undefined).
+ifneq (1,$(ALLOW_COMPILER_WARNINGS))
+CXXFLAGS += $(WARNINGS_AS_ERRORS)
+CFLAGS += $(WARNINGS_AS_ERRORS)
+endif # ALLOW_COMPILER_WARNINGS
+
+COMPILE_CFLAGS = $(VISIBILITY_FLAGS) $(DEFINES) $(INCLUDES) $(OS_INCLUDES) $(DSO_CFLAGS) $(DSO_PIC_CFLAGS) $(RTL_FLAGS) $(OS_COMPILE_CFLAGS) $(_DEPEND_CFLAGS) $(CFLAGS) $(MOZBUILD_CFLAGS)
+COMPILE_CXXFLAGS = $(if $(DISABLE_STL_WRAPPING),,$(STL_FLAGS)) $(VISIBILITY_FLAGS) $(DEFINES) $(INCLUDES) $(OS_INCLUDES) $(DSO_CFLAGS) $(DSO_PIC_CFLAGS) $(RTL_FLAGS) $(OS_COMPILE_CXXFLAGS) $(_DEPEND_CFLAGS) $(CXXFLAGS) $(MOZBUILD_CXXFLAGS)
+COMPILE_CMFLAGS = $(OS_COMPILE_CMFLAGS) $(MOZBUILD_CMFLAGS)
+COMPILE_CMMFLAGS = $(OS_COMPILE_CMMFLAGS) $(MOZBUILD_CMMFLAGS)
+ASFLAGS += $(MOZBUILD_ASFLAGS)
+
+ifndef CROSS_COMPILE
+HOST_CFLAGS += $(RTL_FLAGS)
+endif
+
+HOST_CFLAGS += $(HOST_DEFINES) $(MOZBUILD_HOST_CFLAGS)
+HOST_CXXFLAGS += $(HOST_DEFINES) $(MOZBUILD_HOST_CXXFLAGS)
+
+#
+# Name of the binary code directories
+#
+# Override defaults
+
+SDK_LIB_DIR = $(DIST)/sdk/lib
+SDK_BIN_DIR = $(DIST)/sdk/bin
+
+DEPENDENCIES = .md
+
+ifdef MACOSX_DEPLOYMENT_TARGET
+export MACOSX_DEPLOYMENT_TARGET
+endif # MACOSX_DEPLOYMENT_TARGET
+
+# 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
+
+# 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
+
+ifdef _MSC_VER
+ifeq ($(CPU_ARCH),x86_64)
+# set stack to 2MB on x64 build. See bug 582910
+WIN32_EXE_LDFLAGS += -STACK:2097152
+endif
+endif
+
+#
+# Include any personal overrides the user might think are needed.
+#
+-include $(topsrcdir)/$(MOZ_BUILD_APP)/app-config.mk
+-include $(MY_CONFIG)
+
+######################################################################
+
+GARBAGE += $(DEPENDENCIES) core $(wildcard core.[0-9]*) $(wildcard *.err) $(wildcard *.pure) $(wildcard *_pure_*.o) Templates.DB
+
+ifeq ($(OS_ARCH),Darwin)
+ifndef NSDISTMODE
+NSDISTMODE=absolute_symlink
+endif
+PWD := $(CURDIR)
+endif
+
+NSINSTALL_PY := $(PYTHON) $(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)
+# Many locales directories want this definition.
+ACDEFINES += -DAB_CD=$(AB_CD)
+
+ifndef L10NBASEDIR
+ L10NBASEDIR = $(error L10NBASEDIR not defined by configure)
+else
+ IS_LANGUAGE_REPACK = 1
+endif
+
+EXPAND_LOCALE_SRCDIR = $(if $(filter en-US,$(AB_CD)),$(topsrcdir)/$(1)/en-US,$(or $(realpath $(L10NBASEDIR)),$(abspath $(L10NBASEDIR)))/$(AB_CD)/$(subst /locales,,$(1)))
+
+ifdef relativesrcdir
+LOCALE_SRCDIR ?= $(call EXPAND_LOCALE_SRCDIR,$(relativesrcdir))
+endif
+
+ifdef relativesrcdir
+MAKE_JARS_FLAGS += --relativesrcdir=$(relativesrcdir)
+ifneq (en-US,$(AB_CD))
+ifdef LOCALE_MERGEDIR
+MAKE_JARS_FLAGS += --locale-mergedir=$(LOCALE_MERGEDIR)
+endif
+ifdef IS_LANGUAGE_REPACK
+MAKE_JARS_FLAGS += --l10n-base=$(L10NBASEDIR)/$(AB_CD)
+endif
+else
+MAKE_JARS_FLAGS += -c $(LOCALE_SRCDIR)
+endif # en-US
+else
+MAKE_JARS_FLAGS += -c $(LOCALE_SRCDIR)
+endif # ! relativesrcdir
+
+ifdef LOCALE_MERGEDIR
+MERGE_FILE = $(firstword \
+ $(wildcard $(LOCALE_MERGEDIR)/$(subst /locales,,$(relativesrcdir))/$(1)) \
+ $(wildcard $(LOCALE_SRCDIR)/$(1)) \
+ $(srcdir)/en-US/$(1) )
+else
+MERGE_FILE = $(LOCALE_SRCDIR)/$(1)
+endif
+MERGE_FILES = $(foreach f,$(1),$(call MERGE_FILE,$(f)))
+
+# These marcros are similar to MERGE_FILE, but no merging, and en-US first.
+# They're used for searchplugins, for example.
+EN_US_OR_L10N_FILE = $(firstword \
+ $(wildcard $(srcdir)/en-US/$(1)) \
+ $(LOCALE_SRCDIR)/$(1) )
+EN_US_OR_L10N_FILES = $(foreach f,$(1),$(call EN_US_OR_L10N_FILE,$(f)))
+
+ifneq (WINNT,$(OS_ARCH))
+RUN_TEST_PROGRAM = $(DIST)/bin/run-mozilla.sh
+endif # ! WINNT
+
+#
+# Java macros
+#
+
+# Make sure any compiled classes work with at least JVM 1.4
+JAVAC_FLAGS += -source 1.4
+
+ifdef MOZ_DEBUG
+JAVAC_FLAGS += -g
+endif
+
+CREATE_PRECOMPLETE_CMD = $(PYTHON) $(abspath $(MOZILLA_DIR)/config/createprecomplete.py)
+
+# MDDEPDIR is the subdirectory where dependency files are stored
+MDDEPDIR := .deps
+
+EXPAND_LIBS_EXEC = $(PYTHON) $(MOZILLA_DIR)/config/expandlibs_exec.py
+EXPAND_LIBS_GEN = $(PYTHON) $(MOZILLA_DIR)/config/expandlibs_gen.py
+EXPAND_AR = $(EXPAND_LIBS_EXEC) --extract -- $(AR)
+EXPAND_CC = $(EXPAND_LIBS_EXEC) --uselist -- $(CC)
+EXPAND_CCC = $(EXPAND_LIBS_EXEC) --uselist -- $(CCC)
+EXPAND_LD = $(EXPAND_LIBS_EXEC) --uselist -- $(LD)
+EXPAND_MKSHLIB_ARGS = --uselist
+ifdef SYMBOL_ORDER
+EXPAND_MKSHLIB_ARGS += --symbol-order $(SYMBOL_ORDER)
+endif
+EXPAND_MKSHLIB = $(EXPAND_LIBS_EXEC) $(EXPAND_MKSHLIB_ARGS) -- $(MKSHLIB)
+
+# $(call CHECK_SYMBOLS,lib,PREFIX,dep_name,test)
+# Checks that the given `lib` doesn't contain dependency on symbols with a
+# version starting with `PREFIX`_ and matching the `test`. `dep_name` is only
+# used for the error message.
+# `test` is an awk expression using the information in the variable `v` which
+# contains a list of version items ([major, minor, ...]).
+define CHECK_SYMBOLS
+@$(TOOLCHAIN_PREFIX)readelf -sW $(1) | \
+awk '$$8 ~ /@$(2)_/ { \
+ split($$8,a,"@"); \
+ split(a[2],b,"_"); \
+ split(b[2],v,"."); \
+ if ($(4)) { \
+ if (!found) { \
+ print "TEST-UNEXPECTED-FAIL | check_stdcxx | We do not want these $(3) symbol versions to be used:" \
+ } \
+ print " ",$$8; \
+ found=1 \
+ } \
+} \
+END { \
+ if (found) { \
+ exit(1) \
+ } \
+}'
+endef
+
+ifneq (,$(MOZ_LIBSTDCXX_TARGET_VERSION)$(MOZ_LIBSTDCXX_HOST_VERSION))
+CHECK_STDCXX = $(call CHECK_SYMBOLS,$(1),GLIBCXX,libstdc++,v[1] > 3 || (v[1] == 3 && v[2] == 4 && v[3] > 16))
+CHECK_GLIBC = $(call CHECK_SYMBOLS,$(1),GLIBC,libc,v[1] > 2 || (v[1] == 2 && v[2] > 12))
+endif
+
+ifeq (,$(filter $(OS_TARGET),WINNT Darwin))
+CHECK_TEXTREL = @$(TOOLCHAIN_PREFIX)readelf -d $(1) | grep TEXTREL > /dev/null && echo 'TEST-UNEXPECTED-FAIL | check_textrel | We do not want text relocations in libraries and programs' || true
+endif
+
+ifeq ($(MOZ_WIDGET_TOOLKIT),android)
+# While this is very unlikely (libc being added by the compiler at the end
+# of the linker command line), if libmozglue.so ends up after libc.so, all
+# hell breaks loose, so better safe than sorry, and check it's actually the
+# case.
+CHECK_MOZGLUE_ORDER = @$(TOOLCHAIN_PREFIX)readelf -d $(1) | grep NEEDED | awk '{ libs[$$NF] = ++n } END { if (libs["[libmozglue.so]"] && libs["[libc.so]"] < libs["[libmozglue.so]"]) { print "libmozglue.so must be linked before libc.so"; exit 1 } }'
+endif
+
+define CHECK_BINARY
+$(call CHECK_GLIBC,$(1))
+$(call CHECK_STDCXX,$(1))
+$(call CHECK_TEXTREL,$(1))
+$(call LOCAL_CHECKS,$(1))
+$(call CHECK_MOZGLUE_ORDER,$(1))
+endef
+
+# autoconf.mk sets OBJ_SUFFIX to an error to avoid use before including
+# this file
+OBJ_SUFFIX := $(_OBJ_SUFFIX)
+
+# PGO builds with GCC build objects with instrumentation in a first pass,
+# then objects optimized, without instrumentation, in a second pass. If
+# we overwrite the objects from the first pass with those from the second,
+# we end up not getting instrumentation data for better optimization on
+# incremental builds. As a consequence, we use a different object suffix
+# for the first pass.
+ifndef NO_PROFILE_GUIDED_OPTIMIZE
+ifdef MOZ_PROFILE_GENERATE
+ifdef GNU_CC
+OBJ_SUFFIX := i_o
+endif
+endif
+endif
+
+PLY_INCLUDE = -I$(MOZILLA_DIR)/other-licenses/ply
+
+export CL_INCLUDES_PREFIX
+# Make sure that the build system can handle non-ASCII characters
+# in environment variables to prevent it from breking silently on
+# non-English systems.
+export NONASCII
diff --git a/config/createprecomplete.py b/config/createprecomplete.py
new file mode 100644
index 000000000..3241d526b
--- /dev/null
+++ b/config/createprecomplete.py
@@ -0,0 +1,67 @@
+# 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 sys
+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 = open(precomplete_file_path, "wb")
+ rel_file_path_list, rel_dir_path_list = get_build_entries(root_path)
+ for rel_file_path in rel_file_path_list:
+ precomplete_file.writelines("remove \""+rel_file_path+"\"\n")
+
+ for rel_dir_path in rel_dir_path_list:
+ precomplete_file.writelines("rmdir \""+rel_dir_path+"\"\n")
+
+ precomplete_file.close()
+
+if __name__ == "__main__":
+ generate_precomplete(os.getcwd())
diff --git a/config/doxygen.cfg.in b/config/doxygen.cfg.in
new file mode 100644
index 000000000..3096b37de
--- /dev/null
+++ b/config/doxygen.cfg.in
@@ -0,0 +1,1364 @@
+/* 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/. */
+
+# Doxyfile 1.5.5
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME = "Mozilla"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = @MOZ_DOC_OUTPUT_DIR@
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek,
+# Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish,
+# Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish,
+# and Ukrainian.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF = YES
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member
+# documentation.
+
+DETAILS_AT_TOP = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 4
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES = "status=\par Status:\n"
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for
+# Java. For instance, namespaces will be presented as packages, qualified
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources only. Doxygen will then generate output that is more tailored for
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
+# Doxygen will parse them like normal C++ but will assume all classes use public
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT = NO
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = YES
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
+# is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically
+# be useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base
+# name of the file that contains the anonymous namespace. By default
+# anonymous namespace are hidden.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
+# hierarchy of group names into alphabetical order. If set to NO (the default)
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = NO
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES = NO
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = NO
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT =
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = @MOZ_DOC_INPUT_DIRS@
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
+# also the default input encoding. Doxygen uses libiconv (or the iconv built
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
+# the list of possible encodings.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
+
+FILE_PATTERNS = *.idl \
+ *.cpp \
+ *.h
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS = nsI*.h mozI*.h imgI*.h
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS = nsCOMPtr_base
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output. If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# is applied to all files.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default)
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES (the default)
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code. Otherwise they will link to the documentstion.
+
+REFERENCES_LINK_SOURCE = NO
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = YES
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX = nsI ns \
+ mozI moz \
+ imgI img
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT =
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET =
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files
+# will be generated that can be used as input for Apple's Xcode 3
+# integrated development environment, introduced with OSX 10.5 (Leopard).
+# To create a documentation set, doxygen will generate a Makefile in the
+# HTML output directory. Running make will produce the docset in that
+# directory and running "make install" will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
+# it at startup.
+
+GENERATE_DOCSET = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
+# feed. A documentation feed provides an umbrella under which multiple
+# documentation sets from a single provider (such as a company or product suite)
+# can be grouped.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
+# should uniquely identify the documentation set bundle. This should be a
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded. For this to work a browser that supports
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT =
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT =
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT =
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION =
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader. This is useful
+# if you want to understand what is going on. On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = YES
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH = @MOZ_DOC_INCLUDE_DIRS@
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS = *.h
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
+# powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = YES
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then
+# doxygen will generate a call dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable call graphs
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
+# doxygen will generate a caller dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable caller
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the
+# number of direct children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH = 3
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is enabled by default, which results in a transparent
+# background. Warning: Depending on the platform used, enabling this option
+# may lead to badly anti-aliased labels on the edges of a graph (i.e. they
+# become hard to read).
+
+DOT_TRANSPARENT = YES
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE = NO
diff --git a/config/emptyvars-js.mk.in b/config/emptyvars-js.mk.in
new file mode 100644
index 000000000..388cf2a35
--- /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 000000000..388cf2a35
--- /dev/null
+++ b/config/emptyvars.mk.in
@@ -0,0 +1 @@
+@ALLEMPTYSUBSTS@
diff --git a/config/expandlibs.py b/config/expandlibs.py
new file mode 100644
index 000000000..ac06c432f
--- /dev/null
+++ b/config/expandlibs.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/.
+
+'''Expandlibs is a system that allows to replace some libraries with a
+descriptor file containing some linking information about them.
+
+The descriptor file format is as follows:
+---8<-----
+OBJS = a.o b.o ...
+LIBS = libfoo.a libbar.a ...
+--->8-----
+
+(In the example above, OBJ_SUFFIX is o and LIB_SUFFIX is a).
+
+Expandlibs also canonicalizes how to pass libraries to the linker, such
+that only the ${LIB_PREFIX}${ROOT}.${LIB_SUFFIX} form needs to be used:
+given a list of files, expandlibs will replace items with the form
+${LIB_PREFIX}${ROOT}.${LIB_SUFFIX} following these rules:
+
+- If a ${DLL_PREFIX}${ROOT}.${DLL_SUFFIX} or
+ ${DLL_PREFIX}${ROOT}.${IMPORT_LIB_SUFFIX} file exists, use that instead
+- If the ${LIB_PREFIX}${ROOT}.${LIB_SUFFIX} file exists, use it
+- If a ${LIB_PREFIX}${ROOT}.${LIB_SUFFIX}.${LIB_DESC_SUFFIX} file exists,
+ replace ${LIB_PREFIX}${ROOT}.${LIB_SUFFIX} with the OBJS and LIBS the
+ descriptor contains. And for each of these LIBS, also apply the same
+ rules.
+'''
+from __future__ import with_statement
+import sys, os, errno
+import expandlibs_config as conf
+
+def ensureParentDir(file):
+ '''Ensures the directory parent to the given file exists'''
+ dir = os.path.dirname(file)
+ if dir and not os.path.exists(dir):
+ try:
+ os.makedirs(dir)
+ except OSError, error:
+ if error.errno != errno.EEXIST:
+ raise
+
+def relativize(path):
+ '''Returns a path relative to the current working directory, if it is
+ shorter than the given path'''
+ def splitpath(path):
+ dir, file = os.path.split(path)
+ if os.path.splitdrive(dir)[1] == os.sep:
+ return [file]
+ return splitpath(dir) + [file]
+
+ if not os.path.exists(path):
+ return path
+ curdir = splitpath(os.path.abspath(os.curdir))
+ abspath = splitpath(os.path.abspath(path))
+ while curdir and abspath and curdir[0] == abspath[0]:
+ del curdir[0]
+ del abspath[0]
+ if not curdir and not abspath:
+ return '.'
+ relpath = os.path.join(*[os.pardir for i in curdir] + abspath)
+ if len(path) > len(relpath):
+ return relpath
+ return path
+
+def isObject(path):
+ '''Returns whether the given path points to an object file, that is,
+ ends with OBJ_SUFFIX or .i_o'''
+ return os.path.splitext(path)[1] in [conf.OBJ_SUFFIX, '.i_o']
+
+def isDynamicLib(path):
+ '''Returns whether the given path points to a dynamic library, that is,
+ ends with DLL_SUFFIX.'''
+ # On mac, the xul library is named XUL, instead of libxul.dylib. Assume any
+ # file by that name is a dynamic library.
+ return os.path.splitext(path)[1] == conf.DLL_SUFFIX or os.path.basename(path) == 'XUL'
+
+class LibDescriptor(dict):
+ KEYS = ['OBJS', 'LIBS']
+
+ def __init__(self, content=None):
+ '''Creates an instance of a lib descriptor, initialized with contents
+ from a list of strings when given. This is intended for use with
+ file.readlines()'''
+ if isinstance(content, list) and all([isinstance(item, str) for item in content]):
+ pass
+ elif content is not None:
+ raise TypeError("LibDescriptor() arg 1 must be None or a list of strings")
+ super(LibDescriptor, self).__init__()
+ for key in self.KEYS:
+ self[key] = []
+ if not content:
+ return
+ for key, value in [(s.strip() for s in item.split('=', 2)) for item in content if item.find('=') >= 0]:
+ if key in self.KEYS:
+ self[key] = value.split()
+
+ def __str__(self):
+ '''Serializes the lib descriptor'''
+ return '\n'.join('%s = %s' % (k, ' '.join(self[k])) for k in self.KEYS if len(self[k]))
+
+class ExpandArgs(list):
+ def __init__(self, args):
+ '''Creates a clone of the |args| list and performs file expansion on
+ each item it contains'''
+ super(ExpandArgs, self).__init__()
+ self._descs = set()
+ for arg in args:
+ self += self._expand(arg)
+
+ def _expand(self, arg):
+ '''Internal function doing the actual work'''
+ (root, ext) = os.path.splitext(arg)
+ if ext != conf.LIB_SUFFIX or not os.path.basename(root).startswith(conf.LIB_PREFIX):
+ return [relativize(arg)]
+ if conf.LIB_PREFIX:
+ dll = root.replace(conf.LIB_PREFIX, conf.DLL_PREFIX, 1) + conf.DLL_SUFFIX
+ else:
+ dll = root + conf.DLL_SUFFIX
+ if os.path.exists(dll):
+ if conf.IMPORT_LIB_SUFFIX:
+ return [relativize(root + conf.IMPORT_LIB_SUFFIX)]
+ else:
+ return [relativize(dll)]
+ return self._expand_desc(arg)
+
+ def _expand_desc(self, arg):
+ '''Internal function taking care of lib descriptor expansion only'''
+ desc = os.path.abspath(arg + conf.LIBS_DESC_SUFFIX)
+ if os.path.exists(desc):
+ if desc in self._descs:
+ return []
+ self._descs.add(desc)
+ with open(desc, 'r') as f:
+ desc = LibDescriptor(f.readlines())
+ objs = [relativize(o) for o in desc['OBJS']]
+ for lib in desc['LIBS']:
+ objs += self._expand(lib)
+ return objs
+ return [relativize(arg)]
+
+if __name__ == '__main__':
+ print " ".join(ExpandArgs(sys.argv[1:]))
diff --git a/config/expandlibs_config.py b/config/expandlibs_config.py
new file mode 100644
index 000000000..8365f77cd
--- /dev/null
+++ b/config/expandlibs_config.py
@@ -0,0 +1,27 @@
+# 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 buildconfig import substs
+
+def normalize_suffix(suffix):
+ '''Returns a normalized suffix, i.e. ensures it starts with a dot and
+ doesn't starts or ends with whitespace characters'''
+ value = suffix.strip()
+ if len(value) and not value.startswith('.'):
+ value = '.' + value
+ return value
+
+# Variables from the build system
+AR = substs['AR']
+AR_EXTRACT = substs['AR_EXTRACT'].replace('$(AR)', AR)
+DLL_PREFIX = substs['DLL_PREFIX']
+LIB_PREFIX = substs['LIB_PREFIX']
+OBJ_SUFFIX = normalize_suffix(substs['OBJ_SUFFIX'])
+LIB_SUFFIX = normalize_suffix(substs['LIB_SUFFIX'])
+DLL_SUFFIX = normalize_suffix(substs['DLL_SUFFIX'])
+IMPORT_LIB_SUFFIX = normalize_suffix(substs['IMPORT_LIB_SUFFIX'])
+LIBS_DESC_SUFFIX = normalize_suffix(substs['LIBS_DESC_SUFFIX'])
+EXPAND_LIBS_LIST_STYLE = substs['EXPAND_LIBS_LIST_STYLE']
+EXPAND_LIBS_ORDER_STYLE = substs['EXPAND_LIBS_ORDER_STYLE']
+LD_PRINT_ICF_SECTIONS = substs['LD_PRINT_ICF_SECTIONS']
diff --git a/config/expandlibs_exec.py b/config/expandlibs_exec.py
new file mode 100644
index 000000000..c05343022
--- /dev/null
+++ b/config/expandlibs_exec.py
@@ -0,0 +1,354 @@
+# 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/.
+
+'''expandlibs-exec.py applies expandlibs rules, and some more (see below) to
+a given command line, and executes that command line with the expanded
+arguments.
+
+With the --extract argument (useful for e.g. $(AR)), it extracts object files
+from static libraries (or use those listed in library descriptors directly).
+
+With the --uselist argument (useful for e.g. $(CC)), it replaces all object
+files with a list file. This can be used to avoid limitations in the length
+of a command line. The kind of list file format used depends on the
+EXPAND_LIBS_LIST_STYLE variable: 'list' for MSVC style lists (@file.list)
+or 'linkerscript' for GNU ld linker scripts.
+See https://bugzilla.mozilla.org/show_bug.cgi?id=584474#c59 for more details.
+
+With the --symbol-order argument, followed by a file name, it will add the
+relevant linker options to change the order in which the linker puts the
+symbols appear in the resulting binary. Only works for ELF targets.
+'''
+from __future__ import with_statement
+import sys
+import os
+from expandlibs import (
+ ExpandArgs,
+ relativize,
+ isDynamicLib,
+ isObject,
+)
+import expandlibs_config as conf
+from optparse import OptionParser
+import subprocess
+import tempfile
+import shutil
+import subprocess
+import re
+from mozbuild.makeutil import Makefile
+
+# The are the insert points for a GNU ld linker script, assuming a more
+# or less "standard" default linker script. This is not a dict because
+# order is important.
+SECTION_INSERT_BEFORE = [
+ ('.text', '.fini'),
+ ('.rodata', '.rodata1'),
+ ('.data.rel.ro', '.dynamic'),
+ ('.data', '.data1'),
+]
+
+class ExpandArgsMore(ExpandArgs):
+ ''' Meant to be used as 'with ExpandArgsMore(args) as ...: '''
+ def __enter__(self):
+ self.tmp = []
+ return self
+
+ def __exit__(self, type, value, tb):
+ '''Automatically remove temporary files'''
+ for tmp in self.tmp:
+ if os.path.isdir(tmp):
+ shutil.rmtree(tmp, True)
+ else:
+ os.remove(tmp)
+
+ def extract(self):
+ self[0:] = self._extract(self)
+
+ def _extract(self, args):
+ '''When a static library name is found, either extract its contents
+ in a temporary directory or use the information found in the
+ corresponding lib descriptor.
+ '''
+ ar_extract = conf.AR_EXTRACT.split()
+ newlist = []
+
+ def lookup(base, f):
+ for root, dirs, files in os.walk(base):
+ if f in files:
+ return os.path.join(root, f)
+
+ for arg in args:
+ if os.path.splitext(arg)[1] == conf.LIB_SUFFIX:
+ if os.path.exists(arg + conf.LIBS_DESC_SUFFIX):
+ newlist += self._extract(self._expand_desc(arg))
+ continue
+ elif os.path.exists(arg) and (len(ar_extract) or conf.AR == 'lib'):
+ tmp = tempfile.mkdtemp(dir=os.curdir)
+ self.tmp.append(tmp)
+ if conf.AR == 'lib':
+ out = subprocess.check_output([conf.AR, '-NOLOGO', '-LIST', arg])
+ files = out.splitlines()
+ # If lib -list returns a list full of dlls, it's an
+ # import lib.
+ if all(isDynamicLib(f) for f in files):
+ newlist += [arg]
+ continue
+ for f in files:
+ subprocess.call([conf.AR, '-NOLOGO', '-EXTRACT:%s' % f, os.path.abspath(arg)], cwd=tmp)
+ else:
+ subprocess.call(ar_extract + [os.path.abspath(arg)], cwd=tmp)
+ objs = []
+ basedir = os.path.dirname(arg)
+ for root, dirs, files in os.walk(tmp):
+ for f in files:
+ if isObject(f):
+ # If the file extracted from the library also
+ # exists in the directory containing the
+ # library, or one of its subdirectories, use
+ # that instead.
+ maybe_obj = lookup(os.path.join(basedir, os.path.relpath(root, tmp)), f)
+ if maybe_obj:
+ objs.append(relativize(maybe_obj))
+ else:
+ objs.append(relativize(os.path.join(root, f)))
+ newlist += sorted(objs)
+ continue
+ newlist += [arg]
+ return newlist
+
+ def makelist(self):
+ '''Replaces object file names with a temporary list file, using a
+ list format depending on the EXPAND_LIBS_LIST_STYLE variable
+ '''
+ objs = [o for o in self if isObject(o)]
+ if not len(objs): return
+ fd, tmp = tempfile.mkstemp(suffix=".list",dir=os.curdir)
+ if conf.EXPAND_LIBS_LIST_STYLE == "linkerscript":
+ content = ['INPUT("%s")\n' % obj for obj in objs]
+ ref = tmp
+ elif conf.EXPAND_LIBS_LIST_STYLE == "filelist":
+ content = ["%s\n" % obj for obj in objs]
+ ref = "-Wl,-filelist," + tmp
+ elif conf.EXPAND_LIBS_LIST_STYLE == "list":
+ content = ["%s\n" % obj for obj in objs]
+ ref = "@" + tmp
+ else:
+ os.close(fd)
+ os.remove(tmp)
+ return
+ self.tmp.append(tmp)
+ f = os.fdopen(fd, "w")
+ f.writelines(content)
+ f.close()
+ idx = self.index(objs[0])
+ newlist = self[0:idx] + [ref] + [item for item in self[idx:] if item not in objs]
+ self[0:] = newlist
+
+ def _getFoldedSections(self):
+ '''Returns a dict about folded sections.
+ When section A and B are folded into section C, the dict contains:
+ { 'A': 'C',
+ 'B': 'C',
+ 'C': ['A', 'B'] }'''
+ if not conf.LD_PRINT_ICF_SECTIONS:
+ return {}
+
+ proc = subprocess.Popen(self + [conf.LD_PRINT_ICF_SECTIONS], stdout = subprocess.PIPE, stderr = subprocess.PIPE)
+ (stdout, stderr) = proc.communicate()
+ result = {}
+ # gold's --print-icf-sections output looks like the following:
+ # ld: ICF folding section '.section' in file 'file.o'into '.section' in file 'file.o'
+ # In terms of words, chances are this will change in the future,
+ # especially considering "into" is misplaced. Splitting on quotes
+ # seems safer.
+ for l in stderr.split('\n'):
+ quoted = l.split("'")
+ if len(quoted) > 5 and quoted[1] != quoted[5]:
+ result[quoted[1]] = [quoted[5]]
+ if quoted[5] in result:
+ result[quoted[5]].append(quoted[1])
+ else:
+ result[quoted[5]] = [quoted[1]]
+ return result
+
+ def _getOrderedSections(self, ordered_symbols):
+ '''Given an ordered list of symbols, returns the corresponding list
+ of sections following the order.'''
+ if not conf.EXPAND_LIBS_ORDER_STYLE in ['linkerscript', 'section-ordering-file']:
+ raise Exception('EXPAND_LIBS_ORDER_STYLE "%s" is not supported' % conf.EXPAND_LIBS_ORDER_STYLE)
+ finder = SectionFinder([arg for arg in self if isObject(arg) or os.path.splitext(arg)[1] == conf.LIB_SUFFIX])
+ folded = self._getFoldedSections()
+ sections = set()
+ ordered_sections = []
+ for symbol in ordered_symbols:
+ symbol_sections = finder.getSections(symbol)
+ all_symbol_sections = []
+ for section in symbol_sections:
+ if section in folded:
+ if isinstance(folded[section], str):
+ section = folded[section]
+ all_symbol_sections.append(section)
+ all_symbol_sections.extend(folded[section])
+ else:
+ all_symbol_sections.append(section)
+ for section in all_symbol_sections:
+ if not section in sections:
+ ordered_sections.append(section)
+ sections.add(section)
+ return ordered_sections
+
+ def orderSymbols(self, order):
+ '''Given a file containing a list of symbols, adds the appropriate
+ argument to make the linker put the symbols in that order.'''
+ with open(order) as file:
+ sections = self._getOrderedSections([l.strip() for l in file.readlines() if l.strip()])
+ split_sections = {}
+ linked_sections = [s[0] for s in SECTION_INSERT_BEFORE]
+ for s in sections:
+ for linked_section in linked_sections:
+ if s.startswith(linked_section):
+ if linked_section in split_sections:
+ split_sections[linked_section].append(s)
+ else:
+ split_sections[linked_section] = [s]
+ break
+ content = []
+ # Order is important
+ linked_sections = [s for s in linked_sections if s in split_sections]
+
+ if conf.EXPAND_LIBS_ORDER_STYLE == 'section-ordering-file':
+ option = '-Wl,--section-ordering-file,%s'
+ content = sections
+ for linked_section in linked_sections:
+ content.extend(split_sections[linked_section])
+ content.append('%s.*' % linked_section)
+ content.append(linked_section)
+
+ elif conf.EXPAND_LIBS_ORDER_STYLE == 'linkerscript':
+ option = '-Wl,-T,%s'
+ section_insert_before = dict(SECTION_INSERT_BEFORE)
+ for linked_section in linked_sections:
+ content.append('SECTIONS {')
+ content.append(' %s : {' % linked_section)
+ content.extend(' *(%s)' % s for s in split_sections[linked_section])
+ content.append(' }')
+ content.append('}')
+ content.append('INSERT BEFORE %s' % section_insert_before[linked_section])
+ else:
+ raise Exception('EXPAND_LIBS_ORDER_STYLE "%s" is not supported' % conf.EXPAND_LIBS_ORDER_STYLE)
+
+ fd, tmp = tempfile.mkstemp(dir=os.curdir)
+ f = os.fdopen(fd, "w")
+ f.write('\n'.join(content)+'\n')
+ f.close()
+ self.tmp.append(tmp)
+ self.append(option % tmp)
+
+class SectionFinder(object):
+ '''Instances of this class allow to map symbol names to sections in
+ object files.'''
+
+ def __init__(self, objs):
+ '''Creates an instance, given a list of object files.'''
+ if not conf.EXPAND_LIBS_ORDER_STYLE in ['linkerscript', 'section-ordering-file']:
+ raise Exception('EXPAND_LIBS_ORDER_STYLE "%s" is not supported' % conf.EXPAND_LIBS_ORDER_STYLE)
+ self.mapping = {}
+ for obj in objs:
+ if not isObject(obj) and os.path.splitext(obj)[1] != conf.LIB_SUFFIX:
+ raise Exception('%s is not an object nor a static library' % obj)
+ for symbol, section in SectionFinder._getSymbols(obj):
+ sym = SectionFinder._normalize(symbol)
+ if sym in self.mapping:
+ if not section in self.mapping[sym]:
+ self.mapping[sym].append(section)
+ else:
+ self.mapping[sym] = [section]
+
+ def getSections(self, symbol):
+ '''Given a symbol, returns a list of sections containing it or the
+ corresponding thunks. When the given symbol is a thunk, returns the
+ list of sections containing its corresponding normal symbol and the
+ other thunks for that symbol.'''
+ sym = SectionFinder._normalize(symbol)
+ if sym in self.mapping:
+ return self.mapping[sym]
+ return []
+
+ @staticmethod
+ def _normalize(symbol):
+ '''For normal symbols, return the given symbol. For thunks, return
+ the corresponding normal symbol.'''
+ if re.match('^_ZThn[0-9]+_', symbol):
+ return re.sub('^_ZThn[0-9]+_', '_Z', symbol)
+ return symbol
+
+ @staticmethod
+ def _getSymbols(obj):
+ '''Returns a list of (symbol, section) contained in the given object
+ file.'''
+ proc = subprocess.Popen(['objdump', '-t', obj], stdout = subprocess.PIPE, stderr = subprocess.PIPE)
+ (stdout, stderr) = proc.communicate()
+ syms = []
+ for line in stdout.splitlines():
+ # Each line has the following format:
+ # <addr> [lgu!][w ][C ][W ][Ii ][dD ][FfO ] <section>\t<length> <symbol>
+ tmp = line.split(' ',1)
+ # This gives us ["<addr>", "[lgu!][w ][C ][W ][Ii ][dD ][FfO ] <section>\t<length> <symbol>"]
+ # We only need to consider cases where "<section>\t<length> <symbol>" is present,
+ # and where the [FfO] flag is either F (function) or O (object).
+ if len(tmp) > 1 and len(tmp[1]) > 6 and tmp[1][6] in ['O', 'F']:
+ tmp = tmp[1][8:].split()
+ # That gives us ["<section>","<length>", "<symbol>"]
+ syms.append((tmp[-1], tmp[0]))
+ return syms
+
+def print_command(out, args):
+ print >>out, "Executing: " + " ".join(args)
+ for tmp in [f for f in args.tmp if os.path.isfile(f)]:
+ print >>out, tmp + ":"
+ with open(tmp) as file:
+ print >>out, "".join([" " + l for l in file.readlines()])
+ out.flush()
+
+def main(args, proc_callback=None):
+ parser = OptionParser()
+ parser.add_option("--extract", action="store_true", dest="extract",
+ help="when a library has no descriptor file, extract it first, when possible")
+ parser.add_option("--uselist", action="store_true", dest="uselist",
+ help="use a list file for objects when executing a command")
+ parser.add_option("--verbose", action="store_true", dest="verbose",
+ help="display executed command and temporary files content")
+ parser.add_option("--symbol-order", dest="symbol_order", metavar="FILE",
+ help="use the given list of symbols to order symbols in the resulting binary when using with a linker")
+
+ (options, args) = parser.parse_args(args)
+
+ with ExpandArgsMore(args) as args:
+ if options.extract:
+ args.extract()
+ if options.symbol_order:
+ args.orderSymbols(options.symbol_order)
+ if options.uselist:
+ args.makelist()
+
+ if options.verbose:
+ print_command(sys.stderr, args)
+ try:
+ proc = subprocess.Popen(args, stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
+ if proc_callback:
+ proc_callback(proc)
+ except Exception, e:
+ print >>sys.stderr, 'error: Launching', args, ':', e
+ raise e
+ (stdout, stderr) = proc.communicate()
+ if proc.returncode and not options.verbose:
+ print_command(sys.stderr, args)
+ sys.stderr.write(stdout)
+ sys.stderr.flush()
+ if proc.returncode:
+ return proc.returncode
+ return 0
+
+if __name__ == '__main__':
+ exit(main(sys.argv[1:]))
diff --git a/config/expandlibs_gen.py b/config/expandlibs_gen.py
new file mode 100644
index 000000000..b1de63cd0
--- /dev/null
+++ b/config/expandlibs_gen.py
@@ -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/.
+
+'''Given a list of object files and library names, prints a library
+descriptor to standard output'''
+
+from __future__ import with_statement
+import sys
+import os
+import expandlibs_config as conf
+from expandlibs import LibDescriptor, isObject, ensureParentDir
+from optparse import OptionParser
+
+def generate(args):
+ desc = LibDescriptor()
+ for arg in args:
+ if isObject(arg):
+ if os.path.exists(arg):
+ desc['OBJS'].append(os.path.abspath(arg))
+ else:
+ raise Exception("File not found: %s" % arg)
+ elif os.path.splitext(arg)[1] == conf.LIB_SUFFIX:
+ if os.path.exists(arg) or os.path.exists(arg + conf.LIBS_DESC_SUFFIX):
+ desc['LIBS'].append(os.path.abspath(arg))
+ else:
+ raise Exception("File not found: %s" % arg)
+ return desc
+
+if __name__ == '__main__':
+ parser = OptionParser()
+ parser.add_option("-o", dest="output", metavar="FILE",
+ help="send output to the given file")
+
+ (options, args) = parser.parse_args()
+ if not options.output:
+ raise Exception("Missing option: -o")
+
+ ensureParentDir(options.output)
+ with open(options.output, 'w') as outfile:
+ print >>outfile, generate(args)
diff --git a/config/external/fdlibm/moz.build b/config/external/fdlibm/moz.build
new file mode 100644
index 000000000..51caca532
--- /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/Makefile.in b/config/external/ffi/Makefile.in
new file mode 100644
index 000000000..717b5d829
--- /dev/null
+++ b/config/external/ffi/Makefile.in
@@ -0,0 +1,12 @@
+# -*- Mode: python; c-basic-offset: 4; 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/.
+
+# libffi's assembly files want to be pre-processed, so we still use the libffi
+# wrapper to combine the preprocessor and assembler stages.
+# Bug 1299959 is on file to find a better way to do this in moz.build.
+ifdef _MSC_VER
+AS = $(topsrcdir)/js/src/ctypes/libffi/msvcc.sh
+endif
diff --git a/config/external/ffi/moz.build b/config/external/ffi/moz.build
new file mode 100644
index 000000000..e9ef07de3
--- /dev/null
+++ b/config/external/ffi/moz.build
@@ -0,0 +1,107 @@
+# -*- 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:
+ ALLOW_COMPILER_WARNINGS = True
+ NO_VISIBILITY_FLAGS = True
+
+ CONFIGURE_DEFINE_FILES += [
+ '../../../js/src/ctypes/libffi/fficonfig.h',
+ ]
+ GENERATED_FILES += [
+ '../../../js/src/ctypes/libffi/include/ffi.h',
+ ]
+ ffi_h = GENERATED_FILES['../../../js/src/ctypes/libffi/include/ffi.h']
+ ffi_h.script = 'subst_header.py'
+ ffi_h.inputs = ['../../../js/src/ctypes/libffi/include/ffi.h.in']
+
+ 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.update({
+ 'TARGET': CONFIG['FFI_TARGET'],
+ CONFIG['FFI_TARGET']: True,
+ 'FFI_NO_RAW_API': True,
+ 'HAVE_AS_ASCII_PSEUDO_OP': True,
+ 'HAVE_AS_STRING_PSEUDO_OP': True,
+ 'HAVE_AS_X86_64_UNWIND_SECTION_TYPE': 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'] not in ('WINNT', 'Darwin'):
+ 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"'
+
+ if CONFIG['CLANG_CL']:
+ ASFLAGS += ['-clang-cl']
+
+ # 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 = ()
+ if CONFIG['FFI_TARGET'] == 'ARM':
+ ffi_srcs = ('sysv.S', 'ffi.c')
+ if CONFIG['CLANG_CXX']:
+ ASFLAGS += ['-no-integrated-as']
+ elif CONFIG['FFI_TARGET'] == 'AARCH64':
+ ffi_srcs = ('sysv.S', 'ffi.c')
+ elif CONFIG['FFI_TARGET'] == 'X86':
+ ffi_srcs = ('ffi.c', 'sysv.S', 'win32.S')
+ elif CONFIG['FFI_TARGET'] == 'X86_64':
+ ffi_srcs = ('ffi64.c', 'unix64.S', 'ffi.c', 'sysv.S')
+ elif CONFIG['FFI_TARGET'] == 'X86_WIN32':
+ # MinGW Build for 32 bit
+ if CONFIG['CC_TYPE'] == 'gcc':
+ DEFINES['SYMBOL_UNDERSCORE'] = True
+ ffi_srcs = ('ffi.c', 'win32.S')
+ elif CONFIG['FFI_TARGET'] == 'X86_WIN64':
+ ffi_srcs = ('ffi.c', 'win64.S')
+ ASFLAGS += ['-m64']
+ elif CONFIG['FFI_TARGET'] == 'X86_DARWIN':
+ DEFINES['FFI_MMAP_EXEC_WRIT'] = True
+ if CONFIG['OS_TEST'] != 'x86_64':
+ ffi_srcs = ('ffi.c', 'darwin.S', 'ffi64.c', 'darwin64.S',
+ 'win32.S')
+ DEFINES['SYMBOL_UNDERSCORE'] = True
+ else:
+ ffi_srcs = ('ffi.c', 'darwin.S', 'ffi64.c', 'darwin64.S')
+
+ SOURCES += [
+ '/js/src/ctypes/libffi/src/%s/%s' % (CONFIG['FFI_TARGET_DIR'], s)
+ for s in sorted(ffi_srcs)
+ ]
diff --git a/config/external/ffi/subst_header.py b/config/external/ffi/subst_header.py
new file mode 100644
index 000000000..a138f9020
--- /dev/null
+++ b/config/external/ffi/subst_header.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.og/MPL/2.0/.
+
+import sys
+import buildconfig
+from mozbuild.preprocessor import Preprocessor
+
+def main(output, input_file):
+ pp = Preprocessor()
+ pp.context.update({
+ 'FFI_EXEC_TRAMPOLINE_TABLE': '0',
+ 'HAVE_LONG_DOUBLE': '0',
+ 'TARGET': buildconfig.substs['FFI_TARGET'],
+ 'VERSION': '',
+ })
+ 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/Makefile.in b/config/external/freetype2/Makefile.in
new file mode 100644
index 000000000..95a987103
--- /dev/null
+++ b/config/external/freetype2/Makefile.in
@@ -0,0 +1,12 @@
+# 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_TREE_FREETYPE
+
+include $(topsrcdir)/config/config.mk
+
+$(STATIC_LIBS):
+ $(MAKE) -C $(DEPTH)/modules/freetype2
+
+endif
diff --git a/config/external/freetype2/moz.build b/config/external/freetype2/moz.build
new file mode 100644
index 000000000..c1f20b4fe
--- /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']:
+ USE_LIBS += [
+ 'static:/modules/freetype2/.libs/freetype',
+ ]
+else:
+ OS_LIBS += CONFIG['FT2_LIBS']
diff --git a/config/external/icu/common/moz.build b/config/external/icu/common/moz.build
new file mode 100644
index 000000000..031f7f813
--- /dev/null
+++ b/config/external/icu/common/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/.
+
+Library('icuuc')
+FINAL_LIBRARY = 'icu'
+
+DEFINES['U_COMMON_IMPLEMENTATION'] = True
+# This normally gets defined in the SDK but our WINVER is too low.
+#FIXME: should probably stop including mozilla-config.h
+DEFINES['LOCALE_SNAME'] = 0x5c
+
+LOCAL_INCLUDES += ['/intl/icu/source/i18n']
+
+include('../defs.mozbuild')
+include('sources.mozbuild')
diff --git a/config/external/icu/common/sources.mozbuild b/config/external/icu/common/sources.mozbuild
new file mode 100644
index 000000000..562cd9133
--- /dev/null
+++ b/config/external/icu/common/sources.mozbuild
@@ -0,0 +1,281 @@
+# 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/bytestream.cpp',
+ '/intl/icu/source/common/bytestrie.cpp',
+ '/intl/icu/source/common/bytestriebuilder.cpp',
+ '/intl/icu/source/common/bytestrieiterator.cpp',
+ '/intl/icu/source/common/caniter.cpp',
+ '/intl/icu/source/common/chariter.cpp',
+ '/intl/icu/source/common/charstr.cpp',
+ '/intl/icu/source/common/cmemory.c',
+ '/intl/icu/source/common/cstr.cpp',
+ '/intl/icu/source/common/cstring.c',
+ '/intl/icu/source/common/cwchar.c',
+ '/intl/icu/source/common/dictbe.cpp',
+ '/intl/icu/source/common/dictionarydata.cpp',
+ '/intl/icu/source/common/dtintrv.cpp',
+ '/intl/icu/source/common/errorcode.cpp',
+ '/intl/icu/source/common/filteredbrk.cpp',
+ '/intl/icu/source/common/filterednormalizer2.cpp',
+ '/intl/icu/source/common/icudataver.c',
+ '/intl/icu/source/common/icuplug.cpp',
+ '/intl/icu/source/common/listformatter.cpp',
+ '/intl/icu/source/common/loadednormalizer2impl.cpp',
+ '/intl/icu/source/common/locavailable.cpp',
+ '/intl/icu/source/common/locbased.cpp',
+ '/intl/icu/source/common/locdispnames.cpp',
+ '/intl/icu/source/common/locdspnm.cpp',
+ '/intl/icu/source/common/locid.cpp',
+ '/intl/icu/source/common/loclikely.cpp',
+ '/intl/icu/source/common/locmap.c',
+ '/intl/icu/source/common/locresdata.cpp',
+ '/intl/icu/source/common/locutil.cpp',
+ '/intl/icu/source/common/messagepattern.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/pluralmap.cpp',
+ '/intl/icu/source/common/propname.cpp',
+ '/intl/icu/source/common/propsvec.c',
+ '/intl/icu/source/common/punycode.cpp',
+ '/intl/icu/source/common/putil.cpp',
+ '/intl/icu/source/common/rbbi.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/resbund_cnv.cpp',
+ '/intl/icu/source/common/resource.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/stringpiece.cpp',
+ '/intl/icu/source/common/stringtriebuilder.cpp',
+ '/intl/icu/source/common/uarrsort.c',
+ '/intl/icu/source/common/ubidi.c',
+ '/intl/icu/source/common/ubidi_props.c',
+ '/intl/icu/source/common/ubidiln.c',
+ '/intl/icu/source/common/ubiditransform.c',
+ '/intl/icu/source/common/ubidiwrt.c',
+ '/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/ucat.c',
+ '/intl/icu/source/common/uchar.c',
+ '/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.c',
+ '/intl/icu/source/common/ucnv.c',
+ '/intl/icu/source/common/ucnv2022.cpp',
+ '/intl/icu/source/common/ucnv_bld.cpp',
+ '/intl/icu/source/common/ucnv_cb.c',
+ '/intl/icu/source/common/ucnv_cnv.c',
+ '/intl/icu/source/common/ucnv_ct.c',
+ '/intl/icu/source/common/ucnv_err.c',
+ '/intl/icu/source/common/ucnv_ext.cpp',
+ '/intl/icu/source/common/ucnv_io.cpp',
+ '/intl/icu/source/common/ucnv_lmb.c',
+ '/intl/icu/source/common/ucnv_set.c',
+ '/intl/icu/source/common/ucnv_u16.c',
+ '/intl/icu/source/common/ucnv_u32.c',
+ '/intl/icu/source/common/ucnv_u7.c',
+ '/intl/icu/source/common/ucnv_u8.c',
+ '/intl/icu/source/common/ucnvbocu.cpp',
+ '/intl/icu/source/common/ucnvdisp.c',
+ '/intl/icu/source/common/ucnvhz.c',
+ '/intl/icu/source/common/ucnvisci.c',
+ '/intl/icu/source/common/ucnvlat1.c',
+ '/intl/icu/source/common/ucnvmbcs.cpp',
+ '/intl/icu/source/common/ucnvscsu.c',
+ '/intl/icu/source/common/ucnvsel.cpp',
+ '/intl/icu/source/common/ucol_swp.cpp',
+ '/intl/icu/source/common/ucurr.cpp',
+ '/intl/icu/source/common/udata.cpp',
+ '/intl/icu/source/common/udatamem.c',
+ '/intl/icu/source/common/udataswp.c',
+ '/intl/icu/source/common/uenum.c',
+ '/intl/icu/source/common/uhash.c',
+ '/intl/icu/source/common/uhash_us.cpp',
+ '/intl/icu/source/common/uidna.cpp',
+ '/intl/icu/source/common/uinit.cpp',
+ '/intl/icu/source/common/uinvchar.c',
+ '/intl/icu/source/common/uiter.cpp',
+ '/intl/icu/source/common/ulist.c',
+ '/intl/icu/source/common/ulistformatter.cpp',
+ '/intl/icu/source/common/uloc.cpp',
+ '/intl/icu/source/common/uloc_keytype.cpp',
+ '/intl/icu/source/common/uloc_tag.c',
+ '/intl/icu/source/common/umapfile.c',
+ '/intl/icu/source/common/umath.c',
+ '/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/unorm.cpp',
+ '/intl/icu/source/common/unormcmp.cpp',
+ '/intl/icu/source/common/uobject.cpp',
+ '/intl/icu/source/common/uprops.cpp',
+ '/intl/icu/source/common/ures_cnv.c',
+ '/intl/icu/source/common/uresbund.cpp',
+ '/intl/icu/source/common/uresdata.cpp',
+ '/intl/icu/source/common/usc_impl.c',
+ '/intl/icu/source/common/uscript.c',
+ '/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/ushape.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/ustr_wcs.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.c',
+ '/intl/icu/source/common/ustring.cpp',
+ '/intl/icu/source/common/ustrtrns.cpp',
+ '/intl/icu/source/common/utext.cpp',
+ '/intl/icu/source/common/utf_impl.c',
+ '/intl/icu/source/common/util.cpp',
+ '/intl/icu/source/common/util_props.cpp',
+ '/intl/icu/source/common/utrace.c',
+ '/intl/icu/source/common/utrie.cpp',
+ '/intl/icu/source/common/utrie2.cpp',
+ '/intl/icu/source/common/utrie2_builder.cpp',
+ '/intl/icu/source/common/uts46.cpp',
+ '/intl/icu/source/common/utypes.c',
+ '/intl/icu/source/common/uvector.cpp',
+ '/intl/icu/source/common/uvectr32.cpp',
+ '/intl/icu/source/common/uvectr64.cpp',
+ '/intl/icu/source/common/wintz.c',
+]
+
+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/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/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/listformatter.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/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/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/ulistformatter.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/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/icudata.s b/config/external/icu/data/icudata.s
new file mode 100644
index 000000000..a740f3260
--- /dev/null
+++ b/config/external/icu/data/icudata.s
@@ -0,0 +1,31 @@
+;; 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 PREFIX
+ %define DATA_SYMBOL _ %+ ICU_DATA_SYMBOL
+%else
+ %define DATA_SYMBOL ICU_DATA_SYMBOL
+%endif
+
+%ifidn __OUTPUT_FORMAT__,elf
+ %define FORMAT_ELF 1
+%elifidn __OUTPUT_FORMAT__,elf32
+ %define FORMAT_ELF 1
+%elifidn __OUTPUT_FORMAT__,elf64
+ %define FORMAT_ELF 1
+%else
+ %define FORMAT_ELF 0
+%endif
+
+%if FORMAT_ELF
+ global DATA_SYMBOL:data hidden
+ ; This is needed for ELF, otherwise the GNU linker assumes the stack is executable by default.
+ [SECTION .note.GNU-stack noalloc noexec nowrite progbits]
+%else
+ global DATA_SYMBOL
+%endif
+
+SECTION .rodata align=16
+DATA_SYMBOL:
+ incbin ICU_DATA_FILE
diff --git a/config/external/icu/data/icudata_gas.S b/config/external/icu/data/icudata_gas.S
new file mode 100644
index 000000000..7690ac9da
--- /dev/null
+++ b/config/external/icu/data/icudata_gas.S
@@ -0,0 +1,12 @@
+# 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(__linux__) && defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
+.global ICU_DATA_SYMBOL
+.data
+.balign 16
+ICU_DATA_SYMBOL:
+ .incbin ICU_DATA_FILE
diff --git a/config/external/icu/data/icudt58l.dat b/config/external/icu/data/icudt58l.dat
new file mode 100644
index 000000000..7ade5b8fa
--- /dev/null
+++ b/config/external/icu/data/icudt58l.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 000000000..91aa52aab
--- /dev/null
+++ b/config/external/icu/data/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/.
+
+if CONFIG['MOZ_ICU_DATA_ARCHIVE']:
+ # Copy the pre-built ICU data file to dist/bin.
+ FINAL_TARGET_FILES += [CONFIG['ICU_DATA_FILE']]
+
+# 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')
+
+if CONFIG['OS_ARCH'] == 'WINNT':
+ if CONFIG['CPU_ARCH'] == 'x86':
+ ASFLAGS += ['-DPREFIX']
+elif CONFIG['OS_ARCH'] == 'Darwin':
+ ASFLAGS += ['-DPREFIX']
+
+ASFLAGS += [
+ '-DICU_DATA_FILE="%s"' % CONFIG['ICU_DATA_FILE'],
+ '-DICU_DATA_SYMBOL=icudt%s_dat' % CONFIG['MOZ_ICU_VERSION'],
+]
+LOCAL_INCLUDES += ['.']
+
+if CONFIG['HAVE_YASM']:
+ USE_YASM = True
+ SOURCES += ['icudata.s']
+elif CONFIG['GNU_AS']:
+ SOURCES += ['icudata_gas.S']
diff --git a/config/external/icu/defs.mozbuild b/config/external/icu/defs.mozbuild
new file mode 100644
index 000000000..666bd4f6d
--- /dev/null
+++ b/config/external/icu/defs.mozbuild
@@ -0,0 +1,49 @@
+# -*- 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/.
+
+DEFINES.update(
+ # Don't use icu namespace automatically in client code.
+ U_USING_ICU_NAMESPACE = 0,
+
+ # Don't include obsolete header files.
+ U_NO_DEFAULT_INCLUDE_UTF_HEADERS = 1,
+
+ # Remove chunks of the library that we don't need (yet).
+ UCONFIG_NO_LEGACY_CONVERSION = True,
+ UCONFIG_NO_TRANSLITERATION = True,
+ UCONFIG_NO_REGULAR_EXPRESSIONS = True,
+ UCONFIG_NO_BREAK_ITERATION = True,
+
+ # We don't need to pass data to and from legacy char* APIs.
+ U_CHARSET_IS_UTF8 = True,
+)
+
+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['GNU_CXX']:
+ CXXFLAGS += ['-frtti']
+elif CONFIG['OS_TARGET'] == 'WINNT':
+ CXXFLAGS += ['-GR']
+
+DISABLE_STL_WRAPPING = True
+ALLOW_COMPILER_WARNINGS = True
+
+# We allow compiler warnings, but we can at least cut down on spammy
+# warnings that get triggered for every file.
+if CONFIG['CLANG_CL']:
+ CFLAGS += [
+ '-Wno-macro-redefined',
+ '-Wno-microsoft-include',
+ ]
+ CXXFLAGS += [
+ '-Wno-macro-redefined',
+ '-Wno-microsoft-include',
+ ]
diff --git a/config/external/icu/i18n/moz.build b/config/external/icu/i18n/moz.build
new file mode 100644
index 000000000..f5482351c
--- /dev/null
+++ b/config/external/icu/i18n/moz.build
@@ -0,0 +1,15 @@
+# -*- 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']
+
+include('../defs.mozbuild')
+include('sources.mozbuild')
diff --git a/config/external/icu/i18n/sources.mozbuild b/config/external/icu/i18n/sources.mozbuild
new file mode 100644
index 000000000..8bb619545
--- /dev/null
+++ b/config/external/icu/i18n/sources.mozbuild
@@ -0,0 +1,280 @@
+# THIS FILE IS GENERATED BY /intl/icu_sources_data.py DO NOT EDIT
+SOURCES += [
+ '/intl/icu/source/i18n/affixpatternparser.cpp',
+ '/intl/icu/source/i18n/alphaindex.cpp',
+ '/intl/icu/source/i18n/anytrans.cpp',
+ '/intl/icu/source/i18n/astro.cpp',
+ '/intl/icu/source/i18n/basictz.cpp',
+ '/intl/icu/source/i18n/bocsu.cpp',
+ '/intl/icu/source/i18n/brktrans.cpp',
+ '/intl/icu/source/i18n/buddhcal.cpp',
+ '/intl/icu/source/i18n/calendar.cpp',
+ '/intl/icu/source/i18n/casetrn.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/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/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.c',
+ '/intl/icu/source/i18n/decfmtst.cpp',
+ '/intl/icu/source/i18n/decimalformatpattern.cpp',
+ '/intl/icu/source/i18n/decimfmt.cpp',
+ '/intl/icu/source/i18n/decimfmtimpl.cpp',
+ '/intl/icu/source/i18n/decNumber.c',
+ '/intl/icu/source/i18n/digitaffix.cpp',
+ '/intl/icu/source/i18n/digitaffixesandpadding.cpp',
+ '/intl/icu/source/i18n/digitformatter.cpp',
+ '/intl/icu/source/i18n/digitgrouping.cpp',
+ '/intl/icu/source/i18n/digitinterval.cpp',
+ '/intl/icu/source/i18n/digitlst.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/esctrn.cpp',
+ '/intl/icu/source/i18n/ethpccal.cpp',
+ '/intl/icu/source/i18n/fmtable.cpp',
+ '/intl/icu/source/i18n/fmtable_cnv.cpp',
+ '/intl/icu/source/i18n/format.cpp',
+ '/intl/icu/source/i18n/fphdlimp.cpp',
+ '/intl/icu/source/i18n/fpositer.cpp',
+ '/intl/icu/source/i18n/funcrepl.cpp',
+ '/intl/icu/source/i18n/gender.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/inputext.cpp',
+ '/intl/icu/source/i18n/islamcal.cpp',
+ '/intl/icu/source/i18n/japancal.cpp',
+ '/intl/icu/source/i18n/measfmt.cpp',
+ '/intl/icu/source/i18n/measunit.cpp',
+ '/intl/icu/source/i18n/measure.cpp',
+ '/intl/icu/source/i18n/msgfmt.cpp',
+ '/intl/icu/source/i18n/name2uni.cpp',
+ '/intl/icu/source/i18n/nfrs.cpp',
+ '/intl/icu/source/i18n/nfrule.cpp',
+ '/intl/icu/source/i18n/nfsubs.cpp',
+ '/intl/icu/source/i18n/nortrans.cpp',
+ '/intl/icu/source/i18n/nultrans.cpp',
+ '/intl/icu/source/i18n/numfmt.cpp',
+ '/intl/icu/source/i18n/numsys.cpp',
+ '/intl/icu/source/i18n/olsontz.cpp',
+ '/intl/icu/source/i18n/persncal.cpp',
+ '/intl/icu/source/i18n/pluralaffix.cpp',
+ '/intl/icu/source/i18n/plurfmt.cpp',
+ '/intl/icu/source/i18n/plurrule.cpp',
+ '/intl/icu/source/i18n/precision.cpp',
+ '/intl/icu/source/i18n/quant.cpp',
+ '/intl/icu/source/i18n/quantityformatter.cpp',
+ '/intl/icu/source/i18n/rbnf.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/rbtz.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/region.cpp',
+ '/intl/icu/source/i18n/reldatefmt.cpp',
+ '/intl/icu/source/i18n/reldtfmt.cpp',
+ '/intl/icu/source/i18n/rematch.cpp',
+ '/intl/icu/source/i18n/remtrans.cpp',
+ '/intl/icu/source/i18n/repattrn.cpp',
+ '/intl/icu/source/i18n/rulebasedcollator.cpp',
+ '/intl/icu/source/i18n/scientificnumberformatter.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/smallintformatter.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/strmatch.cpp',
+ '/intl/icu/source/i18n/strrepl.cpp',
+ '/intl/icu/source/i18n/stsearch.cpp',
+ '/intl/icu/source/i18n/taiwncal.cpp',
+ '/intl/icu/source/i18n/timezone.cpp',
+ '/intl/icu/source/i18n/titletrn.cpp',
+ '/intl/icu/source/i18n/tmunit.cpp',
+ '/intl/icu/source/i18n/tmutamt.cpp',
+ '/intl/icu/source/i18n/tmutfmt.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/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/ucsdet.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/ulocdata.c',
+ '/intl/icu/source/i18n/umsg.cpp',
+ '/intl/icu/source/i18n/unesctrn.cpp',
+ '/intl/icu/source/i18n/uni2name.cpp',
+ '/intl/icu/source/i18n/unum.cpp',
+ '/intl/icu/source/i18n/unumsys.cpp',
+ '/intl/icu/source/i18n/upluralrules.cpp',
+ '/intl/icu/source/i18n/uregex.cpp',
+ '/intl/icu/source/i18n/uregexc.cpp',
+ '/intl/icu/source/i18n/uregion.cpp',
+ '/intl/icu/source/i18n/usearch.cpp',
+ '/intl/icu/source/i18n/uspoof.cpp',
+ '/intl/icu/source/i18n/uspoof_build.cpp',
+ '/intl/icu/source/i18n/uspoof_conf.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.c',
+ '/intl/icu/source/i18n/utrans.cpp',
+ '/intl/icu/source/i18n/valueformatter.cpp',
+ '/intl/icu/source/i18n/visibledigits.cpp',
+ '/intl/icu/source/i18n/vtzone.cpp',
+ '/intl/icu/source/i18n/vzone.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',
+ '/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/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/fpositer.h',
+ '/intl/icu/source/i18n/unicode/gender.h',
+ '/intl/icu/source/i18n/unicode/gregocal.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/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/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/ufieldpositer.h',
+ '/intl/icu/source/i18n/unicode/uformattable.h',
+ '/intl/icu/source/i18n/unicode/ugender.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/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/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/moz.build b/config/external/icu/moz.build
new file mode 100644
index 000000000..248652a85
--- /dev/null
+++ b/config/external/icu/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('icu')
+
+if CONFIG['MOZ_SYSTEM_ICU']:
+ OS_LIBS += CONFIG['MOZ_ICU_LIBS']
+else:
+ DIRS += [
+ 'common',
+ 'data',
+ 'i18n',
+ ]
+ if CONFIG['MOZ_ICU_DATA_ARCHIVE']:
+ DIRS += ['stubdata']
+ USE_LIBS += ['icustubdata']
+ else:
+ USE_LIBS += ['icudata']
diff --git a/config/external/icu/stubdata/moz.build b/config/external/icu/stubdata/moz.build
new file mode 100644
index 000000000..b956840c6
--- /dev/null
+++ b/config/external/icu/stubdata/moz.build
@@ -0,0 +1,13 @@
+# -*- 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 builds the ICU stubdata library, since we are shipping ICU
+# data in a separate data file. ICU needs a data symbol to link against
+# even if you're loading its data from a file.
+
+Library('icustubdata')
+
+SOURCES += ['/intl/icu/source/stubdata/stubdata.c']
diff --git a/config/external/lgpllibs/lgpllibs.def b/config/external/lgpllibs/lgpllibs.def
new file mode 100644
index 000000000..359d97e71
--- /dev/null
+++ b/config/external/lgpllibs/lgpllibs.def
@@ -0,0 +1,10 @@
+; 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 lgpllibs.dll
+
+EXPORTS
+ av_rdft_init
+ av_rdft_calc
+ av_rdft_end
diff --git a/config/external/lgpllibs/moz.build b/config/external/lgpllibs/moz.build
new file mode 100644
index 000000000..fad4bfb46
--- /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'
+
+if CONFIG['MOZ_LIBAV_FFT']:
+ DIRS += ['/media/libav']
+ DEFFILE = SRCDIR + '/lgpllibs.def'
diff --git a/config/external/moz.build b/config/external/moz.build
new file mode 100644
index 000000000..029ff8504
--- /dev/null
+++ b/config/external/moz.build
@@ -0,0 +1,67 @@
+# -*- 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 += [
+ 'lgpllibs',
+ 'sqlite',
+]
+if not CONFIG['MOZ_SYSTEM_JPEG']:
+ external_dirs += ['media/libjpeg']
+
+if CONFIG['MOZ_UPDATER']:
+ if not CONFIG['MOZ_SYSTEM_BZ2']:
+ external_dirs += ['modules/libbz2']
+
+# There's no "native" brotli or woff2 yet, but probably in the future...
+external_dirs += ['modules/brotli']
+external_dirs += ['modules/woff2']
+
+if CONFIG['MOZ_VORBIS']:
+ external_dirs += ['media/libvorbis']
+
+if CONFIG['MOZ_TREMOR']:
+ external_dirs += ['media/libtremor']
+
+if CONFIG['MOZ_WEBM_ENCODER']:
+ external_dirs += ['media/libmkv']
+
+if not CONFIG['MOZ_SYSTEM_LIBVPX']:
+ external_dirs += ['media/libvpx']
+
+if not CONFIG['MOZ_SYSTEM_PNG']:
+ external_dirs += ['media/libpng']
+
+if CONFIG['CPU_ARCH'] == 'arm':
+ external_dirs += ['media/openmax_dl']
+
+if CONFIG['MOZ_WEBSPEECH_POCKETSPHINX']:
+ external_dirs += [
+ 'media/sphinxbase',
+ 'media/pocketsphinx',
+ ]
+
+if CONFIG['MOZ_FFVPX']:
+ external_dirs += ['media/ffvpx']
+
+external_dirs += [
+ 'media/kiss_fft',
+ 'media/libcubeb',
+ 'media/libnestegg',
+ 'media/libogg',
+ 'media/libopus',
+ 'media/libtheora',
+ 'media/libspeex_resampler',
+ 'media/libstagefright',
+ 'media/libsoundtouch',
+ 'media/psshparser'
+]
+
+if CONFIG['MOZ_LINKER']:
+ external_dirs += ['modules/xz-embedded']
+
+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 000000000..57fb0e988
--- /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 000000000..1e36c69f1
--- /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 000000000..b49867abb
--- /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
+ALLOW_COMPILER_WARNINGS = True
+
+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 000000000..f8a4705b2
--- /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
+ALLOW_COMPILER_WARNINGS = True
+
+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 000000000..062970203
--- /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 000000000..cda249b8a
--- /dev/null
+++ b/config/external/nspr/pr/moz.build
@@ -0,0 +1,232 @@
+# -*- 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
+ALLOW_COMPILER_WARNINGS = True
+
+DEFINES['_NSPR_BUILD_'] = True
+if CONFIG['OS_ARCH'] == 'Linux':
+ OS_LIBS += CONFIG['REALTIME_LIBS']
+ DEFINES.update(
+ LINUX=True,
+ HAVE_FCNTL_FILE_LOCKING=True,
+ _GNU_SOURCE=True,
+ )
+ SOURCES += ['/nsprpub/pr/src/md/unix/linux.c']
+ if CONFIG['CPU_ARCH'] == 'x86_64':
+ SOURCES += ['/nsprpub/pr/src/md/unix/os_Linux_x86_64.s']
+ elif CONFIG['CPU_ARCH'] == 'x86':
+ DEFINES['i386'] = True
+ SOURCES += ['/nsprpub/pr/src/md/unix/os_Linux_x86.s']
+ elif CONFIG['CPU_ARCH'] == 'ppc':
+ SOURCES += ['/nsprpub/pr/src/md/unix/os_Linux_ppc.s']
+elif CONFIG['OS_TARGET'] in ('FreeBSD', 'OpenBSD', 'NetBSD'):
+ DEFINES.update(
+ HAVE_BSD_FLOCK=True,
+ HAVE_SOCKLEN_T=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']
+ DEFINES.update(
+ DARWIN=True,
+ HAVE_BSD_FLOCK=True,
+ HAVE_SOCKLEN_T=True,
+ )
+ SOURCES += [
+ '/nsprpub/pr/src/md/unix/darwin.c',
+ '/nsprpub/pr/src/md/unix/os_Darwin.s',
+ ]
+ if not CONFIG['MOZ_IOS']:
+ DEFINES['HAVE_CRT_EXTERNS_H'] = True
+elif CONFIG['OS_TARGET'] == 'WINNT':
+ OS_LIBS += [
+ 'advapi32',
+ 'ws2_32',
+ 'mswsock',
+ 'winmm',
+ ]
+ DEFINES.update(
+ XP_PC=True,
+ WIN32=True,
+ # For historical reasons we use the WIN95 NSPR target instead of
+ # WINNT.
+ WIN95=True,
+ WINNT=False,
+ _PR_GLOBAL_THREADS_ONLY=True,
+ )
+ if CONFIG['CPU_ARCH'] == 'x86_64':
+ DEFINES['_AMD64_'] = True
+ else:
+ DEFINES['_X86_'] = True
+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/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/prpolevt.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/prshm.c',
+ '/nsprpub/pr/src/memory/prshma.c',
+ '/nsprpub/pr/src/misc/pralarm.c',
+ '/nsprpub/pr/src/misc/pratom.c',
+ '/nsprpub/pr/src/misc/praton.c',
+ '/nsprpub/pr/src/misc/prcountr.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/prlong.c',
+ '/nsprpub/pr/src/misc/prnetdb.c',
+ '/nsprpub/pr/src/misc/prolock.c',
+ '/nsprpub/pr/src/misc/prrng.c',
+ '/nsprpub/pr/src/misc/prsystem.c',
+ '/nsprpub/pr/src/misc/prthinfo.c',
+ '/nsprpub/pr/src/misc/prtime.c',
+ '/nsprpub/pr/src/misc/prtpool.c',
+ '/nsprpub/pr/src/misc/prtrace.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
+ 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/md/unix/uxwrap.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 += [
+ '/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/ntinrval.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/w32poll.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/w95sock.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/prcountr.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/prolock.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/_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 000000000..5f7962733
--- /dev/null
+++ b/config/external/nspr/prcpucfg.h
@@ -0,0 +1,29 @@
+/* -*- 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"
+#else
+#error "Unsupported platform!"
+#endif
+
+#endif /* NSPR_PRCPUCFG_H_ */
diff --git a/config/external/nss/Makefile.in b/config/external/nss/Makefile.in
new file mode 100644
index 000000000..4b95a32bd
--- /dev/null
+++ b/config/external/nss/Makefile.in
@@ -0,0 +1,488 @@
+#
+# 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 MOZ_SYSTEM_NSS
+
+CC_WRAPPER =
+CXX_WRAPPER =
+
+default::
+
+include $(topsrcdir)/config/makefiles/functions.mk
+
+NSS_LIBS = \
+ nss3 \
+ nssutil3 \
+ smime3 \
+ ssl3 \
+ $(NULL)
+
+ifdef MOZ_FOLD_LIBS
+NSS_DLLS = $(LIBRARY_NAME)
+else
+NSS_DLLS = $(NSS_LIBS)
+endif
+
+NSS_EXTRA_DLLS = \
+ nssckbi \
+ softokn3 \
+ $(NULL)
+
+ifndef NSS_DISABLE_DBM
+NSS_EXTRA_DLLS += nssdbm3
+endif
+
+SDK_LIBS = crmf
+
+ifneq (,$(filter WINNT,$(OS_ARCH)))
+SDK_LIBS += $(NSS_DLLS)
+endif
+
+# Default
+HAVE_FREEBL_LIBS = 1
+
+# 32-bit HP-UX PA-RISC
+ifeq ($(OS_ARCH), HP-UX)
+ifneq ($(OS_TEST), ia64)
+ifndef HAVE_64BIT_BUILD
+HAVE_FREEBL_LIBS =
+HAVE_FREEBL_LIBS_32INT32 = 1
+HAVE_FREEBL_LIBS_32FPU = 1
+endif
+endif
+endif
+
+# SunOS SPARC
+ifeq ($(OS_ARCH), SunOS)
+ifneq (86,$(findstring 86,$(OS_TEST)))
+ifdef HAVE_64BIT_BUILD
+HAVE_FREEBL_LIBS =
+HAVE_FREEBL_LIBS_64 = 1
+else
+HAVE_FREEBL_LIBS =
+HAVE_FREEBL_LIBS_32FPU = 1
+HAVE_FREEBL_LIBS_32INT64 = 1
+endif
+endif
+endif
+
+ifeq ($(OS_TARGET),Linux)
+HAVE_FREEBL_LIBS =
+HAVE_FREEBL_LIBS_PRIV = 1
+FREEBL_LOWHASH_FLAG = FREEBL_LOWHASH=1
+endif
+
+ifdef HAVE_FREEBL_LIBS
+NSS_EXTRA_DLLS += freebl3
+endif
+ifdef HAVE_FREEBL_LIBS_PRIV
+NSS_EXTRA_DLLS += freeblpriv3
+endif
+ifdef HAVE_FREEBL_LIBS_32INT32
+NSS_EXTRA_DLLS += freebl_32int_3
+endif
+ifdef HAVE_FREEBL_LIBS_32FPU
+NSS_EXTRA_DLLS += freebl_32fpu_3
+endif
+ifdef HAVE_FREEBL_LIBS_32INT64
+NSS_EXTRA_DLLS += freebl_32int64_3
+endif
+ifdef HAVE_FREEBL_LIBS_64
+NSS_EXTRA_DLLS += freebl_64int_3
+NSS_EXTRA_DLLS += freebl_64fpu_3
+endif
+
+# For all variables such as DLLFLAGS, that may contain $(DIST)
+DIST := $(ABS_DIST)
+# TODO: move this all to configure, but in Python
+ifndef MOZ_BUILD_NSPR
+NSPR_INCLUDE_DIR = $(firstword $(filter -I%,$(NSPR_CFLAGS)))
+ifneq (,$(strip $(NSPR_INCLUDE_DIR)))
+NSPR_INCLUDE_DIR := $(subst -I,,$(subst -I$(DIST),-I$(ABS_DIST),$(NSPR_INCLUDE_DIR)))
+else
+$(error Your NSPR CFLAGS are broken!)
+endif
+NSPR_LIB_DIR = $(firstword $(filter -L%,$(NSPR_LIBS)))
+ifneq (,$(strip $(NSPR_LIB_DIR)))
+NSPR_LIB_DIR := $(subst -L,,$(subst -L$(DIST),-L$(ABS_DIST),$(NSPR_LIB_DIR)))
+else
+$(error Your NSPR LDFLAGS are broken!)
+endif
+endif
+
+# To get debug symbols from NSS
+export MOZ_DEBUG_SYMBOLS
+
+DEFAULT_GMAKE_FLAGS =
+DEFAULT_GMAKE_FLAGS += CC='$(CC)'
+DEFAULT_GMAKE_FLAGS += MT='$(MT)'
+DEFAULT_GMAKE_FLAGS += LD='$(LD)'
+DEFAULT_GMAKE_FLAGS += SOURCE_MD_DIR=$(ABS_DIST)
+DEFAULT_GMAKE_FLAGS += SOURCE_MDHEADERS_DIR=$(NSPR_INCLUDE_DIR)
+DEFAULT_GMAKE_FLAGS += DIST=$(ABS_DIST)
+DEFAULT_GMAKE_FLAGS += NSPR_INCLUDE_DIR=$(NSPR_INCLUDE_DIR)
+DEFAULT_GMAKE_FLAGS += NSPR_LIB_DIR=$(NSPR_LIB_DIR)
+DEFAULT_GMAKE_FLAGS += MOZILLA_CLIENT=1
+DEFAULT_GMAKE_FLAGS += NO_MDUPDATE=1
+DEFAULT_GMAKE_FLAGS += NSS_ENABLE_ECC=1
+DEFAULT_GMAKE_FLAGS += NSS_ENABLE_TLS_1_3=1
+ifeq ($(OS_ARCH)_$(GNU_CC),WINNT_1)
+DEFAULT_GMAKE_FLAGS += OS_DLLFLAGS='-static-libgcc' NSPR31_LIB_PREFIX=lib
+endif
+ifndef MOZ_SYSTEM_SQLITE
+ifdef MOZ_FOLD_LIBS
+DEFAULT_GMAKE_FLAGS += SQLITE_LIB_NAME=nss3
+else
+DEFAULT_GMAKE_FLAGS += SQLITE_LIB_NAME=mozsqlite3
+DEFAULT_GMAKE_FLAGS += SQLITE_LIB_DIR=$(ABS_DIST)/../config/external/sqlite
+endif # MOZ_FOLD_LIBS
+DEFAULT_GMAKE_FLAGS += SQLITE_INCLUDE_DIR=$(ABS_DIST)/include
+endif
+ifdef NSS_DISABLE_DBM
+DEFAULT_GMAKE_FLAGS += NSS_DISABLE_DBM=1
+endif
+# Hack to force NSS build system to use "normal" object directories
+DEFAULT_GMAKE_FLAGS += topsrcdir='$(topsrcdir)'
+# topsrcdir can't be expanded here because msys path mangling likes to break
+# paths in that case.
+DEFAULT_GMAKE_FLAGS += BUILD='$(MOZ_BUILD_ROOT)/security/$$(subst $$(topsrcdir)/security/,,$$(CURDIR))'
+DEFAULT_GMAKE_FLAGS += BUILD_TREE='$$(BUILD)' OBJDIR='$$(BUILD)' DEPENDENCIES='$$(BUILD)/.deps' SINGLE_SHLIB_DIR='$$(BUILD)'
+DEFAULT_GMAKE_FLAGS += SOURCE_XP_DIR=$(ABS_DIST)
+ifndef MOZ_DEBUG
+DEFAULT_GMAKE_FLAGS += BUILD_OPT=1 OPT_CODE_SIZE=1
+endif
+ifdef GNU_CC
+DEFAULT_GMAKE_FLAGS += NS_USE_GCC=1
+else
+DEFAULT_GMAKE_FLAGS += NS_USE_GCC=
+endif
+ifdef USE_N32
+# It is not really necessary to specify USE_PTHREADS=1. USE_PTHREADS
+# merely adds _PTH to coreconf's OBJDIR name.
+DEFAULT_GMAKE_FLAGS += USE_N32=1 USE_PTHREADS=1
+endif
+ifdef HAVE_64BIT_BUILD
+DEFAULT_GMAKE_FLAGS += USE_64=1
+endif
+ifeq ($(OS_ARCH),WINNT)
+DEFAULT_GMAKE_FLAGS += OS_TARGET=WIN95
+ifdef MOZ_DEBUG
+ifndef MOZ_NO_DEBUG_RTL
+DEFAULT_GMAKE_FLAGS += USE_DEBUG_RTL=1
+endif
+endif
+endif # WINNT
+ifeq ($(OS_ARCH),Darwin)
+# Make nsinstall use absolute symlinks by default when building NSS
+# for Mozilla on Mac OS X. (Bugzilla bug 193164)
+ifndef NSDISTMODE
+DEFAULT_GMAKE_FLAGS += NSDISTMODE=absolute_symlink
+endif
+ifdef MACOS_SDK_DIR
+DEFAULT_GMAKE_FLAGS += MACOS_SDK_DIR=$(MACOS_SDK_DIR)
+endif
+endif
+
+# Turn off TLS compression support because it requires system zlib.
+# See bug 580679 comment 18.
+DEFAULT_GMAKE_FLAGS += NSS_SSL_ENABLE_ZLIB=
+
+# Disable building of the test programs in security/nss/lib/zlib
+DEFAULT_GMAKE_FLAGS += PROGRAMS=
+
+# Disable creating .chk files. They will be generated from packager.mk
+# When bug 681624 lands, we can replace CHECKLOC= with SKIP_SHLIBSIGN=1
+DEFAULT_GMAKE_FLAGS += CHECKLOC=
+
+ifdef CROSS_COMPILE
+
+DEFAULT_GMAKE_FLAGS += \
+ NATIVE_CC='$(HOST_CC)' \
+ CC='$(CC)' \
+ CCC='$(CXX)' \
+ AS='$(AS)' \
+ AR='$(AR) $(AR_FLAGS:$@=$$@)' \
+ RANLIB='$(RANLIB)' \
+ RC='$(RC) $(RCFLAGS)' \
+ OS_ARCH='$(OS_ARCH)' \
+ OS_TEST='$(OS_TEST)' \
+ CPU_ARCH='$(TARGET_CPU)' \
+ $(NULL)
+
+# Android has pthreads integrated into -lc, so OS_PTHREAD is set to nothing
+ifeq ($(OS_TARGET), Android)
+DEFAULT_GMAKE_FLAGS += \
+ OS_RELEASE='2.6' \
+ OS_PTHREAD= \
+ $(NULL)
+
+DEFAULT_GMAKE_FLAGS += ARCHFLAG='$(filter-out -W%,$(CFLAGS)) -DCHECK_FORK_GETPID $(addprefix -DANDROID_VERSION=,$(ANDROID_VERSION)) -include $(topsrcdir)/security/manager/android_stub.h'
+endif
+endif
+
+ifdef WRAP_LDFLAGS
+NSS_EXTRA_LDFLAGS += $(WRAP_LDFLAGS)
+endif
+
+# The SHARED_LIBS part is needed unconditionally on Android. It's not
+# clear why this is the case, but see bug 1133073 (starting around
+# comment #8) for context.
+ifneq (,$(or $(MOZ_GLUE_WRAP_LDFLAGS), $(filter Android, $(OS_TARGET))))
+NSS_EXTRA_LDFLAGS += $(SHARED_LIBS:$(DEPTH)%=$(MOZ_BUILD_ROOT)%) $(MOZ_GLUE_WRAP_LDFLAGS)
+endif
+
+ifneq (,$(NSS_EXTRA_LDFLAGS))
+DEFAULT_GMAKE_FLAGS += \
+ LDFLAGS='$(LDFLAGS) $(NSS_EXTRA_LDFLAGS)' \
+ DSO_LDOPTS='$(DSO_LDOPTS) $(LDFLAGS) $(NSS_EXTRA_LDFLAGS)' \
+ $(NULL)
+endif
+
+DEFAULT_GMAKE_FLAGS += FREEBL_NO_DEPEND=0 $(FREEBL_LOWHASH_FLAG)
+DEFAULT_GMAKE_FLAGS += NSS_ALLOW_SSLKEYLOGFILE=1
+
+ifdef MOZ_NO_WLZDEFS
+DEFAULT_GMAKE_FLAGS += ZDEFS_FLAG=
+endif
+ifdef MOZ_CFLAGS_NSS
+NSS_XCFLAGS += $(filter-out -W%,$(CFLAGS))
+DEFAULT_GMAKE_FLAGS += DARWIN_DYLIB_VERSIONS='-compatibility_version 1 -current_version 1 $(LDFLAGS)'
+endif
+ifeq (1_1,$(CLANG_CL)_$(MOZ_ASAN))
+XLDFLAGS := $(OS_LDFLAGS)
+DEFAULT_GMAKE_FLAGS += XLDFLAGS='$(XLDFLAGS)'
+endif
+
+DEFAULT_GMAKE_FLAGS += NSS_NO_PKCS11_BYPASS=1
+
+# Put NSS headers directly under $(DIST)/include
+DEFAULT_GMAKE_FLAGS += PUBLIC_EXPORT_DIR='$(ABS_DIST)/include/$$(MODULE)'
+DEFAULT_GMAKE_FLAGS += SOURCE_XPHEADERS_DIR='$$(SOURCE_XP_DIR)/include/$$(MODULE)'
+DEFAULT_GMAKE_FLAGS += MODULE_INCLUDES='$$(addprefix -I$$(SOURCE_XP_DIR)/include/,$$(REQUIRES))'
+
+# Work around NSS's MAKE_OBJDIR being racy. See bug #836220
+DEFAULT_GMAKE_FLAGS += MAKE_OBJDIR='$$(INSTALL) -D $$(OBJDIR)'
+
+# Work around NSS adding IMPORT_LIBRARY to TARGETS with no rule for
+# it, creating race conditions. See bug #836220
+DEFAULT_GMAKE_FLAGS += TARGETS='$$(LIBRARY) $$(SHARED_LIBRARY) $$(PROGRAM)'
+
+ifdef MOZ_FOLD_LIBS_FLAGS
+NSS_XCFLAGS += $(MOZ_FOLD_LIBS_FLAGS)
+endif
+
+# Pass on the MSVC target arch from the main build system.
+# Note this is case- and switch-character sensitive, while
+# the MSVC option is not.
+ifeq (WINNT,$(OS_TARGET))
+NSS_XCFLAGS += $(filter -arch:%,$(CFLAGS))
+endif
+
+# Enable short header experiment. Firefox only.
+NSS_XCFLAGS += -DNSS_ENABLE_TLS13_SHORT_HEADERS
+
+# Export accumulated XCFLAGS to modify nss defaults.
+DEFAULT_GMAKE_FLAGS += XCFLAGS='$(NSS_XCFLAGS)'
+
+NSS_SRCDIR = $(topsrcdir)
+
+NSS_DIRS =
+ifndef MOZ_FOLD_LIBS
+NSS_DIRS += nss/lib
+else
+ifndef NSS_DISABLE_DBM
+NSS_DIRS += nss/lib/dbm
+endif
+endif
+NSS_DIRS += \
+ nss/cmd/lib \
+ nss/cmd/shlibsign \
+ $(NULL)
+
+ifdef ENABLE_TESTS
+NSS_DIRS += \
+ nss/cmd/certutil \
+ nss/cmd/pk12util \
+ nss/cmd/modutil \
+ $(NULL)
+endif
+
+ifneq (,$(filter %--build-id,$(LDFLAGS)))
+DEFAULT_GMAKE_ENV = LDFLAGS=-Wl,--build-id
+endif
+
+ifdef MOZ_FOLD_LIBS
+# TODO: The following can be replaced by something simpler when bug 844880
+# is fixed.
+# All static libraries required for nss, smime, ssl and nssutil.
+# The strip is needed to remove potential linefeed characters, since they hang
+# around in some cases on Windows.
+NSS_STATIC_LIBS := $(strip $(shell $(MAKE) --no-print-directory -f $(srcdir)/nss.mk DEPTH='$(DEPTH)' topsrcdir='$(topsrcdir)' srcdir='$(srcdir)' echo-variable-libs))
+# Corresponding build directories
+NSS_STATIC_DIRS := $(foreach lib,$(NSS_STATIC_LIBS),$(patsubst %/,%,$(dir $(lib))))
+NSS_DIRS += $(NSS_STATIC_DIRS)
+
+# TODO: The following can be replaced by something simpler when bug 844884
+# is fixed.
+# Remaining nss/lib directories
+NSS_DIRS += nss/lib/freebl nss/lib/softoken nss/lib/jar nss/lib/crmf nss/lib/ckfw
+
+DEFAULT_GMAKE_FLAGS += NSS_DISABLE_LIBPKIX=1
+
+ifeq (WINNT,$(OS_TARGET))
+NSS_DIRS += nss/lib/zlib
+endif
+endif # MOZ_FOLD_LIBS
+
+# Filter-out $(LIBRARY_NAME) because it's already handled in config/rules.mk.
+NSS_DIST_DLL_FILES := $(addprefix $(DIST)/lib/$(DLL_PREFIX),$(addsuffix $(DLL_SUFFIX),$(filter-out $(LIBRARY_NAME),$(NSS_DLLS)) $(NSS_EXTRA_DLLS)))
+NSS_DIST_DLL_DEST := $(DIST)/bin
+NSS_DIST_DLL_TARGET := target
+INSTALL_TARGETS += NSS_DIST_DLL
+
+ifeq ($(OS_ARCH)_$(1), SunOS_softokn3)
+# has to use copy mode on Solaris, see #665509
+$(DIST)/bin/$(DLL_PREFIX)softokn3$(DLL_SUFFIX): INSTALL := $(INSTALL) -t
+endif
+
+NSS_SDK_LIB_FILES := \
+ $(addprefix $(DIST)/lib/$(LIB_PREFIX),$(addsuffix .$(LIB_SUFFIX),$(SDK_LIBS))) \
+ $(addprefix $(DIST)/bin/$(DLL_PREFIX),$(addsuffix $(DLL_SUFFIX),$(NSS_DLLS))) \
+ $(NULL)
+NSS_SDK_LIB_DEST := $(DIST)/sdk/lib
+NSS_SDK_LIB_TARGET := target
+INSTALL_TARGETS += NSS_SDK_LIB
+
+ifdef MOZ_FOLD_LIBS
+# Add all static libraries for nss, smime, ssl and nssutil
+STATIC_LIBS += $(addprefix $(DEPTH)/security/,$(NSS_STATIC_LIBS))
+
+IMPORT_LIB_FILES = $(IMPORT_LIBRARY)
+IMPORT_LIB_DEST ?= $(DIST)/lib
+IMPORT_LIB_TARGET = target
+INSTALL_TARGETS += IMPORT_LIB
+
+endif # MOZ_FOLD_LIBS
+
+include $(topsrcdir)/config/rules.mk
+
+ifeq (1,$(ALLOW_COMPILER_WARNINGS))
+DEFAULT_GMAKE_FLAGS += NSS_ENABLE_WERROR=0
+endif
+
+# Can't pass this in DEFAULT_GMAKE_FLAGS because that overrides
+# definitions in NSS, so just export it into the sub-make's environment.
+ifeq (WINNT_1,$(OS_TARGET)_$(MOZ_MEMORY))
+DLLFLAGS := -LIBPATH:$(ABS_DIST)/../mozglue/build -DEFAULTLIB:mozglue
+export DLLFLAGS
+endif
+
+ifdef MOZ_FOLD_LIBS
+# Force the linker to include everything from the static libraries.
+EXPAND_LIBS_EXEC += --extract
+
+$(SHARED_LIBRARY): $(addprefix $(DEPTH)/security/,$(NSS_STATIC_LIBS))
+
+ifdef IMPORT_LIB_SUFFIX
+IMPORT_PREFIX = $(LIB_PREFIX)
+IMPORT_SUFFIX = .$(IMPORT_LIB_SUFFIX)
+else
+IMPORT_PREFIX = $(DLL_PREFIX)
+IMPORT_SUFFIX = $(DLL_SUFFIX)
+endif
+
+NSPR_IMPORT_LIBS = $(addprefix $(DIST)/lib/$(IMPORT_PREFIX),$(addsuffix $(IMPORT_SUFFIX),nspr4 plc4 plds4))
+SQLITE_IMPORT_LIB = $(DIST)/lib/$(IMPORT_PREFIX)mozsqlite3$(IMPORT_SUFFIX)
+
+# TODO: The following can be replaced by something simpler when bug 844884
+# is fixed.
+# Associate target files with the rules that build them.
+$(DIST)/lib/$(LIB_PREFIX)crmf.$(LIB_SUFFIX): libs-nss/lib/crmf
+$(DIST)/lib/$(DLL_PREFIX)freebl3$(DLL_SUFFIX): libs-nss/lib/freebl
+$(DIST)/lib/$(DLL_PREFIX)nssckbi$(DLL_SUFFIX): libs-nss/lib/ckfw
+$(DIST)/lib/$(DLL_PREFIX)softokn3$(DLL_SUFFIX): libs-nss/lib/softoken
+$(DIST)/lib/$(DLL_PREFIX)nssdbm3$(DLL_SUFFIX): libs-nss/lib/softoken
+$(foreach lib,$(NSS_STATIC_LIBS),$(eval $(DEPTH)/security/$(lib): libs-$(patsubst %/,%,$(dir $(lib)))))
+
+# Create fake import libraries for the folded libraries, so that linking
+# against them works both for the NSS build system (see dependencies below)
+# and for the rest of the mozilla build system.
+$(NSPR_IMPORT_LIBS) \
+$(SQLITE_IMPORT_LIB) \
+$(DIST)/lib/$(IMPORT_PREFIX)nssutil3$(IMPORT_SUFFIX) \
+$(DIST)/lib/$(IMPORT_PREFIX)ssl3$(IMPORT_SUFFIX) \
+$(DIST)/lib/$(IMPORT_PREFIX)smime3$(IMPORT_SUFFIX): $(DIST)/lib/$(IMPORT_PREFIX)nss3$(IMPORT_SUFFIX)
+ifeq (WINNT,$(OS_TARGET))
+ cp $< $@
+else
+ ln -sf $< $@
+endif
+
+# Interdependencies between nss sub-directories, and dependencies on NSPR/SQLite
+libs-nss/lib/ckfw: libs-nss/lib/nss/../base $(NSPR_IMPORT_LIBS)
+libs-nss/lib/softoken: $(NSPR_IMPORT_LIBS) $(SQLITE_IMPORT_LIB)
+libs-nss/lib/softoken: libs-nss/lib/freebl
+ifndef NSS_DISABLE_DBM
+libs-nss/lib/softoken: libs-nss/lib/dbm
+endif
+libs-nss/lib/softoken: $(DIST)/lib/$(IMPORT_PREFIX)nssutil3$(IMPORT_SUFFIX)
+libs-nss/lib/freebl: $(DIST)/lib/$(IMPORT_PREFIX)nssutil3$(IMPORT_SUFFIX) $(NSPR_IMPORT_LIBS)
+
+# For each directory where we build static libraries, force the NSS build system
+# to only build static libraries.
+$(addprefix libs-,$(NSS_STATIC_DIRS)): DEFAULT_GMAKE_FLAGS += SHARED_LIBRARY= IMPORT_LIBRARY=
+else
+$(STATIC_LIBS) $(NSS_DIST_DLL_FILES) $(NSS_SDK_LIB_FILES): libs-nss/lib
+endif # MOZ_FOLD_LIBS
+
+ifeq ($(NSINSTALL_PY),$(NSINSTALL))
+DEFAULT_GMAKE_FLAGS += PYTHON='$(PYTHON)'
+DEFAULT_GMAKE_FLAGS += NSINSTALL_PY='$(abspath $(topsrcdir)/config/nsinstall.py)'
+DEFAULT_GMAKE_FLAGS += NSINSTALL='$$(PYTHON) $$(NSINSTALL_PY)'
+else
+DEFAULT_GMAKE_FLAGS += NSINSTALL='$(abspath $(NSINSTALL))'
+endif
+ifeq ($(OS_ARCH),WINNT)
+DEFAULT_GMAKE_FLAGS += INSTALL='$$(NSINSTALL) -t'
+endif
+DEFAULT_GMAKE_FLAGS += $(EXTRA_GMAKE_FLAGS)
+
+$(addprefix libs-,$(NSS_DIRS)): libs-%:
+# Work around NSS's export rule being racy when recursing for private_export
+# See bug #836220.
+$(addprefix export-,$(NSS_DIRS)): EXTRA_GMAKE_FLAGS = PRIVATE_EXPORTS=
+$(addprefix export-,$(NSS_DIRS)): export-%: private_export-%
+$(addprefix private_export-,$(NSS_DIRS)): EXTRA_GMAKE_FLAGS =
+$(addprefix private_export-,$(NSS_DIRS)): private_export-%:
+
+$(foreach p,libs export private_export,$(addprefix $(p)-,$(NSS_DIRS))):
+ $(DEFAULT_GMAKE_ENV) $(MAKE) -C $(NSS_SRCDIR)/security/$* $(@:-$*=) $(DEFAULT_GMAKE_FLAGS)
+
+export:: $(addprefix export-,$(NSS_DIRS))
+
+$(addprefix clean-,$(NSS_DIRS)): clean-%:
+ $(MAKE) -C $(NSS_SRCDIR)/security/$* $(DEFAULT_GMAKE_FLAGS) clean
+
+clean clobber clobber_all realclean distclean depend:: $(addprefix clean-,$(NSS_DIRS))
+
+NSS_CMD_TARGETS := $(addprefix libs-,$(filter-out nss/cmd/lib,$(filter nss/cmd/%,$(NSS_DIRS))))
+target:: $(NSS_CMD_TARGETS)
+
+ifdef MOZ_FOLD_LIBS
+$(NSS_CMD_TARGETS): $(addprefix $(DIST)/lib/$(IMPORT_PREFIX),$(addsuffix $(IMPORT_SUFFIX),$(NSS_LIBS)))
+libs-nss/cmd/modutil: libs-nss/lib/jar
+ifeq (WINNT,$(OS_TARGET))
+libs-nss/cmd/modutil: libs-nss/lib/zlib
+endif
+$(NSS_CMD_TARGETS): libs-nss/cmd/lib
+else
+$(NSS_CMD_TARGETS): libs-nss/lib libs-nss/cmd/lib
+endif # MOZ_FOLD_LIBS
+
+# Work around NSS build system race condition creating certdata.c in
+# security/nss/lib/ckfw/builtins. See bug #836220.
+libs-nss/lib$(if $(MOZ_FOLD_LIBS),/ckfw): $(call mkdir_deps,$(DEPTH)/security/nss/lib/ckfw/builtins)
+
+endif
diff --git a/config/external/nss/crmf/moz.build b/config/external/nss/crmf/moz.build
new file mode 100644
index 000000000..d2004a509
--- /dev/null
+++ b/config/external/nss/crmf/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/.
+
+Library('crmf')
+
+if CONFIG['MOZ_SYSTEM_NSS']:
+ OS_LIBS += [l for l in CONFIG['NSS_LIBS'] if l.startswith('-L')]
+ OS_LIBS += ['-lcrmf']
+else:
+ USE_LIBS += [
+ # The dependency on nss is not real, but is required to force the
+ # parent directory being built before this one. This has no
+ # practical effect on linkage, since the only thing linking crmf
+ # will need nss anyways.
+ 'nss',
+ 'static:/security/nss/lib/crmf/crmf',
+ ]
diff --git a/config/external/nss/moz.build b/config/external/nss/moz.build
new file mode 100644
index 000000000..1c61b28fd
--- /dev/null
+++ b/config/external/nss/moz.build
@@ -0,0 +1,42 @@
+# -*- 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 += ['crmf']
+
+if CONFIG['MOZ_SYSTEM_NSS']:
+ Library('nss')
+ OS_LIBS += CONFIG['NSS_LIBS']
+elif CONFIG['MOZ_FOLD_LIBS']:
+ GeckoSharedLibrary('nss', linkage=None)
+ # TODO: The library name can be changed when bug 845217 is fixed.
+ SHARED_LIBRARY_NAME = 'nss3'
+
+ SDK_LIBRARY = True
+
+ USE_LIBS += [
+ 'nspr4',
+ 'plc4',
+ 'plds4',
+ ]
+
+ OS_LIBS += CONFIG['REALTIME_LIBS']
+
+ SYMBOLS_FILE = 'nss.symbols'
+else:
+ Library('nss')
+ USE_LIBS += [
+ '/security/nss/lib/nss/nss3',
+ '/security/nss/lib/smime/smime3',
+ '/security/nss/lib/ssl/ssl3',
+ '/security/nss/lib/util/nssutil3',
+ 'sqlite',
+ ]
+
+# XXX: We should fix these warnings.
+ALLOW_COMPILER_WARNINGS = True
+
+if CONFIG['NSS_EXTRA_SYMBOLS_FILE']:
+ DEFINES['NSS_EXTRA_SYMBOLS_FILE'] = CONFIG['NSS_EXTRA_SYMBOLS_FILE']
diff --git a/config/external/nss/nss.mk b/config/external/nss/nss.mk
new file mode 100644
index 000000000..38d234a0b
--- /dev/null
+++ b/config/external/nss/nss.mk
@@ -0,0 +1,27 @@
+# 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 $(DEPTH)/config/autoconf.mk
+
+include $(topsrcdir)/config/config.mk
+
+dirs :=
+
+define add_dirs
+SHARED_LIBRARY_DIRS :=
+include $(topsrcdir)/security/$(1)/config.mk
+dirs += $$(addprefix $(1)/,$$(SHARED_LIBRARY_DIRS)) $(1)
+endef
+$(foreach dir,util nss ssl smime,$(eval $(call add_dirs,nss/lib/$(dir))))
+
+libs :=
+define add_lib
+LIBRARY_NAME :=
+include $(topsrcdir)/security/$(1)/manifest.mn
+libs += $$(addprefix $(1)/,$(LIB_PREFIX)$$(LIBRARY_NAME).$(LIB_SUFFIX))
+endef
+$(foreach dir,$(dirs),$(eval $(call add_lib,$(dir))))
+
+echo-variable-%:
+ @echo $($*)
diff --git a/config/external/nss/nss.symbols b/config/external/nss/nss.symbols
new file mode 100644
index 000000000..592c50b1f
--- /dev/null
+++ b/config/external/nss/nss.symbols
@@ -0,0 +1,724 @@
+# 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 XP_WIN
+# NSPR, unlike NSS, exports symbols with symbol visibility (Unix) or __declspec
+# (Windows). When using a linker script, however, we need to explicitly
+# specify that NSPR's symbols should be globally visible. Otherwise, NSPR's
+# exported symbols would be hidden.
+# .def files on Windows don't allow wildcards, of course, which is why this is
+# excluded on Windows, but it doesn't matter because the symbols are already
+# exported in NSPR (Windows peculiarity).
+PR_*
+PL_*
+#endif
+#include ../../../db/sqlite3/src/sqlite.symbols
+ATOB_AsciiToData
+ATOB_AsciiToData_Util
+ATOB_ConvertAsciiToItem
+ATOB_ConvertAsciiToItem_Util
+BTOA_ConvertItemToAscii_Util
+BTOA_DataToAscii
+BTOA_DataToAscii_Util
+CERT_AddCertToListHead
+CERT_AddCertToListTail
+CERT_AddExtension
+CERT_AddExtensionByOID
+__CERT_AddTempCertToPerm
+CERT_AsciiToName
+CERT_CacheOCSPResponseFromSideChannel
+CERT_CertChainFromCert
+CERT_CertificateRequestTemplate @DATA@
+CERT_CertificateTemplate @DATA@
+CERT_CertListFromCert
+CERT_ChangeCertTrust
+CERT_CheckCertUsage
+CERT_CheckCertValidTimes
+CERT_CheckNameSpace
+CERT_ClearOCSPCache
+CERT_CompareCerts
+CERT_CompareName
+CERT_ConvertAndDecodeCertificate
+CERT_CopyName
+CERT_CopyRDN
+CERT_CreateCertificate
+CERT_CreateCertificateRequest
+CERT_CreateSubjectCertList
+CERT_CreateValidity
+CERT_CrlTemplate @DATA@
+CERT_DecodeAltNameExtension
+CERT_DecodeAuthInfoAccessExtension
+CERT_DecodeAuthKeyID
+CERT_DecodeAVAValue
+CERT_DecodeBasicConstraintValue
+CERT_DecodeCertFromPackage
+CERT_DecodeCertificatePoliciesExtension
+CERT_DecodeCertPackage
+CERT_DecodeCRLDistributionPoints
+CERT_DecodeNameConstraintsExtension
+CERT_DecodeOidSequence
+CERT_DecodePrivKeyUsagePeriodExtension
+CERT_DecodeTrustString
+CERT_DecodeUserNotice
+CERT_DerNameToAscii
+CERT_DestroyCertArray
+CERT_DestroyCertificate
+CERT_DestroyCertificateList
+CERT_DestroyCertificatePoliciesExtension
+CERT_DestroyCertificateRequest
+CERT_DestroyCertList
+CERT_DestroyName
+CERT_DestroyOidSequence
+CERT_DestroyUserNotice
+CERT_DestroyValidity
+CERT_DisableOCSPChecking
+CERT_DisableOCSPDefaultResponder
+CERT_DupCertificate
+CERT_EnableOCSPChecking
+CERT_EncodeAltNameExtension
+CERT_EncodeAndAddBitStrExtension
+CERT_EncodeAuthKeyID
+CERT_EncodeBasicConstraintValue
+CERT_EncodeCertPoliciesExtension
+CERT_EncodeCRLDistributionPoints
+CERT_EncodeInfoAccessExtension
+CERT_EncodeInhibitAnyExtension
+CERT_EncodeNameConstraintsExtension
+CERT_EncodeNoticeReference
+CERT_EncodePolicyConstraintsExtension
+CERT_EncodePolicyMappingExtension
+CERT_EncodeSubjectKeyID
+CERT_EncodeUserNotice
+CERT_ExtractPublicKey
+CERT_FilterCertListByCANames
+CERT_FilterCertListByUsage
+CERT_FilterCertListForUserCerts
+CERT_FindCertByDERCert
+CERT_FindCertByIssuerAndSN
+CERT_FindCertByName
+CERT_FindCertByNickname
+CERT_FindCertByNicknameOrEmailAddr
+CERT_FindCertExtension
+CERT_FindCertIssuer
+CERT_FindKeyUsageExtension
+CERT_FindUserCertByUsage
+CERT_FindUserCertsByUsage
+CERT_FinishCertificateRequestAttributes
+CERT_FinishExtensions
+CERT_ForcePostMethodForOCSP
+CERT_FreeNicknames
+CERT_GenTime2FormattedAscii_Util
+CERT_GetCertChainFromCert
+CERT_GetCertEmailAddress
+CERT_GetCertificateRequestExtensions
+CERT_GetCertTimes
+CERT_GetCertTrust
+CERT_GetCommonName
+CERT_GetConstrainedCertificateNames
+CERT_GetCountryName
+CERT_GetDefaultCertDB
+CERT_GetFirstEmailAddress
+CERT_GetGeneralNameTypeFromString
+CERT_GetImposedNameConstraints
+CERT_GetLocalityName
+CERT_GetNextEmailAddress
+CERT_GetNextGeneralName
+CERT_GetNextNameConstraint
+CERT_GetOCSPAuthorityInfoAccessLocation
+CERT_GetOidString
+CERT_GetOrgName
+CERT_GetOrgUnitName
+CERT_GetStateName
+CERT_Hexify
+CERT_ImportCerts
+CERT_IsCACert
+CERT_IsUserCert
+CERT_MakeCANickname
+CERT_MergeExtensions
+CERT_NameTemplate @DATA@
+CERT_NameToAscii
+CERT_NewCertList
+CERT_NewTempCertificate
+CERT_NicknameStringsFromCertList
+CERT_OCSPCacheSettings
+CERT_RemoveCertListNode
+CERT_RFC1485_EscapeAndQuote
+CERT_SaveSMimeProfile
+CERT_SequenceOfCertExtensionTemplate @DATA@
+CERT_SetOCSPFailureMode
+CERT_SetOCSPTimeout
+CERT_SignedCrlTemplate @DATA@
+CERT_SignedDataTemplate @DATA@
+CERT_StartCertExtensions
+CERT_StartCertificateRequestAttributes
+CERT_SubjectPublicKeyInfoTemplate @DATA@
+CERT_TimeChoiceTemplate @DATA@
+CERT_VerifyCertificate
+CERT_VerifySignedDataWithPublicKeyInfo
+DER_AsciiToTime_Util
+DER_DecodeTimeChoice_Util
+DER_Encode
+DER_EncodeTimeChoice_Util
+DER_Encode_Util
+DER_GeneralizedTimeToTime
+DER_GeneralizedTimeToTime_Util
+DER_GetInteger
+DER_GetInteger_Util
+DER_Lengths
+DER_SetUInteger
+DER_UTCTimeToTime_Util
+DSAU_DecodeDerSigToLen
+DSAU_EncodeDerSigWithLen
+DTLS_GetHandshakeTimeout
+DTLS_ImportFD
+HASH_Begin
+HASH_Create
+HASH_Destroy
+HASH_End
+HASH_GetHashObject
+HASH_GetType
+HASH_HashBuf
+HASH_ResultLenByOidTag
+HASH_Update
+NSSBase64_DecodeBuffer
+NSSBase64_EncodeItem
+NSSBase64_EncodeItem_Util
+NSS_CMSContentInfo_GetContent
+NSS_CMSContentInfo_GetContentTypeTag
+NSS_CMSContentInfo_SetContent_Data
+NSS_CMSContentInfo_SetContent_EnvelopedData
+NSS_CMSContentInfo_SetContent_SignedData
+NSS_CMSDecoder_Cancel
+NSS_CMSDecoder_Finish
+NSS_CMSDecoder_Start
+NSS_CMSDecoder_Update
+NSS_CMSEncoder_Cancel
+NSS_CMSEncoder_Finish
+NSS_CMSEncoder_Start
+NSS_CMSEncoder_Update
+NSS_CMSEnvelopedData_AddRecipient
+NSS_CMSEnvelopedData_Create
+NSS_CMSEnvelopedData_GetContentInfo
+NSS_CMSMessage_ContentLevel
+NSS_CMSMessage_ContentLevelCount
+NSS_CMSMessage_Create
+NSS_CMSMessage_CreateFromDER
+NSS_CMSMessage_Destroy
+NSS_CMSMessage_GetContent
+NSS_CMSMessage_GetContentInfo
+NSS_CMSMessage_IsEncrypted
+NSS_CMSMessage_IsSigned
+NSS_CMSRecipientInfo_Create
+NSS_CMSSignedData_AddCertificate
+NSS_CMSSignedData_AddCertList
+NSS_CMSSignedData_AddSignerInfo
+NSS_CMSSignedData_Create
+NSS_CMSSignedData_CreateCertsOnly
+NSS_CMSSignedData_Destroy
+NSS_CMSSignedData_GetContentInfo
+NSS_CMSSignedData_GetSignerInfo
+NSS_CMSSignedData_ImportCerts
+NSS_CMSSignedData_SetDigestValue
+NSS_CMSSignedData_SignerInfoCount
+NSS_CMSSignedData_VerifySignerInfo
+NSS_CMSSignerInfo_AddMSSMIMEEncKeyPrefs
+NSS_CMSSignerInfo_AddSigningTime
+NSS_CMSSignerInfo_AddSMIMECaps
+NSS_CMSSignerInfo_AddSMIMEEncKeyPrefs
+NSS_CMSSignerInfo_Create
+NSS_CMSSignerInfo_GetSignerCommonName
+NSS_CMSSignerInfo_GetSignerEmailAddress
+NSS_CMSSignerInfo_GetSigningCertificate
+NSS_CMSSignerInfo_IncludeCerts
+NSS_CMSSignerInfo_Verify
+NSS_FindCertKEAType
+NSS_GetAlgorithmPolicy
+NSS_Get_CERT_CertificateRequestTemplate
+NSS_Get_CERT_CertificateTemplate
+NSS_Get_CERT_CrlTemplate
+NSS_Get_CERT_NameTemplate
+NSS_Get_CERT_SequenceOfCertExtensionTemplate
+NSS_Get_CERT_SignedCrlTemplate
+NSS_Get_CERT_SignedDataTemplate
+NSS_Get_CERT_SubjectPublicKeyInfoTemplate
+NSS_Get_CERT_TimeChoiceTemplate
+NSS_Get_SEC_AnyTemplate_Util
+NSS_Get_SEC_BitStringTemplate
+NSS_Get_SEC_BitStringTemplate_Util
+NSS_Get_SEC_BMPStringTemplate
+NSS_Get_SEC_BooleanTemplate_Util
+NSS_Get_SEC_GeneralizedTimeTemplate_Util
+NSS_Get_SEC_IA5StringTemplate
+NSS_Get_SEC_IA5StringTemplate_Util
+NSS_Get_SEC_IntegerTemplate
+NSS_Get_SEC_IntegerTemplate_Util
+NSS_Get_SECKEY_RSAPSSParamsTemplate
+NSS_Get_SEC_NullTemplate_Util
+NSS_Get_SEC_ObjectIDTemplate_Util
+NSS_Get_SEC_OctetStringTemplate
+NSS_Get_SEC_OctetStringTemplate_Util
+NSS_Get_SECOID_AlgorithmIDTemplate
+NSS_Get_SECOID_AlgorithmIDTemplate_Util
+NSS_Get_SEC_SignedCertificateTemplate
+NSS_Get_SEC_UTF8StringTemplate
+NSS_Get_SEC_UTF8StringTemplate_Util
+NSS_GetVersion
+NSS_Init
+NSS_Initialize
+NSS_InitWithMerge
+NSS_IsInitialized
+NSS_OptionSet
+NSS_NoDB_Init
+NSS_SecureMemcmp
+NSS_SetAlgorithmPolicy
+NSS_SetDomesticPolicy
+NSS_Shutdown
+NSSSMIME_GetVersion
+NSS_SMIMESignerInfo_SaveSMIMEProfile
+NSS_SMIMEUtil_FindBulkAlgForRecipients
+NSSSSL_GetVersion
+NSSUTIL_ArgDecodeNumber
+NSSUTIL_ArgFetchValue
+NSSUTIL_ArgGetLabel
+NSSUTIL_ArgGetParamValue
+NSSUTIL_ArgHasFlag
+NSSUTIL_ArgIsBlank
+NSSUTIL_ArgParseCipherFlags
+NSSUTIL_ArgParseModuleSpec
+NSSUTIL_ArgParseSlotFlags
+NSSUTIL_ArgParseSlotInfo
+NSSUTIL_ArgReadLong
+NSSUTIL_ArgSkipParameter
+NSSUTIL_ArgStrip
+NSSUTIL_DoModuleDBFunction
+_NSSUTIL_EvaluateConfigDir
+_NSSUTIL_GetSecmodName
+NSSUTIL_GetVersion
+NSSUTIL_MkModuleSpec
+NSSUTIL_MkNSSString
+NSSUTIL_MkSlotString
+NSSUTIL_Quote
+PK11_AlgtagToMechanism
+PK11_Authenticate
+PK11_ChangePW
+PK11_CheckUserPassword
+PK11_CipherOp
+PK11_ConfigurePKCS11
+PK11_CreateContextBySymKey
+PK11_CreateDigestContext
+PK11_CreateGenericObject
+PK11_CreateMergeLog
+PK11_CreatePBEV2AlgorithmID
+PK11_Decrypt
+PK11_DeleteTokenCertAndKey
+PK11_DeleteTokenPrivateKey
+PK11_DeleteTokenPublicKey
+PK11_DEREncodePublicKey
+PK11_Derive
+PK11_DeriveWithTemplate
+PK11_DestroyContext
+PK11_DestroyGenericObject
+PK11_DestroyMergeLog
+PK11_DestroyObject
+PK11_DestroyTokenObject
+PK11_DigestBegin
+PK11_DigestFinal
+PK11_DigestOp
+PK11_DoesMechanism
+PK11_Encrypt
+PK11_ExportDERPrivateKeyInfo
+PK11_ExportEncryptedPrivKeyInfo
+PK11_ExtractKeyValue
+PK11_FindCertFromNickname
+PK11_FindCertInSlot
+PK11_FindCertsFromEmailAddress
+PK11_FindCertsFromNickname
+PK11_FindKeyByAnyCert
+PK11_FindKeyByDERCert
+PK11_FindKeyByKeyID
+PK11_FindSlotByName
+PK11_FindSlotsByNames
+PK11_FreeSlot
+PK11_FreeSlotList
+PK11_FreeSlotListElement
+PK11_FreeSymKey
+PK11_GenerateKeyPair
+PK11_GenerateKeyPairWithFlags
+PK11_GenerateKeyPairWithOpFlags
+PK11_GenerateRandom
+PK11_GenerateRandomOnSlot
+PK11_GetAllSlotsForCert
+PK11_GetAllTokens
+PK11_GetBestSlot
+PK11_GetBestSlotMultiple
+PK11_GetBlockSize
+PK11_GetCertFromPrivateKey
+PK11_GetDefaultArray
+PK11_GetDefaultFlags
+PK11_GetDisabledReason
+PK11_GetFirstSafe
+PK11_GetInternalKeySlot
+PK11_GetInternalSlot
+PK11_GetIVLength
+PK11_GetKeyData
+PK11_GetKeyGen
+PK11_GetLowLevelKeyIDForPrivateKey
+PK11_GetMechanism
+PK11_GetMinimumPwdLength
+PK11_GetModInfo
+PK11_GetNextSafe
+PK11_GetNextSymKey
+PK11_GetPadMechanism
+PK11_GetPrivateKeyNickname
+PK11_GetPrivateModulusLen
+PK11_GetSlotID
+PK11_GetSlotInfo
+PK11_GetSlotName
+PK11_GetSlotPWValues
+PK11_GetSlotSeries
+PK11_GetSymKeyNickname
+PK11_GetTokenInfo
+PK11_GetTokenName
+PK11_HashBuf
+PK11_HasRootCerts
+PK11_ImportCert
+PK11_ImportCertForKey
+PK11_ImportCRL
+PK11_ImportDERPrivateKeyInfoAndReturnKey
+PK11_ImportPublicKey
+PK11_ImportSymKey
+PK11_InitPin
+PK11_IsDisabled
+PK11_IsFIPS
+PK11_IsFriendly
+PK11_IsHW
+PK11_IsInternal
+PK11_IsLoggedIn
+PK11_IsPresent
+PK11_IsReadOnly
+PK11_IsRemovable
+PK11_KeyForCertExists
+PK11_KeyGen
+PK11_KeyGenWithTemplate
+PK11_ListCerts
+PK11_ListCertsInSlot
+PK11_ListFixedKeysInSlot
+PK11_ListPrivateKeysInSlot
+PK11_ListPrivKeysInSlot
+PK11_LoadPrivKey
+PK11_Logout
+PK11_LogoutAll
+PK11_MakeIDFromPubKey
+PK11_MapSignKeyType
+PK11_MechanismToAlgtag
+PK11_MergeTokens
+PK11_NeedLogin
+PK11_NeedUserInit
+PK11_ParamFromIV
+PK11_PBEKeyGen
+PK11_PrivDecrypt
+PK11_PrivDecryptPKCS1
+PK11_ProtectedAuthenticationPath
+PK11_PubDeriveWithKDF
+PK11_PubEncrypt
+PK11_PubEncryptPKCS1
+PK11_PubUnwrapSymKey
+PK11_PubWrapSymKey
+PK11_RandomUpdate
+PK11_ReadRawAttribute
+PK11_ReferenceSlot
+PK11_ResetToken
+PK11SDR_Decrypt
+PK11SDR_Encrypt
+PK11_SetPasswordFunc
+PK11_SetSlotPWValues
+PK11_SetSymKeyNickname
+PK11_Sign
+PK11_SignatureLen
+PK11_SignWithMechanism
+PK11_TokenKeyGenWithFlags
+PK11_UnwrapPrivKey
+PK11_UnwrapSymKey
+PK11_UpdateSlotAttribute
+PK11_UserDisableSlot
+PK11_UserEnableSlot
+PK11_VerifyWithMechanism
+PK11_WrapPrivKey
+PK11_WrapSymKey
+PORT_Alloc
+PORT_Alloc_Util
+PORT_ArenaAlloc
+PORT_ArenaAlloc_Util
+PORT_ArenaGrow_Util
+PORT_ArenaMark_Util
+PORT_ArenaRelease_Util
+PORT_ArenaStrdup
+PORT_ArenaStrdup_Util
+PORT_ArenaUnmark_Util
+PORT_ArenaZAlloc
+PORT_ArenaZAlloc_Util
+PORT_DestroyCheapArena
+PORT_Free
+PORT_FreeArena
+PORT_FreeArena_Util
+PORT_Free_Util
+PORT_GetError
+PORT_GetError_Util
+PORT_InitCheapArena
+PORT_NewArena
+PORT_NewArena_Util
+PORT_Realloc_Util
+PORT_RegExpSearch
+PORT_SetError
+PORT_SetError_Util
+PORT_SetUCS2_ASCIIConversionFunction
+PORT_SetUCS2_ASCIIConversionFunction_Util
+PORT_Strdup
+PORT_Strdup_Util
+PORT_UCS2_ASCIIConversion_Util
+PORT_UCS2_UTF8Conversion
+PORT_UCS2_UTF8Conversion_Util
+PORT_ZAlloc
+PORT_ZAlloc_Util
+PORT_ZFree_Util
+SEC_AnyTemplate_Util @DATA@
+SEC_ASN1Decode
+SEC_ASN1DecodeInteger
+SEC_ASN1DecodeItem
+SEC_ASN1DecodeItem_Util
+SEC_ASN1Decode_Util
+SEC_ASN1EncodeInteger_Util
+SEC_ASN1EncodeItem
+SEC_ASN1EncodeItem_Util
+SEC_ASN1EncodeUnsignedInteger_Util
+SEC_ASN1Encode_Util
+SEC_BitStringTemplate @DATA@
+SEC_BitStringTemplate_Util @DATA@
+SEC_BMPStringTemplate @DATA@
+SEC_BooleanTemplate_Util @DATA@
+SEC_CertNicknameConflict
+SEC_DeletePermCertificate
+SEC_DerSignData
+SEC_DestroyCrl
+SEC_GeneralizedTimeTemplate_Util @DATA@
+SEC_GetSignatureAlgorithmOidTag
+SEC_IA5StringTemplate @DATA@
+SEC_IA5StringTemplate_Util @DATA@
+SEC_IntegerTemplate @DATA@
+SEC_IntegerTemplate_Util @DATA@
+SECITEM_AllocArray
+SECITEM_AllocItem
+SECITEM_AllocItem_Util
+SECITEM_ArenaDupItem_Util
+SECITEM_CompareItem
+SECITEM_CompareItem_Util
+SECITEM_CopyItem
+SECITEM_CopyItem_Util
+SECITEM_DupArray
+SECITEM_DupItem
+SECITEM_DupItem_Util
+SECITEM_FreeItem
+SECITEM_FreeItem_Util
+SECITEM_HashCompare
+SECITEM_ItemsAreEqual
+SECITEM_ItemsAreEqual_Util
+SECITEM_ReallocItemV2
+SECITEM_ZfreeItem
+SECITEM_ZfreeItem_Util
+SECKEY_ConvertToPublicKey
+SECKEY_CopyPrivateKey
+SECKEY_CopyPublicKey
+SECKEY_CopySubjectPublicKeyInfo
+SECKEY_CreateSubjectPublicKeyInfo
+SECKEY_DecodeDERSubjectPublicKeyInfo
+SECKEY_DestroyEncryptedPrivateKeyInfo
+SECKEY_DestroyPrivateKey
+SECKEY_DestroyPrivateKeyList
+SECKEY_DestroyPublicKey
+SECKEY_DestroySubjectPublicKeyInfo
+SECKEY_ECParamsToBasePointOrderLen
+SECKEY_ECParamsToKeySize
+SECKEY_EncodeDERSubjectPublicKeyInfo
+SECKEY_ExtractPublicKey
+SECKEY_GetPublicKeyType
+SECKEY_ImportDERPublicKey
+SECKEY_PublicKeyStrength
+SECKEY_RSAPSSParamsTemplate @DATA@
+SECKEY_SignatureLen
+SECMIME_DecryptionAllowed
+SECMOD_AddNewModule
+SECMOD_AddNewModuleEx
+SECMOD_CancelWait
+SECMOD_CanDeleteInternalModule
+SECMOD_CloseUserDB
+SECMOD_CreateModule
+SECMOD_DeleteInternalModule
+SECMOD_DeleteModule
+SECMOD_DestroyModule
+SECMOD_FindModule
+SECMOD_GetDeadModuleList
+SECMOD_GetDefaultModuleList
+SECMOD_GetDefaultModuleListLock
+SECMOD_GetInternalModule
+SECMOD_GetModuleSpecList
+SECMOD_GetReadLock
+SECMOD_HasRemovableSlots
+SECMOD_InternaltoPubMechFlags
+SECMOD_LoadModule
+SECMOD_LoadUserModule
+SECMOD_OpenUserDB
+SECMOD_PubCipherFlagstoInternal
+SECMOD_PubMechFlagstoInternal
+SECMOD_ReferenceModule
+SECMOD_ReleaseReadLock
+SECMOD_UnloadUserModule
+SECMOD_UpdateModule
+SECMOD_WaitForAnyTokenEvent
+SEC_NullTemplate_Util @DATA@
+SEC_ObjectIDTemplate_Util @DATA@
+SEC_OctetStringTemplate @DATA@
+SEC_OctetStringTemplate_Util @DATA@
+SECOID_AddEntry
+SECOID_AddEntry_Util
+SECOID_AlgorithmIDTemplate @DATA@
+SECOID_AlgorithmIDTemplate_Util @DATA@
+SECOID_CopyAlgorithmID_Util
+SECOID_DestroyAlgorithmID
+SECOID_DestroyAlgorithmID_Util
+SECOID_FindOID
+SECOID_FindOIDByMechanism
+SECOID_FindOIDByTag
+SECOID_FindOIDByTag_Util
+SECOID_FindOIDTag
+SECOID_FindOIDTagDescription_Util
+SECOID_FindOIDTag_Util
+SECOID_FindOID_Util
+SECOID_GetAlgorithmTag
+SECOID_GetAlgorithmTag_Util
+SECOID_Init
+SECOID_SetAlgorithmID
+SECOID_SetAlgorithmID_Util
+SECOID_Shutdown
+SEC_PKCS12AddCertAndKey
+SEC_PKCS12AddPasswordIntegrity
+SEC_PKCS12CreateExportContext
+SEC_PKCS12CreatePasswordPrivSafe
+SEC_PKCS12CreateUnencryptedSafe
+SEC_PKCS12DecoderFinish
+SEC_PKCS12DecoderImportBags
+SEC_PKCS12DecoderIterateInit
+SEC_PKCS12DecoderIterateNext
+SEC_PKCS12DecoderRenameCertNicknames
+SEC_PKCS12DecoderStart
+SEC_PKCS12DecoderUpdate
+SEC_PKCS12DecoderValidateBags
+SEC_PKCS12DecoderVerify
+SEC_PKCS12DestroyExportContext
+SEC_PKCS12EnableCipher
+SEC_PKCS12Encode
+SEC_PKCS12IsEncryptionAllowed
+SEC_PKCS12SetPreferredCipher
+SEC_PKCS5GetPBEAlgorithm
+SEC_PKCS5IsAlgorithmPBEAlgTag
+SEC_PKCS7AddSigningTime
+SEC_PKCS7ContentIsEncrypted
+SEC_PKCS7ContentIsSigned
+SEC_PKCS7CopyContentInfo
+SEC_PKCS7CreateSignedData
+SEC_PKCS7DecodeItem
+SEC_PKCS7DecoderFinish
+SEC_PKCS7DecoderStart
+SEC_PKCS7DecoderUpdate
+SEC_PKCS7DestroyContentInfo
+SEC_PKCS7Encode
+SEC_PKCS7IncludeCertChain
+SEC_PKCS7VerifyDetachedSignature
+SEC_QuickDERDecodeItem
+SEC_QuickDERDecodeItem_Util
+SEC_RegisterDefaultHttpClient
+SEC_SignData
+SEC_SignedCertificateTemplate @DATA@
+SEC_StringToOID
+SEC_UTF8StringTemplate @DATA@
+SEC_UTF8StringTemplate_Util @DATA@
+SGN_Begin
+SGN_CreateDigestInfo
+SGN_CreateDigestInfo_Util
+SGN_DecodeDigestInfo
+SGN_DestroyContext
+SGN_DestroyDigestInfo
+SGN_DestroyDigestInfo_Util
+SGN_End
+SGN_NewContext
+SGN_Update
+SSL_AuthCertificateComplete
+SSL_AuthCertificateHook
+SSL_CipherPrefGet
+SSL_CipherPrefSet
+SSL_CipherPrefSetDefault
+SSL_ClearSessionCache
+SSL_ConfigSecureServer
+SSL_ConfigSecureServerWithCertChain
+SSL_ConfigServerSessionIDCache
+SSL_ExportKeyingMaterial
+SSL_ForceHandshake
+SSL_GetChannelInfo
+SSL_GetCipherSuiteInfo
+SSL_GetClientAuthDataHook
+SSL_GetImplementedCiphers
+SSL_GetNextProto
+SSL_GetNumImplementedCiphers
+SSL_GetSRTPCipher
+SSL_GetStatistics
+SSL_HandshakeCallback
+SSL_HandshakeNegotiatedExtension
+SSL_ImplementedCiphers @DATA@
+SSL_ImportFD
+SSL_NamedGroupConfig
+SSL_NumImplementedCiphers @DATA@
+SSL_OptionSet
+SSL_OptionSetDefault
+SSL_PeerCertificate
+SSL_PeerCertificateChain
+SSL_PeerSignedCertTimestamps
+SSL_PeerStapledOCSPResponses
+SSL_ResetHandshake
+SSL_SendAdditionalKeyShares
+SSL_SetCanFalseStartCallback
+SSL_SetDowngradeCheckVersion
+SSL_SetNextProtoNego
+SSL_SetPKCS11PinArg
+SSL_SetSockPeerID
+SSL_SetSRTPCiphers
+SSL_SetStapledOCSPResponses
+SSL_SetTrustAnchors
+SSL_SetURL
+SSL_ShutdownServerSessionIDCache
+SSL_SignatureSchemePrefSet
+SSL_SNISocketConfigHook
+SSL_VersionRangeGet
+SSL_VersionRangeGetDefault
+SSL_VersionRangeGetSupported
+SSL_VersionRangeSet
+SSL_VersionRangeSetDefault
+UTIL_SetForkState
+VFY_Begin
+VFY_CreateContext
+VFY_DestroyContext
+VFY_End
+VFY_EndWithSignature
+VFY_Update
+VFY_VerifyData
+VFY_VerifyDataWithAlgorithmID
+VFY_VerifyDigestDirect
+_SGN_VerifyPKCS1DigestInfo
+__PK11_SetCertificateNickname
+# These symbols are not used by Firefox itself, but are used by Java's security
+# libraries, which in turn are used by Java applets/plugins/etc. Provide them
+# to make Java code happy.
+NSS_VersionCheck
+NSS_Initialize
+#ifdef NSS_EXTRA_SYMBOLS_FILE
+#include @NSS_EXTRA_SYMBOLS_FILE@
+#endif
diff --git a/config/external/sqlite/moz.build b/config/external/sqlite/moz.build
new file mode 100644
index 000000000..76908d902
--- /dev/null
+++ b/config/external/sqlite/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/.
+
+if CONFIG['MOZ_SYSTEM_SQLITE']:
+ Library('sqlite')
+ OS_LIBS += CONFIG['SQLITE_LIBS']
+else:
+ DIRS += ['../../../db/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 = '/db/sqlite3/src/sqlite.symbols'
diff --git a/config/external/zlib/moz.build b/config/external/zlib/moz.build
new file mode 100644
index 000000000..c6b7cfe7d
--- /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 000000000..9d7b322fa
--- /dev/null
+++ b/config/faster/rules.mk
@@ -0,0 +1,110 @@
+# 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
+
+# Extra define to trigger some workarounds. We should strive to limit the
+# use of those. As of writing the only ones are in
+# toolkit/content/buildconfig.html and browser/locales/jar.mn.
+ACDEFINES += -DBUILD_FASTER
+
+# 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 /,_,$*)
+ @# BOOKMARKS_INCLUDE_DIR is for bookmarks.html only.
+ $(PYTHON) -m mozbuild.action.process_install_manifest \
+ --track install_$(subst /,_,$*).track \
+ $(TOPOBJDIR)/$* \
+ -DAB_CD=en-US \
+ -DBOOKMARKS_INCLUDE_DIR=$(TOPSRCDIR)/browser/locales/en-US/profile \
+ $(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.
+
+# The xpidl target in config/makefiles/xpidl requires the install manifest for
+# dist/idl to have been processed. When using the hybrid
+# FasterMake/RecursiveMake backend, this dependency is handled in the top-level
+# Makefile.
+ifndef FASTER_RECURSIVE_MAKE
+$(TOPOBJDIR)/config/makefiles/xpidl/xpidl: $(TOPOBJDIR)/install-dist_idl
+endif
+# It also requires all the install manifests for dist/bin to have been processed
+# because it adds interfaces.manifest references with buildlist.py.
+$(TOPOBJDIR)/config/makefiles/xpidl/xpidl: $(addprefix install-,$(filter dist/bin%,$(INSTALL_MANIFESTS)))
diff --git a/config/find_OOM_errors.py b/config/find_OOM_errors.py
new file mode 100644
index 000000000..16065119b
--- /dev/null
+++ b/config/find_OOM_errors.py
@@ -0,0 +1,352 @@
+#!/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/.
+from __future__ import print_function
+
+usage = """%prog: A test for OOM conditions in the shell.
+
+%prog finds segfaults and other errors caused by incorrect handling of
+allocation during OOM (out-of-memory) conditions.
+"""
+
+help = """Check for regressions only. This runs a set of files with a known
+number of OOM errors (specified by REGRESSION_COUNT), and exits with a non-zero
+result if more or less errors are found. See js/src/Makefile.in for invocation.
+"""
+
+
+import hashlib
+import re
+import shlex
+import subprocess
+import sys
+import threading
+import time
+
+from optparse import OptionParser
+
+#####################################################################
+# Utility functions
+#####################################################################
+def run(args, stdin=None):
+ class ThreadWorker(threading.Thread):
+ def __init__(self, pipe):
+ super(ThreadWorker, self).__init__()
+ self.all = ""
+ self.pipe = pipe
+ self.setDaemon(True)
+
+ def run(self):
+ while True:
+ line = self.pipe.readline()
+ if line == '': break
+ else:
+ self.all += line
+
+ try:
+ if type(args) == str:
+ args = shlex.split(args)
+
+ args = [str(a) for a in args] # convert to strs
+
+ stdin_pipe = subprocess.PIPE if stdin else None
+ proc = subprocess.Popen(args, stdin=stdin_pipe, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ if stdin_pipe:
+ proc.stdin.write(stdin)
+ proc.stdin.close()
+
+ stdout_worker = ThreadWorker(proc.stdout)
+ stderr_worker = ThreadWorker(proc.stderr)
+ stdout_worker.start()
+ stderr_worker.start()
+
+ proc.wait()
+ stdout_worker.join()
+ stderr_worker.join()
+
+ except KeyboardInterrupt as e:
+ sys.exit(-1)
+
+ stdout, stderr = stdout_worker.all, stderr_worker.all
+ result = (stdout, stderr, proc.returncode)
+ return result
+
+def get_js_files():
+ (out, err, exit) = run('find ../jit-test/tests -name "*.js"')
+ if (err, exit) != ("", 0):
+ sys.exit("Wrong directory, run from an objdir")
+ return out.split()
+
+
+
+#####################################################################
+# Blacklisting
+#####################################################################
+def in_blacklist(sig):
+ return sig in blacklist
+
+def add_to_blacklist(sig):
+ blacklist[sig] = blacklist.get(sig, 0)
+ blacklist[sig] += 1
+
+# How often is a particular lines important for this.
+def count_lines():
+ """Keep track of the amount of times individual lines occur, in order to
+ prioritize the errors which occur most frequently."""
+ counts = {}
+ for string,count in blacklist.items():
+ for line in string.split("\n"):
+ counts[line] = counts.get(line, 0) + count
+
+ lines = []
+ for k,v in counts.items():
+ lines.append("{0:6}: {1}".format(v, k))
+
+ lines.sort()
+
+ countlog = file("../OOM_count_log", "w")
+ countlog.write("\n".join(lines))
+ countlog.flush()
+ countlog.close()
+
+
+#####################################################################
+# Output cleaning
+#####################################################################
+def clean_voutput(err):
+ # Skip what we can't reproduce
+ err = re.sub(r"^--\d+-- run: /usr/bin/dsymutil \"shell/js\"$", "", err, flags=re.MULTILINE)
+ err = re.sub(r"^==\d+==", "", err, flags=re.MULTILINE)
+ err = re.sub(r"^\*\*\d+\*\*", "", err, flags=re.MULTILINE)
+ err = re.sub(r"^\s+by 0x[0-9A-Fa-f]+: ", "by: ", err, flags=re.MULTILINE)
+ err = re.sub(r"^\s+at 0x[0-9A-Fa-f]+: ", "at: ", err, flags=re.MULTILINE)
+ err = re.sub(r"(^\s+Address 0x)[0-9A-Fa-f]+( is not stack'd)", r"\1\2", err, flags=re.MULTILINE)
+ err = re.sub(r"(^\s+Invalid write of size )\d+", r"\1x", err, flags=re.MULTILINE)
+ err = re.sub(r"(^\s+Invalid read of size )\d+", r"\1x", err, flags=re.MULTILINE)
+ err = re.sub(r"(^\s+Address 0x)[0-9A-Fa-f]+( is )\d+( bytes inside a block of size )[0-9,]+( free'd)", r"\1\2\3\4", err, flags=re.MULTILINE)
+
+ # Skip the repeating bit due to the segfault
+ lines = []
+ for l in err.split('\n'):
+ if l == " Process terminating with default action of signal 11 (SIGSEGV)":
+ break
+ lines.append(l)
+ err = '\n'.join(lines)
+
+ return err
+
+def remove_failed_allocation_backtraces(err):
+ lines = []
+
+ add = True
+ for l in err.split('\n'):
+
+ # Set start and end conditions for including text
+ if l == " The site of the failed allocation is:":
+ add = False
+ elif l[:2] not in ['by: ', 'at:']:
+ add = True
+
+ if add:
+ lines.append(l)
+
+
+ err = '\n'.join(lines)
+
+ return err
+
+
+def clean_output(err):
+ err = re.sub(r"^js\(\d+,0x[0-9a-f]+\) malloc: \*\*\* error for object 0x[0-9a-f]+: pointer being freed was not allocated\n\*\*\* set a breakppoint in malloc_error_break to debug\n$", "pointer being freed was not allocated", err, flags=re.MULTILINE)
+
+ return err
+
+
+#####################################################################
+# Consts, etc
+#####################################################################
+
+command_template = 'shell/js' \
+ + ' -m -j -p' \
+ + ' -e "const platform=\'darwin\'; const libdir=\'../jit-test/lib/\';"' \
+ + ' -f ../jit-test/lib/prolog.js' \
+ + ' -f {0}'
+
+
+# Blacklists are things we don't want to see in our logs again (though we do
+# want to count them when they happen). Whitelists we do want to see in our
+# logs again, principally because the information we have isn't enough.
+
+blacklist = {}
+add_to_blacklist(r"('', '', 1)") # 1 means OOM if the shell hasn't launched yet.
+add_to_blacklist(r"('', 'out of memory\n', 1)")
+
+whitelist = set()
+whitelist.add(r"('', 'out of memory\n', -11)") # -11 means OOM
+whitelist.add(r"('', 'out of memory\nout of memory\n', -11)")
+
+
+
+#####################################################################
+# Program
+#####################################################################
+
+# Options
+parser = OptionParser(usage=usage)
+parser.add_option("-r", "--regression", action="store", metavar="REGRESSION_COUNT", help=help,
+ type="int", dest="regression", default=None)
+
+(OPTIONS, args) = parser.parse_args()
+
+
+if OPTIONS.regression != None:
+ # TODO: This should be expanded as we get a better hang of the OOM problems.
+ # For now, we'll just check that the number of OOMs in one short file does not
+ # increase.
+ files = ["../jit-test/tests/arguments/args-createontrace.js"]
+else:
+ files = get_js_files()
+
+ # Use a command-line arg to reduce the set of files
+ if len (args):
+ files = [f for f in files if f.find(args[0]) != -1]
+
+
+if OPTIONS.regression == None:
+ # Don't use a logfile, this is automated for tinderbox.
+ log = file("../OOM_log", "w")
+
+
+num_failures = 0
+for f in files:
+
+ # Run it once to establish boundaries
+ command = (command_template + ' -O').format(f)
+ out, err, exit = run(command)
+ max = re.match(".*OOM max count: (\d+).*", out, flags=re.DOTALL).groups()[0]
+ max = int(max)
+
+ # OOMs don't recover well for the first 20 allocations or so.
+ # TODO: revisit this.
+ for i in range(20, max):
+
+ if OPTIONS.regression == None:
+ print("Testing allocation {0}/{1} in {2}".format(i,max,f))
+ else:
+ sys.stdout.write('.') # something short for tinderbox, no space or \n
+
+ command = (command_template + ' -A {0}').format(f, i)
+ out, err, exit = run(command)
+
+ # Success (5 is SM's exit code for controlled errors)
+ if exit == 5 and err.find("out of memory") != -1:
+ continue
+
+ # Failure
+ else:
+
+ if OPTIONS.regression != None:
+ # Just count them
+ num_failures += 1
+ continue
+
+ #########################################################################
+ # The regression tests ends above. The rest of this is for running the
+ # script manually.
+ #########################################################################
+
+ problem = str((out, err, exit))
+ if in_blacklist(problem) and problem not in whitelist:
+ add_to_blacklist(problem)
+ continue
+
+ add_to_blacklist(problem)
+
+
+ # Get valgrind output for a good stack trace
+ vcommand = "valgrind --dsymutil=yes -q --log-file=OOM_valgrind_log_file " + command
+ run(vcommand)
+ vout = file("OOM_valgrind_log_file").read()
+ vout = clean_voutput(vout)
+ sans_alloc_sites = remove_failed_allocation_backtraces(vout)
+
+ # Don't print duplicate information
+ if in_blacklist(sans_alloc_sites):
+ add_to_blacklist(sans_alloc_sites)
+ continue
+
+ add_to_blacklist(sans_alloc_sites)
+
+ log.write ("\n")
+ log.write ("\n")
+ log.write ("=========================================================================")
+ log.write ("\n")
+ log.write ("An allocation failure at\n\tallocation {0}/{1} in {2}\n\t"
+ "causes problems (detected using bug 624094)"
+ .format(i, max, f))
+ log.write ("\n")
+ log.write ("\n")
+
+ log.write ("Command (from obj directory, using patch from bug 624094):\n " + command)
+ log.write ("\n")
+ log.write ("\n")
+ log.write ("stdout, stderr, exitcode:\n " + problem)
+ log.write ("\n")
+ log.write ("\n")
+
+ double_free = err.find("pointer being freed was not allocated") != -1
+ oom_detected = err.find("out of memory") != -1
+ multiple_oom_detected = err.find("out of memory\nout of memory") != -1
+ segfault_detected = exit == -11
+
+ log.write ("Diagnosis: ")
+ log.write ("\n")
+ if multiple_oom_detected:
+ log.write (" - Multiple OOMs reported")
+ log.write ("\n")
+ if segfault_detected:
+ log.write (" - segfault")
+ log.write ("\n")
+ if not oom_detected:
+ log.write (" - No OOM checking")
+ log.write ("\n")
+ if double_free:
+ log.write (" - Double free")
+ log.write ("\n")
+
+ log.write ("\n")
+
+ log.write ("Valgrind info:\n" + vout)
+ log.write ("\n")
+ log.write ("\n")
+ log.flush()
+
+ if OPTIONS.regression == None:
+ count_lines()
+
+print()
+
+# Do the actual regression check
+if OPTIONS.regression != None:
+ expected_num_failures = OPTIONS.regression
+
+ if num_failures != expected_num_failures:
+
+ print("TEST-UNEXPECTED-FAIL |", end='')
+ if num_failures > expected_num_failures:
+ print("More out-of-memory errors were found ({0}) than expected ({1}). "
+ "This probably means an allocation site has been added without a "
+ "NULL-check. If this is unavoidable, you can account for it by "
+ "updating Makefile.in.".format(num_failures, expected_num_failures),
+ end='')
+ else:
+ print("Congratulations, you have removed {0} out-of-memory error(s) "
+ "({1} remain)! Please account for it by updating Makefile.in."
+ .format(expected_num_failures - num_failures, num_failures),
+ end='')
+ sys.exit(-1)
+ else:
+ print('TEST-PASS | find_OOM_errors | Found the expected number of OOM '
+ 'errors ({0})'.format(expected_num_failures))
+
diff --git a/config/gcc-stl-wrapper.template.h b/config/gcc-stl-wrapper.template.h
new file mode 100644
index 000000000..9b4a61d24
--- /dev/null
+++ b/config/gcc-stl-wrapper.template.h
@@ -0,0 +1,69 @@
+/* -*- 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
+
+// For some reason, Apple's GCC refuses to honor -fno-exceptions when
+// compiling ObjC.
+#if defined(__EXCEPTIONS) && __EXCEPTIONS && !(__OBJC__ && __GNUC__ && XP_IOS)
+# 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 for cstdlib. See bug 1245076.
+#ifndef moz_dont_include_mozalloc_for_cstdlib
+# define moz_dont_include_mozalloc_for_cstdlib
+#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. NB: this duplicates
+// code in nscore.h because nscore.h pulls in prtypes.h, and chromium
+// can't build with that being included before base/basictypes.h.
+# if !defined(XPCOM_GLUE) && !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 000000000..075e68c88
--- /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 000000000..f429b6765
--- /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/link.py b/config/link.py
new file mode 100644
index 000000000..be63216a0
--- /dev/null
+++ b/config/link.py
@@ -0,0 +1,47 @@
+# 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 expandlibs_exec
+import sys
+import threading
+import time
+
+def periodically_print_status(proc):
+ """
+ Print something to the console every 20 minutes to prevent the build job
+ from getting killed when linking a large binary.
+ Check status of the linker every 0.5 seconds.
+ """
+ idleTime = 0
+ while proc.returncode is None:
+ time.sleep(0.5)
+ idleTime += 0.5
+ if idleTime > 20 * 60:
+ print "Still linking, 20 minutes passed..."
+ sys.stdout.flush()
+ idleTime = 0
+
+def wrap_linker(args):
+ """
+ Execute |args| and pass resulting |proc| object to a second thread that
+ will track the status of the started |proc|.
+ """
+
+ # This needs to be a list in order for the callback to set the
+ # variable properly with python-2's scoping rules.
+ t = [None]
+ def callback(proc):
+ t[0] = threading.Thread(target=periodically_print_status,
+ args=(proc,))
+ t[0].start()
+ exitcode = expandlibs_exec.main(args, proc_callback=callback)
+ # Wait for the background thread to finish.
+ t[0].join()
+ return exitcode
+
+if __name__ == "__main__":
+ if len(sys.argv) < 2:
+ print >>sys.stderr, "Usage: link.py <commandline>"
+ sys.exit(1)
+ sys.exit(wrap_linker(sys.argv[1:]))
diff --git a/config/make-stl-wrappers.py b/config/make-stl-wrappers.py
new file mode 100644
index 000000000..c0ab21c7e
--- /dev/null
+++ b/config/make-stl-wrappers.py
@@ -0,0 +1,52 @@
+# 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 __future__ import print_function
+import os, re, string, sys
+from mozbuild.util import FileAvoidWrite
+
+def find_in_path(file, searchpath):
+ for dir in searchpath.split(os.pathsep):
+ f = os.path.join(dir, file)
+ if os.path.exists(f):
+ return f
+ return ''
+
+def header_path(header, compiler):
+ if compiler == 'gcc':
+ # we use include_next on gcc
+ return header
+ elif compiler == 'msvc':
+ return find_in_path(header, os.environ.get('INCLUDE', ''))
+ else:
+ # hope someone notices this ...
+ raise NotImplementedError(compiler)
+
+def is_comment(line):
+ return re.match(r'\s*#.*', line)
+
+def main(outdir, compiler, template_file, header_list_file):
+ if not os.path.isdir(outdir):
+ os.mkdir(outdir)
+
+ template = open(template_file, 'r').read()
+
+ for header in open(header_list_file, 'r'):
+ header = header.rstrip()
+ if 0 == len(header) or is_comment(header):
+ continue
+
+ path = header_path(header, compiler)
+ with FileAvoidWrite(os.path.join(outdir, header)) as f:
+ f.write(string.Template(template).substitute(HEADER=header,
+ HEADER_PATH=path))
+
+
+if __name__ == '__main__':
+ if 5 != len(sys.argv):
+ print("""Usage:
+ python {0} OUT_DIR ('msvc'|'gcc') TEMPLATE_FILE HEADER_LIST_FILE
+""".format(sys.argv[0]), file=sys.stderr)
+ sys.exit(1)
+
+ main(*sys.argv[1:])
diff --git a/config/makefiles/autotargets.mk b/config/makefiles/autotargets.mk
new file mode 100644
index 000000000..16e06fb2a
--- /dev/null
+++ b/config/makefiles/autotargets.mk
@@ -0,0 +1,94 @@
+# -*- 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)
+ GARBAGE_DIRS +=$(GENERATED_DIRS)
+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 000000000..ff4f917e3
--- /dev/null
+++ b/config/makefiles/debugmake.mk
@@ -0,0 +1,119 @@
+# -*- 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) $(HOST_LIBRARY) $(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_BUILD_ROOT \
+ MOZ_WIDGET_TOOLKIT \
+ CC \
+ CXX \
+ CCC \
+ CPP \
+ LD \
+ AR \
+ IMPLIB \
+ FILTER \
+ 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 \
+ EXTRA_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 \
+ HOST_LIBRARY \
+ )
+
+INCLUDED_DEBUGMAKE_MK = 1
+endif #}
diff --git a/config/makefiles/functions.mk b/config/makefiles/functions.mk
new file mode 100644
index 000000000..ac3632b48
--- /dev/null
+++ b/config/makefiles/functions.mk
@@ -0,0 +1,30 @@
+#
+# 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)
+py_action = $(PYTHON) -m mozbuild.action.$(1) $(2)
diff --git a/config/makefiles/java-build.mk b/config/makefiles/java-build.mk
new file mode 100644
index 000000000..bf667ac44
--- /dev/null
+++ b/config/makefiles/java-build.mk
@@ -0,0 +1,159 @@
+# -*- 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_JAVA_BUILD_MK #{
+
+ifdef JAVAFILES #{
+GENERATED_DIRS += classes
+
+export:: classes
+classes: $(call mkdir_deps,classes)
+endif #} JAVAFILES
+
+default_bootclasspath_jars := \
+ $(ANDROID_SDK)/android.jar \
+ $(NULL)
+
+default_classpath_jars := \
+ $(NULL)
+
+# Turn a possibly empty list of JAR files into a Java classpath, like a.jar:b.jar.
+# Arg 1: Possibly empty list of JAR files.
+define classpath_template
+$(subst $(NULL) ,:,$(strip $(1)))
+endef
+
+ifdef ANDROID_APK_NAME #{
+$(if $(ANDROID_APK_PACKAGE),,$(error Missing ANDROID_APK_PACKAGE with ANDROID_APK_NAME))
+
+android_res_dirs := $(or $(ANDROID_RES_DIRS),$(srcdir)/res)
+_ANDROID_RES_FLAG := $(addprefix -S ,$(android_res_dirs))
+_ANDROID_ASSETS_FLAG := $(if $(ANDROID_ASSETS_DIRS),$(addprefix -A ,$(ANDROID_ASSETS_DIRS)))
+android_manifest := $(or $(ANDROID_MANIFEST_FILE),AndroidManifest.xml)
+
+GENERATED_DIRS += classes generated
+
+generated_r_java := generated/$(subst .,/,$(ANDROID_APK_PACKAGE))/R.java
+
+classes.dex: $(call mkdir_deps,classes)
+classes.dex: $(generated_r_java)
+classes.dex: $(ANDROID_APK_NAME).ap_
+classes.dex: $(default_classpath_jars) $(ANDROID_CLASSPATH_JARS)
+classes.dex: $(default_bootclasspath_jars) $(ANDROID_BOOTCLASSPATH_JARS) $(ANDROID_EXTRA_JARS)
+classes.dex: $(JAVAFILES)
+ $(JAVAC) $(JAVAC_FLAGS) -d classes $(filter %.java,$^) \
+ $(addprefix -bootclasspath ,$(call classpath_template,$(default_bootclasspath_jars) $(ANDROID_BOOTCLASSPATH_JARS))) \
+ $(addprefix -classpath ,$(call classpath_template,$(default_classpath_jars) $(ANDROID_CLASSPATH_JARS) $(ANDROID_EXTRA_JARS)))
+ $(DX) --dex --output=$@ classes $(ANDROID_EXTRA_JARS)
+
+# R.java and $(ANDROID_APK_NAME).ap_ are both produced by aapt. To
+# save an aapt invocation, we produce them both at the same time. The
+# trailing semi-colon defines an empty recipe; defining no recipe at
+# all causes Make to treat the target differently, in a way that
+# defeats our dependencies.
+
+$(generated_r_java): .aapt.deps ;
+$(ANDROID_APK_NAME).ap_: .aapt.deps ;
+
+# This uses the fact that Android resource directories list all
+# resource files one subdirectory below the parent resource directory.
+android_res_files := $(wildcard $(addsuffix /*,$(wildcard $(addsuffix /*,$(android_res_dirs)))))
+
+# An extra package like org.example.app generates dependencies like:
+# generated/org/example/app/R.java: .aapt.deps ;
+# classes.dex: generated/org/example/app/R.java
+# GARBAGE: generated/org/example/app/R.java
+$(foreach extra_package,$(ANDROID_EXTRA_PACKAGES), \
+ $(eval generated/$(subst .,/,$(extra_package))/R.java: .aapt.deps ;) \
+ $(eval classes.dex: generated/$(subst .,/,$(extra_package))/R.java) \
+ $(eval GARBAGE: generated/$(subst .,/,$(extra_package))/R.java) \
+)
+
+# aapt flag -m: 'make package directories under location specified by -J'.
+# The --extra-package list is colon separated.
+.aapt.deps: $(android_manifest) $(android_res_files) $(wildcard $(ANDROID_ASSETS_DIRS))
+ @$(TOUCH) $@
+ $(AAPT) package -f -M $< -I $(ANDROID_SDK)/android.jar $(_ANDROID_RES_FLAG) $(_ANDROID_ASSETS_FLAG) \
+ --custom-package $(ANDROID_APK_PACKAGE) \
+ --non-constant-id \
+ --auto-add-overlay \
+ $(if $(ANDROID_EXTRA_PACKAGES),--extra-packages $(subst $(NULL) ,:,$(strip $(ANDROID_EXTRA_PACKAGES)))) \
+ $(if $(ANDROID_EXTRA_RES_DIRS),$(addprefix -S ,$(ANDROID_EXTRA_RES_DIRS))) \
+ -m \
+ -J ${@D}/generated \
+ -F $(ANDROID_APK_NAME).ap_
+
+$(ANDROID_APK_NAME)-unsigned-unaligned.apk: $(ANDROID_APK_NAME).ap_ classes.dex
+ cp $< $@
+ $(ZIP) -0 $@ classes.dex
+
+$(ANDROID_APK_NAME)-unaligned.apk: $(ANDROID_APK_NAME)-unsigned-unaligned.apk
+ cp $< $@
+ $(DEBUG_JARSIGNER) $@
+
+$(ANDROID_APK_NAME).apk: $(ANDROID_APK_NAME)-unaligned.apk
+ $(ZIPALIGN) -f 4 $< $@
+
+GARBAGE += \
+ $(generated_r_java) \
+ classes.dex \
+ $(ANDROID_APK_NAME).ap_ \
+ $(ANDROID_APK_NAME)-unsigned-unaligned.apk \
+ $(ANDROID_APK_NAME)-unaligned.apk \
+ $(ANDROID_APK_NAME).apk \
+ $(NULL)
+
+# Include Android specific java flags, instead of what's in rules.mk.
+include $(topsrcdir)/config/android-common.mk
+endif #} ANDROID_APK_NAME
+
+
+ifdef JAVA_JAR_TARGETS #{
+# Arg 1: Output target name with .jar suffix, like jars/jarfile.jar.
+# Intermediate class files are generated in jars/jarfile-classes.
+# Arg 2: Java sources list. We use VPATH and $^ so sources can be
+# relative to $(srcdir) or $(CURDIR).
+# Arg 3: List of extra jars to link against. We do not use VPATH so
+# jars must be relative to $(CURDIR).
+# Arg 4: Additional JAVAC_FLAGS.
+
+# Note: Proguard fails when stale .class files corresponding to
+# removed inner classes are present in the object directory. These
+# stale class files get packaged into the .jar file, which then gets
+# processed by Proguard. To work around this, we always delete any
+# existing jarfile-classes directory and start fresh.
+
+define java_jar_template
+$(1): $(2) $(3) $(default_bootclasspath_jars) $(default_classpath_jars)
+ $$(REPORT_BUILD)
+ @$$(RM) -rf $(1:.jar=)-classes
+ @$$(NSINSTALL) -D $(1:.jar=)-classes
+ @$$(if $$(filter-out .,$$(@D)),$$(NSINSTALL) -D $$(@D))
+ $$(JAVAC) $$(JAVAC_FLAGS)\
+ $(4)\
+ -d $(1:.jar=)-classes\
+ $(addprefix -bootclasspath ,$(call classpath_template,$(default_bootclasspath_jars)))\
+ $(addprefix -classpath ,$(call classpath_template,$(default_classpath_jars) $(3)))\
+ $$(filter %.java,$$^)
+ $$(JAR) cMf $$@ -C $(1:.jar=)-classes .
+
+GARBAGE += $(1)
+
+GARBAGE_DIRS += $(1:.jar=)-classes
+endef
+
+$(foreach jar,$(JAVA_JAR_TARGETS),\
+ $(if $($(jar)_DEST),,$(error Missing $(jar)_DEST))\
+ $(if $($(jar)_JAVAFILES) $($(jar)_PP_JAVAFILES),,$(error Must provide at least one of $(jar)_JAVAFILES and $(jar)_PP_JAVAFILES))\
+ $(eval $(call java_jar_template,$($(jar)_DEST),$($(jar)_JAVAFILES) $($(jar)_PP_JAVAFILES),$($(jar)_EXTRA_JARS),$($(jar)_JAVAC_FLAGS)))\
+)
+endif #} JAVA_JAR_TARGETS
+
+
+INCLUDED_JAVA_BUILD_MK := 1
+
+endif #} INCLUDED_JAVA_BUILD_MK
diff --git a/config/makefiles/makeutils.mk b/config/makefiles/makeutils.mk
new file mode 100644
index 000000000..95c7791a4
--- /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 000000000..498de568e
--- /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/target_binaries.mk b/config/makefiles/target_binaries.mk
new file mode 100644
index 000000000..04999f841
--- /dev/null
+++ b/config/makefiles/target_binaries.mk
@@ -0,0 +1,42 @@
+# -*- 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 $(PROGRAM)$(SIMPLE_PROGRAMS)))
+PROGRAMS_EXECUTABLES = $(SIMPLE_PROGRAMS) $(PROGRAM)
+PROGRAMS_DEST ?= $(FINAL_TARGET)
+PROGRAMS_TARGET := target
+INSTALL_TARGETS += PROGRAMS
+endif
+
+ifdef LIBRARY
+ifdef DIST_INSTALL
+ifdef IS_COMPONENT
+$(error Shipping static component libs makes no sense.)
+endif
+endif # DIST_INSTALL
+endif # LIBRARY
+
+
+ifdef SHARED_LIBRARY
+SHARED_LIBRARY_FILES = $(SHARED_LIBRARY)
+SHARED_LIBRARY_DEST ?= $(FINAL_TARGET)$(if $(IS_COMPONENT),/components)
+SHARED_LIBRARY_TARGET = target
+INSTALL_TARGETS += SHARED_LIBRARY
+endif # SHARED_LIBRARY
+
+ifneq (,$(strip $(HOST_SIMPLE_PROGRAMS)$(HOST_PROGRAM)))
+HOST_PROGRAMS_EXECUTABLES = $(HOST_SIMPLE_PROGRAMS) $(HOST_PROGRAM)
+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/test/Makefile.in b/config/makefiles/test/Makefile.in
new file mode 100644
index 000000000..6c66d820e
--- /dev/null
+++ b/config/makefiles/test/Makefile.in
@@ -0,0 +1,98 @@
+# -*- 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/.
+
+STANDALONE_MAKEFILE := 1
+USE_AUTOTARGETS_MK = 1
+MAKEUTILS_UNIT_TEST = 1
+include $(topsrcdir)/config/makefiles/makeutils.mk
+
+dir-ts = .deps/test
+check-arglist = $(dir-ts)/arglist.ts
+check-autotargets = $(dir-ts)/autotargets_mk.ts
+check-XinY = $(dir-ts)/check_XinY_mk.ts
+check-tests =\
+ $(check-arglist) \
+ $(check-autotargets) \
+ $(check-XinY) \
+ $(NULL)
+
+
+##------------------_##
+##---] TARGETS [---##
+##------------------_##
+all::
+
+clean:
+ $(RM) $(check-tests)
+
+###########################################################################
+## Logic processed at compile time so be selective about when to test
+## $(MAKE) check VERBOSE=1
+ifneq ($(NULL),$(findstring check,$(MAKECMDGOALS))) #
+
+check-preqs =\
+ $(call mkdir_deps,$(dir-ts)) \
+ $(check-tests) \
+ $(NULL)
+
+check:: $(check-preqs)
+ @true
+
+
+ifdef VERBOSE #{ gmake check VERBOSE=1
+ $(info ===========================================================================)
+ $(info Running test: $(MAKECMDGOALS): pwd=$(CURDIR))
+ $(info ===========================================================================)
+endif #}
+
+ifndef requiredfunction
+ $(error requiredfunction is not defined)
+endif
+
+
+##################
+check-XinY-preqs=\
+ $(call mkdir_deps,$(dir-ts)) \
+ $(topsrcdir)/config/makefiles/makeutils.mk \
+ $(srcdir)/check_XinY.mk \
+ $(eval include $(srcdir)/check_XinY.mk) \
+ $(NULL)
+
+$(check-XinY): $(check-XinY-preqs)
+ @$(TOUCH) $@
+# </check-XinY.mk>
+
+
+###########################################################################
+## check-arglist.mk always invoked as a compile time test
+## maintain real file dependencies for use later on.
+check-arglist-preqs=\
+ $(call mkdir_deps,$(dir-ts)) \
+ $(topsrcdir)/config/makefiles/makeutils.mk \
+ $(srcdir)/check-arglist.mk \
+ $(eval include $(srcdir)/check-arglist.mk) \
+ $(NULL)
+
+$(check-arglist): $(check-arglist-preqs)
+ @$(TOUCH) $@
+# </check-arglist.mk>
+
+
+###########################################################################
+# <CHECK: autotargets.mk>
+check-autotargets-preqs=\
+ $(call mkdir_deps,$(dir-ts)) \
+ $(topsrcdir)/config/makefiles/makeutils.mk \
+ $(topsrcdir)/config/makefiles/autotargets.mk \
+ $(srcdir)/check-autotargets.mk \
+ $(eval include $(srcdir)/check-autotargets.mk) \
+ $(NULL)
+
+$(check-autotargets): $(check-autotargets-preqs)
+ @$(TOUCH) $@
+# </CHECK: autotargets.mk>
+
+endif #} findstring MAKECMDGOAL
diff --git a/config/makefiles/test/check-arglist.mk b/config/makefiles/test/check-arglist.mk
new file mode 100644
index 000000000..fb720ee42
--- /dev/null
+++ b/config/makefiles/test/check-arglist.mk
@@ -0,0 +1,100 @@
+# -*- 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/.
+
+ifdef VERBOSE
+ $(warning loading test)
+endif
+
+
+$(call requiredfunction,getargv)
+$(call requiredfunction,subargv)
+$(call requiredfunction,istype isval isvar)
+
+# arg_scalar = [scalar|literal]
+arg_list = foo bar
+arg_ref = arg_list
+
+## Identify type of function argument(s)
+########################################
+ifneq (scalar,$(call istype,arg_scalar))
+ $(error istype(arg_scalar)=scalar, found [$(call istype,arg_scalar)])
+endif
+ifneq (list,$(call istype,arg_list))
+ $(error istype(arg_list)=list, found [$(call istype,arg_list)])
+endif
+ifneq (list,$(call istype,arg_ref))
+ $(error istype(arg_ref)=list, found [$(call istype,arg_ref)])
+endif
+
+## Type == scalar or a list of values
+#####################################
+ifneq (true,$(call isval,scalar))
+ $(error isval(scalar)=true, found [$(call isval,scalar)])
+endif
+ifneq ($(NULL),$(call isval,arg_list))
+ $(error isval(arg_list)=null, found [$(call isval,arg_list)])
+endif
+
+## type == reference: macro=>macro => $($(1))
+#############################################
+ifneq ($(NULL),$(call isvar,scalar))
+ $(error isvar(scalar)=$(NULL), found [$(call isvar,scalar)])
+endif
+ifneq (true,$(call isvar,arg_list))
+ $(error isvar(arg_list)=true, found [$(call isvar,arg_list)])
+endif
+ifneq (true,$(call isvar,arg_ref))
+ $(error isvar(arg_ref)=true, found [$(call isvar,arg_ref)])
+endif
+
+# Verify getargv expansion
+##########################
+ifneq (scalar,$(call getargv,scalar))
+ $(error getargv(scalar)=scalar, found [$(call getargv,scalar)])
+endif
+ifneq ($(arg_list),$(call getargv,arg_list))
+ $(error getargv(arg_list)=list, found [$(call getargv,arg_list)])
+endif
+ifneq (arg_list,$(call getargv,arg_ref))
+ $(error getargv(arg_ref)=list, found [$(call getargv,arg_ref)])
+endif
+
+###########################################################################
+##
+###########################################################################
+ifdef MANUAL_TEST #{
+ # For automated testing a callback is needed that can set an external status
+ # variable that can be tested. Syntax is tricky to get correct functionality.
+ ifdef VERBOSE
+ $(info )
+ $(info ===========================================================================)
+ $(info Running test: checkIfEmpty)
+ $(info ===========================================================================)
+ endif
+
+ #status =
+ #setTRUE =status=true
+ #setFALSE =status=$(NULL)
+ #$(call checkIfEmpty,setFALSE NULL)
+ #$(if $(status),$(error checkIfEmpty(xyz) failed))
+ #$(call checkIfEmpty,setTRUE xyz)
+ #$(if $(status),$(error checkIfEmpty(xyz) failed))
+ xyz=abc
+ $(info STATUS: warnIfEmpty - two vars)
+ $(call warnIfEmpty,foo xyz bar)
+ $(info STATUS: errorIfEmpty - on first var)
+ $(call errorIfEmpty,foo xyz bar)
+ $(error TEST FAILED: processing should not reach this point)
+endif #}
+
+# Verify subargv expansion
+##########################
+subargs=foo bar tans fans
+subargs_exp=tans fans
+subargs_found=$(call subargv,4,$(subargs))
+ifneq ($(subargs_exp),$(subargs_found))
+ $(error subargv(4,$(subargs)): expected [$(subargs_exp)] found [$(subargs_found)])
+endif
diff --git a/config/makefiles/test/check-autotargets.mk b/config/makefiles/test/check-autotargets.mk
new file mode 100644
index 000000000..c103f1d02
--- /dev/null
+++ b/config/makefiles/test/check-autotargets.mk
@@ -0,0 +1,84 @@
+# -*- 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/.
+
+ifdef VERBOSE
+ $(warning loading test)
+endif
+
+space=$(null) $(null)
+GENERATED_DIRS = bogus # test data
+
+undefine USE_AUTOTARGETS_MK
+undefine INCLUDED_AUTOTARGETS_MK
+include $(topsrcdir)/config/makefiles/autotargets.mk
+
+ifndef INCLUDED_AUTOTARGETS_MK
+ $(error autotargets.mk was not included
+endif
+
+$(call requiredfunction,mkdir_deps)
+
+
+# Verify test data populated makefile vars correctly
+vars = AUTO_DEPS GARBAGE_DIRS GENERATED_DIRS_DEPS
+$(foreach var,$(vars),$(call errorIfEmpty,$(var)))
+
+# Data should also be valid
+ifneq (bogus,$(findstring bogus,$(AUTO_DEPS)))
+ $(error AUTO_DEPS=[$(AUTO_DEPS)] is not set correctly)
+endif
+
+
+# relpath
+path := foo/bar.c
+exp := foo/.mkdir.done
+found := $(call mkdir_deps,$(dir $(path)))
+ifneq ($(exp),$(found))
+ $(error mkdir_deps($(path))=$(exp) not set correctly [$(found)])
+endif
+
+# abspath
+path := /foo//bar/
+exp := /foo/bar/.mkdir.done
+found := $(call mkdir_deps,$(path))
+ifneq ($(exp),$(found))
+ $(error mkdir_deps($(path))=$(exp) not set correctly [$(found)])
+endif
+
+
+## verify strip_slash
+#####################
+
+path := a/b//c///d////e/////
+exp := a/b/c/d/e/.mkdir.done
+found := $(call mkdir_deps,$(path))
+ifneq ($(exp),$(found))
+ $(error mkdir_deps($(path))=$(exp) not set correctly [$(found)])
+endif
+
+
+## verify mkdir_stem()
+######################
+path := verify/mkdir_stem
+pathD = $(call mkdir_deps,$(path))
+pathS = $(call mkdir_stem,$(pathD))
+exp := $(path)
+
+ifeq ($(pathD),$(pathS))
+ $(error mkdir_deps and mkdir_stem should not match [$(pathD)])
+endif
+ifneq ($(pathS),$(exp))
+ $(error mkdir_stem=[$(pathS)] != exp=[$(exp)])
+endif
+
+
+## Verify embedded whitespace has been protected
+path := a/b$(space)c//d
+exp := a/b$(space)c/d
+found := $(call slash_strip,$(path))
+ifneq ($(exp),$(found))
+ $(error slash_strip($(path))=$(exp) not set correctly [$(found)])
+endif
diff --git a/config/makefiles/test/check_XinY.mk b/config/makefiles/test/check_XinY.mk
new file mode 100644
index 000000000..1e7a19f0e
--- /dev/null
+++ b/config/makefiles/test/check_XinY.mk
@@ -0,0 +1,70 @@
+# -*- 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/.
+
+# Verify dependencies are available
+$(call requiredfunction,getargv subargv is_XinY errorifneq)
+
+ifdef VERBOSE
+ $(warning loading test)
+endif
+
+zero := 0
+one := 1
+
+# Verify 'invalid' is not matched
+val := invalid
+$(call errorifneq,$(zero),$(words $(call is_XinY,foo,$(val))))
+$(call errorifneq,$(zero),$(words $(call is_XinY,clean,$(val))))
+$(call errorifneq,$(zero),$(words $(call is_XinY,clean%,$(val))))
+
+# verify strcmp('clean')
+val := clean
+$(call errorifneq,$(zero),$(words $(call is_XinY,foo,$(val))))
+$(call errorifneq,$(one),$(words $(call is_XinY,clean,$(val))))
+$(call errorifneq,$(one),$(words $(call is_XinY,clean%,$(val))))
+$(call errorifneq,$(one),$(words $(call is_XinY,%clean,$(val))))
+
+# List match for 'clean'
+val := blah clean distclean FcleanG clean-level-1
+wanted := clean distclean clean-level-1
+$(call errorifneq,$(zero),$(words $(call is_XinY_debug,foo,$(val))))
+$(call errorifneq,$(one),$(words $(call is_XinY,clean,$(val))))
+$(call errorifneq,$(one),$(words $(call is_XinY,distclean,$(val))))
+
+# pattern match 'clean'
+# match: clean, distclean, clean-level-1
+# exclude: FcleanG
+TEST_MAKECMDGOALS := $(val)
+$(call errorifneq,3,$(words $(call isTargetStemClean)))
+
+TEST_MAKECMDGOALS := invalid
+$(call errorifneq,$(zero),$(words $(call isTargetStemClean)))
+
+
+#############################
+ifdef VERBOSE
+ $(call banner,Unit test: isTargetStem)
+endif
+
+# Verify list argument processing
+TEST_MAKECMDGOALS := echo
+$(call errorifneq,$(one),$(words $(call isTargetStem,echo,show)))
+
+TEST_MAKECMDGOALS := echo-123
+$(call errorifneq,$(one),$(words $(call isTargetStem,echo,show)))
+
+TEST_MAKECMDGOALS := show
+$(call errorifneq,$(one),$(words $(call isTargetStem,echo,show)))
+
+TEST_MAKECMDGOALS := show-123
+$(call errorifneq,$(one),$(words $(call isTargetStem,echo,show)))
+
+TEST_MAKECMDGOALS := show-123-echo
+$(call errorifneq,$(one),$(words $(call isTargetStem,echo,show)))
+
+TEST_MAKECMDGOALS := invalid
+$(call errorifneq,$(zero),$(words $(call isTargetStem,echo,show)))
+
diff --git a/config/makefiles/test/moz.build b/config/makefiles/test/moz.build
new file mode 100644
index 000000000..28919c271
--- /dev/null
+++ b/config/makefiles/test/moz.build
@@ -0,0 +1,6 @@
+# -*- 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/.
+
diff --git a/config/makefiles/xpidl/Makefile.in b/config/makefiles/xpidl/Makefile.in
new file mode 100644
index 000000000..6329d34d1
--- /dev/null
+++ b/config/makefiles/xpidl/Makefile.in
@@ -0,0 +1,93 @@
+# 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
+process_py := $(topsrcdir)/python/mozbuild/mozbuild/action/xpidl-process.py
+
+# TODO we should use py_action, but that would require extra directories to be
+# in the virtualenv.
+%.xpt:
+ @echo "$(@F)"
+ $(PYTHON_PATH) $(PLY_INCLUDE) -I$(topsrcdir)/xpcom/idl-parser -I$(DEPTH)/xpcom/idl-parser/xpidl \
+ $(process_py) --cache-dir $(DEPTH)/xpcom/idl-parser/xpidl --depsdir $(idl_deps_dir) \
+ $(dist_idl_dir) $(dist_include_dir) $(@D) $(libxul_sdk_includes) \
+ $(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
+
+# Chrome manifests may be written from several Makefiles at various times during
+# the build. The 'buildlist' action adds to the file if it already exists, but
+# if it does exist, make considers it to be up-to-date (as we have no inputs to
+# depend on). We use FORCE to ensure that we always add the interface manifest,
+# whether or not the chrome manifest already exists.
+%/chrome.manifest: FORCE
+ $(call py_action,buildlist,$@ 'manifest components/interfaces.manifest')
+
+chrome_manifests := @chrome_manifests@
+
+%/interfaces.manifest: Makefile
+ $(call py_action,buildlist,$@ $(foreach xpt,$(filter $*/%,$(registered_xpt_files)),'interfaces $(notdir $(xpt))'))
+
+interfaces_manifests := @interfaces_manifests@
+
+xpidl_modules := @xpidl_modules@
+registered_xpt_files := @registered_xpt_files@
+xpt_files := $(registered_xpt_files) @xpt_files@
+
+@xpidl_rules@
+
+depends_files := $(foreach root,$(xpidl_modules),$(idl_deps_dir)/$(root).pp)
+
+GARBAGE += $(xpt_files) $(depends_files)
+
+ifdef COMPILE_ENVIRONMENT
+xpidl:: $(xpt_files) $(chrome_manifests) $(interfaces_manifests)
+endif
+
+$(xpt_files): $(process_py) $(call mkdir_deps,$(idl_deps_dir) $(dist_include_dir))
+
+-include $(depends_files)
+
+define xpt_deps
+$(1): $(call mkdir_deps,$(dir $(1)))
+$(1): $(addsuffix .idl,$(addprefix $(dist_idl_dir)/,$($(basename $(notdir $(1)))_deps)))
+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 000000000..48a995e3c
--- /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 milestone.py.
+# Hopefully I'll be able to automate replacement of *all*
+# hardcoded milestones in the tree from these two files.
+#--------------------------------------------------------
+
+52.6.0
diff --git a/config/moz.build b/config/moz.build
new file mode 100644
index 000000000..7bcac7992
--- /dev/null
+++ b/config/moz.build
@@ -0,0 +1,49 @@
+# -*- 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', 'Build Config')
+
+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.
+NO_VISIBILITY_FLAGS = True
+
+CONFIGURE_SUBST_FILES += [
+ 'doxygen.cfg',
+ 'makefiles/test/Makefile',
+ 'tests/makefiles/autodeps/Makefile',
+ 'tests/src-simple/Makefile',
+]
+
+if CONFIG['HOST_OS_ARCH'] != 'WINNT':
+ HOST_SOURCES += [
+ 'nsinstall.c',
+ 'pathsub.c',
+ ]
+ # stdc++compat depends on config/export, so avoid a circular
+ # dependency added by HostProgram depending on stdc++compat,
+ # while the program here is in C.
+ HostProgram('nsinstall_real', c_only=True)
+
+if CONFIG['MOZ_SYSTEM_ICU']:
+ DEFINES['MOZ_SYSTEM_ICU'] = True
+
+PYTHON_UNIT_TESTS += [
+ 'tests/test_mozbuild_reading.py',
+ 'tests/unit-expandlibs.py',
+ 'tests/unit-mozunit.py',
+ 'tests/unit-nsinstall.py',
+ 'tests/unit-printprereleasesuffix.py',
+]
+
+if CONFIG['GNU_CC'] and CONFIG['MOZ_OPTIMIZE']:
+ CFLAGS += ['-O3']
+
+HOST_DEFINES = {
+ 'UNICODE': True,
+ '_UNICODE': True,
+}
diff --git a/config/mozunit.py b/config/mozunit.py
new file mode 100644
index 000000000..3dddf84ee
--- /dev/null
+++ b/config/mozunit.py
@@ -0,0 +1,207 @@
+# 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 unittest import TextTestRunner as _TestRunner, TestResult as _TestResult
+import unittest
+import inspect
+from StringIO import StringIO
+import os
+import sys
+
+'''Helper to make python unit tests report the way that the Mozilla
+unit test infrastructure expects tests to report.
+
+Usage:
+
+import unittest
+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.message.splitlines()[0] if value.message else 'NO MESSAGE'
+ # 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
+
+class MockedFile(StringIO):
+ def __init__(self, context, filename, content = ''):
+ self.context = context
+ self.name = filename
+ StringIO.__init__(self, content)
+
+ def close(self):
+ self.context.files[self.name] = self.getvalue()
+ StringIO.close(self)
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, type, value, traceback):
+ self.close()
+
+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 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.
+
+ 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.iteritems():
+ self.files[normcase(os.path.abspath(name))] = content
+
+ def __call__(self, name, mode = 'r'):
+ absname = normcase(os.path.abspath(name))
+ if 'w' in mode:
+ file = MockedFile(self, absname)
+ elif absname in self.files:
+ file = MockedFile(self, absname, self.files[absname])
+ elif 'a' in mode:
+ file = MockedFile(self, absname, self.open(name, 'r').read())
+ else:
+ file = self.open(name, mode)
+ if 'a' in mode:
+ file.seek(0, os.SEEK_END)
+ return file
+
+ def __enter__(self):
+ import __builtin__
+ self.open = __builtin__.open
+ self._orig_path_exists = os.path.exists
+ self._orig_path_isdir = os.path.isdir
+ self._orig_path_isfile = os.path.isfile
+ __builtin__.open = self
+ 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 __builtin__
+ __builtin__.open = self.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) or
+ self._orig_path_exists(p))
+
+ def _wrapped_isfile(self, p):
+ p = normcase(p)
+ if p in self.files:
+ return True
+
+ abspath = normcase(os.path.abspath(p))
+ if abspath in self.files:
+ return True
+
+ 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_exists(p)
+
+def main(*args, **kwargs):
+ unittest.main(testRunner=MozTestRunner(), *args, **kwargs)
diff --git a/config/msvc-stl-wrapper.template.h b/config/msvc-stl-wrapper.template.h
new file mode 100644
index 000000000..ed9d98b0d
--- /dev/null
+++ b/config/msvc-stl-wrapper.template.h
@@ -0,0 +1,81 @@
+/* -*- 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
+
+// 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
+
+// Code built with !_HAS_EXCEPTIONS calls std::_Throw(), but the win2k
+// CRT doesn't export std::_Throw(). So we define it.
+#ifndef mozilla_Throw_h
+# include "mozilla/throw_msvc.h"
+#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
+
+// C4275: When _HAS_EXCEPTIONS is set to 0, system STL header
+// will generate the warning which we can't modify.
+// C4530: We know that code won't be able to catch exceptions,
+// but that's OK because we're not throwing them.
+#pragma warning( push )
+#pragma warning( disable : 4275 4530 )
+
+#ifdef __clang__
+#include_next <${HEADER}>
+#else
+#include <${HEADER_PATH}>
+#endif
+
+#pragma warning( pop )
+
+#ifdef MOZ_INCLUDE_MOZALLOC_H_FROM_${HEADER}
+// See if we're in code that can use mozalloc. NB: this duplicates
+// code in nscore.h because nscore.h pulls in prtypes.h, and chromium
+// can't build with that being included before base/basictypes.h.
+# if !defined(XPCOM_GLUE) && !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
+
+#endif // if mozilla_${HEADER}_h
diff --git a/config/nsinstall.c b/config/nsinstall.c
new file mode 100644
index 000000000..d36176c01
--- /dev/null
+++ b/config/nsinstall.c
@@ -0,0 +1,451 @@
+/* -*- 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 100755
index 000000000..481413370
--- /dev/null
+++ b/config/nsinstall.py
@@ -0,0 +1,182 @@
+# 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.
+from __future__ import print_function
+from optparse import OptionParser
+import mozfile
+import os
+import os.path
+import sys
+import shutil
+import stat
+
+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:
+ 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(p) for p 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([unicode(arg, "utf-8") for arg in argv])
+
+if __name__ == '__main__':
+ # sys.argv corrupts characters outside the system code page on Windows
+ # <http://bugs.python.org/issue2128>. Use ctypes instead. This is also
+ # useful because switching to Unicode strings makes python use the wide
+ # Windows APIs, which is what we want here since the wide APIs normally do a
+ # better job at handling long paths and such.
+ if sys.platform == "win32":
+ import ctypes
+ from ctypes import wintypes
+ GetCommandLine = ctypes.windll.kernel32.GetCommandLineW
+ GetCommandLine.argtypes = []
+ GetCommandLine.restype = wintypes.LPWSTR
+
+ CommandLineToArgv = ctypes.windll.shell32.CommandLineToArgvW
+ CommandLineToArgv.argtypes = [wintypes.LPWSTR, ctypes.POINTER(ctypes.c_int)]
+ CommandLineToArgv.restype = ctypes.POINTER(wintypes.LPWSTR)
+
+ argc = ctypes.c_int(0)
+ argv_arr = CommandLineToArgv(GetCommandLine(), ctypes.byref(argc))
+ # The first argv will be "python", the second will be the .py file
+ argv = argv_arr[1:argc.value]
+ else:
+ # For consistency, do it on Unix as well
+ if sys.stdin.encoding is not None:
+ argv = [unicode(arg, sys.stdin.encoding) for arg in sys.argv]
+ else:
+ argv = [unicode(arg) for arg in sys.argv]
+
+ sys.exit(_nsinstall_internal(argv[1:]))
diff --git a/config/pathsub.c b/config/pathsub.c
new file mode 100644
index 000000000..8a8ea254f
--- /dev/null
+++ b/config/pathsub.c
@@ -0,0 +1,215 @@
+/* -*- 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
+
+#ifndef D_INO
+#define D_INO d_ino
+#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 000000000..3cebd0e92
--- /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 000000000..ef900a6c0
--- /dev/null
+++ b/config/printconfigsetting.py
@@ -0,0 +1,31 @@
+# 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 configobj
+import sys
+import re
+from StringIO import StringIO
+
+try:
+ (file, section, key) = sys.argv[1:]
+except ValueError:
+ print "Usage: printconfigsetting.py <file> <section> <setting>"
+ sys.exit(1)
+
+with open(file) as fh:
+ content = re.sub('^\s*;', '#', fh.read(), flags=re.M)
+
+c = configobj.ConfigObj(StringIO(content))
+
+try:
+ s = c[section]
+except KeyError:
+ print >>sys.stderr, "Section [%s] not found." % section
+ sys.exit(1)
+
+try:
+ print s[key]
+except KeyError:
+ print >>sys.stderr, "Key %s not found." % key
+ sys.exit(1)
diff --git a/config/printprereleasesuffix.py b/config/printprereleasesuffix.py
new file mode 100644
index 000000000..b7cddaf62
--- /dev/null
+++ b/config/printprereleasesuffix.py
@@ -0,0 +1,31 @@
+# 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 > ""
+from __future__ import print_function
+
+import sys
+import re
+
+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/pythonpath.py b/config/pythonpath.py
new file mode 100644
index 000000000..031806614
--- /dev/null
+++ b/config/pythonpath.py
@@ -0,0 +1,56 @@
+# 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/.
+
+"""
+Run a python script, adding extra directories to the python path.
+"""
+
+
+def main(args):
+ def usage():
+ print >>sys.stderr, "pythonpath.py -I directory script.py [args...]"
+ sys.exit(150)
+
+ paths = []
+
+ while True:
+ try:
+ arg = args[0]
+ except IndexError:
+ usage()
+
+ if arg == '-I':
+ args.pop(0)
+ try:
+ path = args.pop(0)
+ except IndexError:
+ usage()
+
+ paths.append(os.path.abspath(path))
+ continue
+
+ if arg.startswith('-I'):
+ paths.append(os.path.abspath(args.pop(0)[2:]))
+ continue
+
+ break
+
+ script = args[0]
+
+ sys.path[0:0] = [os.path.abspath(os.path.dirname(script))] + paths
+ sys.argv = args
+ sys.argc = len(args)
+
+ frozenglobals['__name__'] = '__main__'
+ frozenglobals['__file__'] = script
+
+ execfile(script, frozenglobals)
+
+# Freeze scope here ... why this makes things work I have no idea ...
+frozenglobals = globals()
+
+import sys, os
+
+if __name__ == '__main__':
+ main(sys.argv[1:])
diff --git a/config/rebuild_check.py b/config/rebuild_check.py
new file mode 100644
index 000000000..a6c3dc87a
--- /dev/null
+++ b/config/rebuild_check.py
@@ -0,0 +1,44 @@
+# 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 errno
+
+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 mtime(dep) > t:
+ newer.append(dep)
+
+ if newer and removed:
+ print 'Rebuilding %s because %s changed and %s was removed' % (target, ', '.join(newer), ', '.join(removed))
+ elif newer:
+ print 'Rebuilding %s because %s changed' % (target, ', '.join(newer))
+ elif removed:
+ print 'Rebuilding %s because %s was removed' % (target, ', '.join(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 000000000..0b469c1c3
--- /dev/null
+++ b/config/recurse.mk
@@ -0,0 +1,180 @@
+# 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.
+$(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
+
+# Carefully avoid $(eval) type of rule generation, which makes pymake slower
+# than necessary.
+# Get current tier and corresponding subtiers from the data in root.mk.
+CURRENT_TIER := $(filter $(foreach tier,$(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
+
+# 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: $(compile_targets)
+$(compile_targets):
+ $(if $(filter $(RECURSE_BASE_DIR)%,$@),$(call SUBMAKE,$(@F),$(@D)))
+
+# 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 SUBMAKE,$(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))
+
+$(TIERS)::
+
+else
+#########################
+# Tier traversal handling
+#########################
+
+define CREATE_SUBTIER_TRAVERSAL_RULE
+.PHONY: $(1)
+
+$(1):: $$(SUBMAKEFILES)
+ $$(LOOP_OVER_DIRS)
+
+endef
+
+$(foreach subtier,$(filter-out compile,$(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))
+# Interdependencies for parallel export.
+js/xpconnect/src/export: dom/bindings/export xpcom/xpidl/export
+accessible/xpcom/export: xpcom/xpidl/export
+
+# The widget binding generator code is part of the annotationProcessors.
+widget/android/bindings/export: build/annotationProcessors/export
+
+# .xpt generation needs the xpidl lex/yacc files
+xpcom/xpidl/export: xpcom/idl-parser/xpidl/export
+
+# The roboextender addon includes a classes.dex containing a test Java addon.
+# The test addon must be built first.
+mobile/android/tests/browser/robocop/roboextender/tools: mobile/android/tests/javaaddons/tools
+
+ifdef ENABLE_CLANG_PLUGIN
+$(filter-out config/host build/unix/stdc++compat/% build/clang-plugin/%,$(compile_targets)): build/clang-plugin/target build/clang-plugin/tests/target
+build/clang-plugin/tests/target: build/clang-plugin/target
+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
+ifeq ($(MOZ_WIDGET_TOOLKIT),gtk3)
+toolkit/library/target: widget/gtk/mozgtk/gtk3/target
+endif
+ifdef MOZ_LDAP_XPCOM
+ldap/target: config/external/nss/target mozglue/build/target
+toolkit/library/target: ldap/target
+endif
+ifeq ($(MOZ_REPLACE_MALLOC_LINKAGE),dummy library)
+mozglue/build/target memory/replace/logalloc/replay/target: memory/replace/dummy/target
+endif
+endif
+ifeq (,$(MOZ_SYSTEM_NSPR)$(MOZ_SYSTEM_NSS)$(MOZ_FOLD_LIBS))
+config/external/nss/target: config/external/nspr/pr/target config/external/nspr/ds/target config/external/nspr/libc/target
+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/target: config/export
diff --git a/config/rules.mk b/config/rules.mk
new file mode 100644
index 000000000..a21128cf1
--- /dev/null
+++ b/config/rules.mk
@@ -0,0 +1,1541 @@
+# -*- 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
+
+ifndef INCLUDED_VERSION_MK
+include $(MOZILLA_DIR)/config/version.mk
+endif
+
+USE_AUTOTARGETS_MK = 1
+include $(MOZILLA_DIR)/config/makefiles/makeutils.mk
+
+ifdef REBUILD_CHECK
+REPORT_BUILD = $(info $(shell $(PYTHON) $(MOZILLA_DIR)/config/rebuild_check.py $@ $^))
+REPORT_BUILD_VERBOSE = $(REPORT_BUILD)
+else
+REPORT_BUILD = $(info $(notdir $@))
+
+ifdef BUILD_VERBOSE_LOG
+REPORT_BUILD_VERBOSE = $(REPORT_BUILD)
+else
+REPORT_BUILD_VERBOSE =
+endif
+
+endif
+
+EXEC = exec
+
+# ELOG prints out failed command when building silently (gmake -s). Pymake
+# prints out failed commands anyway, so ELOG just makes things worse by
+# forcing shell invocations.
+ifneq (,$(findstring s, $(filter-out --%, $(MAKEFLAGS))))
+ ELOG := $(EXEC) sh $(BUILD_TOOLS)/print-failed-commands.sh
+else
+ ELOG :=
+endif # -s
+
+_VPATH_SRCS = $(abspath $<)
+
+################################################################################
+# 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)
+INCLUDES += -I$(ABS_DIST)/include/testing
+
+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::
+ @$(PYTHON) $(MOZILLA_DIR)/testing/runcppunittests.py --xre-path=$(DIST)/bin --symbols-path=$(DIST)/crashreporter-symbols $(CPP_UNIT_TESTS)
+
+cppunittests-remote: DM_TRANS?=adb
+cppunittests-remote:
+ @if [ '${TEST_DEVICE}' != '' -o '$(DM_TRANS)' = 'adb' ]; then \
+ $(PYTHON) -u $(MOZILLA_DIR)/testing/remotecppunittests.py \
+ --xre-path=$(DEPTH)/dist/bin \
+ --localLib=$(DEPTH)/dist/$(MOZ_APP_NAME) \
+ --dm_trans=$(DM_TRANS) \
+ --deviceIP=${TEST_DEVICE} \
+ $(CPP_UNIT_TESTS) $(EXTRA_TEST_ARGS); \
+ else \
+ echo 'please prepare your host with environment variables for TEST_DEVICE'; \
+ fi
+
+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
+# Don't build actual static library if a shared library is also built
+ifdef FORCE_SHARED_LIB
+# ... except when we really want one
+ifdef NO_EXPAND_LIBS
+LIBRARY := $(REAL_LIBRARY)
+else
+LIBRARY := $(REAL_LIBRARY).$(LIBS_DESC_SUFFIX)
+endif
+else
+# Only build actual library if it is installed in DIST/lib or SDK
+ifeq (,$(SDK_LIBRARY)$(DIST_INSTALL)$(NO_EXPAND_LIBS))
+LIBRARY := $(REAL_LIBRARY).$(LIBS_DESC_SUFFIX)
+else
+ifdef NO_EXPAND_LIBS
+LIBRARY := $(REAL_LIBRARY)
+else
+LIBRARY := $(REAL_LIBRARY) $(REAL_LIBRARY).$(LIBS_DESC_SUFFIX)
+endif
+endif
+endif
+endif # REAL_LIBRARY
+endif # LIBRARY
+
+ifndef HOST_LIBRARY
+ifdef HOST_LIBRARY_NAME
+HOST_LIBRARY := $(LIB_PREFIX)$(HOST_LIBRARY_NAME).$(LIB_SUFFIX)
+endif
+endif
+
+ifdef LIBRARY
+ifdef FORCE_SHARED_LIB
+ifdef MKSHLIB
+
+ifdef LIB_IS_C_ONLY
+MKSHLIB = $(MKCSHLIB)
+endif
+
+EMBED_MANIFEST_AT=2
+
+endif # MKSHLIB
+endif # FORCE_SHARED_LIB
+endif # LIBRARY
+
+ifeq ($(OS_ARCH),WINNT)
+ifndef GNU_CC
+
+#
+# Unless we're building SIMPLE_PROGRAMS, all C++ files share a PDB file per
+# directory. For parallel builds, this PDB file is shared and locked by
+# MSPDBSRV.EXE, starting with MSVC8 SP1. If you're using MSVC 7.1 or MSVC8
+# without SP1, don't do parallel builds.
+#
+# The final PDB for libraries and programs is created by the linker and uses
+# a different name from the single PDB file created by the compiler. See
+# bug 462740.
+#
+
+ifdef SIMPLE_PROGRAMS
+COMPILE_PDB_FLAG ?= -Fd$(basename $(@F)).pdb
+else
+COMPILE_PDB_FLAG ?= -Fdgenerated.pdb
+endif
+COMPILE_CFLAGS += $(COMPILE_PDB_FLAG)
+COMPILE_CXXFLAGS += $(COMPILE_PDB_FLAG)
+
+LINK_PDBFILE ?= $(basename $(@F)).pdb
+ifdef MOZ_DEBUG
+CODFILE=$(basename $(@F)).cod
+endif
+
+ifdef DEFFILE
+OS_LDFLAGS += -DEF:$(call normalizepath,$(DEFFILE))
+EXTRA_DEPS += $(DEFFILE)
+endif
+
+else #!GNU_CC
+
+ifdef DEFFILE
+OS_LDFLAGS += $(call normalizepath,$(DEFFILE))
+EXTRA_DEPS += $(DEFFILE)
+endif
+
+endif # !GNU_CC
+
+endif # WINNT
+
+ifeq (arm-Darwin,$(CPU_ARCH)-$(OS_TARGET))
+ifdef PROGRAM
+MOZ_PROGRAM_LDFLAGS += -Wl,-rpath -Wl,@executable_path/Frameworks
+endif
+endif
+
+ifeq ($(HOST_OS_ARCH),WINNT)
+HOST_PDBFILE=$(basename $(@F)).pdb
+HOST_PDB_FLAG ?= -Fd$(HOST_PDBFILE)
+HOST_CFLAGS += $(HOST_PDB_FLAG)
+HOST_CXXFLAGS += $(HOST_PDB_FLAG)
+endif
+
+# Don't build SIMPLE_PROGRAMS during the MOZ_PROFILE_GENERATE pass
+ifdef MOZ_PROFILE_GENERATE
+SIMPLE_PROGRAMS :=
+endif
+
+ifdef COMPILE_ENVIRONMENT
+ifndef TARGETS
+TARGETS = $(LIBRARY) $(SHARED_LIBRARY) $(PROGRAM) $(SIMPLE_PROGRAMS) $(HOST_LIBRARY) $(HOST_PROGRAM) $(HOST_SIMPLE_PROGRAMS)
+endif
+
+COBJS = $(notdir $(CSRCS:.c=.$(OBJ_SUFFIX)))
+SOBJS = $(notdir $(SSRCS:.S=.$(OBJ_SUFFIX)))
+# CPPSRCS can have different extensions (eg: .cpp, .cc)
+CPPOBJS = $(notdir $(addsuffix .$(OBJ_SUFFIX),$(basename $(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)
+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_LIBRARY :=
+HOST_PROGRAM :=
+HOST_SIMPLE_PROGRAMS :=
+SDK_LIBRARY :=
+endif
+
+ALL_TRASH = \
+ $(GARBAGE) $(TARGETS) $(OBJS) $(PROGOBJS) LOGS TAGS a.out \
+ $(filter-out $(ASFILES),$(OBJS:.$(OBJ_SUFFIX)=.s)) $(OBJS:.$(OBJ_SUFFIX)=.ii) \
+ $(OBJS:.$(OBJ_SUFFIX)=.i) $(OBJS:.$(OBJ_SUFFIX)=.i_o) \
+ $(HOST_PROGOBJS) $(HOST_OBJS) $(IMPORT_LIBRARY) \
+ $(EXE_DEF_FILE) so_locations _gen _stubs $(wildcard *.res) $(wildcard *.RES) \
+ $(wildcard *.pdb) $(CODFILE) $(IMPORT_LIBRARY) \
+ $(SHARED_LIBRARY:$(DLL_SUFFIX)=.exp) $(wildcard *.ilk) \
+ $(PROGRAM:$(BIN_SUFFIX)=.exp) $(SIMPLE_PROGRAMS:$(BIN_SUFFIX)=.exp) \
+ $(PROGRAM:$(BIN_SUFFIX)=.lib) $(SIMPLE_PROGRAMS:$(BIN_SUFFIX)=.lib) \
+ $(SIMPLE_PROGRAMS:$(BIN_SUFFIX)=.$(OBJ_SUFFIX)) \
+ $(wildcard gts_tmp_*) $(LIBRARY:%.a=.%.timestamp)
+ALL_TRASH_DIRS = \
+ $(GARBAGE_DIRS) /no-such-file
+
+ifdef QTDIR
+GARBAGE += $(MOCSRCS)
+endif
+
+ifdef SIMPLE_PROGRAMS
+GARBAGE += $(SIMPLE_PROGRAMS:%=%.$(OBJ_SUFFIX))
+endif
+
+ifdef HOST_SIMPLE_PROGRAMS
+GARBAGE += $(HOST_SIMPLE_PROGRAMS:%=%.$(OBJ_SUFFIX))
+endif
+
+ifdef MACH
+ifndef NO_BUILDSTATUS_MESSAGES
+define BUILDSTATUS
+@echo 'BUILDSTATUS $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
+
+GARBAGE_DIRS += $(wildcard $(CURDIR)/$(MDDEPDIR))
+
+#
+# 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
+
+#
+# This will strip out symbols that the component should not be
+# exporting from the .dynsym section.
+#
+ifdef IS_COMPONENT
+EXTRA_DSO_LDOPTS += $(MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS)
+endif # IS_COMPONENT
+
+#
+# MacOS X specific stuff
+#
+
+ifeq ($(OS_ARCH),Darwin)
+ifdef SHARED_LIBRARY
+ifdef IS_COMPONENT
+EXTRA_DSO_LDOPTS += -bundle
+else
+ifdef MOZ_IOS
+_LOADER_PATH := @rpath
+else
+_LOADER_PATH := @executable_path
+endif
+EXTRA_DSO_LDOPTS += -dynamiclib -install_name $(_LOADER_PATH)/$(SHARED_LIBRARY) -compatibility_version 1 -current_version 1 -single_module
+endif
+endif
+endif
+
+#
+# On NetBSD a.out systems, use -Bsymbolic. This fixes what would otherwise be
+# fatal symbol name clashes between components.
+#
+ifeq ($(OS_ARCH),NetBSD)
+ifeq ($(DLL_SUFFIX),.so.1.0)
+ifdef IS_COMPONENT
+EXTRA_DSO_LDOPTS += -Wl,-Bsymbolic
+endif
+endif
+endif
+
+ifeq ($(OS_ARCH),FreeBSD)
+ifdef IS_COMPONENT
+EXTRA_DSO_LDOPTS += -Wl,-Bsymbolic
+endif
+endif
+
+ifeq ($(OS_ARCH),NetBSD)
+ifneq (,$(filter arc cobalt hpcmips mipsco newsmips pmax sgimips,$(OS_TEST)))
+ifneq (,$(filter layout/%,$(relativesrcdir)))
+OS_CFLAGS += -Wa,-xgot
+OS_CXXFLAGS += -Wa,-xgot
+endif
+endif
+endif
+
+#
+# HP-UXBeOS specific section: for COMPONENTS only, add -Bsymbolic flag
+# which uses internal symbols first
+#
+ifeq ($(OS_ARCH),HP-UX)
+ifdef IS_COMPONENT
+ifeq ($(GNU_CC)$(GNU_CXX),)
+EXTRA_DSO_LDOPTS += -Wl,-Bsymbolic
+ifneq ($(HAS_EXTRAEXPORTS),1)
+MKSHLIB += -Wl,+eNSGetModule -Wl,+eerrno
+MKCSHLIB += +eNSGetModule +eerrno
+ifneq ($(OS_TEST),ia64)
+MKSHLIB += -Wl,+e_shlInit
+MKCSHLIB += +e_shlInit
+endif # !ia64
+endif # !HAS_EXTRAEXPORTS
+endif # non-gnu compilers
+endif # IS_COMPONENT
+endif # HP-UX
+
+ifeq ($(OS_ARCH),AIX)
+ifdef IS_COMPONENT
+ifneq ($(HAS_EXTRAEXPORTS),1)
+MKSHLIB += -bE:$(MOZILLA_DIR)/build/unix/aix.exp -bnoexpall
+MKCSHLIB += -bE:$(MOZILLA_DIR)/build/unix/aix.exp -bnoexpall
+endif # HAS_EXTRAEXPORTS
+endif # IS_COMPONENT
+endif # AIX
+
+#
+# Linux: add -Bsymbolic flag for components
+#
+ifeq ($(OS_ARCH),Linux)
+ifdef IS_COMPONENT
+EXTRA_DSO_LDOPTS += -Wl,-Bsymbolic
+endif
+ifdef LD_VERSION_SCRIPT
+EXTRA_DSO_LDOPTS += -Wl,--version-script,$(LD_VERSION_SCRIPT)
+EXTRA_DEPS += $(LD_VERSION_SCRIPT)
+endif
+endif
+
+ifdef SYMBOLS_FILE
+ifeq ($(OS_TARGET),WINNT)
+ifndef GNU_CC
+EXTRA_DSO_LDOPTS += -DEF:$(call normalizepath,$(SYMBOLS_FILE))
+else
+EXTRA_DSO_LDOPTS += $(call normalizepath,$(SYMBOLS_FILE))
+endif
+else
+ifdef GCC_USE_GNU_LD
+EXTRA_DSO_LDOPTS += -Wl,--version-script,$(SYMBOLS_FILE)
+else
+ifeq ($(OS_TARGET),Darwin)
+EXTRA_DSO_LDOPTS += -Wl,-exported_symbols_list,$(SYMBOLS_FILE)
+endif
+endif
+endif
+EXTRA_DEPS += $(SYMBOLS_FILE)
+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
+ifndef IS_COMPONENT
+DSO_LDOPTS += -Wl,--out-implib -Wl,$(IMPORT_LIBRARY)
+endif
+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
+
+ifneq (,$(filter ml%,$(AS)))
+ASOUTOPTION = -Fo# eol
+else
+ASOUTOPTION = -o # eol
+endif
+
+ifeq (,$(CROSS_COMPILE))
+HOST_OUTOPTION = $(OUTOPTION)
+else
+HOST_OUTOPTION = -o # eol
+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)))
+
+ifeq ($(findstring s,$(filter-out --%, $(MAKEFLAGS))),)
+ECHO := echo
+QUIET :=
+else
+ECHO := true
+QUIET := -q
+endif
+
+# Do everything from scratch
+everything::
+ $(MAKE) clean
+ $(MAKE) all
+
+STATIC_LIB_DEP = $(if $(wildcard $(1).$(LIBS_DESC_SUFFIX)),$(1).$(LIBS_DESC_SUFFIX),$(1))
+STATIC_LIBS_DEPS := $(foreach l,$(STATIC_LIBS),$(call STATIC_LIB_DEP,$(l)))
+
+# Dependencies which, if modified, should cause everything to rebuild
+GLOBAL_DEPS += Makefile $(addprefix $(DEPTH)/config/,$(INCLUDED_AUTOCONF_MK)) $(MOZILLA_DIR)/config/config.mk
+
+##############################################
+ifdef COMPILE_ENVIRONMENT
+OBJ_TARGETS = $(OBJS) $(PROGOBJS) $(HOST_OBJS) $(HOST_PROGOBJS)
+
+compile:: host target
+
+host:: $(HOST_LIBRARY) $(HOST_PROGRAM) $(HOST_SIMPLE_PROGRAMS)
+
+target:: $(LIBRARY) $(SHARED_LIBRARY) $(PROGRAM) $(SIMPLE_PROGRAMS) $(RUST_LIBRARY_FILE)
+
+include $(MOZILLA_DIR)/config/makefiles/target_binaries.mk
+endif
+
+##############################################
+ifneq (1,$(NO_PROFILE_GUIDED_OPTIMIZE))
+ifdef MOZ_PROFILE_USE
+ifeq ($(OS_ARCH)_$(GNU_CC), WINNT_)
+# When building with PGO, we have to make sure to re-link
+# in the MOZ_PROFILE_USE phase if we linked in the
+# MOZ_PROFILE_GENERATE phase. We'll touch this pgo.relink
+# file in the link rule in the GENERATE phase to indicate
+# that we need a relink.
+ifdef SHARED_LIBRARY
+$(SHARED_LIBRARY): pgo.relink
+endif
+ifdef PROGRAM
+$(PROGRAM): pgo.relink
+endif
+
+# In the second pass, we need to merge the pgc files into the pgd file.
+# The compiler would do this for us automatically if they were in the right
+# place, but they're in dist/bin.
+ifneq (,$(SHARED_LIBRARY)$(PROGRAM))
+export::
+ifdef PROGRAM
+ $(PYTHON) $(MOZILLA_DIR)/build/win32/pgomerge.py \
+ $(PROGRAM:$(BIN_SUFFIX)=) $(DIST)/bin
+endif
+ifdef SHARED_LIBRARY
+ $(PYTHON) $(MOZILLA_DIR)/build/win32/pgomerge.py \
+ $(patsubst $(DLL_PREFIX)%$(DLL_SUFFIX),%,$(SHARED_LIBRARY)) $(DIST)/bin
+endif
+endif # SHARED_LIBRARY || PROGRAM
+endif # WINNT_
+endif # MOZ_PROFILE_USE
+ifdef MOZ_PROFILE_GENERATE
+# Clean up profiling data during PROFILE_GENERATE phase
+export::
+ifeq ($(OS_ARCH)_$(GNU_CC), WINNT_)
+ $(foreach pgd,$(wildcard *.pgd),pgomgr -clear $(pgd);)
+else
+ifdef GNU_CC
+ -$(RM) *.gcda
+endif
+endif
+endif
+
+ifneq (,$(MOZ_PROFILE_GENERATE)$(MOZ_PROFILE_USE))
+ifdef GNU_CC
+# Force rebuilding libraries and programs in both passes because each
+# pass uses different object files.
+$(PROGRAM) $(SHARED_LIBRARY) $(LIBRARY): FORCE
+endif
+endif
+
+endif # NO_PROFILE_GUIDED_OPTIMIZE
+
+##############################################
+
+checkout:
+ $(MAKE) -C $(topsrcdir) -f client.mk checkout
+
+clean clobber realclean clobber_all::
+ -$(RM) $(ALL_TRASH)
+ -$(RM) -r $(ALL_TRASH_DIRS)
+
+clean clobber realclean clobber_all distclean::
+ $(foreach dir,$(DIRS),-$(call SUBMAKE,$@,$(dir)))
+
+distclean::
+ -$(RM) -r $(ALL_TRASH_DIRS)
+ -$(RM) $(ALL_TRASH) \
+ Makefile .HSancillary \
+ $(wildcard *.$(OBJ_SUFFIX)) $(wildcard *.ho) $(wildcard host_*.o*) \
+ $(wildcard *.$(LIB_SUFFIX)) $(wildcard *$(DLL_SUFFIX)) \
+ $(wildcard *.$(IMPORT_LIB_SUFFIX))
+
+alltags:
+ $(RM) TAGS
+ find $(topsrcdir) -name dist -prune -o \( -name '*.[hc]' -o -name '*.cp' -o -name '*.cpp' -o -name '*.idl' \) -print | $(TAG_PROGRAM)
+
+#
+# PROGRAM = Foo
+# creates OBJS, links with LIBS to create Foo
+#
+$(PROGRAM): $(PROGOBJS) $(STATIC_LIBS_DEPS) $(EXTRA_DEPS) $(EXE_DEF_FILE) $(RESFILE) $(GLOBAL_DEPS)
+ $(REPORT_BUILD)
+ @$(RM) $@.manifest
+ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH))
+ $(EXPAND_LD) -NOLOGO -OUT:$@ -PDB:$(LINK_PDBFILE) $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(MOZ_PROGRAM_LDFLAGS) $(PROGOBJS) $(RESFILE) $(STATIC_LIBS) $(SHARED_LIBS) $(EXTRA_LIBS) $(OS_LIBS)
+ifdef MSMANIFEST_TOOL
+ @if test -f $@.manifest; then \
+ if test -f '$(srcdir)/$@.manifest'; then \
+ echo 'Embedding manifest from $(srcdir)/$@.manifest and $@.manifest'; \
+ $(MT) -NOLOGO -MANIFEST '$(win_srcdir)/$@.manifest' $@.manifest -OUTPUTRESOURCE:$@\;1; \
+ else \
+ echo 'Embedding manifest from $@.manifest'; \
+ $(MT) -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;1; \
+ fi; \
+ elif test -f '$(srcdir)/$@.manifest'; then \
+ echo 'Embedding manifest from $(srcdir)/$@.manifest'; \
+ $(MT) -NOLOGO -MANIFEST '$(win_srcdir)/$@.manifest' -OUTPUTRESOURCE:$@\;1; \
+ fi
+endif # MSVC with manifest tool
+ifdef MOZ_PROFILE_GENERATE
+# touch it a few seconds into the future to work around FAT's
+# 2-second granularity
+ touch -t `date +%Y%m%d%H%M.%S -d 'now+5seconds'` pgo.relink
+endif
+else # !WINNT || GNU_CC
+ $(EXPAND_CCC) -o $@ $(CXXFLAGS) $(PROGOBJS) $(RESFILE) $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(WRAP_LDFLAGS) $(STATIC_LIBS) $(MOZ_PROGRAM_LDFLAGS) $(SHARED_LIBS) $(EXTRA_LIBS) $(OS_LIBS) $(BIN_FLAGS) $(EXE_DEF_FILE)
+ $(call CHECK_BINARY,$@)
+endif # WINNT && !GNU_CC
+
+ifdef ENABLE_STRIP
+ $(STRIP) $(STRIP_FLAGS) $@
+endif
+ifdef MOZ_POST_PROGRAM_COMMAND
+ $(MOZ_POST_PROGRAM_COMMAND) $@
+endif
+
+$(HOST_PROGRAM): $(HOST_PROGOBJS) $(HOST_LIBS) $(HOST_EXTRA_DEPS) $(GLOBAL_DEPS)
+ $(REPORT_BUILD)
+ifeq (_WINNT,$(GNU_CC)_$(HOST_OS_ARCH))
+ $(EXPAND_LIBS_EXEC) -- $(HOST_LD) -NOLOGO -OUT:$@ -PDB:$(HOST_PDBFILE) $(HOST_OBJS) $(WIN32_EXE_LDFLAGS) $(HOST_LDFLAGS) $(HOST_LIBS) $(HOST_EXTRA_LIBS)
+ifdef MSMANIFEST_TOOL
+ @if test -f $@.manifest; then \
+ if test -f '$(srcdir)/$@.manifest'; then \
+ echo 'Embedding manifest from $(srcdir)/$@.manifest and $@.manifest'; \
+ $(MT) -NOLOGO -MANIFEST '$(win_srcdir)/$@.manifest' $@.manifest -OUTPUTRESOURCE:$@\;1; \
+ else \
+ echo 'Embedding manifest from $@.manifest'; \
+ $(MT) -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;1; \
+ fi; \
+ elif test -f '$(srcdir)/$@.manifest'; then \
+ echo 'Embedding manifest from $(srcdir)/$@.manifest'; \
+ $(MT) -NOLOGO -MANIFEST '$(win_srcdir)/$@.manifest' -OUTPUTRESOURCE:$@\;1; \
+ fi
+endif # MSVC with manifest tool
+else
+ifeq ($(HOST_CPP_PROG_LINK),1)
+ $(EXPAND_LIBS_EXEC) -- $(HOST_CXX) -o $@ $(HOST_CXXFLAGS) $(HOST_LDFLAGS) $(HOST_PROGOBJS) $(HOST_LIBS) $(HOST_EXTRA_LIBS)
+else
+ $(EXPAND_LIBS_EXEC) -- $(HOST_CC) -o $@ $(HOST_CFLAGS) $(HOST_LDFLAGS) $(HOST_PROGOBJS) $(HOST_LIBS) $(HOST_EXTRA_LIBS)
+endif # HOST_CPP_PROG_LINK
+endif
+ifndef CROSS_COMPILE
+ $(call CHECK_STDCXX,$@)
+endif
+
+#
+# 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.
+#
+$(SIMPLE_PROGRAMS): %$(BIN_SUFFIX): %.$(OBJ_SUFFIX) $(STATIC_LIBS_DEPS) $(EXTRA_DEPS) $(GLOBAL_DEPS)
+ $(REPORT_BUILD)
+ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH))
+ $(EXPAND_LD) -nologo -out:$@ -pdb:$(LINK_PDBFILE) $< $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(MOZ_PROGRAM_LDFLAGS) $(STATIC_LIBS) $(SHARED_LIBS) $(EXTRA_LIBS) $(OS_LIBS)
+ifdef MSMANIFEST_TOOL
+ @if test -f $@.manifest; then \
+ $(MT) -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;1; \
+ rm -f $@.manifest; \
+ fi
+endif # MSVC with manifest tool
+else
+ $(EXPAND_CCC) $(CXXFLAGS) -o $@ $< $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(WRAP_LDFLAGS) $(STATIC_LIBS) $(MOZ_PROGRAM_LDFLAGS) $(SHARED_LIBS) $(EXTRA_LIBS) $(OS_LIBS) $(BIN_FLAGS)
+ $(call CHECK_BINARY,$@)
+endif # WINNT && !GNU_CC
+
+ifdef ENABLE_STRIP
+ $(STRIP) $(STRIP_FLAGS) $@
+endif
+ifdef MOZ_POST_PROGRAM_COMMAND
+ $(MOZ_POST_PROGRAM_COMMAND) $@
+endif
+
+$(HOST_SIMPLE_PROGRAMS): host_%$(HOST_BIN_SUFFIX): host_%.$(OBJ_SUFFIX) $(HOST_LIBS) $(HOST_EXTRA_DEPS) $(GLOBAL_DEPS)
+ $(REPORT_BUILD)
+ifeq (WINNT_,$(HOST_OS_ARCH)_$(GNU_CC))
+ $(EXPAND_LIBS_EXEC) -- $(HOST_LD) -NOLOGO -OUT:$@ -PDB:$(HOST_PDBFILE) $< $(WIN32_EXE_LDFLAGS) $(HOST_LIBS) $(HOST_EXTRA_LIBS)
+else
+ifneq (,$(HOST_CPPSRCS)$(USE_HOST_CXX))
+ $(EXPAND_LIBS_EXEC) -- $(HOST_CXX) $(HOST_OUTOPTION)$@ $(HOST_CXXFLAGS) $(INCLUDES) $< $(HOST_LIBS) $(HOST_EXTRA_LIBS)
+else
+ $(EXPAND_LIBS_EXEC) -- $(HOST_CC) $(HOST_OUTOPTION)$@ $(HOST_CFLAGS) $(INCLUDES) $< $(HOST_LIBS) $(HOST_EXTRA_LIBS)
+endif
+endif
+ifndef CROSS_COMPILE
+ $(call CHECK_STDCXX,$@)
+endif
+
+ifdef DTRACE_PROBE_OBJ
+EXTRA_DEPS += $(DTRACE_PROBE_OBJ)
+OBJS += $(DTRACE_PROBE_OBJ)
+endif
+
+$(filter %.$(LIB_SUFFIX),$(LIBRARY)): $(OBJS) $(STATIC_LIBS_DEPS) $(filter %.$(LIB_SUFFIX),$(EXTRA_LIBS)) $(EXTRA_DEPS) $(GLOBAL_DEPS)
+ $(REPORT_BUILD)
+# Always remove both library and library descriptor
+ $(RM) $(REAL_LIBRARY) $(REAL_LIBRARY).$(LIBS_DESC_SUFFIX)
+ $(EXPAND_AR) $(AR_FLAGS) $(OBJS) $(STATIC_LIBS) $(filter %.$(LIB_SUFFIX),$(EXTRA_LIBS))
+
+$(filter-out %.$(LIB_SUFFIX),$(LIBRARY)): $(filter %.$(LIB_SUFFIX),$(LIBRARY)) $(OBJS) $(STATIC_LIBS_DEPS) $(filter %.$(LIB_SUFFIX),$(EXTRA_LIBS)) $(EXTRA_DEPS) $(GLOBAL_DEPS)
+# When we only build a library descriptor, blow out any existing library
+ $(REPORT_BUILD)
+ $(if $(filter %.$(LIB_SUFFIX),$(LIBRARY)),,$(RM) $(REAL_LIBRARY))
+ $(EXPAND_LIBS_GEN) -o $@ $(OBJS) $(STATIC_LIBS) $(filter %.$(LIB_SUFFIX),$(EXTRA_LIBS))
+
+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_LIBRARY): $(HOST_OBJS) Makefile
+ $(REPORT_BUILD)
+ $(RM) $@
+ $(EXPAND_LIBS_EXEC) --extract -- $(HOST_AR) $(HOST_AR_FLAGS) $(HOST_OBJS)
+
+ifdef HAVE_DTRACE
+ifndef XP_MACOSX
+ifdef DTRACE_PROBE_OBJ
+ifndef DTRACE_LIB_DEPENDENT
+NON_DTRACE_OBJS := $(filter-out $(DTRACE_PROBE_OBJ),$(OBJS))
+$(DTRACE_PROBE_OBJ): $(NON_DTRACE_OBJS)
+ dtrace -x nolibs -G -C -s $(MOZILLA_DTRACE_SRC) -o $(DTRACE_PROBE_OBJ) $(NON_DTRACE_OBJS)
+endif
+endif
+endif
+endif
+
+# 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) $(RESFILE) $(RUST_STATIC_LIB_FOR_SHARED_LIB) $(STATIC_LIBS_DEPS) $(EXTRA_DEPS) $(GLOBAL_DEPS)
+ $(REPORT_BUILD)
+ifndef INCREMENTAL_LINKER
+ $(RM) $@
+endif
+ifdef DTRACE_LIB_DEPENDENT
+ifndef XP_MACOSX
+ dtrace -x nolibs -G -C -s $(MOZILLA_DTRACE_SRC) -o $(DTRACE_PROBE_OBJ) $(shell $(EXPAND_LIBS) $(MOZILLA_PROBE_LIBS))
+endif
+ $(EXPAND_MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(SUB_SHLOBJS) $(DTRACE_PROBE_OBJ) $(MOZILLA_PROBE_LIBS) $(RESFILE) $(LDFLAGS) $(WRAP_LDFLAGS) $(STATIC_LIBS) $(RUST_STATIC_LIB_FOR_SHARED_LIB) $(SHARED_LIBS) $(EXTRA_DSO_LDOPTS) $(MOZ_GLUE_LDFLAGS) $(EXTRA_LIBS) $(OS_LIBS) $(SHLIB_LDENDFILE)
+ @$(RM) $(DTRACE_PROBE_OBJ)
+else # ! DTRACE_LIB_DEPENDENT
+ $(EXPAND_MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(SUB_SHLOBJS) $(RESFILE) $(LDFLAGS) $(WRAP_LDFLAGS) $(STATIC_LIBS) $(RUST_STATIC_LIB_FOR_SHARED_LIB) $(SHARED_LIBS) $(EXTRA_DSO_LDOPTS) $(MOZ_GLUE_LDFLAGS) $(EXTRA_LIBS) $(OS_LIBS) $(SHLIB_LDENDFILE)
+endif # DTRACE_LIB_DEPENDENT
+ $(call CHECK_BINARY,$@)
+
+ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH))
+ifdef MSMANIFEST_TOOL
+ifdef EMBED_MANIFEST_AT
+ @if test -f $@.manifest; then \
+ if test -f '$(srcdir)/$@.manifest'; then \
+ echo 'Embedding manifest from $(srcdir)/$@.manifest and $@.manifest'; \
+ $(MT) -NOLOGO -MANIFEST '$(win_srcdir)/$@.manifest' $@.manifest -OUTPUTRESOURCE:$@\;$(EMBED_MANIFEST_AT); \
+ else \
+ echo 'Embedding manifest from $@.manifest'; \
+ $(MT) -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;$(EMBED_MANIFEST_AT); \
+ fi; \
+ elif test -f '$(srcdir)/$@.manifest'; then \
+ echo 'Embedding manifest from $(srcdir)/$@.manifest'; \
+ $(MT) -NOLOGO -MANIFEST '$(win_srcdir)/$@.manifest' -OUTPUTRESOURCE:$@\;$(EMBED_MANIFEST_AT); \
+ fi
+endif # EMBED_MANIFEST_AT
+endif # MSVC with manifest tool
+ifdef MOZ_PROFILE_GENERATE
+ touch -t `date +%Y%m%d%H%M.%S -d 'now+5seconds'` pgo.relink
+endif
+endif # WINNT && !GCC
+ chmod +x $@
+ifdef ENABLE_STRIP
+ $(STRIP) $(STRIP_FLAGS) $@
+endif
+
+# 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 $2$(notdir $1)).$(OBJ_SUFFIX): $1 $$(call mkdir_deps,$$(MDDEPDIR))
+endef
+$(foreach f,$(CSRCS) $(SSRCS) $(CPPSRCS) $(CMSRCS) $(CMMSRCS) $(ASFILES),$(eval $(call src_objdep,$(f))))
+$(foreach f,$(HOST_CSRCS) $(HOST_CPPSRCS) $(HOST_CMSRCS) $(HOST_CMMSRCS),$(eval $(call src_objdep,$(f),host_)))
+
+# The Rust compiler only outputs library objects, and so we need different
+# mangling to generate dependency rules for it.
+mk_libname = $(basename lib$(notdir $1)).rlib
+src_libdep = $(call mk_libname,$1): $1 $$(call mkdir_deps,$$(MDDEPDIR))
+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,$(RSSRCS),$(eval $(call src_libdep,$(f))))
+$(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)
+ $(ELOG) $(HOST_CC) $(HOST_OUTOPTION)$@ -c $(HOST_CPPFLAGS) $(HOST_CFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
+
+$(HOST_CPPOBJS):
+ $(REPORT_BUILD_VERBOSE)
+ $(call BUILDSTATUS,OBJECT_FILE $@)
+ $(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CPPFLAGS) $(HOST_CXXFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
+
+$(HOST_CMOBJS):
+ $(REPORT_BUILD_VERBOSE)
+ $(ELOG) $(HOST_CC) $(HOST_OUTOPTION)$@ -c $(HOST_CPPFLAGS) $(HOST_CFLAGS) $(HOST_CMFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
+
+$(HOST_CMMOBJS):
+ $(REPORT_BUILD_VERBOSE)
+ $(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CPPFLAGS) $(HOST_CXXFLAGS) $(HOST_CMMFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
+
+$(COBJS):
+ $(REPORT_BUILD_VERBOSE)
+ $(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $($(notdir $<)_FLAGS) $(_VPATH_SRCS)
+
+# DEFINES and ACDEFINES are needed here to enable conditional compilation of Q_OBJECTs:
+# 'moc' only knows about #defines it gets on the command line (-D...), not in
+# included headers like mozilla-config.h
+$(filter moc_%.cpp,$(CPPSRCS)): moc_%.cpp: %.h
+ $(REPORT_BUILD_VERBOSE)
+ $(ELOG) $(MOC) $(DEFINES) $(ACDEFINES) $< $(OUTOPTION)$@
+
+$(filter moc_%.cc,$(CPPSRCS)): moc_%.cc: %.cc
+ $(REPORT_BUILD_VERBOSE)
+ $(ELOG) $(MOC) $(DEFINES) $(ACDEFINES) $(_VPATH_SRCS:.cc=.h) $(OUTOPTION)$@
+
+$(filter qrc_%.cpp,$(CPPSRCS)): qrc_%.cpp: %.qrc
+ $(REPORT_BUILD_VERBOSE)
+ $(ELOG) $(RCC) -name $* $< $(OUTOPTION)$@
+
+ifdef ASFILES
+# The AS_DASH_C_FLAG is needed cause not all assemblers (Solaris) accept
+# a '-c' flag.
+$(ASOBJS):
+ $(REPORT_BUILD_VERBOSE)
+ $(AS) $(ASOUTOPTION)$@ $(ASFLAGS) $($(notdir $<)_FLAGS) $(AS_DASH_C_FLAG) $(_VPATH_SRCS)
+endif
+
+ifdef MOZ_RUST
+ifdef RUST_LIBRARY_FILE
+
+# Permit users to pass flags to cargo from their mozconfigs (e.g. --color=always).
+cargo_build_flags = $(CARGOFLAGS)
+ifndef MOZ_DEBUG
+cargo_build_flags = --release
+endif
+ifdef MOZ_CARGO_SUPPORTS_FROZEN
+cargo_build_flags += --frozen
+endif
+
+cargo_build_flags += --manifest-path $(CARGO_FILE)
+cargo_build_flags += --target=$(RUST_TARGET)
+cargo_build_flags += --verbose
+
+# 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)))
+cargo_build_flags += --color=always
+endif
+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-build:
+ $(REPORT_BUILD)
+ env CARGO_TARGET_DIR=. RUSTC=$(RUSTC) $(CARGO) build $(cargo_build_flags) --
+
+$(RUST_LIBRARY_FILE): force-cargo-build
+endif # CARGO_FILE
+endif # MOZ_RUST
+
+$(SOBJS):
+ $(REPORT_BUILD)
+ $(AS) -o $@ $(DEFINES) $(ASFLAGS) $($(notdir $<)_FLAGS) $(LOCAL_INCLUDES) -c $<
+
+$(CPPOBJS):
+ $(REPORT_BUILD_VERBOSE)
+ $(call BUILDSTATUS,OBJECT_FILE $@)
+ $(ELOG) $(CCC) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS) $($(notdir $<)_FLAGS) $(_VPATH_SRCS)
+
+$(CMMOBJS):
+ $(REPORT_BUILD_VERBOSE)
+ $(ELOG) $(CCC) -o $@ -c $(COMPILE_CXXFLAGS) $(COMPILE_CMMFLAGS) $($(notdir $<)_FLAGS) $(_VPATH_SRCS)
+
+$(CMOBJS):
+ $(REPORT_BUILD_VERBOSE)
+ $(ELOG) $(CC) -o $@ -c $(COMPILE_CFLAGS) $(COMPILE_CMFLAGS) $($(notdir $<)_FLAGS) $(_VPATH_SRCS)
+
+$(filter %.s,$(CPPSRCS:%.cpp=%.s)): %.s: %.cpp $(call mkdir_deps,$(MDDEPDIR))
+ $(REPORT_BUILD_VERBOSE)
+ $(CCC) -S $(COMPILE_CXXFLAGS) $($(notdir $<)_FLAGS) $(_VPATH_SRCS)
+
+$(filter %.s,$(CPPSRCS:%.cc=%.s)): %.s: %.cc $(call mkdir_deps,$(MDDEPDIR))
+ $(REPORT_BUILD_VERBOSE)
+ $(CCC) -S $(COMPILE_CXXFLAGS) $($(notdir $<)_FLAGS) $(_VPATH_SRCS)
+
+$(filter %.s,$(CPPSRCS:%.cxx=%.s)): %.s: %.cpp $(call mkdir_deps,$(MDDEPDIR))
+ $(REPORT_BUILD_VERBOSE)
+ $(CCC) -S $(COMPILE_CXXFLAGS) $($(notdir $<)_FLAGS) $(_VPATH_SRCS)
+
+$(filter %.s,$(CSRCS:%.c=%.s)): %.s: %.c $(call mkdir_deps,$(MDDEPDIR))
+ $(REPORT_BUILD_VERBOSE)
+ $(CC) -S $(COMPILE_CFLAGS) $($(notdir $<)_FLAGS) $(_VPATH_SRCS)
+
+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))))
+_PREPROCESSED_CPP_FILES := $(call _group_srcs,cpp,$(CPPSRCS))
+_PREPROCESSED_CC_FILES := $(call _group_srcs,cc,$(CPPSRCS))
+_PREPROCESSED_CXX_FILES := $(call _group_srcs,cxx,$(CPPSRCS))
+_PREPROCESSED_C_FILES := $(call _group_srcs,c,$(CSRCS))
+_PREPROCESSED_CMM_FILES := $(call _group_srcs,mm,$(CMMSRCS))
+
+# Hack up VPATH so we can reach the sources. Eg: 'make Parser.i' may need to
+# reach $(srcdir)/frontend/Parser.i
+VPATH += $(addprefix $(srcdir)/,$(sort $(dir $(CPPSRCS) $(CSRCS) $(CMMSRCS))))
+
+# Make preprocessed files PHONY so they are always executed, since they are
+# manual targets and we don't necessarily write to $@.
+.PHONY: $(_PREPROCESSED_CPP_FILES) $(_PREPROCESSED_CC_FILES) $(_PREPROCESSED_CXX_FILES) $(_PREPROCESSED_C_FILES) $(_PREPROCESSED_CMM_FILES)
+
+$(_PREPROCESSED_CPP_FILES): %.i: %.cpp $(call mkdir_deps,$(MDDEPDIR))
+ $(REPORT_BUILD_VERBOSE)
+ $(addprefix $(MKDIR) -p ,$(filter-out .,$(@D)))
+ $(CCC) -C $(PREPROCESS_OPTION)$@ $(COMPILE_CXXFLAGS) $($(notdir $<)_FLAGS) $(_VPATH_SRCS)
+
+$(_PREPROCESSED_CC_FILES): %.i: %.cc $(call mkdir_deps,$(MDDEPDIR))
+ $(REPORT_BUILD_VERBOSE)
+ $(addprefix $(MKDIR) -p ,$(filter-out .,$(@D)))
+ $(CCC) -C $(PREPROCESS_OPTION)$@ $(COMPILE_CXXFLAGS) $($(notdir $<)_FLAGS) $(_VPATH_SRCS)
+
+$(_PREPROCESSED_CXX_FILES): %.i: %.cxx $(call mkdir_deps,$(MDDEPDIR))
+ $(REPORT_BUILD_VERBOSE)
+ $(addprefix $(MKDIR) -p ,$(filter-out .,$(@D)))
+ $(CCC) -C $(PREPROCESS_OPTION)$@ $(COMPILE_CXXFLAGS) $($(notdir $<)_FLAGS) $(_VPATH_SRCS)
+
+$(_PREPROCESSED_C_FILES): %.i: %.c $(call mkdir_deps,$(MDDEPDIR))
+ $(REPORT_BUILD_VERBOSE)
+ $(addprefix $(MKDIR) -p ,$(filter-out .,$(@D)))
+ $(CC) -C $(PREPROCESS_OPTION)$@ $(COMPILE_CFLAGS) $($(notdir $<)_FLAGS) $(_VPATH_SRCS)
+
+$(_PREPROCESSED_CMM_FILES): %.i: %.mm $(call mkdir_deps,$(MDDEPDIR))
+ $(REPORT_BUILD_VERBOSE)
+ $(addprefix $(MKDIR) -p ,$(filter-out .,$(@D)))
+ $(CCC) -C $(PREPROCESS_OPTION)$@ $(COMPILE_CXXFLAGS) $(COMPILE_CMMFLAGS) $($(notdir $<)_FLAGS) $(_VPATH_SRCS)
+
+# 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
+
+$(RESFILE): %.res: %.rc
+ $(REPORT_BUILD)
+ @echo Creating Resource file: $@
+ifdef GNU_CC
+ $(RC) $(RCFLAGS) $(filter-out -U%,$(DEFINES)) $(INCLUDES:-I%=--include-dir %) $(OUTOPTION)$@ $(_VPATH_SRCS)
+else
+ $(RC) $(RCFLAGS) -r $(DEFINES) $(INCLUDES) $(OUTOPTION)$@ $(_VPATH_SRCS)
+endif
+
+# Cancel GNU make built-in implicit rules
+MAKEFLAGS += -r
+
+ifneq (,$(filter WINNT,$(OS_ARCH)))
+SEP := ;
+else
+SEP := :
+endif
+
+EMPTY :=
+SPACE := $(EMPTY) $(EMPTY)
+
+# MSYS has its own special path form, but javac expects the source and class
+# paths to be in the DOS form (i.e. e:/builds/...). This function does the
+# appropriate conversion on Windows, but is a noop on other systems.
+ifeq ($(HOST_OS_ARCH),WINNT)
+# We use 'pwd -W' to get DOS form of the path. However, since the given path
+# could be a file or a non-existent path, we cannot call 'pwd -W' directly
+# on the path. Instead, we extract the root path (i.e. "c:/"), call 'pwd -W'
+# on it, then merge with the rest of the path.
+root-path = $(shell echo $(1) | sed -e 's|\(/[^/]*\)/\?\(.*\)|\1|')
+non-root-path = $(shell echo $(1) | sed -e 's|\(/[^/]*\)/\?\(.*\)|\2|')
+normalizepath = $(foreach p,$(1),$(if $(filter /%,$(1)),$(patsubst %/,%,$(shell cd $(call root-path,$(1)) && pwd -W))/$(call non-root-path,$(1)),$(1)))
+else
+normalizepath = $(1)
+endif
+
+###############################################################################
+# Java rules
+###############################################################################
+ifneq (,$(JAVAFILES)$(ANDROID_RESFILES)$(ANDROID_APKNAME)$(JAVA_JAR_TARGETS))
+ include $(MOZILLA_DIR)/config/makefiles/java-build.mk
+endif
+
+###############################################################################
+# 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
+
+################################################################################
+# SDK
+
+ifneq (,$(SDK_LIBRARY))
+ifndef NO_DIST_INSTALL
+SDK_LIBRARY_FILES := $(SDK_LIBRARY)
+SDK_LIBRARY_DEST := $(SDK_LIB_DIR)
+SDK_LIBRARY_TARGET := target
+INSTALL_TARGETS += SDK_LIBRARY
+endif
+endif # SDK_LIBRARY
+
+################################################################################
+# 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
+
+libs realchrome:: $(FINAL_TARGET)/chrome
+ $(call py_action,jar_maker,\
+ $(QUIET) -d $(FINAL_TARGET) \
+ $(MAKE_JARS_FLAGS) $(DEFINES) $(ACDEFINES) \
+ $(JAR_MANIFEST))
+
+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::
+ifdef STRIP_XPI
+ifndef MOZ_DEBUG
+ @echo 'Stripping $(XPI_PKGNAME) package directory...'
+ @echo $(FINAL_TARGET)
+ @cd $(FINAL_TARGET) && find . ! -type d \
+ ! -name '*.js' \
+ ! -name '*.xpt' \
+ ! -name '*.gif' \
+ ! -name '*.jpg' \
+ ! -name '*.png' \
+ ! -name '*.xpm' \
+ ! -name '*.txt' \
+ ! -name '*.rdf' \
+ ! -name '*.sh' \
+ ! -name '*.properties' \
+ ! -name '*.dtd' \
+ ! -name '*.html' \
+ ! -name '*.xul' \
+ ! -name '*.css' \
+ ! -name '*.xml' \
+ ! -name '*.jar' \
+ ! -name '*.dat' \
+ ! -name '*.tbl' \
+ ! -name '*.src' \
+ ! -name '*.reg' \
+ $(PLATFORM_EXCLUDE_LIST) \
+ -exec $(STRIP) $(STRIP_FLAGS) {} >/dev/null 2>&1 \;
+endif
+endif
+ @echo 'Packaging $(XPI_PKGNAME).xpi...'
+ $(call py_action,zip,-C $(FINAL_TARGET) ../$(XPI_PKGNAME).xpi '*')
+endif
+
+# See comment above about moving this out of the tools tier.
+ifdef INSTALL_EXTENSION_ID
+ifndef XPI_NAME
+$(error XPI_NAME must be set for INSTALL_EXTENSION_ID)
+endif
+
+tools::
+ $(RM) -r '$(DIST)/bin/distribution$(DIST_SUBDIR:%=/%)/extensions/$(INSTALL_EXTENSION_ID)'
+ $(NSINSTALL) -D '$(DIST)/bin/distribution$(DIST_SUBDIR:%=/%)/extensions/$(INSTALL_EXTENSION_ID)'
+ $(call copy_dir,$(FINAL_TARGET),$(DIST)/bin/distribution$(DIST_SUBDIR:%=/%)/extensions/$(INSTALL_EXTENSION_ID))
+
+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.
+
+ifneq (,$(filter-out all chrome default export realchrome clean clobber clobber_all distclean realclean,$(MAKECMDGOALS)))
+MDDEPEND_FILES := $(strip $(wildcard $(addprefix $(MDDEPDIR)/,$(addsuffix .pp,$(notdir $(sort $(OBJS) $(PROGOBJS) $(HOST_OBJS) $(HOST_PROGOBJS)))))))
+
+ifneq (,$(MDDEPEND_FILES))
+-include $(MDDEPEND_FILES)
+endif
+
+endif
+
+MDDEPEND_FILES := $(strip $(wildcard $(addprefix $(MDDEPDIR)/,$(EXTRA_MDDEPEND_FILES))))
+
+ifneq (,$(MDDEPEND_FILES))
+-include $(MDDEPEND_FILES)
+endif
+
+#############################################################################
+
+-include $(topsrcdir)/$(MOZ_BUILD_APP)/app-rules.mk
+-include $(MY_RULES)
+
+#
+# Generate Emacs tags in a file named TAGS if ETAGS was set in $(MY_CONFIG)
+# or in $(MY_RULES)
+#
+ifdef ETAGS
+ifneq ($(CSRCS)$(CPPSRCS)$(HEADERS),)
+all:: TAGS
+TAGS:: $(CSRCS) $(CPPSRCS) $(HEADERS)
+ $(ETAGS) $(CSRCS) $(CPPSRCS) $(HEADERS)
+endif
+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 $(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 install_cmd,$(IFLAGS1) '$<' '$(@D)')
+
+$(sort $(foreach tier,$(INSTALL_TARGETS_TIERS),$(INSTALL_TARGETS_EXECUTABLES_$(tier)))):
+ $(install_targets_sanity)
+ $(call install_cmd,$(IFLAGS2) '$<' '$(@D)')
+
+################################################################################
+# 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 $(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,--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 checkout chrome realchrome clean clobber clobber_all export install libs makefiles realclean 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 #}
+
+documentation:
+ @cd $(DEPTH)
+ $(DOXYGEN) $(DEPTH)/config/doxygen.cfg
+
+ifdef ENABLE_TESTS
+check::
+ $(LOOP_OVER_DIRS)
+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)
+
+PURGECACHES_DIRS ?= $(DIST)/bin
+
+PURGECACHES_FILES = $(addsuffix /.purgecaches,$(PURGECACHES_DIRS))
+
+default all:: $(PURGECACHES_FILES)
+
+$(PURGECACHES_FILES):
+ if test -d $(@D) ; then touch $@ ; fi
+
+.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/static-checking-config.mk b/config/static-checking-config.mk
new file mode 100644
index 000000000..28c2c8998
--- /dev/null
+++ b/config/static-checking-config.mk
@@ -0,0 +1,12 @@
+# 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
+CLANG_PLUGIN := $(topobjdir)/build/clang-plugin/$(DLL_PREFIX)clang-plugin$(DLL_SUFFIX)
+OS_CXXFLAGS += -Xclang -load -Xclang $(CLANG_PLUGIN) -Xclang -add-plugin -Xclang moz-check
+OS_CFLAGS += -Xclang -load -Xclang $(CLANG_PLUGIN) -Xclang -add-plugin -Xclang moz-check
+endif
diff --git a/config/stl-headers b/config/stl-headers
new file mode 100644
index 000000000..d4786f1c9
--- /dev/null
+++ b/config/stl-headers
@@ -0,0 +1,49 @@
+#
+# This file contains a list 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".
+#
+
+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
+deque
+functional
+ios
+iosfwd
+iostream
+istream
+iterator
+limits
+list
+map
+memory
+ostream
+set
+stack
+string
+type_traits
+utility
+vector
+cassert
+climits
+cmath
+cstdarg
+cstdio
+cstdlib
+cstring
+cwchar
+tuple
+xutility
diff --git a/config/string-format.js b/config/string-format.js
new file mode 100644
index 000000000..7319eb859
--- /dev/null
+++ b/config/string-format.js
@@ -0,0 +1,65 @@
+/* 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/. */
+
+String.prototype.format = function string_format() {
+ // there are two modes of operation... unnamed indices are read in order;
+ // named indices using %(name)s. The two styles cannot be mixed.
+ // Unnamed indices can be passed as either a single argument to this function,
+ // multiple arguments to this function, or as a single array argument
+ let curindex = 0;
+ let d;
+
+ if (arguments.length > 1) {
+ d = arguments;
+ }
+ else
+ d = arguments[0];
+
+ function r(s, key, type) {
+ if (type == '%')
+ return '%';
+
+ let v;
+ if (key == "") {
+ if (curindex == -1)
+ throw Error("Cannot mix named and positional indices in string formatting.");
+
+ if (curindex == 0 && (!(d instanceof Object) || !(0 in d))) {
+ v = d;
+ }
+ else if (!(curindex in d))
+ throw Error("Insufficient number of items in format, requesting item %i".format(curindex));
+ else {
+ v = d[curindex];
+ }
+
+ ++curindex;
+ }
+ else {
+ key = key.slice(1, -1);
+ if (curindex > 0)
+ throw Error("Cannot mix named and positional indices in string formatting.");
+ curindex = -1;
+
+ if (!(key in d))
+ throw Error("Key '%s' not present during string substitution.".format(key));
+ v = d[key];
+ }
+ switch (type) {
+ case "s":
+ if (v === undefined)
+ return "<undefined>";
+ return v.toString();
+ case "r":
+ return uneval(v);
+ case "i":
+ return parseInt(v);
+ case "f":
+ return Number(v);
+ default:
+ throw Error("Unexpected format character '%s'.".format(type));
+ }
+ }
+ return this.replace(/%(\([^)]+\))?(.)/g, r);
+};
diff --git a/config/system-headers b/config/system-headers
new file mode 100644
index 000000000..be3162f58
--- /dev/null
+++ b/config/system-headers
@@ -0,0 +1,1337 @@
+nspr.h
+plarena.h
+plarenas.h
+plbase64.h
+plerror.h
+plgetopt.h
+plhash.h
+plstr.h
+pratom.h
+prbit.h
+prclist.h
+prcmon.h
+prcountr.h
+prcpucfg.h
+prcvar.h
+prdtoa.h
+prenv.h
+prerr.h
+prerror.h
+prinet.h
+prinit.h
+prinrval.h
+prio.h
+pripcsem.h
+private
+prlink.h
+prlock.h
+prlog.h
+prlong.h
+prmem.h
+prmon.h
+prmwait.h
+prnetdb.h
+prolock.h
+prpdce.h
+prprf.h
+prproces.h
+prrng.h
+prrwlock.h
+prshm.h
+prshma.h
+prsystem.h
+prthread.h
+prtime.h
+prtpool.h
+prtrace.h
+prtypes.h
+prvrsion.h
+prwin16.h
+base64.h
+blapit.h
+cert.h
+certdb.h
+certt.h
+ciferfam.h
+cmmf.h
+cmmft.h
+cms.h
+cmsreclist.h
+cmst.h
+crmf.h
+crmft.h
+cryptohi.h
+cryptoht.h
+ecl-exp.h
+hasht.h
+jar-ds.h
+jar.h
+jarfile.h
+key.h
+keyhi.h
+keyt.h
+keythi.h
+nss.h
+nssb64.h
+nssb64t.h
+nssbase.h
+nssbaset.h
+nssck.api
+nssckbi.h
+nssckepv.h
+nssckft.h
+nssckfw.h
+nssckfwc.h
+nssckfwt.h
+nssckg.h
+nssckmdt.h
+nssckt.h
+nssilckt.h
+nssilock.h
+nsslocks.h
+nssrwlk.h
+nssrwlkt.h
+nssutil.h
+ocsp.h
+ocspt.h
+p12.h
+p12plcy.h
+p12t.h
+pk11func.h
+pk11pqg.h
+pk11priv.h
+pk11pub.h
+pk11sdr.h
+pkcs11.h
+pkcs11f.h
+pkcs11n.h
+pkcs11p.h
+pkcs11t.h
+pkcs11u.h
+pkcs12.h
+pkcs12t.h
+pkcs7t.h
+portreg.h
+preenc.h
+secasn1.h
+secasn1t.h
+seccomon.h
+secder.h
+secdert.h
+secdig.h
+secdigt.h
+secerr.h
+sechash.h
+secitem.h
+secmime.h
+secmod.h
+secmodt.h
+secoid.h
+secoidt.h
+secpkcs5.h
+secpkcs7.h
+secport.h
+shsign.h
+smime.h
+ssl.h
+sslerr.h
+sslproto.h
+sslt.h
+utilmodt.h
+utilpars.h
+utilparst.h
+utilrename.h
+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
+#ifdef ANDROID
+android/ashmem.h
+android/log.h
+android/looper.h
+android/native_window.h
+android_audio/AudioSystem.h
+#endif
+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
+ATSTypes.h
+ATSUnicode.h
+#ifdef ANDROID
+audio_effects/effect_aec.h
+audio_effects/effect_ns.h
+AudioParameter.h
+AudioSystem.h
+AudioTrack.h
+avc_utils.h
+#endif
+Balloons.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
+#ifdef ANDROID
+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
+#endif
+Bitmap.h
+bitset
+blapi.h
+bsd/libc.h
+bsd/syscall.h
+bstring.h
+builtin.h
+Button.h
+byteswap.h
+pixman.h
+cairo.h
+cairo-atsui.h
+cairo-beos.h
+cairo-ft.h
+cairo-glitz.h
+cairo-gobject.h
+cairo-pdf.h
+cairo-ps.h
+cairo-tee.h
+cairo-quartz.h
+cairo-win32.h
+cairo-xlib.h
+cairo-xlib-xrender.h
+cairo-directfb.h
+cairo-qpainter.h
+cairo-qt.h
+complex
+dfiff.h
+exception
+ffi.h
+fusion/reactor.h
+fusion/property.h
+fusion/conf.h
+fusion/build.h
+fusion/hash.h
+fusion/shm/shm.h
+fusion/shm/shm_internal.h
+fusion/shm/pool.h
+fusion/ref.h
+fusion/fusion_internal.h
+fusion/lock.h
+fusion/types.h
+fusion/vector.h
+fusion/call.h
+fusion/shmalloc.h
+fusion/protocol.h
+fusion/fusion.h
+fusion/arena.h
+fusion/object.h
+dgiff.h
+direct/util.h
+direct/memcpy.h
+direct/interface.h
+direct/conf.h
+direct/tree.h
+direct/signals.h
+direct/build.h
+direct/interface_implementation.h
+direct/utf8.h
+direct/serial.h
+direct/hash.h
+direct/direct.h
+direct/clock.h
+direct/types.h
+direct/mem.h
+direct/thread.h
+direct/debug.h
+direct/stream.h
+direct/messages.h
+direct/trace.h
+direct/modules.h
+direct/log.h
+direct/system.h
+direct/list.h
+dfb_types.h
+directfb_strings.h
+directfb_keyboard.h
+callconv.h
+#ifdef ANDROID
+camera/Camera.h
+camera/CameraParameters.h
+#endif
+Carbon/Carbon.h
+CarbonEvents.h
+Carbon.h
+c_asm.h
+cctype
+cderr.h
+cerrno
+CFBase.h
+CFBundle.h
+CFData.h
+CFDictionary.h
+cf.h
+CFNumber.h
+CFPlugIn.h
+CFPreferences.h
+CFString.h
+CFURL.h
+CGAffineTransform.h
+CheckBox.h
+Clipboard.h
+cmplrs/stsupport.h
+Cocoa/Cocoa.h
+CodeFragments.h
+#ifdef ANDROID
+ColorConverter.h
+#endif
+comdef.h
+commctrl.h
+COMMCTRL.H
+commdlg.h
+compat.h
+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
+cstddef
+ctime
+ctype.h
+curl/curl.h
+curl/easy.h
+curses.h
+#ifdef ANDROID
+cutils/android_reboot.h
+cutils/atomic.h
+cutils/compiler.h
+cutils/log.h
+cutils/native_handle.h
+cutils/properties.h
+cutils/sockets.h
+#endif
+cxxabi.h
+DateTimeUtils.h
+dbus/dbus.h
+dbus/dbus-glib.h
+dbus/dbus-glib-lowlevel.h
+ddeml.h
+Debug.h
+dem.h
+descrip.h
+Devices.h
+Dialogs.h
+direct.h
+dirent.h
+DiskInit.h
+dlfcn.h
+dlgs.h
+dl.h
+#ifdef MOZ_WIDGET_GONK
+dns_sd.h
+#endif
+docobj.h
+dos/dosextens.h
+dos.h
+Drag.h
+DriverServices.h
+DriverSynchronization.h
+DropInPanel.h
+dvidef.h
+elf.h
+endian.h
+Entry.h
+errno.h
+Errors.h
+Events.h
+exdisp.h
+ExDisp.h
+exe386.h
+execinfo.h
+extras.h
+fcntl.h
+features.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/fontconfig.h
+fontconfig/fcfreetype.h
+Font.h
+Fonts.h
+#ifdef ANDROID
+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
+#endif
+fp.h
+fpieee.h
+frame/log.h
+frame/req.h
+freetype/freetype.h
+freetype/ftcache.h
+freetype/ftfntfmt.h
+freetype/ftglyph.h
+freetype/ftsynth.h
+freetype/ftoutln.h
+freetype/ttnameid.h
+freetype/tttables.h
+freetype/t1tables.h
+freetype/ftlcdfil.h
+freetype/ftsizes.h
+freetype/ftadvanc.h
+freetype/ftbitmap.h
+freetype/ftxf86.h
+freetype.h
+ftcache.h
+ftfntfmt.h
+ftglyph.h
+ftsynth.h
+ftoutln.h
+ttnameid.h
+tttables.h
+t1tables.h
+ftlcdfil.h
+ftsizes.h
+ftadvanc.h
+ftbitmap.h
+ftxf86.h
+fribidi/fribidi.h
+FSp_fopen.h
+fstream
+fstream.h
+ft2build.h
+fts.h
+gconf/gconf-client.h
+Gdiplus.h
+gdk/gdk.h
+gdk/gdkkeysyms.h
+gdk/gdkprivate.h
+gdk/gdkx.h
+gdk/gdkdirectfb.h
+gdk-pixbuf/gdk-pixbuf.h
+Gestalt.h
+getopt.h
+glibconfig.h
+glib.h
+glib-object.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
+gtk/gtk.h
+gtk/gtkx.h
+gtk/gtkunixprint.h
+#ifdef ANDROID
+gui/BufferQueue.h
+gui/ConsumerBase.h
+gui/GraphicBufferAlloc.h
+gui/IConsumerListener.h
+gui/IGraphicBufferAlloc.h
+gui/IGraphicBufferProducer.h
+gui/ISurfaceComposer.h
+gui/ISurfaceComposerClient.h
+gui/ISurfaceTexture.h
+gui/Surface.h
+gui/SurfaceComposerClient.h
+gui/SurfaceTextureClient.h
+hardware/audio.h
+hardware/gralloc.h
+hardware/hardware.h
+hardware/hwcomposer.h
+hardware/lights.h
+hardware/power.h
+hardware_legacy/power.h
+hardware_legacy/uevent.h
+hardware_legacy/vibrator.h
+#endif
+HIToolbox/HIToolbox.h
+hlink.h
+#ifdef ANDROID
+HTTPBase.h
+#endif
+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
+#if MOZ_JACK==1
+jack/jack.h
+jack/statistics.h
+#endif
+JavaControl.h
+JavaEmbedding/JavaControl.h
+JavaVM/jni.h
+JManager.h
+JNIEnvTests.h
+jni.h
+#if MOZ_SYSTEM_JPEG==1
+jpeglib.h
+#endif
+JVMManagerTests.h
+Kerberos/Kerberos.h
+kernel/image.h
+kernel/OS.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
+limits.h
+link.h
+#ifdef ANDROID
+linux/android_alarm.h
+linux/ashmem.h
+#endif
+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
+#ifdef ANDROID
+android/native_window.h
+android/native_window_jni.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/MediaBuffer.h
+media/stagefright/MediaBufferGroup.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
+#endif
+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
+nsswitch.h
+objbase.h
+objidl.h
+Objsafe.h
+ojiapitests.h
+ole2.h
+oleidl.h
+#ifdef ANDROID
+OMX.h
+OMX_Component.h
+#endif
+OpenGL/OpenGL.h
+OpenTptInternet.h
+OpenTransport.h
+OS.h
+osreldate.h
+OSUtils.h
+Packages.h
+Palettes.h
+PALM_CMN.H
+pango/pango-modules.h
+pango/pangocairo.h
+pango/pangofc-decoder.h
+pango/pangofc-font.h
+pango/pangofc-fontmap.h
+pango/pango-break.h
+pango/pango-fontmap.h
+pango/pango.h
+pango/pangoxft.h
+pango/pango-utils.h
+pascal.h
+Patches.h
+Path.h
+pcfs/pc_dir.h
+Pgenerr.h
+PGenErr.h
+Ph.h
+PLStringFuncs.h
+PMApplication.h
+pmddim.h
+poll.h
+Polygon.h
+portable.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
+Printing.h
+Print/PMPrintingDialogExtensions.h
+#ifdef ANDROID
+private/android_filesystem_config.h
+private/qucomextra_p.h
+#endif
+Processes.h
+process.h
+Process.h
+proto/dos.h
+proto/exec.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
+rasdlg.h
+raserror.h
+ras.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
+sched.h
+Scrap.h
+Screen.h
+Script.h
+ScrollBar.h
+sec.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
+sigcontext.h
+signal.h
+SimpleGameSound.h
+SIOUX.h
+size_t.h
+sndio.h
+someincludefile.h
+Sound.h
+soundcard.h
+sqlite3.h
+sstream
+#ifdef ANDROID
+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/MediaBuffer.h
+stagefright/MediaBufferGroup.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/OMXCodec.h
+stagefright/OMXClient.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
+#endif
+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
+#ifdef ANDROID
+suspend/autosuspend.h
+#endif
+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/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/system_properties.h
+sys/systeminfo.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/utsname.h
+sys/vfs.h
+sys/wait.h
+#ifdef ANDROID
+sysutils/NetlinkEvent.h
+system/audio.h
+system/graphics.h
+system/window.h
+#endif
+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
+typeinfo
+types.h
+Types.h
+UAppleEventsMgr.h
+UAttachments.h
+ucontext.h
+uconv.h
+UCursor.h
+ucx$inetdef.h
+UDebugging.h
+UDesktop.h
+UDrawingState.h
+UDrawingUtils.h
+UEnvironment.h
+UEventMgr.h
+UException.h
+UExtractFromAEDesc.h
+UGWorld.h
+#ifdef ANDROID
+ui/ANativeObjectBase.h
+ui/egl/android_natives.h
+ui/Fence.h
+ui/FramebufferNativeWindow.h
+ui/GraphicBuffer.h
+ui/Rect.h
+ui/Region.h
+#endif
+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
+UPrinting.h
+UQuickTime.h
+UReanimator.h
+URegions.h
+URegistrar.h
+UResourceMgr.h
+#ifdef ANDROID
+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/threads.h
+utils/TextOutput.h
+utils/Timers.h
+utils/Trace.h
+utils/TypeHelpers.h
+utils/Unicode.h
+utils/Vector.h
+utils/VectorImpl.h
+#endif
+urlhist.h
+urlmon.h
+UScrap.h
+UScreenPort.h
+UTCUtils.h
+UTETextAction.h
+UTEViewTextAction.h
+UTextEdit.h
+UTextTraits.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
+xcb/xcb.h
+xcb/shm.h
+X11/cursorfont.h
+X11/extensions/Print.h
+X11/extensions/shape.h
+X11/extensions/scrnsaver.h
+X11/extensions/XShm.h
+X11/extensions/Xrender.h
+X11/extensions/Xfixes.h
+X11/extensions/Xdamage.h
+X11/extensions/Xcomposite.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
+zmouse.h
+soundtouch/SoundTouch.h
+soundtouch/SoundTouchFactory.h
+#if MOZ_LIBAV_FFT==1
+libavcodec/avfft.h
+#endif
+#if MOZ_SYSTEM_PNG==1
+png.h
+#endif
+#if MOZ_SYSTEM_ZLIB==1
+zlib.h
+#endif
+#ifdef MOZ_ENABLE_STARTUP_NOTIFICATION
+libsn/sn.h
+libsn/sn-common.h
+libsn/sn-launchee.h
+libsn/sn-launcher.h
+libsn/sn-monitor.h
+libsn/sn-util.h
+#endif
+#if MOZ_SYSTEM_HUNSPELL==1
+hunspell.hxx
+#endif
+#if MOZ_SYSTEM_BZ2==1
+bzlib.h
+#endif
+#ifdef MOZ_ENABLE_GIO
+gio/gio.h
+#endif
+#if MOZ_SYSTEM_LIBEVENT==1
+event.h
+#else
+sys/event.h
+#endif
+#ifdef MOZ_ENABLE_LIBPROXY
+proxy.h
+#endif
+#ifdef MOZ_ENABLE_CONTENTMANAGER
+SelectSingleContentItemPage.h
+SelectMultipleContentItemsPage.h
+QtSparql/qsparqlconnection.h
+QtSparql/qsparqlquery.h
+QtSparql/qsparqlresult.h
+#endif
+
+#if MOZ_TREE_PIXMAN!=1
+pixman.h
+#endif
+#if MOZ_SYSTEM_LIBVPX==1
+vpx/svc_context.h
+vpx/vpx_codec.h
+vpx/vpx_decoder.h
+vpx/vpx_encoder.h
+vpx/vp8cx.h
+vpx/vp8dx.h
+vpx_mem/vpx_mem.h
+#endif
+gst/gst.h
+gst/app/gstappsink.h
+gst/app/gstappsrc.h
+gst/video/video.h
+sys/msg.h
+sys/ipc.h
+sys/thr.h
+sys/user.h
+kvm.h
+spawn.h
+err.h
+xlocale.h
+#ifdef MOZ_SYSTEM_ICU
+unicode/locid.h
+unicode/numsys.h
+unicode/timezone.h
+unicode/ucal.h
+unicode/uchar.h
+unicode/uclean.h
+unicode/ucol.h
+unicode/udat.h
+unicode/udatpg.h
+unicode/uenum.h
+unicode/unorm.h
+unicode/unum.h
+unicode/ustring.h
+unicode/utypes.h
+#endif
+libutil.h
+unwind.h
+fenv.h
diff --git a/config/tests/chrome.manifest.flat b/config/tests/chrome.manifest.flat
new file mode 100644
index 000000000..6c0a7e536
--- /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/makefiles/autodeps/Makefile.in b/config/tests/makefiles/autodeps/Makefile.in
new file mode 100644
index 000000000..ea21c5a8e
--- /dev/null
+++ b/config/tests/makefiles/autodeps/Makefile.in
@@ -0,0 +1,36 @@
+# -*- 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/.
+#
+
+export STANDALONE_MAKEFILE=1
+PYTHON ?= python
+PYTEST = $(PYTHON) -E
+
+# python -B not supported by older interpreters
+export PYTHONDONTWRITEBYTECODE=1
+
+include $(topsrcdir)/config/rules.mk
+
+autotgt_tests = .deps/autotargets.mk.ts
+
+tgts =\
+ .deps/.mkdir.done\
+ $(autotgt_tests)
+ $(NULL)
+
+export MAKE
+
+##------------------_##
+##---] TARGETS [---##
+##------------------_##
+all::
+
+check:: $(tgts)
+
+# Only run unit test when autotargets.mk is modified
+$(autotgt_tests): $(topsrcdir)/config/makefiles/autotargets.mk
+ $(PYTEST) $(srcdir)/check_mkdir.tpy
+ @$(TOUCH) $@
diff --git a/config/tests/makefiles/autodeps/check_mkdir.tpy b/config/tests/makefiles/autodeps/check_mkdir.tpy
new file mode 100644
index 000000000..ad633c781
--- /dev/null
+++ b/config/tests/makefiles/autodeps/check_mkdir.tpy
@@ -0,0 +1,269 @@
+#!/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/.
+#
+
+import os
+import sys
+import tempfile
+
+from subprocess import call
+from shutil import rmtree
+
+import logging
+import unittest
+
+
+def banner():
+ """
+ Display interpreter and system info for the test env
+ """
+ print '*' * 75
+ cmd = os.path.basename(__file__)
+ print "%s: python version is %s" % (cmd, sys.version)
+ print '*' * 75
+
+
+def myopts(vals):
+ """
+ Storage for extra command line args passed.
+
+ Returns:
+ hash - argparse::Namespace object values
+ """
+
+ if not hasattr(myopts, 'vals'):
+ if 'argparse' in sys.modules:
+ tmp = { } # key existance enables unittest module debug
+ else:
+ tmp = { 'debug': False, 'verbose': False }
+
+ for k in dir(vals):
+ if k[0:1] == '_':
+ continue
+ tmp[k] = getattr(vals, k)
+ myopts.vals = tmp
+
+ return myopts.vals
+
+
+def path2posix(src):
+ """
+ Normalize directory path syntax
+
+ Keyword arguments:
+ src - path to normalize
+
+ Returns:
+ scalar - a file path with drive separators and windows slashes removed
+
+ Todo:
+ move to {build,config,tools,toolkit}/python for use in a library
+ """
+
+ ## (drive, tail) = os.path.splitdrive(src)
+ ## Support path testing on all platforms
+ drive = ''
+ winpath = src.find(':')
+ if -1 != winpath and 10 > winpath:
+ (drive, tail) = src.split(':', 1)
+
+ if drive:
+ todo = [ '', drive.rstrip(':').lstrip('/').lstrip('\\') ]
+ todo.extend( tail.lstrip('/').lstrip('\\').split('\\') ) # c:\a => [a]
+ else: # os.name == 'posix'
+ todo = src.split('\\')
+
+ dst = '/'.join(todo)
+ return dst
+
+
+def checkMkdir(work, debug=False):
+ """
+ Verify arg permutations for directory mutex creation.
+
+ Keyword arguments:
+ None
+
+ Returns:
+ Exception on error
+
+ Note:
+ Exception() rather than self.assertTrue() is used in this test
+ function to enable scatch cleanup on test exit/failure conditions.
+ Not guaranteed by python closures on early exit.
+ """
+
+ logging.debug("Testing: checkMkdir")
+
+ # On Windows, don't convert paths to POSIX
+ skipposix = sys.platform == "win32"
+ if skipposix:
+ path = os.path.abspath(__file__)
+ dirname_fun = os.path.dirname
+ else:
+ path = path2posix(os.path.abspath(__file__))
+ import posixpath
+ dirname_fun = posixpath.dirname
+
+ src = dirname_fun(path)
+ # root is 5 directories up from path
+ root = reduce(lambda x, _: dirname_fun(x), xrange(5), path)
+
+ rootP = path2posix(root)
+ srcP = path2posix(src)
+ workP = path2posix(work)
+
+ # C:\foo -vs- /c/foo
+ # [0] command paths use /c/foo
+ # [1] os.path.exists() on mingw() requires C:\
+ paths = [
+ "mkdir_bycall", # function generated
+ "mkdir_bydep", # explicit dependency
+ "mkdir_bygen", # by GENERATED_DIRS macro
+ ]
+
+ ## Use make from the parent "make check" call when available
+ cmd = { 'make': 'make' }
+ shell0 = os.environ.get('MAKE')
+ if shell0:
+ shell = os.path.splitext(shell0)[0] # strip: .exe, .py
+ if -1 != shell.find('make'):
+ print "MAKE COMMAND FOUND: %s" % (shell0)
+ cmd['make'] = shell0 if skipposix else path2posix(shell0)
+
+ args = []
+ args.append('%s' % (cmd['make']))
+ args.append('-C %s' % (work if skipposix else workP))
+ args.append("-f %s/testor.tmpl" % (src if skipposix else srcP))
+ args.append('topsrcdir=%s' % (root if skipposix else rootP))
+ args.append('deps_mkdir_bycall=%s' % paths[0])
+ args.append('deps_mkdir_bydep=%s' % paths[1])
+ args.append('deps_mkdir_bygen=%s' % paths[2])
+ args.append('checkup') # target
+
+ # Call will fail on mingw with output redirected ?!?
+ if debug:
+ pass
+ if False: # if not debug:
+ args.append('>/dev/null')
+
+ cmd = '%s' % (' '.join(args))
+ logging.debug("Running: %s" % (cmd))
+ rc = call(cmd, shell=True)
+ if rc:
+ raise Exception("make failed ($?=%s): cmd=%s" % (rc, cmd))
+
+ for i in paths:
+ path = os.path.join(work, i)
+ logging.debug("Did testing mkdir(%s) succeed?" % (path))
+ if not os.path.exists(path):
+ raise Exception("Test path %s does not exist" % (path))
+
+
+def parseargs():
+ """
+ Support additional command line arguments for testing
+
+ Returns:
+ hash - arguments of interested parsed from the command line
+ """
+
+ opts = None
+ try:
+ import argparse2
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--debug',
+ action="store_true",
+ default=False,
+ help='Enable debug mode')
+ # Cannot overload verbose, Verbose: False enables debugging
+ parser.add_argument('--verbose',
+ action="store_true",
+ default=False,
+ help='Enable verbose mode')
+ parser.add_argument('unittest_args',
+ nargs='*'
+ # help='Slurp/pass remaining args to unittest'
+ )
+ opts = parser.parse_args()
+
+ except ImportError:
+ pass
+
+ return opts
+
+
+class TestMakeLogic(unittest.TestCase):
+ """
+ Test suite used to validate makefile library rules and macros
+ """
+
+ def setUp(self):
+ opts = myopts(None) # NameSpace object not hash
+ self.debug = opts['debug']
+ self.verbose = opts['verbose']
+
+ if self.debug:
+ logging.basicConfig(level=logging.DEBUG)
+
+ if self.verbose:
+ print
+ print "ENVIRONMENT DUMP:"
+ print '=' * 75
+ for k,v in os.environ.items():
+ print "env{%s} => %s" % (k, v)
+ print
+
+
+ def test_path2posix(self):
+
+ todo = {
+ '/dev/null' : '/dev/null',
+ 'A:\\a\\b\\c' : '/A/a/b/c',
+ 'B:/x/y' : '/B/x/y',
+ 'C:/x\\y/z' : '/C/x/y/z',
+ '//FOO/bar/tans': '//FOO/bar/tans',
+ '//X\\a/b\\c/d' : '//X/a/b/c/d',
+ '\\c:mozilla\\sandbox': '/c/mozilla/sandbox',
+ }
+
+ for val,exp in todo.items():
+ found = path2posix(val)
+ tst = "posix2path(%s): %s != %s)" % (val, exp, found)
+ self.assertEqual(exp, found, "%s: invalid path detected" % (tst))
+
+
+ def test_mkdir(self):
+ """
+ Verify directory creation rules and macros
+ """
+
+ failed = True
+
+ # Exception handling is used to cleanup scratch space on error
+ try:
+ work = tempfile.mkdtemp()
+ checkMkdir(work, self.debug)
+ failed = False
+ finally:
+ if os.path.exists(work):
+ rmtree(work)
+
+ self.assertFalse(failed, "Unit test failure detected")
+
+
+if __name__ == '__main__':
+ banner()
+ opts = parseargs()
+ myopts(opts)
+
+ if opts:
+ if hasattr(opts, 'unittest_args'):
+ sys.argv[1:] = opts.unittest_args
+ else:
+ sys.argv[1:] = []
+
+ unittest.main()
diff --git a/config/tests/makefiles/autodeps/moz.build b/config/tests/makefiles/autodeps/moz.build
new file mode 100644
index 000000000..28919c271
--- /dev/null
+++ b/config/tests/makefiles/autodeps/moz.build
@@ -0,0 +1,6 @@
+# -*- 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/.
+
diff --git a/config/tests/makefiles/autodeps/testor.tmpl b/config/tests/makefiles/autodeps/testor.tmpl
new file mode 100644
index 000000000..3134277e6
--- /dev/null
+++ b/config/tests/makefiles/autodeps/testor.tmpl
@@ -0,0 +1,64 @@
+# -*- 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/.
+#
+
+###########################################################################
+## Intent: Standalone unit tests for makefile rules and target logic
+###########################################################################
+
+deps =$(NULL)
+tgts =$(NULL)
+
+ifdef VERBOSE
+ tgts += show
+endif
+
+# Define macros
+include $(topsrcdir)/config/makefiles/makeutils.mk
+include $(topsrcdir)/config/makefiles/autotargets.mk
+
+##########################
+## Verify threadsafe mkdir
+##########################
+ifdef deps_mkdir_bycall
+ deps += $(call mkdir_deps,deps_mkdir_bycall)
+ tgts += check_mkdir
+endif
+ifdef deps_mkdir_bydep
+ deps += $(foreach dir,$(deps_mkdir_bydep),$(dir)/.mkdir.done)
+ tgts += check_mkdir
+endif
+ifdef deps_mkdir_bygen
+ GENERATED_DIRS += $(deps_mkdir_bygen)
+ tgts += check_mkdir
+endif
+
+###########################
+## Minimal environment load
+###########################
+MKDIR ?= mkdir -p
+TOUCH ?= touch
+
+INCLUDED_CONFIG_MK = 1
+MOZILLA_DIR := $(topsrcdir)
+include $(topsrcdir)/config/rules.mk
+
+##-------------------##
+##---] TARGETS [---##
+##-------------------##
+all::
+
+# Quarks:
+# o Use of 'all' would trigger export target processing
+checkup: $(tgts)
+
+# AUTO_DEPS - verify GENERATED_DIRS
+check_mkdir: $(deps) $(AUTO_DEPS)
+
+show:
+ @echo "tgts=[$(tgts)]"
+ @echo "deps=[$(deps)]"
+ find $(dir $(deps)) -print
diff --git a/config/tests/ref-simple/one/file.xml b/config/tests/ref-simple/one/file.xml
new file mode 100644
index 000000000..21aacb9bd
--- /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 000000000..3e04d6329
--- /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 000000000..a8a3ee47c
--- /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 000000000..7ce7909ab
--- /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 000000000..6c50abf6f
--- /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 000000000..55fdfd867
--- /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 ! sort $(MY_MANIFEST) | diff --text -U 0 $(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 000000000..12ed607b6
--- /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 000000000..7ce7909ab
--- /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 000000000..eb4454d28
--- /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'] \ No newline at end of file
diff --git a/config/tests/src-simple/thesrcdir/file.xml b/config/tests/src-simple/thesrcdir/file.xml
new file mode 100644
index 000000000..21aacb9bd
--- /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 000000000..16d502418
--- /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 000000000..36171b4bb
--- /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 000000000..6c50abf6f
--- /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 000000000..0cf9dbf3a
--- /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 000000000..e2700dfbe
--- /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 000000000..0cf9dbf3a
--- /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 000000000..8bfcd9f4e
--- /dev/null
+++ b/config/tests/test_mozbuild_reading.py
@@ -0,0 +1,116 @@
+# 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 __future__ import unicode_literals
+
+import os
+import sys
+import unittest
+
+from mozunit import main
+
+from mozbuild.base import MozbuildObject
+from mozpack.files import FileFinder
+from mozbuild.frontend.context import Files
+from mozbuild.frontend.reader import (
+ BuildReader,
+ EmptyConfig,
+)
+
+
+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 e.message == '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, find_executables=False,
+ 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
+ if not pattern_exists(os.path.join(relsrcdir, ctx.pattern)):
+ self.fail("The pattern '%s' in a Files() entry in "
+ "'%s' corresponds to no files in the tree.\n"
+ "Please update this entry." %
+ (ctx.pattern, ctx.main_path))
+ test_files = ctx['IMPACTED_TESTS'].files
+ for p in test_files:
+ if not pattern_exists(os.path.relpath(p.full_path, config.topsrcdir)):
+ self.fail("The pattern '%s' in a dependent tests 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-expandlibs.py b/config/tests/unit-expandlibs.py
new file mode 100644
index 000000000..3c7e5a44d
--- /dev/null
+++ b/config/tests/unit-expandlibs.py
@@ -0,0 +1,431 @@
+import subprocess
+import unittest
+import sys
+import os
+import imp
+from tempfile import mkdtemp
+from shutil import rmtree
+import mozunit
+
+from UserString import UserString
+# Create a controlled configuration for use by expandlibs
+config_win = {
+ 'AR': 'lib',
+ 'AR_EXTRACT': '',
+ 'DLL_PREFIX': '',
+ 'LIB_PREFIX': '',
+ 'OBJ_SUFFIX': '.obj',
+ 'LIB_SUFFIX': '.lib',
+ 'DLL_SUFFIX': '.dll',
+ 'IMPORT_LIB_SUFFIX': '.lib',
+ 'LIBS_DESC_SUFFIX': '.desc',
+ 'EXPAND_LIBS_LIST_STYLE': 'list',
+}
+config_unix = {
+ 'AR': 'ar',
+ 'AR_EXTRACT': 'ar -x',
+ 'DLL_PREFIX': 'lib',
+ 'LIB_PREFIX': 'lib',
+ 'OBJ_SUFFIX': '.o',
+ 'LIB_SUFFIX': '.a',
+ 'DLL_SUFFIX': '.so',
+ 'IMPORT_LIB_SUFFIX': '',
+ 'LIBS_DESC_SUFFIX': '.desc',
+ 'EXPAND_LIBS_LIST_STYLE': 'linkerscript',
+}
+
+config = sys.modules['expandlibs_config'] = imp.new_module('expandlibs_config')
+
+from expandlibs import LibDescriptor, ExpandArgs, relativize
+from expandlibs_gen import generate
+from expandlibs_exec import ExpandArgsMore, SectionFinder
+
+def Lib(name):
+ return config.LIB_PREFIX + name + config.LIB_SUFFIX
+
+def Obj(name):
+ return name + config.OBJ_SUFFIX
+
+def Dll(name):
+ return config.DLL_PREFIX + name + config.DLL_SUFFIX
+
+def ImportLib(name):
+ if not len(config.IMPORT_LIB_SUFFIX): return Dll(name)
+ return config.LIB_PREFIX + name + config.IMPORT_LIB_SUFFIX
+
+class TestRelativize(unittest.TestCase):
+ def test_relativize(self):
+ '''Test relativize()'''
+ os_path_exists = os.path.exists
+ def exists(path):
+ return True
+ os.path.exists = exists
+ self.assertEqual(relativize(os.path.abspath(os.curdir)), os.curdir)
+ self.assertEqual(relativize(os.path.abspath(os.pardir)), os.pardir)
+ self.assertEqual(relativize(os.path.join(os.curdir, 'a')), 'a')
+ self.assertEqual(relativize(os.path.join(os.path.abspath(os.curdir), 'a')), 'a')
+ # relativize is expected to return the absolute path if it is shorter
+ self.assertEqual(relativize(os.sep), os.sep)
+ os.path.exists = os.path.exists
+
+class TestLibDescriptor(unittest.TestCase):
+ def test_serialize(self):
+ '''Test LibDescriptor's serialization'''
+ desc = LibDescriptor()
+ desc[LibDescriptor.KEYS[0]] = ['a', 'b']
+ self.assertEqual(str(desc), "{0} = a b".format(LibDescriptor.KEYS[0]))
+ desc['unsupported-key'] = ['a']
+ self.assertEqual(str(desc), "{0} = a b".format(LibDescriptor.KEYS[0]))
+ desc[LibDescriptor.KEYS[1]] = ['c', 'd', 'e']
+ self.assertEqual(str(desc),
+ "{0} = a b\n{1} = c d e"
+ .format(LibDescriptor.KEYS[0], LibDescriptor.KEYS[1]))
+ desc[LibDescriptor.KEYS[0]] = []
+ self.assertEqual(str(desc), "{0} = c d e".format(LibDescriptor.KEYS[1]))
+
+ def test_read(self):
+ '''Test LibDescriptor's initialization'''
+ desc_list = ["# Comment",
+ "{0} = a b".format(LibDescriptor.KEYS[1]),
+ "", # Empty line
+ "foo = bar", # Should be discarded
+ "{0} = c d e".format(LibDescriptor.KEYS[0])]
+ desc = LibDescriptor(desc_list)
+ self.assertEqual(desc[LibDescriptor.KEYS[1]], ['a', 'b'])
+ self.assertEqual(desc[LibDescriptor.KEYS[0]], ['c', 'd', 'e'])
+ self.assertEqual(False, 'foo' in desc)
+
+def wrap_method(conf, wrapped_method):
+ '''Wrapper used to call a test with a specific configuration'''
+ def _method(self):
+ for key in conf:
+ setattr(config, key, conf[key])
+ self.init()
+ try:
+ wrapped_method(self)
+ except:
+ raise
+ finally:
+ self.cleanup()
+ return _method
+
+class ReplicateTests(type):
+ '''Replicates tests for unix and windows variants'''
+ def __new__(cls, clsName, bases, dict):
+ for name in [key for key in dict if key.startswith('test_')]:
+ dict[name + '_unix'] = wrap_method(config_unix, dict[name])
+ dict[name + '_unix'].__doc__ = dict[name].__doc__ + ' (unix)'
+ dict[name + '_win'] = wrap_method(config_win, dict[name])
+ dict[name + '_win'].__doc__ = dict[name].__doc__ + ' (win)'
+ del dict[name]
+ return type.__new__(cls, clsName, bases, dict)
+
+class TestCaseWithTmpDir(unittest.TestCase):
+ __metaclass__ = ReplicateTests
+ def init(self):
+ self.tmpdir = os.path.abspath(mkdtemp(dir=os.curdir))
+
+ def cleanup(self):
+ rmtree(self.tmpdir)
+
+ def touch(self, files):
+ for f in files:
+ open(f, 'w').close()
+
+ def tmpfile(self, *args):
+ return os.path.join(self.tmpdir, *args)
+
+class TestExpandLibsGen(TestCaseWithTmpDir):
+ def test_generate(self):
+ '''Test library descriptor generation'''
+ files = [self.tmpfile(f) for f in
+ [Lib('a'), Obj('b'), Lib('c'), Obj('d'), Obj('e'), Lib('f')]]
+ self.touch(files[:-1])
+ self.touch([files[-1] + config.LIBS_DESC_SUFFIX])
+
+ desc = generate(files)
+ self.assertEqual(desc['OBJS'], [self.tmpfile(Obj(s)) for s in ['b', 'd', 'e']])
+ self.assertEqual(desc['LIBS'], [self.tmpfile(Lib(s)) for s in ['a', 'c', 'f']])
+
+ self.assertRaises(Exception, generate, files + [self.tmpfile(Obj('z'))])
+ self.assertRaises(Exception, generate, files + [self.tmpfile(Lib('y'))])
+
+class TestExpandInit(TestCaseWithTmpDir):
+ def init(self):
+ ''' Initializes test environment for library expansion tests'''
+ super(TestExpandInit, self).init()
+ # Create 2 fake libraries, each containing 3 objects, and the second
+ # including the first one and another library.
+ os.mkdir(self.tmpfile('libx'))
+ os.mkdir(self.tmpfile('liby'))
+ self.libx_files = [self.tmpfile('libx', Obj(f)) for f in ['g', 'h', 'i']]
+ self.liby_files = [self.tmpfile('liby', Obj(f)) for f in ['j', 'k', 'l']] + [self.tmpfile('liby', Lib('z'))]
+ self.touch(self.libx_files + self.liby_files)
+ with open(self.tmpfile('libx', Lib('x') + config.LIBS_DESC_SUFFIX), 'w') as f:
+ f.write(str(generate(self.libx_files)))
+ with open(self.tmpfile('liby', Lib('y') + config.LIBS_DESC_SUFFIX), 'w') as f:
+ f.write(str(generate(self.liby_files + [self.tmpfile('libx', Lib('x'))])))
+
+ # Create various objects and libraries
+ self.arg_files = [self.tmpfile(f) for f in [Lib('a'), Obj('b'), Obj('c'), Lib('d'), Obj('e')]]
+ # We always give library names (LIB_PREFIX/SUFFIX), even for
+ # dynamic/import libraries
+ self.files = self.arg_files + [self.tmpfile(ImportLib('f'))]
+ self.arg_files += [self.tmpfile(Lib('f'))]
+ self.touch(self.files)
+
+ def assertRelEqual(self, args1, args2):
+ self.assertEqual(args1, [relativize(a) for a in args2])
+
+class TestExpandArgs(TestExpandInit):
+ def test_expand(self):
+ '''Test library expansion'''
+ # Expanding arguments means libraries with a descriptor are expanded
+ # with the descriptor content, and import libraries are used when
+ # a library doesn't exist
+ args = ExpandArgs(['foo', '-bar'] + self.arg_files + [self.tmpfile('liby', Lib('y'))])
+ self.assertRelEqual(args, ['foo', '-bar'] + self.files + self.liby_files + self.libx_files)
+
+ # When a library exists at the same time as a descriptor, we still use
+ # the descriptor.
+ self.touch([self.tmpfile('libx', Lib('x'))])
+ args = ExpandArgs(['foo', '-bar'] + self.arg_files + [self.tmpfile('liby', Lib('y'))])
+ self.assertRelEqual(args, ['foo', '-bar'] + self.files + self.liby_files + self.libx_files)
+
+ self.touch([self.tmpfile('liby', Lib('y'))])
+ args = ExpandArgs(['foo', '-bar'] + self.arg_files + [self.tmpfile('liby', Lib('y'))])
+ self.assertRelEqual(args, ['foo', '-bar'] + self.files + self.liby_files + self.libx_files)
+
+class TestExpandArgsMore(TestExpandInit):
+ def test_makelist(self):
+ '''Test grouping object files in lists'''
+ # ExpandArgsMore does the same as ExpandArgs
+ with ExpandArgsMore(['foo', '-bar'] + self.arg_files + [self.tmpfile('liby', Lib('y'))]) as args:
+ self.assertRelEqual(args, ['foo', '-bar'] + self.files + self.liby_files + self.libx_files)
+
+ # But also has an extra method replacing object files with a list
+ args.makelist()
+ # self.files has objects at #1, #2, #4
+ self.assertRelEqual(args[:3], ['foo', '-bar'] + self.files[:1])
+ self.assertRelEqual(args[4:], [self.files[3]] + self.files[5:] + [self.tmpfile('liby', Lib('z'))])
+
+ # Check the list file content
+ objs = [f for f in self.files + self.liby_files + self.libx_files if f.endswith(config.OBJ_SUFFIX)]
+ if config.EXPAND_LIBS_LIST_STYLE == "linkerscript":
+ self.assertNotEqual(args[3][0], '@')
+ filename = args[3]
+ content = ['INPUT("{0}")'.format(relativize(f)) for f in objs]
+ with open(filename, 'r') as f:
+ self.assertEqual([l.strip() for l in f.readlines() if len(l.strip())], content)
+ elif config.EXPAND_LIBS_LIST_STYLE == "list":
+ self.assertEqual(args[3][0], '@')
+ filename = args[3][1:]
+ content = objs
+ with open(filename, 'r') as f:
+ self.assertRelEqual([l.strip() for l in f.readlines() if len(l.strip())], content)
+
+ tmp = args.tmp
+ # Check that all temporary files are properly removed
+ self.assertEqual(True, all([not os.path.exists(f) for f in tmp]))
+
+ def test_extract(self):
+ '''Test library extraction'''
+ # Divert subprocess.call
+ subprocess_call = subprocess.call
+ subprocess_check_output = subprocess.check_output
+ def call(args, **kargs):
+ if config.AR == 'lib':
+ self.assertEqual(args[:2], [config.AR, '-NOLOGO'])
+ self.assertTrue(args[2].startswith('-EXTRACT:'))
+ extract = [args[2][len('-EXTRACT:'):]]
+ self.assertTrue(extract)
+ args = args[3:]
+ else:
+ # The command called is always AR_EXTRACT
+ ar_extract = config.AR_EXTRACT.split()
+ self.assertEqual(args[:len(ar_extract)], ar_extract)
+ args = args[len(ar_extract):]
+ # Remaining argument is always one library
+ self.assertEqual(len(args), 1)
+ arg = args[0]
+ self.assertEqual(os.path.splitext(arg)[1], config.LIB_SUFFIX)
+ # Simulate file extraction
+ lib = os.path.splitext(os.path.basename(arg))[0]
+ if config.AR != 'lib':
+ extract = [lib, lib + '2']
+ extract = [os.path.join(kargs['cwd'], f) for f in extract]
+ if config.AR != 'lib':
+ extract = [Obj(f) for f in extract]
+ if not lib in extracted:
+ extracted[lib] = []
+ extracted[lib].extend(extract)
+ self.touch(extract)
+ subprocess.call = call
+
+ def check_output(args, **kargs):
+ # The command called is always AR
+ ar = config.AR
+ self.assertEqual(args[0:3], [ar, '-NOLOGO', '-LIST'])
+ # Remaining argument is always one library
+ self.assertRelEqual([os.path.splitext(arg)[1] for arg in args[3:]],
+[config.LIB_SUFFIX])
+ # Simulate LIB -NOLOGO -LIST
+ lib = os.path.splitext(os.path.basename(args[3]))[0]
+ return '%s\n%s\n' % (Obj(lib), Obj(lib + '2'))
+ subprocess.check_output = check_output
+
+ # ExpandArgsMore does the same as ExpandArgs
+ self.touch([self.tmpfile('liby', Lib('y'))])
+ for iteration in (1, 2):
+ with ExpandArgsMore(['foo', '-bar'] + self.arg_files + [self.tmpfile('liby', Lib('y'))]) as args:
+ files = self.files + self.liby_files + self.libx_files
+
+ self.assertRelEqual(args, ['foo', '-bar'] + files)
+
+ extracted = {}
+ # ExpandArgsMore also has an extra method extracting static libraries
+ # when possible
+ args.extract()
+
+ # With AR_EXTRACT, it uses the descriptors when there are, and
+ # actually
+ # extracts the remaining libraries
+ extracted_args = []
+ for f in files:
+ if f.endswith(config.LIB_SUFFIX):
+ base = os.path.splitext(os.path.basename(f))[0]
+ # On the first iteration, we test the behavior of
+ # extracting archives that don't have a copy of their
+ # contents next to them, which is to use the file
+ # extracted from the archive in a temporary directory.
+ # On the second iteration, we test extracting archives
+ # that do have a copy of their contents next to them,
+ # in which case those contents are used instead of the
+ # temporarily extracted files.
+ if iteration == 1:
+ extracted_args.extend(sorted(extracted[base]))
+ else:
+ dirname = os.path.dirname(f[len(self.tmpdir)+1:])
+ if base.endswith('f'):
+ dirname = os.path.join(dirname, 'foo', 'bar')
+ extracted_args.extend([self.tmpfile(dirname, Obj(base)), self.tmpfile(dirname, Obj(base + '2'))])
+ else:
+ extracted_args.append(f)
+ self.assertRelEqual(args, ['foo', '-bar'] + extracted_args)
+
+ tmp = args.tmp
+ # Check that all temporary files are properly removed
+ self.assertEqual(True, all([not os.path.exists(f) for f in tmp]))
+
+ # Create archives contents next to them for the second iteration.
+ base = os.path.splitext(Lib('_'))[0]
+ self.touch(self.tmpfile(Obj(base.replace('_', suffix))) for suffix in ('a', 'a2', 'd', 'd2'))
+ try:
+ os.makedirs(self.tmpfile('foo', 'bar'))
+ except:
+ pass
+ self.touch(self.tmpfile('foo', 'bar', Obj(base.replace('_', suffix))) for suffix in ('f', 'f2'))
+ self.touch(self.tmpfile('liby', Obj(base.replace('_', suffix))) for suffix in ('z', 'z2'))
+
+ # Restore subprocess.call and subprocess.check_output
+ subprocess.call = subprocess_call
+ subprocess.check_output = subprocess_check_output
+
+class FakeProcess(object):
+ def __init__(self, out, err = ''):
+ self.out = out
+ self.err = err
+
+ def communicate(self):
+ return (self.out, self.err)
+
+OBJDUMPS = {
+'foo.o': '''
+00000000 g F .text\t00000001 foo
+00000000 g F .text._Z6foobarv\t00000001 _Z6foobarv
+00000000 g F .text.hello\t00000001 hello
+00000000 g F .text._ZThn4_6foobarv\t00000001 _ZThn4_6foobarv
+''',
+'bar.o': '''
+00000000 g F .text.hi\t00000001 hi
+00000000 g F .text.hot._Z6barbazv\t00000001 .hidden _Z6barbazv
+''',
+}
+
+PRINT_ICF = '''
+ld: ICF folding section '.text.hello' in file 'foo.o'into '.text.hi' in file 'bar.o'
+ld: ICF folding section '.foo' in file 'foo.o'into '.foo' in file 'bar.o'
+'''
+
+class SubprocessPopen(object):
+ def __init__(self, test):
+ self.test = test
+
+ def __call__(self, args, stdout = None, stderr = None):
+ self.test.assertEqual(stdout, subprocess.PIPE)
+ self.test.assertEqual(stderr, subprocess.PIPE)
+ if args[0] == 'objdump':
+ self.test.assertEqual(args[1], '-t')
+ self.test.assertTrue(args[2] in OBJDUMPS)
+ return FakeProcess(OBJDUMPS[args[2]])
+ else:
+ return FakeProcess('', PRINT_ICF)
+
+class TestSectionFinder(unittest.TestCase):
+ def test_getSections(self):
+ '''Test SectionFinder'''
+ # Divert subprocess.Popen
+ subprocess_popen = subprocess.Popen
+ subprocess.Popen = SubprocessPopen(self)
+ config.EXPAND_LIBS_ORDER_STYLE = 'linkerscript'
+ config.OBJ_SUFFIX = '.o'
+ config.LIB_SUFFIX = '.a'
+ finder = SectionFinder(['foo.o', 'bar.o'])
+ self.assertEqual(finder.getSections('foobar'), [])
+ self.assertEqual(finder.getSections('_Z6barbazv'), ['.text.hot._Z6barbazv'])
+ self.assertEqual(finder.getSections('_Z6foobarv'), ['.text._Z6foobarv', '.text._ZThn4_6foobarv'])
+ self.assertEqual(finder.getSections('_ZThn4_6foobarv'), ['.text._Z6foobarv', '.text._ZThn4_6foobarv'])
+ subprocess.Popen = subprocess_popen
+
+class TestSymbolOrder(unittest.TestCase):
+ def test_getOrderedSections(self):
+ '''Test ExpandMoreArgs' _getOrderedSections'''
+ # Divert subprocess.Popen
+ subprocess_popen = subprocess.Popen
+ subprocess.Popen = SubprocessPopen(self)
+ config.EXPAND_LIBS_ORDER_STYLE = 'linkerscript'
+ config.OBJ_SUFFIX = '.o'
+ config.LIB_SUFFIX = '.a'
+ config.LD_PRINT_ICF_SECTIONS = ''
+ args = ExpandArgsMore(['foo', '-bar', 'bar.o', 'foo.o'])
+ self.assertEqual(args._getOrderedSections(['_Z6foobarv', '_Z6barbazv']), ['.text._Z6foobarv', '.text._ZThn4_6foobarv', '.text.hot._Z6barbazv'])
+ self.assertEqual(args._getOrderedSections(['_ZThn4_6foobarv', '_Z6barbazv']), ['.text._Z6foobarv', '.text._ZThn4_6foobarv', '.text.hot._Z6barbazv'])
+ subprocess.Popen = subprocess_popen
+
+ def test_getFoldedSections(self):
+ '''Test ExpandMoreArgs' _getFoldedSections'''
+ # Divert subprocess.Popen
+ subprocess_popen = subprocess.Popen
+ subprocess.Popen = SubprocessPopen(self)
+ config.LD_PRINT_ICF_SECTIONS = '-Wl,--print-icf-sections'
+ args = ExpandArgsMore(['foo', '-bar', 'bar.o', 'foo.o'])
+ self.assertEqual(args._getFoldedSections(), {'.text.hello': ['.text.hi'], '.text.hi': ['.text.hello']})
+ subprocess.Popen = subprocess_popen
+
+ def test_getOrderedSectionsWithICF(self):
+ '''Test ExpandMoreArgs' _getOrderedSections, with ICF'''
+ # Divert subprocess.Popen
+ subprocess_popen = subprocess.Popen
+ subprocess.Popen = SubprocessPopen(self)
+ config.EXPAND_LIBS_ORDER_STYLE = 'linkerscript'
+ config.OBJ_SUFFIX = '.o'
+ config.LIB_SUFFIX = '.a'
+ config.LD_PRINT_ICF_SECTIONS = '-Wl,--print-icf-sections'
+ args = ExpandArgsMore(['foo', '-bar', 'bar.o', 'foo.o'])
+ self.assertEqual(args._getOrderedSections(['hello', '_Z6barbazv']), ['.text.hello', '.text.hi', '.text.hot._Z6barbazv'])
+ self.assertEqual(args._getOrderedSections(['_ZThn4_6foobarv', 'hi', '_Z6barbazv']), ['.text._Z6foobarv', '.text._ZThn4_6foobarv', '.text.hi', '.text.hello', '.text.hot._Z6barbazv'])
+ subprocess.Popen = subprocess_popen
+
+
+if __name__ == '__main__':
+ mozunit.main()
diff --git a/config/tests/unit-mozunit.py b/config/tests/unit-mozunit.py
new file mode 100644
index 000000000..69798f4ba
--- /dev/null
+++ b/config/tests/unit-mozunit.py
@@ -0,0 +1,86 @@
+# 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
+import os
+from mozunit import main, MockedOpen
+import unittest
+from tempfile import mkstemp
+
+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 000000000..2a230841a
--- /dev/null
+++ b/config/tests/unit-nsinstall.py
@@ -0,0 +1,174 @@
+import unittest
+
+import os, sys, os.path, time
+from tempfile import mkdtemp
+from shutil import rmtree
+import mozunit
+from mozprocess import processhandler
+
+from nsinstall import nsinstall
+import nsinstall as nsinstall_module
+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 = unicode(self.tmpdir)
+ else:
+ tmpdir = unicode(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)
+
+ if sys.platform != "win32":
+ # can't run this test on windows, don't have real file modes there
+ 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")))
+
+ if RUN_NON_ASCII_TESTS:
+ def test_nsinstall_non_ascii(self):
+ "Test that nsinstall handles non-ASCII files"
+ filename = u"\u2325\u3452\u2415\u5081"
+ testfile = self.touch(filename)
+ testdir = self.mkdirs(u"\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))
+
+ def test_nsinstall_non_ascii_subprocess(self):
+ "Test that nsinstall as a subprocess handles non-ASCII files"
+ filename = u"\u2325\u3452\u2415\u5081"
+ testfile = self.touch(filename)
+ testdir = self.mkdirs(u"\u4241\u1D04\u1414")
+ # We don't use subprocess because it can't handle Unicode on
+ # Windows <http://bugs.python.org/issue1759845>. mozprocess calls
+ # CreateProcessW directly so it's perfect.
+ p = processhandler.ProcessHandlerMixin([sys.executable,
+ NSINSTALL_PATH,
+ testfile, testdir])
+ p.run()
+ rv = p.waitForFinish()
+
+ 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 000000000..4cf8d2f0e
--- /dev/null
+++ b/config/tests/unit-printprereleasesuffix.py
@@ -0,0 +1,80 @@
+import unittest
+
+import sys
+import os.path
+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 000000000..f9c0419ab
--- /dev/null
+++ b/config/tests/unitMozZipFile.py
@@ -0,0 +1,201 @@
+# 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 unittest
+
+import shutil
+import os
+import re
+import sys
+import random
+import copy
+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__), '..'))
+
+from MozZipFile import ZipFile
+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/version.mk b/config/version.mk
new file mode 100644
index 000000000..1b9f68afa
--- /dev/null
+++ b/config/version.mk
@@ -0,0 +1,51 @@
+# 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_VERSION_MK
+INCLUDED_VERSION_MK=1
+
+# Windows gmake build:
+# Build default .rc file if $(RESFILE) isn't defined.
+# TODO:
+# PBI : Private build info. Not used currently.
+# Guessing the best way would be to set an env var.
+# BINARY : Binary name. Not used currently.
+ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
+ifndef RESFILE
+RCFILE=./module.rc
+RESFILE=./module.res
+_RC_STRING = -QUIET 1 -DEPTH $(DEPTH) -TOPSRCDIR $(MOZILLA_DIR) -OBJDIR . -SRCDIR $(srcdir) -DISPNAME $(MOZ_APP_DISPLAYNAME) -APPVERSION $(MOZ_APP_VERSION)
+ifdef MOZILLA_OFFICIAL
+_RC_STRING += -OFFICIAL 1
+endif
+ifdef MOZ_DEBUG
+_RC_STRING += -DEBUG 1
+endif
+ifdef PROGRAM
+_RC_STRING += -BINARY $(PROGRAM)
+else
+ifdef _PROGRAM
+_RC_STRING += -BINARY $(_PROGRAM)
+else
+ifdef SHARED_LIBRARY
+_RC_STRING += -BINARY $(SHARED_LIBRARY)
+endif
+endif
+endif
+ifdef RCINCLUDE
+_RC_STRING += -RCINCLUDE $(srcdir)/$(RCINCLUDE)
+endif
+
+GARBAGE += $(RESFILE) $(RCFILE)
+
+#dummy target so $(RCFILE) doesn't become the default =P
+all::
+
+$(RCFILE): $(RCINCLUDE) $(MOZILLA_DIR)/config/version_win.pl
+ $(PERL) $(MOZILLA_DIR)/config/version_win.pl $(_RC_STRING)
+
+endif # RESFILE
+endif # Windows
+
+endif
diff --git a/config/version_win.pl b/config/version_win.pl
new file mode 100755
index 000000000..47c7dfe30
--- /dev/null
+++ b/config/version_win.pl
@@ -0,0 +1,374 @@
+#!/usr/bin/perl -w
+
+# 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/.
+
+#use diagnostics;
+require strict;
+my $dir = $0;
+$dir =~ s/[^\/]*$//;
+push(@INC, "$dir");
+require "Moz/Milestone.pm";
+use Getopt::Long;
+use Getopt::Std;
+use POSIX;
+
+# Calculate the number of days since Jan. 1, 2000 from a buildid string
+sub daysFromBuildID
+{
+ my ($buildid,) = @_;
+
+ my ($y, $m, $d, $h) = ($buildid =~ /^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})$/);
+ $d || die("Unrecognized buildid string.");
+
+ my $secondstodays = 60 * 60 * 24;
+ return sprintf("%d",
+ (POSIX::mktime(00, 00, 00, $d, $m - 1, $y - 1900) -
+ POSIX::mktime(00, 00, 00, 01, 00, 100)) / $secondstodays);
+}
+
+#Creates version resource file
+
+#Paramaters are passed on the command line:
+
+#Example: -MODNAME nsToolkitCompsModule -DEBUG=1
+
+# DEBUG - Mozilla's global debug variable - tells if its debug version
+# OFFICIAL - tells Mozilla is building a milestone or nightly
+# MSTONE - tells which milestone is being built;
+# OBJDIR - Holds the object directory;
+# MODNAME - tells what the name of the module is like nsBMPModule
+# DEPTH - Holds the path to the root obj dir
+# TOPSRCDIR - Holds the path to the root mozilla dir
+# SRCDIR - Holds module.ver and source
+# BINARY - Holds the name of the binary file
+# DISPNAME - Holds the display name of the built application
+# APPVERSION - Holds the version string of the built application
+# RCINCLUDE - Holds the name of the RC File to include or ""
+# QUIET - Turns off output
+
+#Description and Comment come from module.ver
+#Bug 23560
+#http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/rc_7x2d.asp
+
+#Get next .ver file entry
+sub getNextEntry
+{
+ while (<VERFILE>)
+ {
+ my $mline = $_;
+ ($mline) = split(/#/,$mline);
+ my ($entry, $value)=split(/=/,$mline,2);
+ if (defined($entry))
+ {
+ if (defined($value))
+ {
+ $entry =~ s/^\s*(.*?)\s*$/$1/;
+ $value =~ s/^\s*(.*?)\s*$/$1/;
+ return ($entry,$value);
+ }
+ }
+ }
+ return undef;
+}
+
+my ($quiet,$objdir,$debug,$official,$milestone,$buildid,$module,$binary,$depth,$rcinclude,$srcdir,$fileversion,$productversion);
+
+GetOptions( "QUIET" => \$quiet,
+ "DEBUG=s" => \$debug,
+ "OFFICIAL=s" => \$official,
+ "MSTONE=s" => \$milestone,
+ "MODNAME=s" => \$module,
+ "BINARY=s" => \$binary,
+ "DISPNAME=s" => \$displayname,
+ "APPVERSION=s" => \$appversion,
+ "SRCDIR=s" => \$srcdir,
+ "TOPSRCDIR=s" => \$topsrcdir,
+ "DEPTH=s" => \$depth,
+ "RCINCLUDE=s" => \$rcinclude,
+ "OBJDIR=s" => \$objdir);
+if (!defined($debug)) {$debug="";}
+if (!defined($official)) {$official="";}
+if (!defined($milestone)) {$milestone="";}
+if (!defined($module)) {$module="";}
+if (!defined($binary)) {$binary="";}
+if (!defined($displayname)) {$displayname="Mozilla";}
+if (!defined($appversion)) {$appversion=$milestone;}
+if (!defined($depth)) {$depth=".";}
+if (!defined($rcinclude)) {$rcinclude="";}
+if (!defined($objdir)) {$objdir=".";}
+if (!defined($srcdir)) {$srcdir=".";}
+if (!defined($topsrcdir)) {$topsrcdir=".";}
+my $mfversion = "Personal";
+my $mpversion = "Personal";
+my @fileflags = ("0");
+my $comment="";
+my $description="";
+if (!defined($module))
+{
+ $module = $binary;
+ ($module) = split(/\./,$module);
+}
+
+my $bufferstr=" ";
+
+my $MILESTONE_FILE = "$topsrcdir/config/milestone.txt";
+my $BUILDID_FILE = "$depth/buildid.h";
+
+#Read module.ver file
+#Version file overrides for WIN32:
+#WIN32_MODULE_COMMENT
+#WIN32_MODULE_DESCRIPTION
+#WIN32_MODULE_FILEVERSION
+#WIN32_MODULE_COMPANYNAME
+#WIN32_MODULE_FILEVERSION_STRING
+#WIN32_MODULE_NAME
+#WIN32_MODULE_COPYRIGHT
+#WIN32_MODULE_TRADEMARKS
+#WIN32_MODULE_ORIGINAL_FILENAME
+#WIN32_MODULE_PRODUCTNAME
+#WIN32_MODULE_PRODUCTVERSION
+#WIN32_MODULE_PRODUCTVERSION_STRING
+
+#Override values obtained from the .ver file
+my $override_comment;
+my $override_description;
+my $override_fileversion;
+my $override_company;
+my $override_mfversion;
+my $override_module;
+my $override_copyright;
+my $override_trademarks;
+my $override_filename;
+my $override_productname;
+my $override_productversion;
+my $override_mpversion;
+if (open(VERFILE, "<$srcdir/module.ver"))
+{
+
+ my ($a,$b) = getNextEntry();
+ while (defined($a))
+ {
+ if ($a eq "WIN32_MODULE_COMMENT") { $override_comment = $b; }
+ if ($a eq "WIN32_MODULE_DESCRIPTION") { $override_description = $b; }
+ if ($a eq "WIN32_MODULE_FILEVERSION") { $override_fileversion = $b; }
+ if ($a eq "WIN32_MODULE_COMPANYNAME") { $override_company = $b; }
+ if ($a eq "WIN32_MODULE_FILEVERSION_STRING") { $override_mfversion = $b; }
+ if ($a eq "WIN32_MODULE_NAME") { $override_module = $b; }
+ if ($a eq "WIN32_MODULE_COPYRIGHT") { $override_copyright = $b; }
+ if ($a eq "WIN32_MODULE_TRADEMARKS") { $override_trademarks = $b; }
+ if ($a eq "WIN32_MODULE_ORIGINAL_FILENAME") { $override_filename = $b; }
+ if ($a eq "WIN32_MODULE_PRODUCTNAME") { $override_productname = $b; }
+ if ($a eq "WIN32_MODULE_PRODUCTVERSION") { $override_productversion = $b; }
+ if ($a eq "WIN32_MODULE_PRODUCTVERSION_STRING") { $override_mpversion = $b; }
+ ($a,$b) = getNextEntry();
+ }
+ close(VERFILE)
+}
+else
+{
+ if (!$quiet || $quiet ne "1") { print "$bufferstr" . "WARNING: No module.ver file included ($module, $binary). Default values used\n"; }
+}
+#Get rid of trailing and leading whitespace
+$debug =~ s/^\s*(.*)\s*$/$1/;
+$comment =~ s/^\s*(.*)\s*$/$1/;
+$official =~ s/^\s*(.*)\s*$/$1/;
+$milestone =~ s/^\s*(.*)\s*$/$1/;
+$description =~ s/^\s*(.*)\s*$/$1/;
+$module =~ s/^\s*(.*)\s*$/$1/;
+$depth =~ s/^\s*(.*)\s*$/$1/;
+$binary =~ s/^\s*(.*)\s*$/$1/;
+$displayname =~ s/^\s*(.*)\s*$/$1/;
+
+open(BUILDID, "<", $BUILDID_FILE) || die("Couldn't open buildid file: $BUILDID_FILE");
+$buildid = <BUILDID>;
+$buildid =~ s/^#define MOZ_BUILDID\s+(\S+)\s*$/$1/;
+close BUILDID;
+
+my $daycount = daysFromBuildID($buildid);
+
+if ($milestone eq "") {
+ $milestone = Moz::Milestone::getOfficialMilestone($MILESTONE_FILE);
+}
+
+$mfversion = $mpversion = $milestone;
+if ($appversion eq "") {
+ $appversion = $milestone;
+}
+
+if ($debug eq "1")
+{
+ push @fileflags, "VS_FF_DEBUG";
+ $mpversion .= " Debug";
+ $mfversion .= " Debug";
+}
+
+if ($official ne "1") {
+ push @fileflags, "VS_FF_PRIVATEBUILD";
+}
+
+if ($milestone =~ /[a-z]/) {
+ push @fileflags, "VS_FF_PRERELEASE";
+}
+
+my @mstone = split(/\./,$milestone);
+$mstone[1] =~s/\D.*$//;
+if (!$mstone[2]) {
+ $mstone[2] = "0";
+}
+else {
+ $mstone[2] =~s/\D.*$//;
+}
+$fileversion = $productversion="$mstone[0],$mstone[1],$mstone[2],$daycount";
+
+my @appver = split(/\./,$appversion);
+for ($j = 1; $j < 4; $j++)
+{
+ if (!$appver[$j]) {
+ $appver[$j] = "0";
+ }
+ else {
+ $appver[$j] =~s/\D.*$//;
+ }
+}
+my $winappversion = "$appver[0],$appver[1],$appver[2],$appver[3]";
+
+my $copyright = "License: MPL 2";
+my $company = "Mozilla Foundation";
+my $trademarks = "Mozilla";
+my $productname = $displayname;
+
+
+if (defined($override_comment)){$override_comment =~ s/\@MOZ_APP_DISPLAYNAME\@/$displayname/g; $comment=$override_comment;}
+if (defined($override_description)){$override_description =~ s/\@MOZ_APP_DISPLAYNAME\@/$displayname/g; $description=$override_description;}
+if (defined($override_fileversion)){$override_fileversion =~ s/\@MOZ_APP_WINVERSION\@/$winappversion/g; $fileversion=$override_fileversion;}
+if (defined($override_mfversion)){$override_mfversion =~ s/\@MOZ_APP_VERSION\@/$appversion/g; $mfversion=$override_mfversion;}
+if (defined($override_company)){$company=$override_company;}
+if (defined($override_module)){$override_module =~ s/\@MOZ_APP_DISPLAYNAME\@/$displayname/g; $module=$override_module;}
+if (defined($override_copyright)){$override_copyright =~ s/\@MOZ_APP_DISPLAYNAME\@/$displayname/g; $copyright=$override_copyright;}
+if (defined($override_trademarks)){$override_trademarks =~ s/\@MOZ_APP_DISPLAYNAME\@/$displayname/g; $trademarks=$override_trademarks;}
+if (defined($override_filename)){$binary=$override_filename;}
+if (defined($override_productname)){$override_productname =~ s/\@MOZ_APP_DISPLAYNAME\@/$displayname/g; $productname=$override_productname;}
+if (defined($override_productversion)){$override_productversion =~ s/\@MOZ_APP_WINVERSION\@/$winappversion/g; $productversion=$override_productversion;}
+if (defined($override_mpversion)){$override_mpversion =~ s/\@MOZ_APP_VERSION\@/$appversion/g; $mpversion=$override_mpversion;}
+
+
+#Override section
+
+open(RCFILE, ">$objdir/module.rc") || die("Can't edit module.rc - It must be locked.\n");
+print RCFILE qq{
+// 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<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.
+
+};
+
+my $versionlevel=0;
+my $insideversion=0;
+if (open(RCINCLUDE, "<$rcinclude"))
+{
+ print RCFILE "// From included resource $rcinclude\n";
+# my $mstring="";
+ while (<RCINCLUDE>)
+ {
+ $_ =~ s/\@MOZ_APP_DISPLAYNAME\@/$displayname/g;
+ print RCFILE $_;
+# my $instr=$_;
+# chomp($instr);
+# $mstring .= "$instr\;";
+ }
+ close(RCINCLUDE);
+# $mstring =~ s/\/\*.*\*\///g;
+# my @mlines = split(/\;/,$mstring);
+# for(@mlines)
+# {
+# my ($nocomment)=split(/\/\//,$_);
+# if (defined($nocomment) && $nocomment ne "")
+# {
+# my ($firststring,$secondstring) = split(/\s+/,$nocomment);
+# if (!defined($firststring)) {$firststring="";}
+# if (!defined($secondstring)) {$secondstring="";}
+# if ($secondstring eq "VERSIONINFO")
+# {
+#if (!$quiet || $quiet ne "1") {
+# print "$bufferstr" . "WARNING: Included RC file ($rcinclude, $module, $binary)\n";
+# print "$bufferstr" . "WARNING: contains versioning information that will be discarded\n";
+# print "$bufferstr" . "WARNING: Remove it and use relevant overrides (in module.ver)\n";
+#}
+# $versionlevel = 0;
+# $insideversion = 1;
+# }
+# if ($firststring eq "BEGIN") { $versionlevel++; }
+# if ($secondstring eq "END")
+# {
+# $versionlevel--;
+# if ($insideversion==1 && $versionlevel==0) {$versionlevel=0;}
+# }
+# my $includecheck = $firststring . $secondstring;
+# $includecheck =~ s/<|>/"/g;
+# $includecheck = lc($includecheck);
+# if ($includecheck ne "#include\"winver.h\"")
+# {
+# if ($insideversion == 0 && $versionlevel == 0)
+# {
+# print RCFILE "$nocomment\n";
+# }
+# }
+# }
+# }
+
+}
+
+my $fileflags = join(' | ', @fileflags);
+
+print RCFILE qq{
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// 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
+
+};
+close(RCFILE);