diff options
author | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
---|---|---|
committer | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
commit | 5f8de423f190bbb79a62f804151bc24824fa32d8 (patch) | |
tree | 10027f336435511475e392454359edea8e25895d /config | |
parent | 49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff) | |
download | UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip |
Add m-esr52 at 52.6.0
Diffstat (limited to 'config')
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 Binary files differnew file mode 100644 index 000000000..7ade5b8fa --- /dev/null +++ b/config/external/icu/data/icudt58l.dat 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); |