aboutsummaryrefslogtreecommitdiffstats
path: root/meta-oe/dynamic-layers
diff options
context:
space:
mode:
authorChangqing Li <changqing.li@windriver.com>2020-03-11 16:42:05 +0800
committerKhem Raj <raj.khem@gmail.com>2020-03-11 08:58:57 -0700
commitd178745cbf5c97b7cdcf274108a58c8e1f88d3ca (patch)
treeab1cf2f60e724eeecbfbf4a6c1973c4b5fee2c65 /meta-oe/dynamic-layers
parentf5d2bf55a8169a9446c2f96f327b3e5d91a6e6cc (diff)
downloadmeta-openembedded-contrib-d178745cbf5c97b7cdcf274108a58c8e1f88d3ca.tar.gz
conf/layer.conf: add BBFILES_DYNAMIC and dynamic layers
some recipes under meta-oe have dependency on meta-python, and test_world of yocto-check-layer will failed with error like: ERROR: test_world (common.CommonCheckLayer) ERROR: Nothing PROVIDES 'python3-pytoml-native' (but /meta-openembedded/meta-oe/recipes-extended/mozjs/mozjs_60.9.0.bb DEPENDS on or otherwise requires it). Close matches: python3-numpy-native python3-pycairo-native python3-rpm-native ERROR: Required build target 'meta-world-pkgdata' has no buildable providers. Missing or unbuildable dependency chain was: ['meta-world-pkgdata', 'mozjs', 'python3-pytoml-native'] fix by make these recipes only active when identified layers are present Signed-off-by: Changqing Li <changqing.li@windriver.com> Signed-off-by: Khem Raj <raj.khem@gmail.com>
Diffstat (limited to 'meta-oe/dynamic-layers')
-rw-r--r--meta-oe/dynamic-layers/meta-python/recipes-benchmark/speedtest-cli/speedtest-cli_2.1.2.bb14
-rw-r--r--meta-oe/dynamic-layers/meta-python/recipes-bsp/rwmem/rwmem_1.2.bb35
-rw-r--r--meta-oe/dynamic-layers/meta-python/recipes-connectivity/lirc/lirc/0001-Fix-build-on-32bit-arches-with-64bit-time_t.patch40
-rw-r--r--meta-oe/dynamic-layers/meta-python/recipes-connectivity/lirc/lirc/lirc.tmpfiles1
-rw-r--r--meta-oe/dynamic-layers/meta-python/recipes-connectivity/lirc/lirc/lirc_options.conf24
-rw-r--r--meta-oe/dynamic-layers/meta-python/recipes-connectivity/lirc/lirc/lircd.conf315
-rw-r--r--meta-oe/dynamic-layers/meta-python/recipes-connectivity/lirc/lirc/lircd.init40
-rw-r--r--meta-oe/dynamic-layers/meta-python/recipes-connectivity/lirc/lirc/lircd.service20
-rw-r--r--meta-oe/dynamic-layers/meta-python/recipes-connectivity/lirc/lirc/lircexec.init37
-rw-r--r--meta-oe/dynamic-layers/meta-python/recipes-connectivity/lirc/lirc/pollfd.patch101
-rw-r--r--meta-oe/dynamic-layers/meta-python/recipes-connectivity/lirc/lirc_0.9.4d.bb86
-rw-r--r--meta-oe/dynamic-layers/meta-python/recipes-core/packagegroups/packagegroup-meta-oe.bb314
-rw-r--r--meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb/0001-IntelRDFPMathLib20U1-Check-for-__DEFINED_wchar_t.patch35
-rw-r--r--meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb/0001-Mark-one-of-strerror_r-implementation-glibc-specific.patch31
-rw-r--r--meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb/0001-Support-deprecated-resolver-functions.patch33
-rw-r--r--meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb/0001-Tell-scons-to-use-build-settings-from-environment-va.patch56
-rw-r--r--meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb/0001-Use-__GLIBC__-to-control-use-of-gnu_get_libc_version.patch41
-rw-r--r--meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb/0001-Use-long-long-instead-of-int64_t.patch66
-rw-r--r--meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb/0001-asio-Dont-use-experimental-with-clang.patch29
-rw-r--r--meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb/0002-Add-a-definition-for-the-macro-__ELF_NATIVE_CLASS.patch35
-rw-r--r--meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb/0002-Fix-default-stack-size-to-256K.patch39
-rw-r--r--meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb/0003-Fix-unknown-prefix-env.patch19
-rw-r--r--meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb/0004-wiredtiger-Disable-strtouq-on-musl.patch26
-rw-r--r--meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb/arm64-support.patch54
-rw-r--r--meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb_git.bb73
-rw-r--r--meta-oe/dynamic-layers/meta-python/recipes-extended/lcdproc/lcdproc/0001-Fix-parallel-build-fix-port-internal-make-dependenci.patch33
-rw-r--r--meta-oe/dynamic-layers/meta-python/recipes-extended/lcdproc/lcdproc/0002-Include-limits.h-for-PATH_MAX-definition.patch41
-rw-r--r--meta-oe/dynamic-layers/meta-python/recipes-extended/lcdproc/lcdproc/0003-Fix-non-x86-platforms-on-musl.patch35
-rw-r--r--meta-oe/dynamic-layers/meta-python/recipes-extended/lcdproc/lcdproc_git.bb105
-rw-r--r--meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0001-Port-build-to-python3.patch6897
-rw-r--r--meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0002-js.pc.in-do-not-include-RequiredDefines.h-for-depend.patch33
-rw-r--r--meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0003-fix-cross-compilation-on-i586-targets.patch38
-rw-r--r--meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0004-do-not-create-python-environment.patch64
-rw-r--r--meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0005-fix-cannot-find-link.patch34
-rw-r--r--meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0006-workaround-autoconf-2.13-detection-failed.patch28
-rw-r--r--meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0007-fix-do_compile-failed-on-mips.patch33
-rw-r--r--meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0008-add-riscv-support.patch50
-rw-r--r--meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0009-mozjs-fix-coredump-caused-by-getenv.patch27
-rw-r--r--meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0010-format-overflow.patch21
-rw-r--r--meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0011-To-fix-build-error-on-arm32BE.patch28
-rw-r--r--meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0012-JS_PUBLIC_API.patch55
-rw-r--r--meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0013-riscv-Disable-atomic-operations.patch38
-rw-r--r--meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0014-fallback-to-2011-C++-standard.patch42
-rw-r--r--meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/mipsarchn32/0001-fix-compiling-failure-on-mips64-n32-bsp.patch80
-rw-r--r--meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/musl/0001-support-musl.patch98
-rw-r--r--meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/musl/0002-js-Fix-build-with-musl.patch31
-rw-r--r--meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs_60.9.0.bb135
-rw-r--r--meta-oe/dynamic-layers/meta-python/recipes-support/smem/smem/0001-smem-fix-support-for-source-option-python3.patch53
-rw-r--r--meta-oe/dynamic-layers/meta-python/recipes-support/smem/smem_1.5.bb43
49 files changed, 9606 insertions, 0 deletions
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-benchmark/speedtest-cli/speedtest-cli_2.1.2.bb b/meta-oe/dynamic-layers/meta-python/recipes-benchmark/speedtest-cli/speedtest-cli_2.1.2.bb
new file mode 100644
index 0000000000..de4fa16426
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-benchmark/speedtest-cli/speedtest-cli_2.1.2.bb
@@ -0,0 +1,14 @@
+SUMMARY = "Command line interface for testing internet bandwidth using speedtest.net"
+AUTHOR = "Matt Martz"
+
+LICENSE="Apache-2.0"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57"
+
+inherit setuptools3
+
+SRC_URI = "git://github.com/sivel/speedtest-cli.git"
+SRCREV = "c58ad3367bf27f4b4a4d5b1bca29ebd574731c5d"
+
+S = "${WORKDIR}/git"
+
+RDEPENDS_${PN} = "python3 python3-setuptools-scm"
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-bsp/rwmem/rwmem_1.2.bb b/meta-oe/dynamic-layers/meta-python/recipes-bsp/rwmem/rwmem_1.2.bb
new file mode 100644
index 0000000000..065243ccfe
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-bsp/rwmem/rwmem_1.2.bb
@@ -0,0 +1,35 @@
+SUMMARY = "A small tool to read/write memory"
+DESCRIPTION = "rwmem is a small tool for reading and writing device registers. \
+rwmem supports two modes: mmap mode and i2c mode. \
+\
+In mmap mode rwmem accesses a file by memory mapping it. \
+Using /dev/mem as the memory mapped file makes rwmem access memory and \
+can thus be used to access devices which have memory mapped registers. \
+\
+In i2c mode rwmem accesses an i2c peripheral by sending i2c messages to it."
+
+LICENSE = "GPLv2+"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=b234ee4d69f5fce4486a80fdaf4a4263"
+
+DEPENDS += "python3 python3-pybind11"
+
+PV .= "+git${SRCPV}"
+
+SRCREV_rwmem = "3ec3e421211b58e766651c2e3a3a21acf14a1906"
+SRCREV_inih = "4b10c654051a86556dfdb634c891b6c3224c4109"
+
+SRCREV_FORMAT = "rwmem_inih"
+
+SRC_URI = " \
+ git://github.com/tomba/rwmem.git;protocol=https;name=rwmem \
+ git://github.com/benhoyt/inih.git;protocol=https;name=inih;nobranch=1;destsuffix=git/ext/inih \
+"
+
+S = "${WORKDIR}/git"
+
+inherit cmake pkgconfig
+
+do_install() {
+ install -D -m 0755 ${B}/bin/rwmem ${D}${bindir}/rwmem
+ install -D -m 0644 ${B}/lib/librwmem.a ${D}${libdir}/librwmem.a
+}
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-connectivity/lirc/lirc/0001-Fix-build-on-32bit-arches-with-64bit-time_t.patch b/meta-oe/dynamic-layers/meta-python/recipes-connectivity/lirc/lirc/0001-Fix-build-on-32bit-arches-with-64bit-time_t.patch
new file mode 100644
index 0000000000..0e38f7d8ec
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-connectivity/lirc/lirc/0001-Fix-build-on-32bit-arches-with-64bit-time_t.patch
@@ -0,0 +1,40 @@
+From 50a48a7bd8d65a165ce2aac4ba0c1e02bded04aa Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Sat, 30 Nov 2019 12:21:31 -0800
+Subject: [PATCH] Fix build on 32bit arches with 64bit time_t
+
+time element is deprecated on new input_event structure in kernel's
+input.h [1]
+
+[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit?id=152194fe9c3f
+
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ plugins/devinput.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/plugins/devinput.c b/plugins/devinput.c
+index d4d733a..feb4a61 100644
+--- a/plugins/devinput.c
++++ b/plugins/devinput.c
+@@ -34,6 +34,11 @@
+ #include <linux/uinput.h>
+ #include <sys/stat.h>
+
++#ifndef input_event_sec
++#define input_event_sec time.tv_sec
++#define input_event_usec time.tv_usec
++#endif
++
+ #ifndef EV_SYN
+ /* previous name */
+ #define EV_SYN EV_RST
+@@ -459,7 +464,7 @@ char* devinput_rec(struct ir_remote* remotes)
+ return 0;
+ }
+
+- log_trace("time %ld.%06ld type %d code %d value %d", event.time.tv_sec, event.time.tv_usec, event.type,
++ log_trace("time %ld.%06ld type %d code %d value %d", event.input_event_sec, event.input_event_usec, event.type,
+ event.code, event.value);
+
+ value = (unsigned)event.value;
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-connectivity/lirc/lirc/lirc.tmpfiles b/meta-oe/dynamic-layers/meta-python/recipes-connectivity/lirc/lirc/lirc.tmpfiles
new file mode 100644
index 0000000000..0b80e2e479
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-connectivity/lirc/lirc/lirc.tmpfiles
@@ -0,0 +1 @@
+d /run/lirc 0755 root root -
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-connectivity/lirc/lirc/lirc_options.conf b/meta-oe/dynamic-layers/meta-python/recipes-connectivity/lirc/lirc/lirc_options.conf
new file mode 100644
index 0000000000..d8ddedd8fa
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-connectivity/lirc/lirc/lirc_options.conf
@@ -0,0 +1,24 @@
+# These are the default options to lircd, if installed as
+# /etc/lirc/lirc_options.conf. See the lircd(8) and lircmd(8)
+# manpages for info on the different options.
+
+[lircd]
+nodaemon = False
+permission = 666
+driver = default
+device = /dev/lirc0
+output = /var/run/lirc/lircd
+pidfile = /var/run/lirc/lircd.pid
+plugindir = /usr/lib/lirc/plugins
+allow-simulate = No
+repeat-max = 600
+#listen = [address:]port
+#connect = host[:port]
+#debug = 5
+#uinput = ...
+#release = ...
+#logfile = ...
+
+[lircmd]
+uinput = False
+nodeamon = False
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-connectivity/lirc/lirc/lircd.conf b/meta-oe/dynamic-layers/meta-python/recipes-connectivity/lirc/lirc/lircd.conf
new file mode 100644
index 0000000000..29b03c72a0
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-connectivity/lirc/lirc/lircd.conf
@@ -0,0 +1,315 @@
+# contributed by angelo castello
+#
+# note: this config file has been deduced starting from the
+# raw codes provided to run mode2 utility.
+#
+# brand: futarque
+
+begin remote
+ name futarque
+ bits 8
+ flags SPACE_ENC|CONST_LENGTH
+ eps 30
+ aeps 100
+
+ header 8048 3898
+ one 555 1436
+ zero 555 439
+ gap 113123
+ ptrail 555
+ pre_data_bits 8
+ pre_data 0x54
+ pre 570 3890
+
+ begin codes
+ MUTE 0x70
+ EXIT 0xA8
+ POWER 0xF0
+ CHANNEL_UP 0x50
+ CHANNEL_DOWN 0xD0
+ VOLUME_UP 0x30
+ VOLUME_DOWN 0xB0
+ OK 0x98
+ FAVORITES 0x04
+ TEXT 0x68
+ EPG 0xC8
+ BACK 0x48
+ MENU 0x88
+ 1 0x00
+ 2 0x80
+ 3 0x40
+ 4 0xC0
+ 5 0x20
+ 6 0xA0
+ 7 0x60
+ 8 0xE0
+ 9 0x10
+ 0 0x90
+ PAUSE 0x84
+ INFO 0x38
+ RED 0xE8
+ GREEN 0x08
+ YELLOW 0x28
+ BLUE 0x78
+ UP 0xD8
+ DOWN 0xB8
+ REWIND 0x44
+ FASTFORWARD 0x24
+ PLAYPAUSE 0xC4
+ STOP 0x64
+ RECORD 0xA4
+ AUDIO 0xE4
+ TAPE 0x14
+ DVD 0x94
+ CAPITAL_A 0xF8
+ CAPITAL_B 0x54
+ end codes
+
+end remote
+
+# brand: STM PVR-1
+
+begin remote
+ name stm_pvr_1
+ bits 16
+ flags SPACE_ENC|CONST_LENGTH
+ eps 30
+ aeps 150
+
+ header 9000 4500
+ one 572 1700
+ zero 572 572
+ ptrail 572
+ repeat 9000 2200
+ pre_data_bits 16
+ pre_data 0xFE
+ gap 100000
+
+ begin codes
+ POWER 0x00ff
+ FAVORITES 0x7887
+ MUTE 0x28d7
+ 0 0x708F
+ 1 0xc03f
+ 2 0x40bf
+ 3 0x807f
+ 4 0xe01f
+ 5 0x609f
+ 6 0xa05f
+ 7 0xd02f
+ 8 0x50af
+ 9 0x906f
+ INFO 0x38c7
+ SUBTITLE 0xe817
+ MENU 0x9867
+ EXIT 0x20df
+ EPG 0xa857
+ BACK 0x48b7
+ CURSOR_UP 0x58a7
+ CURSOR_DOWN 0xd827
+ CURSOR_LEFT 0x8877
+ CURSOR_RIGHT 0xb04f
+ OK 0x10ef
+ VOLUME_UP 0x22dd
+ VOLUME_DOWN 0x8a75
+ CHANNEL_UP 0x12ed
+ CHANNEL_DOWN 0x4ab5
+ TEXT 0xf00f
+ RADIO 0x926d
+ ZOOM 0x6897
+ AUDIO 0x08f7
+ RED 0x42bd
+ GREEN 0xa25d
+ YELLOW 0x827d
+ BLUE 0x02fd
+ CUSTOM0 0x52ad
+ CUSTOM1 0x30cf
+ PLAY 0x629d
+ PAUSE 0xb24d
+ PREVIOUS 0xc837
+ NEXT 0xf807
+ REWIND 0x32cd
+ FASTFORWARD 0x0af5
+ AUX 0x7a85
+ CUSTOM3 0xb847
+ PIP 0x3ac5
+ SWAP 0xba45
+ end codes
+
+end remote
+
+# brand: STM DTV-2
+
+begin remote
+
+ name stm_dtv_2
+ flags SHIFT_ENC|CONST_LENGTH
+ bits 13
+ aeps 150
+
+ one 850 850
+ zero 850 850
+ plead 850
+ gap 67800
+ toggle_bit 2
+
+ begin codes
+ POWER 0x100C
+ FAVORITES 0x1015
+ AUX 0x1038
+ 1 0x1001
+ 2 0x1002
+ 3 0x1003
+ 4 0x1004
+ 5 0x1005
+ 6 0x1006
+ 7 0x1007
+ 8 0x1008
+ 9 0x1009
+ PERIOD 0x1024
+ 0 0x103E
+ BACK 0x1023
+ MENU 0x1016
+ INFO 0x100F
+ EPG 0x101E
+ EXIT 0x1018
+ CURSOR_UP 0x1017
+ CURSOR_DOWN 0x101D
+ CURSOR_LEFT 0x1019
+ CURSOR_RIGHT 0x101B
+ OK 0x101A
+ VOLUME_UP 0x1010
+ VOLUME_DOWN 0x1011
+ CHANNEL_UP 0x1020
+ CHANNEL_DOWN 0x1021
+ TEXT 0x102E
+ SUBTITLE 0x103C
+ FREEZE 0x1014
+ ZOOM 0x102B
+ RED 0x1028
+ GREEN 0x102A
+ YELLOW 0x102F
+ BLUE 0x1030
+ CUSTOM10 0x1022
+ INTERNET 0x1027
+ CUSTOM11 0x102C
+ AUDIO 0x1025
+ RECORD 0x102D
+ PLAYPAUSE 0x1029
+ STOP 0x1026
+ CUSTOM1 0x101C
+ MUTE 0x100d
+ CUSTOM12 0x101F
+ PIP 0x100B
+ SWAP 0x100E
+ end codes
+
+end remote
+
+# brand: Comcast
+# model no. of remote control: XR2
+# 32 bits for the pre-date (should be value 0x170F443E)
+# width between pre_bits and data: 12900 microseconds
+#
+# 24 bits for the data (key code)
+# To get key REPEAT, XOR 0x088 with KEY value
+# There are 8 post bits (both should be zero)
+#
+# Gap between keys: 8100 microseconds
+begin remote
+
+ name Xfinity-XR2
+ bits 24
+ flags XMP
+ eps 20
+ aeps 300
+
+ one 0 137
+ zero 250 710
+ ptrail 250
+ pre_data_bits 32
+ pre_data 0x170F443E
+ post_data_bits 8
+ post_data 0x0
+ pre 250 12921
+ gap 81698
+ toggle_bit_mask 0x0
+
+ begin codes
+ 1 0x1E0001
+ 1_repeat 0x168001
+ 2 0x1D0002
+ 2_repeat 0x158002
+ 3 0x1C0003
+ 3_repeat 0x148003
+ 4 0x1B0004
+ 4_repeat 0x138004
+ 5 0x1A0005
+ 5_repeat 0x128005
+ 6 0x190006
+ 6_repeat 0x118006
+ 7 0x180007
+ 7_repeat 0x108007
+ 8 0x170008
+ 8_repeat 0x1F8008
+ 9 0x160009
+ 9_repeat 0x1E8009
+ 0 0x1F0000
+ 0_repeat 0x178000
+ OK 0x180025
+ OK_repeat 0x108025
+ POWER 0x10000F
+ POWER_repeat 0x18800F
+ UP 0x1C0021
+ UP_repeat 0x148021
+ DOWN 0x1B0022
+ DOWN_repeat 0x138022
+ LEFT 0x1A0023
+ LEFT_repeat 0x128023
+ RIGHT 0x190024
+ RIGHT_repeat 0x118024
+ REWIND 0x190033
+ REWIND_repeat 0x118033
+ PLAY 0x1C0030
+ PLAY_repeat 0x148030
+ FASTFORWARD 0x180034
+ FASTFORWARD_repeat 0x108034
+ RECORD 0x170035
+ RECORD_repeat 0x1F8035
+ REPLAY 0x170053
+ REPLAY_repeat 0x1F8053
+ A 0x190060
+ A_repeat 0x118060
+ B 0x180061
+ B_repeat 0x108061
+ C 0x170062
+ C_repeat 0x1F8062
+ D 0x160063
+ D_repeat 0x1E8063
+ PAGE_UP 0x150028
+ PAGE_UP_repeat 0x1D8028
+ PAGE_DOWN 0x140029
+ PAGE_DOWN_repeat 0x1C8029
+ GUIDE 0x160027
+ GUIDE_repeat 0x1E8027
+ MENU 0x1D0020
+ MENU_repeat 0x158020
+ EXIT 0x13002A
+ EXIT_repeat 0x1B802A
+ INFO 0x170026
+ INFO_repeat 0x1F8026
+ LAST 0x190051
+ LAST_repeat 0x118051
+ VOLUME_UP 0x15000A
+ VOLUME_UP_repeat 0x1D800A
+ CHANNEL_UP 0x12000D
+ CHANNEL_UP_repeat 0x1A800D
+ VOLUME_DOWN 0x14000B
+ VOLUME_DOWN_repeat 0x1C800B
+ CHANNEL_DOWN 0x11000E
+ CHANNEL_DOWN_repeat 0x19800E
+ MUTE 0x13000C
+ MUTE_repeat 0x1B800D
+ end codes
+
+end remote
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-connectivity/lirc/lirc/lircd.init b/meta-oe/dynamic-layers/meta-python/recipes-connectivity/lirc/lirc/lircd.init
new file mode 100644
index 0000000000..8b124af6f2
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-connectivity/lirc/lirc/lircd.init
@@ -0,0 +1,40 @@
+#! /bin/sh
+#
+# This is an init script for Familiar
+# Copy it to /etc/init.d/lircd and type
+# > update-rc.d lircd defaults 20
+#
+
+
+test -f /usr/sbin/lircd || exit 0
+test -f /etc/lircd.conf || exit 0
+
+case "$1" in
+ start)
+ echo -n "Starting lirc daemon: lircd"
+ start-stop-daemon --start --quiet --exec /usr/sbin/lircd -- --device=/dev/lirc0
+ echo "."
+ ;;
+ stop)
+ echo -n "Stopping lirc daemon: lircd"
+ start-stop-daemon --stop --quiet --exec /usr/sbin/lircd
+ echo "."
+ ;;
+ reload|force-reload)
+ start-stop-daemon --stop --quiet --signal 1 --exec /usr/sbin/lircd
+ ;;
+ restart)
+ echo -n "Stopping lirc daemon: lircd"
+ start-stop-daemon --stop --quiet --exec /usr/sbin/lircd
+ sleep 1
+ echo -n "Starting lirc daemon: lircd"
+ start-stop-daemon --start --quiet --exec /usr/sbin/lircd -- --device=/dev/lirc0
+ echo "."
+ ;;
+ *)
+ echo "Usage: /etc/init.d/lircd {start|stop|reload|restart|force-reload}"
+ exit 1
+esac
+
+exit 0
+
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-connectivity/lirc/lirc/lircd.service b/meta-oe/dynamic-layers/meta-python/recipes-connectivity/lirc/lirc/lircd.service
new file mode 100644
index 0000000000..c8661368bb
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-connectivity/lirc/lirc/lircd.service
@@ -0,0 +1,20 @@
+[Unit]
+Description=LIRC Infrared Signal Decoder
+After=network.target
+
+[Service]
+Type=forking
+EnvironmentFile=/etc/lirc/lircd.conf
+PIDFile=/run/lirc/lircd.pid
+ExecStartPre=/bin/mkdir -p /run/lirc
+ExecStartPre=/bin/rm -f /dev/lircd
+ExecStartPre=/bin/rm -f /run/lirc/lircd
+ExecStartPre=/bin/ln -s /run/lirc/lircd /dev/lircd
+
+ExecStart=/usr/sbin/lircd --pidfile=/run/lirc/lircd.pid --device=/dev/lirc0
+
+ExecStopPost=/bin/rm -f /dev/lircd
+ExecStopPost=/bin/rm -fR /run/lirc
+
+[Install]
+WantedBy=multi-user.target
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-connectivity/lirc/lirc/lircexec.init b/meta-oe/dynamic-layers/meta-python/recipes-connectivity/lirc/lirc/lircexec.init
new file mode 100644
index 0000000000..3a8c1a306e
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-connectivity/lirc/lirc/lircexec.init
@@ -0,0 +1,37 @@
+#! /bin/sh
+#
+# This is an init script for Familiar
+# Copy it to /etc/init.d/lircexecd and type
+# > update-rc.d lircexecd defaults 20
+# It must be started after lircd (and it does alphabetically :-)
+# irexec reads /etc/lircrc by default
+
+
+test -f /usr/bin/irexec || exit 0
+test -f /etc/lircrc || exit 0
+
+case "$1" in
+ start)
+ echo -n "Starting lircexec daemon: irexec"
+ start-stop-daemon --start --quiet --exec /usr/bin/irexec -- --daemon
+ echo "."
+ ;;
+ stop)
+ echo -n "Stopping lircexec daemon: irexec"
+ start-stop-daemon --stop --quiet --exec /usr/bin/irexec
+ echo "."
+ ;;
+ restart|force-restart)
+ echo -n "Stopping lircexec daemon: irexec"
+ start-stop-daemon --stop --quiet --exec /usr/bin/irexec
+ sleep 1
+ echo -n "Starting lircexec daemon: irexec"
+ start-stop-daemon --start --quiet --exec /usr/bin/irexec -- --daemon
+ echo "."
+ ;;
+ *)
+ echo "Usage: /etc/init.d/lircexec {start|stop|reload|restart|force-restart}"
+ exit 1
+esac
+
+exit 0
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-connectivity/lirc/lirc/pollfd.patch b/meta-oe/dynamic-layers/meta-python/recipes-connectivity/lirc/lirc/pollfd.patch
new file mode 100644
index 0000000000..4feea80346
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-connectivity/lirc/lirc/pollfd.patch
@@ -0,0 +1,101 @@
+Index: lirc-0.9.4d/daemons/lircrcd.cpp
+===================================================================
+--- lirc-0.9.4d.orig/daemons/lircrcd.cpp
++++ lirc-0.9.4d/daemons/lircrcd.cpp
+@@ -29,10 +29,12 @@
+ #include <sys/un.h>
+ #include <sys/stat.h>
+ #include <sys/types.h>
++#include <poll.h>
+ #include <syslog.h>
+
+ #include "lirc_client.h"
+ #include "lirc/lirc_log.h"
++#include "lirc/curl_poll.h"
+
+ #define MAX_CLIENTS 100
+ #define WHITE_SPACE " \t"
+Index: lirc-0.9.4d/lib/curl_poll.c
+===================================================================
+--- lirc-0.9.4d.orig/lib/curl_poll.c
++++ lirc-0.9.4d/lib/curl_poll.c
+@@ -36,6 +36,7 @@
+ #include <stdlib.h>
+ #include <sys/time.h>
+ #include <sys/types.h>
++#include <sys/poll.h>
+
+ #include "lirc_log.h"
+ #include "curl_poll.h"
+@@ -67,7 +68,7 @@ static const logchannel_t logchannel = L
+
+ #ifdef HAVE_POLL_FINE
+
+-int curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms)
++int curl_poll(struct pollfd *ufds, unsigned int nfds, int timeout_ms)
+ {
+ return poll(ufds, nfds, timeout_ms);
+ }
+@@ -112,7 +113,7 @@ static int verify_sock(int s)
+ }
+
+
+-int curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms)
++int curl_poll(struct pollfd *ufds, unsigned int nfds, int timeout_ms)
+ {
+ struct timeval pending_tv;
+ struct timeval* ptimeout;
+Index: lirc-0.9.4d/lib/curl_poll.h
+===================================================================
+--- lirc-0.9.4d.orig/lib/curl_poll.h
++++ lirc-0.9.4d/lib/curl_poll.h
+@@ -1,5 +1,5 @@
+-#ifndef _POLL_H
+-#define _POLL_H
++#ifndef _LIB_CURL_POLL_H
++#define _LIB_CURL_POLL_H
+ /***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+@@ -29,13 +29,9 @@
+ extern "C" {
+ #endif
+
+-#ifdef HAVE_SYS_POLL_H
+-#include <sys/poll.h>
+-#else
+ #include <poll.h>
+-#endif
+
+-int curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms);
++int curl_poll(struct pollfd *ufds, unsigned int nfds, int timeout_ms);
+
+ #ifdef __cplusplus
+ }
+Index: lirc-0.9.4d/lib/lirc/curl_poll.h
+===================================================================
+--- lirc-0.9.4d.orig/lib/lirc/curl_poll.h
++++ lirc-0.9.4d/lib/lirc/curl_poll.h
+@@ -1,5 +1,5 @@
+-#ifndef _POLL_H
+-#define _POLL_H
++#ifndef _LIRC_CURL_POLL_H
++#define _LIRC_CURL_POLL_H
+ /***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+@@ -29,13 +29,9 @@
+ extern "C" {
+ #endif
+
+-#ifdef HAVE_SYS_POLL_H
+-#include <sys/poll.h>
+-#else
+ #include <poll.h>
+-#endif
+
+-int curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms);
++int curl_poll(struct pollfd *ufds, unsigned int nfds, int timeout_ms);
+
+ #ifdef __cplusplus
+ }
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-connectivity/lirc/lirc_0.9.4d.bb b/meta-oe/dynamic-layers/meta-python/recipes-connectivity/lirc/lirc_0.9.4d.bb
new file mode 100644
index 0000000000..f599696737
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-connectivity/lirc/lirc_0.9.4d.bb
@@ -0,0 +1,86 @@
+DESCRIPTION = "LIRC is a package that allows you to decode and send infra-red signals of many commonly used remote controls."
+DESCRIPTION_append_lirc = " This package contains the lirc daemon, libraries and tools."
+DESCRIPTION_append_lirc-exec = " This package contains a daemon that runs programs on IR signals."
+DESCRIPTION_append_lirc-remotes = " This package contains some config files for remotes."
+DESCRIPTION_append_lirc-nslu2example = " This package contains a working config for RC5 remotes and a modified NSLU2."
+HOMEPAGE = "http://www.lirc.org"
+SECTION = "console/network"
+LICENSE = "GPLv2"
+DEPENDS = "libxslt-native alsa-lib libftdi libusb1 libusb-compat jack portaudio-v19 python3-pyyaml"
+
+LIC_FILES_CHKSUM = "file://COPYING;md5=b234ee4d69f5fce4486a80fdaf4a4263"
+
+SRC_URI = "http://prdownloads.sourceforge.net/lirc/lirc-${PV}.tar.bz2 \
+ file://pollfd.patch \
+ file://0001-Fix-build-on-32bit-arches-with-64bit-time_t.patch \
+ file://lircd.service \
+ file://lircd.init \
+ file://lircexec.init \
+ file://lircd.conf \
+ file://lirc_options.conf \
+ file://lirc.tmpfiles \
+"
+SRC_URI[md5sum] = "0d11679cbdd94a5a6da00a8e7231b4bf"
+SRC_URI[sha256sum] = "c68f18c35b489b865c0a741d119b136e8702191538cd3551b977a7af6c4e41ab"
+
+SYSTEMD_PACKAGES = "lirc lirc-exec"
+SYSTEMD_SERVICE_${PN} = "lircd.service lircmd.service lircd-setup.service lircd-uinput.service"
+SYSTEMD_SERVICE_${PN}-exec = "irexec.service"
+SYSTEMD_AUTO_ENABLE_lirc = "enable"
+SYSTEMD_AUTO_ENABLE_lirc-exec = "enable"
+
+inherit autotools pkgconfig systemd python3native
+
+PACKAGECONFIG[systemd] = "--with-systemdsystemunitdir=${systemd_unitdir}/system/,--without-systemdsystemunitdir,systemd"
+PACKAGECONFIG[x11] = "--with-x,--with-x=no,libx11,"
+
+PACKAGECONFIG ?= " \
+ ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', ' systemd', '', d)} \
+ ${@bb.utils.contains('DISTRO_FEATURES', 'x11', ' x11', '', d)} \
+"
+CACHED_CONFIGUREVARS = "HAVE_WORKING_POLL=yes"
+
+#EXTRA_OEMAKE = 'SUBDIRS="lib daemons tools"'
+do_install_append() {
+ install -m 0755 -d ${D}${sysconfdir}
+ install -m 0755 -d ${D}${sysconfdir}/lirc
+ install -m 0755 -d ${D}${systemd_unitdir}/system
+ install -m 0755 -d ${D}${libdir}/tmpfiles.d
+ install -m 0644 ${WORKDIR}/lircd.conf ${D}${sysconfdir}/lirc/
+ install -m 0644 ${WORKDIR}/lirc_options.conf ${D}${sysconfdir}/lirc/
+ install -m 0644 ${WORKDIR}/lircd.service ${D}${systemd_unitdir}/system/
+ install -m 0755 ${WORKDIR}/lircexec.init ${D}${systemd_unitdir}/system/
+ install -m 0644 ${WORKDIR}/lirc.tmpfiles ${D}${libdir}/tmpfiles.d/lirc.conf
+ rm -rf ${D}${libdir}/lirc/plugins/*.la
+ rmdir ${D}/var/run/lirc ${D}/var/run
+ chown -R root:root ${D}${datadir}/lirc/contrib
+}
+
+PACKAGES =+ "${PN}-contrib ${PN}-exec ${PN}-plugins ${PN}-python"
+
+RDEPENDS_${PN} = "bash"
+RDEPENDS_${PN}-exec = "${PN}"
+RDEPENDS_${PN}-python = "python3-shell python3-pyyaml python3-datetime python3-netclient python3-stringold"
+
+RRECOMMENDS_${PN} = "${PN}-exec ${PN}-plugins"
+
+FILES_${PN}-plugins = "${libdir}/lirc/plugins/*.so ${datadir}/lirc/configs"
+FILES_${PN}-contrib = "${datadir}/lirc/contrib"
+FILES_${PN}-exec = "${bindir}/irexec ${sysconfdir}/lircexec ${systemd_unitdir}/system/irexec.service"
+FILES_${PN} += "${systemd_unitdir}/system/lircexec.init"
+FILES_${PN} += "${systemd_unitdir}/system/lircd.service"
+FILES_${PN} += "${systemd_unitdir}/system/lircd.socket"
+FILES_${PN} += "${libdir}/tmpfiles.d/lirc.conf"
+FILES_${PN}-dbg += "${libdir}/lirc/plugins/.debug"
+FILES_${PN}-python += "${bindir}/irdb-get ${bindir}/irtext2udp ${bindir}/lircd-setup ${bindir}/pronto2lirc ${libdir}/python*/site-packages"
+
+INITSCRIPT_PACKAGES = "lirc lirc-exec"
+INITSCRIPT_NAME_lirc-exec = "lircexec"
+INITSCRIPT_PARAMS_lirc-exec = "defaults 21"
+
+# this is for distributions that don't use udev
+pkg_postinst_${PN}_append() {
+ if [ ! -c $D/dev/lirc -a ! -f /sbin/udevd ]; then mknod $D/dev/lirc c 61 0; fi
+}
+
+SECURITY_CFLAGS = "${SECURITY_NO_PIE_CFLAGS}"
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-core/packagegroups/packagegroup-meta-oe.bb b/meta-oe/dynamic-layers/meta-python/recipes-core/packagegroups/packagegroup-meta-oe.bb
new file mode 100644
index 0000000000..e04b48f85a
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-core/packagegroups/packagegroup-meta-oe.bb
@@ -0,0 +1,314 @@
+SUMMARY = "Meta-oe ptest packagegroups"
+
+PACKAGE_ARCH = "${MACHINE_ARCH}"
+inherit packagegroup
+
+PROVIDES = "${PACKAGES}"
+PACKAGES = ' \
+ packagegroup-meta-oe \
+ packagegroup-meta-oe-benchmarks \
+ packagegroup-meta-oe-connectivity \
+ packagegroup-meta-oe-core \
+ packagegroup-meta-oe-crypto \
+ packagegroup-meta-oe-bsp \
+ packagegroup-meta-oe-dbs \
+ packagegroup-meta-oe-devtools \
+ packagegroup-meta-oe-extended \
+ packagegroup-meta-oe-kernel \
+ packagegroup-meta-oe-multimedia \
+ packagegroup-meta-oe-navigation \
+ packagegroup-meta-oe-security \
+ packagegroup-meta-oe-support \
+ packagegroup-meta-oe-test \
+ ${@bb.utils.contains("DISTRO_FEATURES", "x11", "packagegroup-meta-oe-gnome", "", d)} \
+ ${@bb.utils.contains("DISTRO_FEATURES", "x11", "packagegroup-meta-oe-graphics", "", d)} \
+ ${@bb.utils.contains("DISTRO_FEATURES", "ptest", "packagegroup-meta-oe-ptest-packages", "", d)} \
+'
+
+RDEPENDS_packagegroup-meta-oe = "\
+ packagegroup-meta-oe-benchmarks \
+ packagegroup-meta-oe-connectivity \
+ packagegroup-meta-oe-core \
+ packagegroup-meta-oe-crypto \
+ packagegroup-meta-oe-bsp \
+ packagegroup-meta-oe-dbs \
+ packagegroup-meta-oe-devtools \
+ packagegroup-meta-oe-extended \
+ packagegroup-meta-oe-kernel \
+ packagegroup-meta-oe-multimedia \
+ packagegroup-meta-oe-navigation \
+ packagegroup-meta-oe-security \
+ packagegroup-meta-oe-support \
+ packagegroup-meta-oe-test \
+ ${@bb.utils.contains("DISTRO_FEATURES", "x11", "packagegroup-meta-oe-gnome", "", d)} \
+ ${@bb.utils.contains("DISTRO_FEATURES", "x11", "packagegroup-meta-oe-graphics", "", d)} \
+ ${@bb.utils.contains("DISTRO_FEATURES", "ptest", "packagegroup-meta-oe-ptest-packages", "", d)} \
+"
+
+RDEPENDS_packagegroup-meta-oe-benchmarks = "\
+ dhrystone iperf2 linpack phoronix-test-suite \
+ tiobench bonnie++ fio iperf2 iperf3 lmbench s-suite whetstone \
+ libc-bench memtester sysbench dbench iozone3 libhugetlbfs \
+ nbench-byte tinymembench \
+ ${@bb.utils.contains("DISTRO_FEATURES", "x11 wayland opengl", "glmark2", "", d)} \
+"
+
+RDEPENDS_packagegroup-meta-oe-benchmarks_remove_mipsarch = "libhugetlbfs"
+RDEPENDS_packagegroup-meta-oe-benchmarks_remove_mips64 = "tinymembench"
+RDEPENDS_packagegroup-meta-oe-benchmarks_remove_mips64el = "tinymembench"
+RDEPENDS_packagegroup-meta-oe-benchmarks_remove_riscv64 = "libhugetlbfs"
+RDEPENDS_packagegroup-meta-oe-benchmarks_remove_riscv32 = "libhugetlbfs"
+
+RDEPENDS_packagegroup-meta-oe-connectivity ="\
+ gammu hostapd irssi krb5 libev libimobiledevice \
+ libmbim libmtp libndp libqmi libtorrent \
+ libuv libwebsockets linuxptp lirc loudmouth \
+ modemmanager mosh \
+ paho-mqtt-c phonet-utils rabbitmq-c rfkill rtorrent \
+ ser2net smstools3 telepathy-glib thrift \
+ usbmuxd zabbix zeromq \
+ ${@bb.utils.contains("DISTRO_FEATURES", "x11", "obex-data-server", "", d)} \
+ libmikmod \
+ obexftp openobex libnet \
+ ${@bb.utils.contains("BBFILE_COLLECTIONS", "meta-python2", "telepathy-idle", "", d)} \
+ "
+RDEPENDS_packagegroup-meta-oe-connectivity_append_libc-glibc = " wvstreams wvdial"
+
+# dracut needs dracut
+RDEPENDS_packagegroup-meta-oe-core ="\
+ dbus-daemon-proxy libdbus-c++ \
+ ell glibmm libsigc++-2.0 libxml++ distro-feed-configs \
+ mm-common opencl-headers opencl-icd-loader \
+ proxy-libintl usleep \
+ ${@bb.utils.contains("DISTRO_FEATURES", "systemd", "dbus-broker ndctl", "", d)} \
+ "
+
+RDEPENDS_packagegroup-meta-oe-crypto ="\
+ botan cryptsetup libkcapi libmcrypt \
+ libsodium pkcs11-helper \
+ "
+RDEPENDS_packagegroup-meta-oe-bsp ="\
+ acpitool cpufrequtils edac-utils efibootmgr \
+ efivar flashrom lmsensors lmsensors-config \
+ lsscsi nvme-cli pcmciautils pointercal \
+ "
+RDEPENDS_packagegroup-meta-oe-bsp_remove_mipsarch = "efivar efibootmgr"
+RDEPENDS_packagegroup-meta-oe-bsp_remove_powerpc = "efivar efibootmgr"
+RDEPENDS_packagegroup-meta-oe-bsp_remove_powerpc64 = "efivar efibootmgr"
+RDEPENDS_packagegroup-meta-oe-bsp_remove_powerpc64le = "efivar efibootmgr"
+RDEPENDS_packagegroup-meta-oe-bsp_remove_riscv64 = "efivar efibootmgr"
+RDEPENDS_packagegroup-meta-oe-bsp_remove_riscv32 = "efivar efibootmgr"
+
+RDEPENDS_packagegroup-meta-oe-dbs ="\
+ leveldb libdbi mariadb mariadb-native \
+ postgresql psqlodbc rocksdb soci \
+ sqlite \
+ ${@bb.utils.contains("BBFILE_COLLECTIONS", "meta-python2", "mysql-python", "", d)} \
+ "
+
+RDEPENDS_packagegroup-meta-oe-devtools ="\
+ android-tools android-tools-conf bootchart breakpad \
+ capnproto cgdb cscope ctags \
+ debootstrap dmalloc flatbuffers \
+ giflib grpc icon-slicer iptraf-ng jq jsoncpp jsonrpc json-spirit \
+ kconfig-frontends lemon libedit libgee libsombok3 \
+ libubox log4cplus lshw ltrace lua mcpp memstat mercurial \
+ mpich msgpack-c nlohmann-json openocd pax-utils \
+ ipc-run libdbd-mysql-perl libdbi-perl libio-pty-perl php \
+ protobuf protobuf-c python3-distutils-extra \
+ rapidjson serialcheck sip3 tclap uftrace uw-imap valijson \
+ xmlrpc-c yajl yasm \
+ ${@bb.utils.contains("DISTRO_FEATURES", "x11", "geany geany-plugins glade tk", "", d)} \
+ ${@bb.utils.contains("BBFILE_COLLECTIONS", "meta-python2", "nodejs", "", d)} \
+ "
+
+RDEPENDS_packagegroup-meta-oe-devtools_remove_armv5 = "uftrace nodejs"
+RDEPENDS_packagegroup-meta-oe-devtools_remove_mipsarch = "uftrace lshw"
+RDEPENDS_packagegroup-meta-oe-devtools_remove_mips64 = "nodejs"
+RDEPENDS_packagegroup-meta-oe-devtools_remove_mips64el = "nodejs"
+RDEPENDS_packagegroup-meta-oe-devtools_remove_powerpc = "android-tools breakpad uftrace lshw"
+RDEPENDS_packagegroup-meta-oe-devtools_remove_powerpc64 = "android-tools uftrace lshw"
+RDEPENDS_packagegroup-meta-oe-devtools_remove_powerpc64le = "android-tools uftrace lshw"
+RDEPENDS_packagegroup-meta-oe-devtools_remove_riscv64 = "nodejs uftrace lshw"
+RDEPENDS_packagegroup-meta-oe-devtools_remove_riscv32 = "nodejs uftrace lshw"
+
+RDEPENDS_packagegroup-meta-oe-extended ="\
+ byacc cfengine cfengine-masterfiles cmpi-bindings \
+ ddrescue dialog dumb-init enscript fluentbit \
+ haveged hexedit hiredis hplip hwloc indent iotop isomd5sum \
+ jansson konkretcmpi lcdproc libblockdev libcec libconfig \
+ libdivecomputer libplist libusbmuxd \
+ liblockfile liblogging liblognorm libmodbus libmodbus \
+ libpwquality libqb libuio \
+ lockfile-progs logwatch lprng mailx md5deep \
+ mozjs mraa nana nicstat \
+ p7zip p8platform libfile-fnmatch-perl \
+ rarpd redis rrdtool libfastjson librelp rsyslog sanlock \
+ sblim-cmpi-devel sblim-sfc-common sblim-sfcc \
+ scsirastools sgpio smartmontools snappy \
+ can-utils libsocketcan tipcutils tiptop \
+ tmux uml-utilities upm vlock volume-key wipe zlog zram \
+ ${@bb.utils.contains("DISTRO_FEATURES", "x11 wayland opengl", "boinc-client", "", d)} \
+ ${@bb.utils.contains("DISTRO_FEATURES", "x11", " libgxim gnuplot libwmf", "", d)} \
+ ${@bb.utils.contains("DISTRO_FEATURES", "bluez", "collectd", "", d)} \
+ ${@bb.utils.contains("DISTRO_FEATURES", "pam", "pam-plugin-ccreds pam-plugin-ldapdb", "", d)} \
+ ${@bb.utils.contains("DISTRO_FEATURES", "pam", "pam-ssh-agent-auth openwsman sblim-sfcb ", "", d)} \
+ ${@bb.utils.contains("DISTRO_FEATURES", "polkit", "polkit polkit-group-rule-datetime ", "", d)} \
+ ${@bb.utils.contains("DISTRO_FEATURES", "polkit", "polkit-group-rule-network ", "", d)} \
+ ${@bb.utils.contains("BBFILE_COLLECTIONS", "meta-python2", "openlmi-tools", "", d)} \
+ "
+RDEPENDS_packagegroup-meta-oe-extended_remove_mipsarch = "upm mraa tiptop"
+RDEPENDS_packagegroup-meta-oe-extended_remove_powerpc = "upm mraa"
+RDEPENDS_packagegroup-meta-oe-extended_remove_powerpc64 = "upm mraa"
+RDEPENDS_packagegroup-meta-oe-extended_remove_powerpc64le = "upm mraa"
+RDEPENDS_packagegroup-meta-oe-extended_remove_riscv64 = "upm mraa tiptop"
+RDEPENDS_packagegroup-meta-oe-extended_remove_riscv32 = "upm mraa tiptop"
+RDEPENDS_packagegroup-meta-oe-extended_remove_libc-musl = "lcdproc"
+
+RDEPENDS_packagegroup-meta-oe-gnome ="\
+ atkmm gnome-common gnome-doc-utils-stub gtkmm \
+ gtkmm3 pyxdg vte9 \
+ "
+
+RDEPENDS_packagegroup-meta-oe-graphics ="\
+ cairomm dietsplash directfb directfb-examples \
+ ${@bb.utils.contains("PACKAGE_CLASSES", "package_rpm", "dnfdragora dnf-plugin-tui", "", d)} \
+ fbgrab fbida fontforge fvwm glm gphoto2 libgphoto2 \
+ gtkperf jasper leptonica libmng libsdl2-image libsdl2-mixer libsdl2-net \
+ libsdl-gfx libsdl-image libsdl-mixer libsdl-net libsdl-ttf \
+ libvncserver libyui libyui-ncurses lxdm numlockx openbox openjpeg \
+ packagegroup-fonts-truetype pangomm qrencode takao-fonts terminus-font \
+ tesseract tesseract-lang tigervnc tslib source-han-sans-cn-fonts \
+ source-han-sans-jp-fonts source-han-sans-kr-fonts source-han-sans-tw-fonts ttf-abyssinica \
+ libvdpau x11vnc xcursorgen xdotool \
+ bdftopcf iceauth sessreg setxkbmap twm xclock xfontsel xgamma xkbevd xkbprint xkbutils \
+ xlsatoms xlsclients xlsfonts xmag xmessage xrdb xrefresh xsetmode xsetroot xstdcmap \
+ xterm xwd xwud xbitmaps xorg-sgml-doctools \
+ font-adobe-100dpi font-adobe-utopia-100dpi \
+ font-bh-100dpi font-bh-lucidatypewriter-100dpi font-bitstream-100dpi font-cursor-misc \
+ font-misc-misc xorg-fonts-100dpi liblbxutil libxaw libxkbui libxpresent xserver-common \
+ ${@bb.utils.contains("DISTRO_FEATURES", "opengl", "freeglut libsdl2-ttf", "", d)} \
+ "
+
+
+
+RDEPENDS_packagegroup-meta-oe-kernel ="\
+ agent-proxy broadcom-bt-firmware cpupower \
+ crash ipmitool minicoredumper oprofile \
+ "
+RDEPENDS_packagegroup-meta-oe-kernel_append_x86 = " pm-graph "
+RDEPENDS_packagegroup-meta-oe-kernel_append_x86-64 = " pm-graph "
+
+RDEPENDS_packagegroup-meta-oe-kernel_remove_libc-musl = "crash minicoredumper"
+
+RDEPENDS_packagegroup-meta-oe-kernel_remove_mips64 = "crash"
+RDEPENDS_packagegroup-meta-oe-kernel_remove_mips64el = "crash"
+
+RDEPENDS_packagegroup-meta-oe-multimedia ="\
+ alsa-oss audiofile cdrkit id3lib \
+ a2jmidid jack libass libburn libcdio libcdio-paranoia \
+ libdvdread libmms libmodplug libopus live555 \
+ mplayer-common opus-tools \
+ sound-theme-freedesktop v4l-utils yavta wavpack libvpx \
+ ${@bb.utils.contains("DISTRO_FEATURES", "x11", "xpext pavucontrol xsp", "", d)} \
+ libmikmod \
+ ${@bb.utils.contains("LICENSE_FLAGS_WHITELIST", "commercial", "libmad faad2 mpv", "", d)} \
+ "
+RDEPENDS_packagegroup-meta-oe-multimedia_remove_libc-musl = "alsa-oss"
+
+RDEPENDS_packagegroup-meta-oe-navigation ="\
+ geoclue geos libspatialite proj \
+ ${@bb.utils.contains("DISTRO_FEATURES", "x11", "orrery", "", d)} \
+ ${@bb.utils.contains("DISTRO_FEATURES", "bluz4", "gpsd gpsd-machine-conf", "", d)} \
+ "
+
+RDEPENDS_packagegroup-meta-oe-security ="\
+ tomoyo-tools \
+ ${@bb.utils.contains("DISTRO_FEATURES", "pam", "passwdqc", "", d)} \
+ ${@bb.utils.contains("DISTRO_FEATURES", "bluz5", "nmap", "", d)} \
+ "
+
+RDEPENDS_packagegroup-meta-oe-shells ="\
+ dash tcsh zsh \
+ "
+
+NE10 = ""
+NE10_aarch64 = "ne10"
+NE10_armv7a = "ne10"
+NE10_armv7ve = "ne10"
+
+RDEPENDS_packagegroup-meta-oe-support ="\
+ anthy asio atop augeas avro-c bdwgc frame grail c-ares \
+ ccid ceres-solver ckermit cpprest ctapi-common daemonize \
+ daemontools debsums devmem2 dfu-util dfu-util-native digitemp \
+ dstat eject enca epeg espeak fbset fbset-modes \
+ fftw fltk-native gd gflags glog gnulib gperftools \
+ gpm gradm gsl gsoap hddtemp hidapi htop hunspell hwdata iksemel \
+ libinih inotify-tools joe lcms lcov libatasmart libbytesize \
+ libcereal libcyusbserial libee libeigen libestr libftdi libgit2 \
+ libgpiod libiio libjs-jquery libjs-sizzle liblinebreak libmicrohttpd \
+ libmxml liboauth libol liboop libp11 libraw1394 libsmi libsoc libssh2 \
+ libssh libtar libteam libtinyxml2 libtinyxml libusbg libusb-compat libutempter \
+ links lockdev log4c log4cpp logwarn libdevmapper lvm2 \
+ mailcap mbuffer mg minini \
+ multipath-tools nano neon nmon numactl onig openct openldap \
+ opensc wbxml2 p910nd pcsc-lite picocom libotr pidgin \
+ pngcheck poco poppler poppler-data portaudio-v19 pps-tools \
+ pv pxaregs raptor2 rdfind read-edid rsnapshot \
+ satyr sdparm pty-forward-native serial-forward \
+ sg3-utils sharutils smem spitools srecord ssiapi stm32flash \
+ syslog-ng system-config-keyboard tbb thin-provisioning-tools tokyocabinet \
+ tree uhubctl unixodbc uriparser usb-modeswitch \
+ usb-modeswitch-data uthash utouch-evemu utouch-frame \
+ vim vim-tiny websocketpp xdelta3 xdg-user-dirs xmlstarlet \
+ zbar zile \
+ ${@bb.utils.contains("DISTRO_FEATURES", "x11", "geis toscoterm uim synergy utouch-mtview links-x11 fltk pidgin-otr", "", d)} \
+ libcanberra \
+ ${@bb.utils.contains("DISTRO_FEATURES", "x11 pam", "xorgxrdp xrdp", "", d)} \
+ procmail \
+ ${@bb.utils.contains("DISTRO_FEATURES", "polkit", "udisks2 upower", "", d)} \
+ ${NE10} \
+ ${@bb.utils.contains("BBFILE_COLLECTIONS", "meta-python2", "lio-utils", "", d)} \
+ "
+
+RDEPENDS_packagegroup-meta-oe-support_remove_arm ="numactl"
+RDEPENDS_packagegroup-meta-oe-support_remove_mipsarch = "gperftools"
+RDEPENDS_packagegroup-meta-oe-support_remove_riscv64 = "uim"
+RDEPENDS_packagegroup-meta-oe-support_remove_riscv32 = "uim"
+RDEPENDS_packagegroup-meta-oe-support_remove_powerpc = "ssiapi"
+
+RDEPENDS_packagegroup-meta-oe-support-egl ="\
+ freerdp libnice opencv \
+ "
+
+RDEPENDS_packagegroup-meta-oe-test ="\
+ catch2 cppunit cunit cxxtest evtest fb-test \
+ fwts googletest pm-qa stress-ng testfloat \
+ "
+RDEPENDS_packagegroup-meta-oe-test_remove_libc-musl = "pm-qa"
+RDEPENDS_packagegroup-meta-oe-test_remove_arm = "fwts"
+RDEPENDS_packagegroup-meta-oe-test_remove_mipsarch = "fwts"
+RDEPENDS_packagegroup-meta-oe-test_remove_powerpc = "fwts"
+RDEPENDS_packagegroup-meta-oe-test_remove_riscv64 = "fwts"
+RDEPENDS_packagegroup-meta-oe-test_remove_riscv32 = "fwts"
+
+RDEPENDS_packagegroup-meta-oe-ptest-packages = "\
+ zeromq-ptest \
+ leveldb-ptest \
+ psqlodbc-ptest \
+ lua-ptest \
+ protobuf-ptest \
+ rsyslog-ptest \
+ oprofile-ptest \
+ libteam-ptest \
+ uthash-ptest \
+ libee-ptest \
+ poco-ptest \
+ "
+RDEPENDS_packagegroup-meta-oe-ptest-packages_append_x86 = "\
+ mcelog-ptest \
+"
+RDEPENDS_packagegroup-meta-oe-ptest-packages_append_x86-64 = "\
+ mcelog-ptest \
+"
+RDEPENDS_packagegroup-meta-oe-ptest-packages_remove_arm = "numactl-ptest"
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb/0001-IntelRDFPMathLib20U1-Check-for-__DEFINED_wchar_t.patch b/meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb/0001-IntelRDFPMathLib20U1-Check-for-__DEFINED_wchar_t.patch
new file mode 100644
index 0000000000..e636adc556
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb/0001-IntelRDFPMathLib20U1-Check-for-__DEFINED_wchar_t.patch
@@ -0,0 +1,35 @@
+From 97914aeab52b4d0ea0ab9e5ff985a1c5cddb0fa1 Mon Sep 17 00:00:00 2001
+From: Vincent Prince <vincent.prince.fr@gmail.com>
+Date: Mon, 16 Sep 2019 13:41:39 +0200
+Subject: [PATCH 06/10] IntelRDFPMathLib20U1: Check for __DEFINED_wchar_t
+
+This is defined by musl if wchar_t is already defined
+
+avoids errors like
+
+src/third_party/IntelRDFPMathLib20U1/LIBRARY/src/bid_functions.h:46:15: error: typedef redefinition with different types
+ ('int' vs 'unsigned int')
+typedef int wchar_t;
+
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+Signed-off-by: Vincent Prince <vincent.prince.fr@gmail.com>
+---
+ src/third_party/IntelRDFPMathLib20U1/LIBRARY/src/bid_functions.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/third_party/IntelRDFPMathLib20U1/LIBRARY/src/bid_functions.h b/src/third_party/IntelRDFPMathLib20U1/LIBRARY/src/bid_functions.h
+index 56775bc..be96a85 100755
+--- a/src/third_party/IntelRDFPMathLib20U1/LIBRARY/src/bid_functions.h
++++ b/src/third_party/IntelRDFPMathLib20U1/LIBRARY/src/bid_functions.h
+@@ -43,7 +43,7 @@
+
+ #if 0 // MongoDB Modification -- just `#include <stddef.h>`
+ // Fix system header issue on Sun solaris and define required type by ourselves
+-#if !defined(_WCHAR_T) && !defined(_WCHAR_T_DEFINED) && !defined(__QNX__)
++#if !defined(_WCHAR_T) && !defined(_WCHAR_T_DEFINED) && !defined(__QNX__) && !defined(__DEFINED_wchar_t)
+ typedef int wchar_t;
+ #endif
+ #else
+--
+2.7.4
+
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb/0001-Mark-one-of-strerror_r-implementation-glibc-specific.patch b/meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb/0001-Mark-one-of-strerror_r-implementation-glibc-specific.patch
new file mode 100644
index 0000000000..5337fcdbfd
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb/0001-Mark-one-of-strerror_r-implementation-glibc-specific.patch
@@ -0,0 +1,31 @@
+From ca004968b8d2149f72d4edcfe029489a8c5e10ca Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Mon, 23 Sep 2019 12:31:31 -0700
+Subject: [PATCH] Mark one of strerror_r implementation glibc specific
+
+glibc has two incompatible strerror_r definitions, one of them is
+specific to glibc, mark this one so
+
+Upstream-Status: Pending
+
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ src/mongo/util/errno_util.cpp | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/mongo/util/errno_util.cpp b/src/mongo/util/errno_util.cpp
+index 564c0071ea..4f7e1d3a38 100644
+--- a/src/mongo/util/errno_util.cpp
++++ b/src/mongo/util/errno_util.cpp
+@@ -61,7 +61,7 @@ std::string errnoWithDescription(int errNumber) {
+ char buf[kBuflen];
+ char* msg{nullptr};
+
+-#if defined(__GNUC__) && defined(_GNU_SOURCE) && \
++#if defined(__GNUC__) && defined(_GNU_SOURCE) && defined(__GLIBC__) && \
+ (!defined(__ANDROID_API__) || !(__ANDROID_API__ <= 22)) && !defined(EMSCRIPTEN)
+ msg = strerror_r(errNumber, buf, kBuflen);
+ #elif defined(_WIN32)
+--
+2.23.0
+
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb/0001-Support-deprecated-resolver-functions.patch b/meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb/0001-Support-deprecated-resolver-functions.patch
new file mode 100644
index 0000000000..3d949c8730
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb/0001-Support-deprecated-resolver-functions.patch
@@ -0,0 +1,33 @@
+From 8d035e84c2edb44461ef4df9cdef0a6dfce0a1d7 Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Fri, 24 Aug 2018 12:56:22 -0700
+Subject: [PATCH 07/10] Support deprecated resolver functions
+
+Needed for musl libc
+
+Upstream-Status: Pending
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ src/mongo/util/dns_query_posix-impl.h | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/src/mongo/util/dns_query_posix-impl.h b/src/mongo/util/dns_query_posix-impl.h
+index a5e3629..fb29d2d 100644
+--- a/src/mongo/util/dns_query_posix-impl.h
++++ b/src/mongo/util/dns_query_posix-impl.h
+@@ -54,6 +54,12 @@
+
+ #include <boost/noncopyable.hpp>
+
++#ifndef res_ninit
++#define res_nclose(arg)
++#define res_ninit(arg) res_init()
++#define res_nsearch(sta, nam, clas, typ, ans, alen) res_search(nam, clas, typ, ans, alen)
++#endif
++
+ namespace mongo {
+ namespace dns {
+ // The anonymous namespace is safe, in this header, as it is not really a header. It is only used
+--
+2.7.4
+
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb/0001-Tell-scons-to-use-build-settings-from-environment-va.patch b/meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb/0001-Tell-scons-to-use-build-settings-from-environment-va.patch
new file mode 100644
index 0000000000..1908846245
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb/0001-Tell-scons-to-use-build-settings-from-environment-va.patch
@@ -0,0 +1,56 @@
+From 1b2e24e14ee72e54e466be2512c78272f62d60b4 Mon Sep 17 00:00:00 2001
+From: Vincent Prince <vincent.prince.fr@gmail.com>
+Date: Mon, 16 Sep 2019 13:21:44 +0200
+Subject: [PATCH 01/10] Tell scons to use build settings from environment
+ variables
+
+Signed-off-by: Sven Ebenfeld <sven.ebenfeld@gmail.com>
+Signed-off-by: Vincent Prince <vincent.prince.fr@gmail.com>
+---
+ SConstruct | 8 ++++++--
+ 1 files changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/SConstruct b/SConstruct
+index 7ebbcbc..e63cf15 100644
+--- a/SConstruct
++++ b/SConstruct
+@@ -608,6 +608,7 @@ def variable_arch_converter(val):
+ 'amd64': 'x86_64',
+ 'emt64': 'x86_64',
+ 'x86': 'i386',
++ 'aarch64': 'arm64',
+ }
+ val = val.lower()
+
+@@ -695,7 +696,8 @@ env_vars.Add(
+ )
+
+ env_vars.Add('CC',
+- help='Select the C compiler to use')
++ help='Select the C compiler to use',
++ default=os.getenv('CC'))
+
+ env_vars.Add('CCFLAGS',
+ help='Sets flags for the C and C++ compiler',
+@@ -715,7 +717,8 @@ env_vars.Add('CPPPATH',
+ converter=variable_shlex_converter)
+
+ env_vars.Add('CXX',
+- help='Select the C++ compiler to use')
++ help='Select the C++ compiler to use',
++ default=os.getenv('CXX'))
+
+ env_vars.Add('CXXFLAGS',
+ help='Sets flags for the C++ compiler',
+@@ -1018,6 +1021,7 @@ envDict = dict(BUILD_ROOT=buildDir,
+ )
+
+ env = Environment(variables=env_vars, **envDict)
++env.PrependENVPath('PATH', os.getenv('PATH'))
+ del envDict
+
+ for var in ['CC', 'CXX']:
+
+--
+2.7.4
+
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb/0001-Use-__GLIBC__-to-control-use-of-gnu_get_libc_version.patch b/meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb/0001-Use-__GLIBC__-to-control-use-of-gnu_get_libc_version.patch
new file mode 100644
index 0000000000..d98fa56cbb
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb/0001-Use-__GLIBC__-to-control-use-of-gnu_get_libc_version.patch
@@ -0,0 +1,41 @@
+From d701ceeb15662038435b80ba556a80c17f76d2dc Mon Sep 17 00:00:00 2001
+From: Vincent Prince <vincent.prince.fr@gmail.com>
+Date: Mon, 16 Sep 2019 13:30:13 +0200
+Subject: [PATCH 03/10] Use __GLIBC__ to control use of gnu_get_libc_version
+
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+Signed-off-by: Vincent Prince <vincent.prince.fr@gmail.com>
+---
+ src/mongo/util/processinfo_linux.cpp | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/src/mongo/util/processinfo_linux.cpp b/src/mongo/util/processinfo_linux.cpp
+index cccb91c..45c4b7d 100644
+--- a/src/mongo/util/processinfo_linux.cpp
++++ b/src/mongo/util/processinfo_linux.cpp
+@@ -44,10 +44,10 @@
+ #include <unistd.h>
+ #ifdef __BIONIC__
+ #include <android/api-level.h>
+-#elif __UCLIBC__
+-#include <features.h>
+-#else
++#elif defined(__GLIBC__) && !defined(__UCLIBC__)
+ #include <gnu/libc-version.h>
++#else
++#include <features.h>
+ #endif
+
+ #include <boost/filesystem.hpp>
+@@ -546,7 +546,7 @@ void ProcessInfo::SystemInfo::collectSystemInfo() {
+ std::stringstream ss;
+ ss << "uClibc-" << __UCLIBC_MAJOR__ << "." << __UCLIBC_MINOR__ << "." << __UCLIBC_SUBLEVEL__;
+ bExtra.append("libcVersion", ss.str());
+-#else
++#elif defined(__GLIBC__)
+ bExtra.append("libcVersion", gnu_get_libc_version());
+ #endif
+ if (!verSig.empty())
+--
+2.7.4
+
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb/0001-Use-long-long-instead-of-int64_t.patch b/meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb/0001-Use-long-long-instead-of-int64_t.patch
new file mode 100644
index 0000000000..b9c6704075
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb/0001-Use-long-long-instead-of-int64_t.patch
@@ -0,0 +1,66 @@
+From 20fcbf2a05ee6542aba942f6006d149db70fb9ce Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Sat, 2 Sep 2017 10:03:37 -0700
+Subject: [PATCH 02/10] Use long long instead of int64_t
+
+Fixes
+error: call to member function 'appendNumber' is ambiguous
+since this function expects long long as parameter and not int64_t
+
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ src/mongo/util/procparser.cpp | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/src/mongo/util/procparser.cpp b/src/mongo/util/procparser.cpp
+index c574a3f..5ea66b7 100644
+--- a/src/mongo/util/procparser.cpp
++++ b/src/mongo/util/procparser.cpp
+@@ -261,7 +261,7 @@ Status parseProcStat(const std::vector<StringData>& keys,
+
+ StringData stringValue((*partIt).begin(), (*partIt).end() - (*partIt).begin());
+
+- uint64_t value;
++ long long value;
+
+ if (!parseNumberFromString(stringValue, &value).isOK()) {
+ value = 0;
+@@ -273,7 +273,7 @@ Status parseProcStat(const std::vector<StringData>& keys,
+ } else {
+ StringData stringValue((*partIt).begin(), (*partIt).end() - (*partIt).begin());
+
+- uint64_t value;
++ long long value;
+
+ if (!parseNumberFromString(stringValue, &value).isOK()) {
+ value = 0;
+@@ -366,7 +366,7 @@ Status parseProcMemInfo(const std::vector<StringData>& keys,
+
+ StringData stringValue((*partIt).begin(), (*partIt).end());
+
+- uint64_t value;
++ long long value;
+
+ if (!parseNumberFromString(stringValue, &value).isOK()) {
+ value = 0;
+@@ -522,7 +522,7 @@ Status parseProcDiskStats(const std::vector<StringData>& disks,
+ StringData data,
+ BSONObjBuilder* builder) {
+ bool foundKeys = false;
+- std::vector<uint64_t> stats;
++ std::vector<long long> stats;
+ stats.reserve(kDiskFieldCount);
+
+ using string_split_iterator = boost::split_iterator<StringData::const_iterator>;
+@@ -597,7 +597,7 @@ Status parseProcDiskStats(const std::vector<StringData>& disks,
+
+ StringData stringValue((*partIt).begin(), (*partIt).end());
+
+- uint64_t value;
++ long long value;
+
+ if (!parseNumberFromString(stringValue, &value).isOK()) {
+ value = 0;
+--
+2.7.4
+
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb/0001-asio-Dont-use-experimental-with-clang.patch b/meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb/0001-asio-Dont-use-experimental-with-clang.patch
new file mode 100644
index 0000000000..e726933f56
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb/0001-asio-Dont-use-experimental-with-clang.patch
@@ -0,0 +1,29 @@
+From 097e8a66930cfa28ac8bfa35f62d0a9ee3b74488 Mon Sep 17 00:00:00 2001
+From: Vincent Prince <vincent.prince.fr@gmail.com>
+Date: Mon, 16 Sep 2019 13:46:52 +0200
+Subject: [PATCH 10/10] asio: Dont use experimental with clang
+
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+Signed-off-by: Vincent Prince <vincent.prince.fr@gmail.com>
+---
+ src/third_party/asio-master/asio/include/asio/detail/string_view.hpp | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/src/third_party/asio-master/asio/include/asio/detail/string_view.hpp b/src/third_party/asio-master/asio/include/asio/detail/string_view.hpp
+index f09cebc..fa307b5 100644
+--- a/src/third_party/asio-master/asio/include/asio/detail/string_view.hpp
++++ b/src/third_party/asio-master/asio/include/asio/detail/string_view.hpp
+@@ -33,8 +33,8 @@ namespace asio {
+ using std::basic_string_view;
+ using std::string_view;
+ #elif defined(ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW)
+-using std::experimental::basic_string_view;
+-using std::experimental::string_view;
++using std::basic_string_view;
++using std::string_view;
+ #endif // defined(ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW)
+
+ } // namespace asio
+--
+2.7.4
+
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb/0002-Add-a-definition-for-the-macro-__ELF_NATIVE_CLASS.patch b/meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb/0002-Add-a-definition-for-the-macro-__ELF_NATIVE_CLASS.patch
new file mode 100644
index 0000000000..869d2849df
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb/0002-Add-a-definition-for-the-macro-__ELF_NATIVE_CLASS.patch
@@ -0,0 +1,35 @@
+From 73c6374ceb0c062e91210cc9ef3e0e9fa30ee514 Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Sat, 2 Sep 2017 12:42:30 -0700
+Subject: [PATCH 04/10] Add a definition for the macro __ELF_NATIVE_CLASS
+
+It depends on the native arch's word size.
+
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ src/mongo/util/stacktrace_posix.cpp | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/src/mongo/util/stacktrace_posix.cpp b/src/mongo/util/stacktrace_posix.cpp
+index 1d7b3d7..f81e329 100644
+--- a/src/mongo/util/stacktrace_posix.cpp
++++ b/src/mongo/util/stacktrace_posix.cpp
+@@ -39,6 +39,15 @@
+ #include <string>
+ #include <sys/utsname.h>
+
++#if !defined(__GLIBC__)
++#if defined __x86_64__ && !defined __ILP32__
++# define __WORDSIZE 64
++#else
++# define __WORDSIZE 32
++#endif
++#define __ELF_NATIVE_CLASS __WORDSIZE
++#endif
++
+ #include "mongo/base/init.h"
+ #include "mongo/config.h"
+ #include "mongo/db/jsobj.h"
+--
+2.7.4
+
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb/0002-Fix-default-stack-size-to-256K.patch b/meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb/0002-Fix-default-stack-size-to-256K.patch
new file mode 100644
index 0000000000..59066b2600
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb/0002-Fix-default-stack-size-to-256K.patch
@@ -0,0 +1,39 @@
+From ffe6045b190b735601cd209d3e7ac121604c5a4e Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Fri, 24 Aug 2018 13:07:01 -0700
+Subject: [PATCH 08/10] Fix default stack size to 256K
+
+On musl default stack size is ~80K which is too low
+for mongodb
+
+Upstream-Status: Pending
+
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ src/mongo/platform/stack_locator_pthread_getattr_np.cpp | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/src/mongo/platform/stack_locator_pthread_getattr_np.cpp b/src/mongo/platform/stack_locator_pthread_getattr_np.cpp
+index 4f3044c..68e47e3 100644
+--- a/src/mongo/platform/stack_locator_pthread_getattr_np.cpp
++++ b/src/mongo/platform/stack_locator_pthread_getattr_np.cpp
+@@ -36,6 +36,16 @@
+ #include "mongo/util/assert_util.h"
+ #include "mongo/util/scopeguard.h"
+
++__attribute__((constructor))
++static void set_default_stack_size(void)
++{
++ pthread_attr_t attr;
++ invariant(pthread_attr_init(&attr) == 0);
++ invariant(pthread_attr_setstacksize(&attr, 256*1024) == 0);
++ pthread_setattr_default_np(&attr);
++ invariant(pthread_attr_destroy(&attr) == 0);
++}
++
+ namespace mongo {
+
+ StackLocator::StackLocator() {
+--
+2.7.4
+
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb/0003-Fix-unknown-prefix-env.patch b/meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb/0003-Fix-unknown-prefix-env.patch
new file mode 100644
index 0000000000..3a27aacfe4
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb/0003-Fix-unknown-prefix-env.patch
@@ -0,0 +1,19 @@
+Index: git/SConstruct
+===================================================================
+--- git.orig/SConstruct
++++ git/SConstruct
+@@ -884,6 +884,14 @@ env_vars.Add('WINDOWS_OPENSSL_BIN',
+ help='Sets the path to the openssl binaries for packaging',
+ default='c:/openssl/bin')
+
++env_vars.Add('PREFIX',
++ help='installation prefix')
++
++env_vars.Add('prefix',
++ help='installation prefix')
++
++
++
+ # -- Validate user provided options --
+
+ # A dummy environment that should *only* have the variables we have set. In practice it has
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb/0004-wiredtiger-Disable-strtouq-on-musl.patch b/meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb/0004-wiredtiger-Disable-strtouq-on-musl.patch
new file mode 100644
index 0000000000..2cea9bc31f
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb/0004-wiredtiger-Disable-strtouq-on-musl.patch
@@ -0,0 +1,26 @@
+From cc95a8878fa581b164dee8fb1f07b05b9d919ef0 Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Sat, 2 Sep 2017 13:13:15 -0700
+Subject: [PATCH 09/10] wiredtiger: Disable strtouq on musl
+
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ src/third_party/wiredtiger/build_linux/wiredtiger_config.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/third_party/wiredtiger/build_linux/wiredtiger_config.h b/src/third_party/wiredtiger/build_linux/wiredtiger_config.h
+index 82e9994..0399a67 100644
+--- a/src/third_party/wiredtiger/build_linux/wiredtiger_config.h
++++ b/src/third_party/wiredtiger/build_linux/wiredtiger_config.h
+@@ -104,7 +104,7 @@
+ #define HAVE_STRING_H 1
+
+ /* Define to 1 if you have the `strtouq' function. */
+-#define HAVE_STRTOUQ 1
++/* #undef HAVE_STRTOUQ 1 */
+
+ /* Define to 1 if you have the `sync_file_range' function. */
+ /* #undef HAVE_SYNC_FILE_RANGE */
+--
+2.7.4
+
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb/arm64-support.patch b/meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb/arm64-support.patch
new file mode 100644
index 0000000000..15bd7da702
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb/arm64-support.patch
@@ -0,0 +1,54 @@
+From c9fc9e9a44b0fb764ce86a5e57f17d3c5bbfd8cd Mon Sep 17 00:00:00 2001
+From: Vincent Prince <vincent.prince.fr@gmail.com>
+Date: Mon, 16 Sep 2019 13:37:10 +0200
+Subject: [PATCH 05/10] Add alises for arm64 which is same as aarch64
+
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+Signed-off-by: Vincent Prince <vincent.prince.fr@gmail.com>
+---
+ SConstruct | 1 +
+ src/third_party/IntelRDFPMathLib20U1/SConscript | 2 +-
+ src/third_party/wiredtiger/SConscript | 2 +-
+ 3 files changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/SConstruct b/SConstruct
+index e63cf15..5593c78 100644
+--- a/SConstruct
++++ b/SConstruct
+@@ -1129,6 +1129,7 @@ elif endian == "big":
+ processor_macros = {
+ 'arm' : { 'endian': 'little', 'defines': ('__arm__',) },
+ 'aarch64' : { 'endian': 'little', 'defines': ('__arm64__', '__aarch64__')},
++ 'arm64' : { 'endian': 'little', 'defines': ('__arm64__', '__aarch64__')},
+ 'i386' : { 'endian': 'little', 'defines': ('__i386', '_M_IX86')},
+ 'ppc64le' : { 'endian': 'little', 'defines': ('__powerpc64__',)},
+ 's390x' : { 'endian': 'big', 'defines': ('__s390x__',)},
+diff --git a/src/third_party/IntelRDFPMathLib20U1/SConscript b/src/third_party/IntelRDFPMathLib20U1/SConscript
+index f23c071..fb82cd6 100644
+--- a/src/third_party/IntelRDFPMathLib20U1/SConscript
++++ b/src/third_party/IntelRDFPMathLib20U1/SConscript
+@@ -308,7 +308,7 @@ if processor == 'i386' or processor == 'emscripten':
+ elif processor == 'arm':
+ cpp_defines['IA32'] = '1'
+ cpp_defines['ia32'] = '1'
+-elif processor == "aarch64":
++elif processor == "aarch64" or processor == 'arm64':
+ cpp_defines['efi2'] = '1'
+ cpp_defines['EFI2'] = '1'
+ # Using 64 bit little endian
+diff --git a/src/third_party/wiredtiger/SConscript b/src/third_party/wiredtiger/SConscript
+index cdd090b..97a1b3b 100644
+--- a/src/third_party/wiredtiger/SConscript
++++ b/src/third_party/wiredtiger/SConscript
+@@ -152,7 +152,7 @@ condition_map = {
+ 'POSIX_HOST' : not env.TargetOSIs('windows'),
+ 'WINDOWS_HOST' : env.TargetOSIs('windows'),
+
+- 'ARM64_HOST' : env['TARGET_ARCH'] == 'aarch64',
++ 'ARM64_HOST' : env['TARGET_ARCH'] in ('aarch64', 'arm64'),
+ 'POWERPC_HOST' : env['TARGET_ARCH'] == 'ppc64le',
+ 'X86_HOST' : env['TARGET_ARCH'] == 'x86_64',
+ 'ZSERIES_HOST' : env['TARGET_ARCH'] == 's390x',
+--
+2.7.4
+
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb_git.bb b/meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb_git.bb
new file mode 100644
index 0000000000..6f460bf762
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-dbs/mongodb/mongodb_git.bb
@@ -0,0 +1,73 @@
+SUMMARY = "mongodb"
+LICENSE = "SSPL-1 & Apache-2.0 & Zlib"
+LIC_FILES_CHKSUM = "file://LICENSE-Community.txt;md5=3a865f27f11f43ecbe542d9ea387dcf1 \
+ file://APACHE-2.0.txt;md5=3b83ef96387f14655fc854ddc3c6bd57"
+
+DEPENDS = "openssl libpcap zlib boost curl python3 \
+ python3-setuptools-native \
+ python3-pyyaml-native python3-cheetah-native \
+ python3-psutil-native python3-regex-native \
+ "
+
+inherit scons dos2unix siteinfo python3native
+
+PV = "4.2.2"
+#v4.2.2
+SRCREV = "a0bbbff6ada159e19298d37946ac8dc4b497eadf"
+SRC_URI = "git://github.com/mongodb/mongo.git;branch=v4.2 \
+ file://0001-Tell-scons-to-use-build-settings-from-environment-va.patch \
+ file://0001-Use-long-long-instead-of-int64_t.patch \
+ file://0001-Use-__GLIBC__-to-control-use-of-gnu_get_libc_version.patch \
+ file://0002-Add-a-definition-for-the-macro-__ELF_NATIVE_CLASS.patch \
+ file://arm64-support.patch \
+ file://0001-IntelRDFPMathLib20U1-Check-for-__DEFINED_wchar_t.patch \
+ file://0001-Support-deprecated-resolver-functions.patch \
+ file://0003-Fix-unknown-prefix-env.patch \
+ "
+SRC_URI_append_libc-musl ="\
+ file://0001-Mark-one-of-strerror_r-implementation-glibc-specific.patch \
+ file://0002-Fix-default-stack-size-to-256K.patch \
+ file://0004-wiredtiger-Disable-strtouq-on-musl.patch \
+ "
+
+SRC_URI_append_toolchain-clang = "\
+ file://0001-asio-Dont-use-experimental-with-clang.patch \
+ "
+
+S = "${WORKDIR}/git"
+
+COMPATIBLE_HOST ?= '(x86_64|powerpc64|aarch64).*-linux'
+
+PACKAGECONFIG ??= "tcmalloc system-pcre"
+# gperftools compilation fails for arm below v7 because of missing support of
+# dmb operation. So we use system-allocator instead of tcmalloc
+PACKAGECONFIG_remove_armv6 = "tcmalloc"
+PACKAGECONFIG_remove_libc-musl = "tcmalloc"
+
+PACKAGECONFIG[tcmalloc] = "--use-system-tcmalloc,--allocator=system,gperftools,"
+PACKAGECONFIG[shell] = ",--js-engine=none,,"
+PACKAGECONFIG[system-pcre] = "--use-system-pcre,,libpcre,"
+
+EXTRA_OESCONS = "--prefix=${D}${prefix} \
+ LIBPATH=${STAGING_LIBDIR} \
+ LINKFLAGS='${LDFLAGS}' \
+ CXXFLAGS='${CXXFLAGS}' \
+ TARGET_ARCH=${TARGET_ARCH} \
+ --ssl \
+ --disable-warnings-as-errors \
+ --use-system-zlib \
+ --nostrip \
+ --endian=${@oe.utils.conditional('SITEINFO_ENDIANNESS', 'le', 'little', 'big', d)} \
+ --wiredtiger=${@['off','on'][d.getVar('SITEINFO_BITS') != '32']} \
+ ${PACKAGECONFIG_CONFARGS} \
+ core"
+
+scons_do_compile() {
+ ${STAGING_BINDIR_NATIVE}/scons ${PARALLEL_MAKE} ${EXTRA_OESCONS} || \
+ die "scons build execution failed."
+}
+
+scons_do_install() {
+ ${STAGING_BINDIR_NATIVE}/scons install ${EXTRA_OESCONS}|| \
+ die "scons install execution failed."
+}
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-extended/lcdproc/lcdproc/0001-Fix-parallel-build-fix-port-internal-make-dependenci.patch b/meta-oe/dynamic-layers/meta-python/recipes-extended/lcdproc/lcdproc/0001-Fix-parallel-build-fix-port-internal-make-dependenci.patch
new file mode 100644
index 0000000000..f6a7956db2
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-extended/lcdproc/lcdproc/0001-Fix-parallel-build-fix-port-internal-make-dependenci.patch
@@ -0,0 +1,33 @@
+From a20feee4963bc38975fbaf44bbe85a31825f59db Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Sat, 6 Apr 2019 17:28:28 -0700
+Subject: [PATCH 1/3] Fix parallel build (fix port-internal make dependencies)
+ on many cores
+
+Upstream-Status: Submitted [https://github.com/lcdproc/lcdproc/pull/142]
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ server/drivers/Makefile.am | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/server/drivers/Makefile.am b/server/drivers/Makefile.am
+index e08f2b2d..4fd2e3f1 100644
+--- a/server/drivers/Makefile.am
++++ b/server/drivers/Makefile.am
+@@ -47,11 +47,11 @@ CwLnx_LDADD = libLCD.a libbignum.a
+ futaba_LDADD = @LIBUSB_LIBS@ @LIBUSB_1_0_LIBS@ libLCD.a
+ g15_LDADD = @LIBG15@
+ glcd_LDADD = libLCD.a @GLCD_DRIVERS@ @FT2_LIBS@ @LIBPNG_LIBS@ @LIBSERDISP@ @LIBUSB_LIBS@ @LIBX11_LIBS@
+-glcd_DEPENDENCIES = @GLCD_DRIVERS@ glcd-glcd-render.o
++glcd_DEPENDENCIES = @GLCD_DRIVERS@ glcd-glcd-render.o libLCD.a
+ glcdlib_LDADD = @LIBGLCD@
+ glk_LDADD = libbignum.a
+ hd44780_LDADD = libLCD.a @HD44780_DRIVERS@ @HD44780_I2C@ @LIBUSB_LIBS@ @LIBFTDI_LIBS@ @LIBUGPIO@ libbignum.a
+-hd44780_DEPENDENCIES = @HD44780_DRIVERS@ @HD44780_I2C@
++hd44780_DEPENDENCIES = @HD44780_DRIVERS@ @HD44780_I2C@ libLCD.a libbignum.a
+ i2500vfd_LDADD = @LIBFTDI_LIBS@
+ imon_LDADD = libLCD.a libbignum.a
+ imonlcd_LDADD = libLCD.a
+--
+2.24.1
+
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-extended/lcdproc/lcdproc/0002-Include-limits.h-for-PATH_MAX-definition.patch b/meta-oe/dynamic-layers/meta-python/recipes-extended/lcdproc/lcdproc/0002-Include-limits.h-for-PATH_MAX-definition.patch
new file mode 100644
index 0000000000..eb866bf10a
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-extended/lcdproc/lcdproc/0002-Include-limits.h-for-PATH_MAX-definition.patch
@@ -0,0 +1,41 @@
+From d447a05ee560ba5894d2ed4cd93d0475c2f3c08e Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Tue, 17 Dec 2019 17:39:32 -0800
+Subject: [PATCH 2/3] Include <limits.h> for PATH_MAX definition
+
+musl libc exposes the missing include
+
+Upstream-Status: Submitted [https://github.com/lcdproc/lcdproc/pull/142]
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ server/drivers/hidraw_lib.c | 1 +
+ server/drivers/linux_input.c | 1 +
+ 2 files changed, 2 insertions(+)
+
+diff --git a/server/drivers/hidraw_lib.c b/server/drivers/hidraw_lib.c
+index 49b03f20..3b51f279 100644
+--- a/server/drivers/hidraw_lib.c
++++ b/server/drivers/hidraw_lib.c
+@@ -8,6 +8,7 @@
+ #include <dirent.h>
+ #include <errno.h>
+ #include <fcntl.h>
++#include <limits.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <sys/ioctl.h>
+diff --git a/server/drivers/linux_input.c b/server/drivers/linux_input.c
+index 5b914d4c..6fcfc591 100644
+--- a/server/drivers/linux_input.c
++++ b/server/drivers/linux_input.c
+@@ -5,6 +5,7 @@
+
+ #include <dirent.h>
+ #include <errno.h>
++#include <limits.h>
+ #include <stdint.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+--
+2.24.1
+
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-extended/lcdproc/lcdproc/0003-Fix-non-x86-platforms-on-musl.patch b/meta-oe/dynamic-layers/meta-python/recipes-extended/lcdproc/lcdproc/0003-Fix-non-x86-platforms-on-musl.patch
new file mode 100644
index 0000000000..e39e9bda14
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-extended/lcdproc/lcdproc/0003-Fix-non-x86-platforms-on-musl.patch
@@ -0,0 +1,35 @@
+From 7fd144f101fa5c9316d3468ed26f55629afe1305 Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Tue, 17 Dec 2019 17:55:54 -0800
+Subject: [PATCH 3/3] Fix non x86 platforms on musl
+
+Musl only specifies in/outb for x86/x86. Use the fallback path in case
+musl is used.
+
+This should fail compilation during the linking stage but for some reason
+does not. Will do if -Werror=implicit-function-declaration is specified.
+
+Original here: https://github.com/openwrt/packages/blob/master/utils/lcdproc/patches/110-in-outb.patch
+Upstream-Status: Pending
+
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ server/drivers/port.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/server/drivers/port.h b/server/drivers/port.h
+index c584cd4e..bde235b3 100644
+--- a/server/drivers/port.h
++++ b/server/drivers/port.h
+@@ -94,7 +94,7 @@ static inline int port_deny_multiple(unsigned short port, unsigned short count);
+ /* ---------------------------- Linux ------------------------------------ */
+ /* Use ioperm, inb and outb in <sys/io.h> (Linux) */
+ /* And iopl for higher addresses of PCI LPT cards */
+-#if defined HAVE_IOPERM
++#if defined(__GLIBC__) || (defined(__x86__) || defined(__x86_64__))
+
+ /* Glibc2 and Glibc1 */
+ # ifdef HAVE_SYS_IO_H
+--
+2.24.1
+
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-extended/lcdproc/lcdproc_git.bb b/meta-oe/dynamic-layers/meta-python/recipes-extended/lcdproc/lcdproc_git.bb
new file mode 100644
index 0000000000..275b984e47
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-extended/lcdproc/lcdproc_git.bb
@@ -0,0 +1,105 @@
+DESCRIPTION = "LCDproc is a client/server suite to drive all kinds of LCD (-like) devices. The client \
+shipped with this package can be used to acquire various kinds of system stats."
+SUMMARY = "Drivers for character-based LCD displays"
+HOMEPAGE = "http://lcdproc.org"
+SECTION = "utils"
+LICENSE = "GPLv2+"
+DEPENDS = "ncurses lirc"
+
+LIC_FILES_CHKSUM = "file://COPYING;md5=18810669f13b87348459e611d31ab760 \
+ file://README.md;beginline=107;md5=5db392f043253a2d64b1737068ce6b58"
+
+PV = "0.5.9+git${SRCPV}"
+SRCREV = "3a3d622d9bb74c44fa67bc20573751a207514134"
+SRC_URI = "git://github.com/lcdproc/lcdproc \
+ file://0001-Fix-parallel-build-fix-port-internal-make-dependenci.patch \
+ file://0002-Include-limits.h-for-PATH_MAX-definition.patch \
+ file://0003-Fix-non-x86-platforms-on-musl.patch \
+ "
+
+S = "${WORKDIR}/git"
+
+inherit autotools pkgconfig update-rc.d
+
+LCD_DRIVERS ?= "all,!irman,!svga${SERIALVFD}"
+SERIALVFD ?= ""
+SERIALVFD_libc-musl = ",!serialVFD"
+SERIALVFD_libc-musl_x86 = ""
+SERIALVFD_libc-musl_x86-64 = ""
+
+LCD_DEFAULT_DRIVER ?= "curses"
+
+PACKAGECONFIG ??= "usb"
+PACKAGECONFIG[usb] = "--enable-libusb,--disable-libusb,virtual/libusb0"
+PACKAGECONFIG[ftdi] = "--enable-libftdi,--disable-libftdi,libftdi"
+PACKAGECONFIG[g15] = ",,libg15 g15daemon libg15render,"
+PACKAGECONFIG[hid] = "--enable-libhid,--disable-libhid,libhid"
+PACKAGECONFIG[png] = "--enable-libpng,--disable-libpng,libpng"
+
+LCD_DRIVERS_append = "${@bb.utils.contains('PACKAGECONFIG', 'g15', '', ',!g15', d)}"
+
+EXTRA_OECONF = "--enable-drivers='${LCD_DRIVERS}'"
+
+do_install () {
+ # binaries
+ install -D -m 0755 server/LCDd ${D}${sbindir}/LCDd
+ install -D -m 0755 clients/lcdproc/lcdproc ${D}${bindir}/lcdproc
+
+ # init scripts
+ install -d ${D}${sysconfdir}/init.d
+ # so far, not fixed :-( and now even uglier :-((
+ cat scripts/init-LCDd.debian | sed -e s'/--oknodo//' -e 's/ -s -f / -s 1 -f 1 /' -e 's/force-reload/force-restart/' -e 's/sleep 1/sleep 4/' > ${D}${sysconfdir}/init.d/lcdd
+ chmod 0755 ${D}${sysconfdir}/init.d/lcdd
+ install -m 0755 scripts/init-lcdproc.debian ${D}${sysconfdir}/init.d/lcdproc
+ sed -i s'/--oknodo//' ${D}${sysconfdir}/init.d/lcdproc
+
+ # configuration files
+ install -m 0644 ${S}/LCDd.conf ${D}${sysconfdir}/LCDd.conf
+ sed -i 's!^DriverPath=.*!DriverPath=${libdir}/lcdproc/!' ${D}${sysconfdir}/LCDd.conf
+ sed -i 's!^Driver=.*!Driver=${LCD_DEFAULT_DRIVER}!' ${D}${sysconfdir}/LCDd.conf
+ install -m 0644 ${S}/clients/lcdproc/lcdproc.conf ${D}${sysconfdir}/lcdproc.conf
+
+ # driver library files
+ install -d ${D}${libdir}/lcdproc
+ for i in server/drivers/*.so; do
+ install -m 0644 $i ${D}${libdir}/lcdproc/
+ done
+ # binaries
+ install -D -m 0755 clients/lcdvc/lcdvc ${D}${sbindir}/lcdvc
+
+ # configuration files
+ install -D -m 0644 ${S}/clients/lcdvc/lcdvc.conf ${D}${sysconfdir}/lcdvc.conf
+}
+
+PACKAGES =+ "lcdd lcdvc"
+
+RRECOMMENDS_${PN} = "lcdd"
+
+FILES_lcdd = "${sysconfdir}/LCDd.conf \
+ ${sbindir}/LCDd \
+ ${sysconfdir}/init.d/lcdd"
+
+CONFFILES_lcdd = "${sysconfdir}/LCDd.conf"
+CONFFILES_${PN} = "${sysconfdir}/lcdproc.conf"
+CONFFILES_lcdvc = "${sysconfdir}/lcdvc.conf"
+FILES_lcdvc = "${sysconfdir}/lcdvc.conf ${sbindir}/lcdvc"
+
+# Driver packages
+
+# USB / no USB trickery
+
+RCONFLICTS_lcdd-driver-hd47780nousb = "lcdd-driver-hd44780"
+RCONFLICTS_lcdd-driver-hd47780 = "lcdd-driver-hd44780nousb"
+
+INITSCRIPT_PACKAGES = "lcdd lcdproc"
+INITSCRIPT_NAME_lcdd = "lcdd"
+INITSCRIPT_NAME_lcdproc = "lcdproc"
+INITSCRIPT_PARAMS_lcdd = "defaults 70 21"
+INITSCRIPT_PARAMS_lcdproc = "defaults 71 20"
+
+python populate_packages_prepend() {
+ plugindir = d.expand('${libdir}/lcdproc')
+ do_split_packages(d, plugindir, '(.*)\.so$', 'lcdd-driver-%s', 'LCDd driver for %s', prepend=True)
+}
+
+PACKAGES_DYNAMIC += "^lcdd-driver-.*"
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0001-Port-build-to-python3.patch b/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0001-Port-build-to-python3.patch
new file mode 100644
index 0000000000..e525047df4
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0001-Port-build-to-python3.patch
@@ -0,0 +1,6897 @@
+From 33a373ba41d978af60c2f0230bcba6ad27357ec8 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Andreas=20M=C3=BCller?= <schnitzeltony@gmail.com>
+Date: Wed, 29 Jan 2020 16:25:11 +0100
+Subject: [PATCH] Port build to python3
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+* first tool of choice was 2to3
+* some parts were taken from [1] but during work it was found that this patch
+ introduces interesting effects - see hash functions. Working more on this
+ makes me guess that one has never worked...
+* Few parts were taken from upstream mirror [2]. Since they use six for porting
+ to python3 it adds us a new dependency.
+* To get a better overview what is going on or failing some additional messages
+ were added. The most verbose one is left disabled - see
+ python/mozbuild/mozbuild/configure/__init__.py / Line 310 onwards
+* major changes upstream on build are not to expect so upgrading should cause
+ little trouble and changes can be tracked by [3]
+* some solutions are workarounds/hacks so this patch will not be accepeted
+ upstream. This should not be a probelme for us: once mozjs >= 68 will arrive
+ we have to go to rust/cargo based build anyway.
+
+[1] https://code.foxkit.us/adelie/packages/blob/f2b5773da19ab397fbe64fd32dacc383cfe4cd77/user/mozjs/python3.patch
+[2] https://github.com/mozilla/gecko-dev
+[3] https://github.com/mozilla/gecko-dev/tree/esr60
+
+Upstream-Status: Inaproppriate [Some Hacks]
+
+Signed-off-by: Andreas Müller <schnitzeltony@gmail.com>
+---
+ build/autoconf/config.status.m4 | 2 +-
+ build/moz.configure/android-ndk.configure | 4 +-
+ build/moz.configure/checks.configure | 4 +-
+ build/moz.configure/init.configure | 31 +-
+ build/moz.configure/keyfiles.configure | 4 +-
+ build/moz.configure/old.configure | 32 +-
+ build/moz.configure/toolchain.configure | 18 +-
+ build/moz.configure/util.configure | 9 +-
+ build/moz.configure/windows.configure | 10 +-
+ build/templates.mozbuild | 2 +-
+ config/MozZipFile.py | 12 +-
+ config/expandlibs.py | 6 +-
+ config/expandlibs_exec.py | 14 +-
+ config/expandlibs_gen.py | 4 +-
+ configure.py | 42 +-
+ js/src/build/moz.build | 8 +-
+ js/src/builtin/embedjs.py | 10 +-
+ js/src/configure | 2 +-
+ js/src/frontend/GenerateReservedWords.py | 6 +-
+ js/src/gc/GenerateStatsPhases.py | 4 +-
+ js/src/old-configure.in | 2 +
+ memory/build/moz.build | 8 +-
+ mozglue/build/moz.build | 22 +-
+ .../mozbuild/mozbuild/action/check_binary.py | 2 +
+ .../mozbuild/action/process_define_files.py | 4 +-
+ python/mozbuild/mozbuild/backend/base.py | 8 +-
+ python/mozbuild/mozbuild/backend/common.py | 8 +-
+ .../mozbuild/backend/configenvironment.py | 14 +-
+ .../mozbuild/mozbuild/backend/fastermake.py | 10 +-
+ .../mozbuild/backend/recursivemake.py | 181 +++----
+ python/mozbuild/mozbuild/config_status.py | 7 +-
+ .../mozbuild/mozbuild/configure/__init__.py | 83 +++-
+ .../mozbuild/configure/check_debug_ranges.py | 6 +-
+ python/mozbuild/mozbuild/configure/options.py | 24 +-
+ python/mozbuild/mozbuild/configure/util.py | 12 +-
+ .../mozbuild/mozbuild/controller/building.py | 16 +-
+ python/mozbuild/mozbuild/frontend/context.py | 89 ++--
+ python/mozbuild/mozbuild/frontend/data.py | 8 +-
+ python/mozbuild/mozbuild/frontend/emitter.py | 50 +-
+ python/mozbuild/mozbuild/frontend/reader.py | 49 +-
+ python/mozbuild/mozbuild/frontend/sandbox.py | 3 +-
+ python/mozbuild/mozbuild/jar.py | 12 +-
+ python/mozbuild/mozbuild/makeutil.py | 24 +-
+ python/mozbuild/mozbuild/mozinfo.py | 8 +-
+ python/mozbuild/mozbuild/preprocessor.py | 27 +-
+ python/mozbuild/mozbuild/shellutil.py | 6 +-
+ .../test/backend/test_recursivemake.py | 18 +-
+ .../mozbuild/test/configure/common.py | 8 +-
+ .../mozbuild/mozbuild/test/configure/lint.py | 8 +-
+ .../test/configure/test_checks_configure.py | 8 +-
+ .../test/configure/test_compile_checks.py | 4 +-
+ .../mozbuild/test/configure/test_configure.py | 244 +++++-----
+ .../mozbuild/test/configure/test_lint.py | 24 +-
+ .../test/configure/test_moz_configure.py | 32 +-
+ .../mozbuild/test/configure/test_options.py | 450 +++++++++---------
+ .../configure/test_toolchain_configure.py | 22 +-
+ .../test/configure/test_toolchain_helpers.py | 62 +--
+ .../configure/test_toolkit_moz_configure.py | 2 +-
+ .../mozbuild/test/configure/test_util.py | 8 +-
+ python/mozbuild/mozbuild/testing.py | 10 +-
+ python/mozbuild/mozbuild/util.py | 79 ++-
+ python/mozbuild/mozbuild/virtualenv.py | 6 +-
+ python/mozbuild/mozpack/chrome/manifest.py | 6 +-
+ python/mozbuild/mozpack/copier.py | 12 +-
+ python/mozbuild/mozpack/files.py | 22 +-
+ python/mozbuild/mozpack/manifests.py | 16 +-
+ python/mozbuild/mozpack/mozjar.py | 37 +-
+ .../manifestparser/manifestparser/ini.py | 13 +-
+ .../manifestparser/manifestparser.py | 24 +-
+ testing/mozbase/mozinfo/mozinfo/mozinfo.py | 26 +-
+ .../mozprocess/mozprocess/processhandler.py | 10 +-
+ third_party/python/which/which.py | 18 +-
+ 72 files changed, 1081 insertions(+), 993 deletions(-)
+
+diff --git a/build/autoconf/config.status.m4 b/build/autoconf/config.status.m4
+index c75575386..543c2d682 100644
+--- a/build/autoconf/config.status.m4
++++ b/build/autoconf/config.status.m4
+@@ -122,7 +122,7 @@ trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+ dnl We're going to need [ ] for python syntax.
+ changequote(<<<, >>>)dnl
+-echo creating $CONFIG_STATUS
++echo creating $CONFIG_STATUS in `pwd`
+
+ cat > $CONFIG_STATUS <<EOF
+
+diff --git a/build/moz.configure/android-ndk.configure b/build/moz.configure/android-ndk.configure
+index 1067b8619..3b592a237 100644
+--- a/build/moz.configure/android-ndk.configure
++++ b/build/moz.configure/android-ndk.configure
+@@ -30,7 +30,7 @@ js_option('--with-android-version',
+
+
+ @depends('--with-android-version', min_android_version, '--help')
+-@imports(_from='__builtin__', _import='ValueError')
++@imports(_from='builtins', _import='ValueError')
+ def android_version(value, min_version, _):
+ if not value:
+ # Someone has passed --without-android-version.
+@@ -68,7 +68,7 @@ add_old_configure_assignment('android_ndk', ndk)
+
+ @depends(ndk)
+ @checking('for android ndk version')
+-@imports(_from='__builtin__', _import='open')
++@imports(_from='builtins', _import='open')
+ def ndk_version(ndk):
+ if not ndk:
+ # Building 'js/src' for non-Android.
+diff --git a/build/moz.configure/checks.configure b/build/moz.configure/checks.configure
+index 516652da9..11e1091c6 100644
+--- a/build/moz.configure/checks.configure
++++ b/build/moz.configure/checks.configure
+@@ -14,7 +14,7 @@
+
+
+ @template
+-@imports(_from='__builtin__', _import='Exception')
++@imports(_from='builtins', _import='Exception')
+ def _declare_exceptions():
+ class FatalCheckError(Exception):
+ '''An exception to throw from a function decorated with @checking.
+@@ -57,7 +57,7 @@ def checking(what, callback=None):
+ try:
+ ret = func(*args, **kwargs)
+ except FatalCheckError as e:
+- error = e.message
++ error = str(e)
+ display_ret = callback(ret) if callback else ret
+ if display_ret is True:
+ log.info('yes')
+diff --git a/build/moz.configure/init.configure b/build/moz.configure/init.configure
+index 648ac2ded..4d74547d8 100644
+--- a/build/moz.configure/init.configure
++++ b/build/moz.configure/init.configure
+@@ -14,7 +14,7 @@ option(env='DIST', nargs=1, help='DIST directory')
+
+
+ @depends('--help', 'DIST')
+-@imports(_from='__builtin__', _import='open')
++@imports(_from='builtins', _import='open')
+ @imports(_from='os.path', _import='exists')
+ def check_build_environment(help, dist):
+ topobjdir = os.path.realpath(os.path.abspath('.'))
+@@ -65,7 +65,7 @@ def check_build_environment(help, dist):
+ # Check for CRLF line endings.
+ with open(os.path.join(topsrcdir, 'configure.py'), 'rb') as fh:
+ data = fh.read()
+- if '\r' in data:
++ if b'\r' in data:
+ die('\n ***\n'
+ ' * The source tree appears to have Windows-style line endings.\n'
+ ' *\n'
+@@ -269,7 +269,7 @@ def early_options():
+ def early_options():
+ return set(
+ option.env
+- for option in __sandbox__._options.itervalues()
++ for option in __sandbox__._options.values()
+ if option.env
+ )
+ return early_options
+@@ -307,15 +307,15 @@ def mozconfig_options(mozconfig, automation, help):
+ log.info(' %s' % arg)
+ helper.add(arg, origin='mozconfig', args=helper._args)
+
+- for key, value in mozconfig['env']['added'].iteritems():
++ for key, value in mozconfig['env']['added'].items():
+ add(key, value)
+ os.environ[key] = value
+- for key, (_, value) in mozconfig['env']['modified'].iteritems():
++ for key, (_, value) in mozconfig['env']['modified'].items():
+ add(key, value)
+ os.environ[key] = value
+- for key, value in mozconfig['vars']['added'].iteritems():
++ for key, value in mozconfig['vars']['added'].items():
+ add(key, value)
+- for key, (_, value) in mozconfig['vars']['modified'].iteritems():
++ for key, (_, value) in mozconfig['vars']['modified'].items():
+ add(key, value)
+
+
+@@ -353,7 +353,7 @@ option(env='PYTHON3', nargs=1, help='Python 3 interpreter (3.5 or later)')
+ @depends('PYTHON3')
+ @checking('for Python 3',
+ callback=lambda x: '%s (%s)' % (x.path, x.str_version) if x else 'no')
+-@imports(_from='__builtin__', _import='Exception')
++@imports(_from='builtins', _import='Exception')
+ @imports(_from='mozbuild.pythonutil', _import='find_python3_executable')
+ @imports(_from='mozbuild.pythonutil', _import='python_executable_version')
+ def python3(env_python):
+@@ -377,9 +377,6 @@ def python3(env_python):
+ if not python:
+ return None
+
+- # The API returns a bytes whereas everything in configure is unicode.
+- python = python.decode('utf-8')
+-
+ return namespace(
+ path=python,
+ version=version,
+@@ -481,6 +478,8 @@ def hg_config(build_env, hg, version):
+ @imports('re')
+ def git_version(git):
+ out = check_cmd_output(git, '--version').rstrip()
++ if isinstance(out, bytes):
++ out = out.decode('utf-8')
+
+ match = re.search('git version (.*)$', out)
+
+@@ -551,8 +550,8 @@ option('--target', nargs=1,
+ @imports(_from='mozbuild.configure.constants', _import='Endianness')
+ @imports(_from='mozbuild.configure.constants', _import='Kernel')
+ @imports(_from='mozbuild.configure.constants', _import='OS')
+-@imports(_from='__builtin__', _import='KeyError')
+-@imports(_from='__builtin__', _import='ValueError')
++@imports(_from='builtins', _import='KeyError')
++@imports(_from='builtins', _import='ValueError')
+ def split_triplet(triplet, allow_unknown=False):
+ # The standard triplet is defined as
+ # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+@@ -562,6 +561,8 @@ def split_triplet(triplet, allow_unknown=False):
+ # Additionally, some may omit "unknown" when the manufacturer
+ # is not specified and emit
+ # CPU_TYPE-OPERATING_SYSTEM
++ if isinstance(triplet, bytes):
++ triplet = triplet.decode('utf-8')
+ parts = triplet.split('-', 2)
+ if len(parts) == 3:
+ cpu, _, os = parts
+@@ -987,7 +988,7 @@ add_old_configure_assignment('MOZ_BUILD_APP', build_project)
+ # - otherwise, if we have "a" in GRE_MILESTONE, we're building Nightly or Aurora
+ # - otherwise, we're building Release/Beta (define RELEASE_OR_BETA)
+ @depends(check_build_environment, '--help')
+-@imports(_from='__builtin__', _import='open')
++@imports(_from='builtins', _import='open')
+ @imports('re')
+ def milestone(build_env, _):
+ milestone_path = os.path.join(build_env.topsrcdir,
+@@ -1105,7 +1106,7 @@ def enabled_in_nightly(milestone, _):
+ def all_configure_options():
+ result = []
+ previous = None
+- for option in __sandbox__._options.itervalues():
++ for option in __sandbox__._options.values():
+ # __sandbox__._options contains items for both option.name and
+ # option.env. But it's also an OrderedDict, meaning both are
+ # consecutive.
+diff --git a/build/moz.configure/keyfiles.configure b/build/moz.configure/keyfiles.configure
+index 5d51cccea..14a35a3c6 100644
+--- a/build/moz.configure/keyfiles.configure
++++ b/build/moz.configure/keyfiles.configure
+@@ -16,8 +16,8 @@ def keyfile(desc, default=None, help=None, callback=lambda x: x):
+
+ @depends('--with-%s-keyfile' % name)
+ @checking('for the %s key' % desc, lambda x: x and x is not no_key)
+- @imports(_from='__builtin__', _import='open')
+- @imports(_from='__builtin__', _import='IOError')
++ @imports(_from='builtins', _import='open')
++ @imports(_from='builtins', _import='IOError')
+ def keyfile(value):
+ if value:
+ try:
+diff --git a/build/moz.configure/old.configure b/build/moz.configure/old.configure
+index 81c10b91f..29b496bae 100644
+--- a/build/moz.configure/old.configure
++++ b/build/moz.configure/old.configure
+@@ -64,9 +64,9 @@ set_config('AUTOCONF', autoconf)
+
+ @depends('OLD_CONFIGURE', mozconfig, autoconf, check_build_environment, shell,
+ old_configure_assignments, build_project)
+-@imports(_from='__builtin__', _import='open')
+-@imports(_from='__builtin__', _import='print')
+-@imports(_from='__builtin__', _import='sorted')
++@imports(_from='builtins', _import='open')
++@imports(_from='builtins', _import='print')
++@imports(_from='builtins', _import='sorted')
+ @imports('glob')
+ @imports('itertools')
+ @imports('subprocess')
+@@ -113,7 +113,7 @@ def prepare_configure(old_configure, mozconfig, autoconf, build_env, shell,
+
+ # Make old-configure append to config.log, where we put our own log.
+ # This could be done with a m4 macro, but it's way easier this way
+- script = script.replace('>./config.log', '>>./config.log')
++ script = script.replace(b'>./config.log', b'>>./config.log')
+
+ with open(old_configure, 'wb') as fh:
+ fh.write(script)
+@@ -282,8 +282,8 @@ def old_configure_options(*options):
+ '--x-includes',
+ '--x-libraries',
+ )
+-@imports(_from='__builtin__', _import='compile')
+-@imports(_from='__builtin__', _import='open')
++@imports(_from='builtins', _import='compile')
++@imports(_from='builtins', _import='open')
+ @imports('logging')
+ @imports('os')
+ @imports('subprocess')
+@@ -326,7 +326,7 @@ def old_configure(prepare_configure, extra_old_configure_args, all_options,
+ log.debug('Running %s', quote(*cmd))
+ if extra_env:
+ log.debug('with extra environment: %s',
+- ' '.join('%s=%s' % pair for pair in extra_env.iteritems()))
++ ' '.join('%s=%s' % pair for pair in extra_env.items()))
+
+ # Our logging goes to config.log, the same file old.configure uses.
+ # We can't share the handle on the file, so close it. We assume nothing
+@@ -359,7 +359,7 @@ def old_configure(prepare_configure, extra_old_configure_args, all_options,
+ # Every variation of the exec() function I tried led to:
+ # SyntaxError: unqualified exec is not allowed in function 'main' it
+ # contains a nested function with free variables
+- exec code in raw_config # noqa
++ exec(code, raw_config) # noqa
+
+ # Ensure all the flags known to old-configure appear in the
+ # @old_configure_options above.
+@@ -393,16 +393,24 @@ def set_old_configure_define(name, value):
+ @depends(old_configure)
+ @imports('types')
+ def post_old_configure(raw_config):
++ log.info('post_old_configure started')
++
+ for k, v in raw_config['substs']:
+ set_old_configure_config(
+- k[1:-1], v[1:-1] if isinstance(v, types.StringTypes) else v)
++ k[1:-1], v[1:-1] if isinstance(v, str) else v)
++
++ log.info('post_old_configure 1 finished')
+
+- for k, v in dict(raw_config['defines']).iteritems():
++ for k, v in dict(raw_config['defines']).items():
+ set_old_configure_define(k[1:-1], v[1:-1])
+
++ log.info('post_old_configure 2 finished')
++
+ set_old_configure_config('non_global_defines',
+ raw_config['non_global_defines'])
+
++ log.info('post_old_configure 3 finished')
++
+
+ # Assuming no other option is declared after this function, handle the
+ # env options that were injected by mozconfig_options by creating dummy
+@@ -414,6 +422,7 @@ def post_old_configure(raw_config):
+ @imports('__sandbox__')
+ @imports(_from='mozbuild.configure.options', _import='Option')
+ def remaining_mozconfig_options(_):
++ log.info('remaining_mozconfig_options started')
+ helper = __sandbox__._helper
+ for arg in helper:
+ if helper._origins[arg] != 'mozconfig':
+@@ -422,5 +431,6 @@ def remaining_mozconfig_options(_):
+ if name.isupper() and name not in __sandbox__._options:
+ option = Option(env=name, nargs='*', help=name)
+ helper.handle(option)
++ log.info('remaining_mozconfig_options finished')
+
+ # Please do not add anything after remaining_mozconfig_options()
+diff --git a/build/moz.configure/toolchain.configure b/build/moz.configure/toolchain.configure
+index fc640c75e..c5508dfb7 100755
+--- a/build/moz.configure/toolchain.configure
++++ b/build/moz.configure/toolchain.configure
+@@ -391,7 +391,7 @@ def get_compiler_info(compiler, language):
+ ('CPU', CPU_preprocessor_checks),
+ ('KERNEL', kernel_preprocessor_checks),
+ ):
+- for n, (value, condition) in enumerate(preprocessor_checks.iteritems()):
++ for n, (value, condition) in enumerate(preprocessor_checks.items()):
+ check += dedent('''\
+ #%(if)s %(condition)s
+ %%%(name)s "%(value)s"
+@@ -425,9 +425,9 @@ def get_compiler_info(compiler, language):
+ data = {}
+ for line in result.splitlines():
+ if line.startswith(b'%'):
+- k, _, v = line.partition(' ')
+- k = k.lstrip('%')
+- data[k] = v.replace(' ', '').lstrip('"').rstrip('"')
++ k, _, v = line.partition(b' ')
++ k = k.lstrip(b'%').decode('utf-8')
++ data[k] = v.replace(b' ', b'').lstrip(b'"').rstrip(b'"').decode('utf-8')
+ log.debug('%s = %s', k, data[k])
+
+ try:
+@@ -551,7 +551,7 @@ def check_compiler(compiler, language, target):
+ )
+
+
+-@imports(_from='__builtin__', _import='open')
++@imports(_from='builtins', _import='open')
+ @imports('json')
+ @imports('subprocess')
+ @imports('sys')
+@@ -606,7 +606,7 @@ def vs_major_version(value):
+
+
+ @depends(host, target, vs_major_version, check_build_environment, '--with-visual-studio-version')
+-@imports(_from='__builtin__', _import='sorted')
++@imports(_from='builtins', _import='sorted')
+ @imports(_from='operator', _import='itemgetter')
+ @imports('platform')
+ def vc_compiler_path(host, target, vs_major_version, env, vs_release_name):
+@@ -807,7 +807,7 @@ def compiler(language, host_or_target, c_compiler=None, other_compiler=None,
+ target.os != 'Android':
+ return namespace(**{
+ k: [] if k == 'flags' else v
+- for k, v in other_compiler.__dict__.iteritems()
++ for k, v in other_compiler.__dict__.items()
+ })
+
+ # Normally, we'd use `var` instead of `_var`, but the interaction with
+@@ -1238,7 +1238,7 @@ set_config('VISIBILITY_FLAGS', visibility_flags)
+
+ @depends(c_compiler)
+ @imports('multiprocessing')
+-@imports(_from='__builtin__', _import='min')
++@imports(_from='builtins', _import='min')
+ def pgo_flags(compiler):
+ if compiler.type in ('gcc', 'clang'):
+ return namespace(
+@@ -1517,6 +1517,8 @@ def enable_gnu_linker(enable_gold_option, c_compiler, developer_options, build_e
+ gold = check_cmd_output(*detection_cmd).strip()
+ if not gold:
+ return
++ if isinstance(gold, bytes):
++ gold = gold.decode('utf-8')
+
+ goldFullPath = find_program(gold)
+ if goldFullPath is None:
+diff --git a/build/moz.configure/util.configure b/build/moz.configure/util.configure
+index 3284fd8b5..218813e2d 100644
+--- a/build/moz.configure/util.configure
++++ b/build/moz.configure/util.configure
+@@ -25,7 +25,6 @@ def configure_error(message):
+ # does not.
+
+
+-@imports(_from='__builtin__', _import='unicode')
+ @imports('subprocess')
+ @imports('sys')
+ @imports(_from='mozbuild.configure.util', _import='LineIO')
+@@ -39,10 +38,10 @@ def check_cmd_output(*args, **kwargs):
+ if 'env' in kwargs:
+ normalized_env = {}
+ for k, v in kwargs['env'].items():
+- if isinstance(k, unicode):
++ if isinstance(k, str):
+ k = k.encode('utf-8', 'strict')
+
+- if isinstance(v, unicode):
++ if isinstance(v, str):
+ v = v.encode('utf-8', 'strict')
+
+ normalized_env[k] = v
+@@ -285,7 +284,7 @@ def unique_list(l):
+ # ('19.0', 'x64', r'C:\...\amd64\cl.exe')
+ # ('19.0', 'x86', r'C:\...\amd64_x86\cl.exe')
+ @imports(_import='_winreg', _as='winreg')
+-@imports(_from='__builtin__', _import='WindowsError')
++@imports(_from='builtins', _import='WindowsError')
+ @imports(_from='fnmatch', _import='fnmatch')
+ def get_registry_values(pattern, get_32_and_64_bit=False):
+ def enum_helper(func, key):
+@@ -360,6 +359,8 @@ def get_registry_values(pattern, get_32_and_64_bit=False):
+ @imports(_from='mozbuild.configure.util', _import='Version', _as='_Version')
+ def Version(v):
+ 'A version number that can be compared usefully.'
++ if isinstance(v, bytes):
++ v = v.decode('utf-8')
+ return _Version(v)
+
+ # Denotes a deprecated option. Combines option() and @depends:
+diff --git a/build/moz.configure/windows.configure b/build/moz.configure/windows.configure
+index a5b790e3b..2b88fc447 100644
+--- a/build/moz.configure/windows.configure
++++ b/build/moz.configure/windows.configure
+@@ -10,7 +10,7 @@ option('--with-windows-version', nargs=1, default='603',
+
+
+ @depends('--with-windows-version')
+-@imports(_from='__builtin__', _import='ValueError')
++@imports(_from='builtins', _import='ValueError')
+ def valid_windows_version(value):
+ if not value:
+ die('Cannot build with --without-windows-version')
+@@ -50,8 +50,8 @@ def windows_sdk_dir(value, host):
+
+ @imports('os')
+ @imports('re')
+-@imports(_from='__builtin__', _import='sorted')
+-@imports(_from='__builtin__', _import='WindowsError')
++@imports(_from='builtins', _import='sorted')
++@imports(_from='builtins', _import='WindowsError')
+ def get_sdk_dirs(sdk, subdir):
+ def get_dirs_containing(sdk, stem, subdir):
+ base = os.path.join(sdk, stem)
+@@ -96,7 +96,7 @@ def valid_windows_sdk_dir_result(value):
+
+ @depends(c_compiler, windows_sdk_dir, valid_windows_version, 'WINDOWSSDKDIR')
+ @checking('for Windows SDK', valid_windows_sdk_dir_result)
+-@imports(_from='__builtin__', _import='sorted')
++@imports(_from='builtins', _import='sorted')
+ @imports(_from='textwrap', _import='dedent')
+ def valid_windows_sdk_dir(compiler, windows_sdk_dir, target_version,
+ windows_sdk_dir_env):
+@@ -174,7 +174,7 @@ def valid_ucrt_sdk_dir_result(value):
+ @depends(windows_sdk_dir, 'WINDOWSSDKDIR', c_compiler)
+ @checking('for Universal CRT SDK', valid_ucrt_sdk_dir_result)
+ @imports('os')
+-@imports(_from='__builtin__', _import='sorted')
++@imports(_from='builtins', _import='sorted')
+ @imports(_import='mozpack.path', _as='mozpath')
+ def valid_ucrt_sdk_dir(windows_sdk_dir, windows_sdk_dir_env, c_compiler):
+ if windows_sdk_dir_env:
+diff --git a/build/templates.mozbuild b/build/templates.mozbuild
+index 3da850ce5..ae5e410fe 100644
+--- a/build/templates.mozbuild
++++ b/build/templates.mozbuild
+@@ -10,7 +10,7 @@ def Binary():
+ templates.'''
+
+ # Add -llog by default, since we use it all over the place.
+- if CONFIG['OS_TARGET'] == 'Android':
++ if str(CONFIG['OS_TARGET']) == 'Android':
+ OS_LIBS += ['log']
+
+
+diff --git a/config/MozZipFile.py b/config/MozZipFile.py
+index 337fe0521..dc7add4c3 100644
+--- a/config/MozZipFile.py
++++ b/config/MozZipFile.py
+@@ -18,7 +18,7 @@ class ZipFile(zipfile.ZipFile):
+ def __init__(self, file, mode="r", compression=zipfile.ZIP_STORED,
+ lock = False):
+ if lock:
+- assert isinstance(file, basestring)
++ assert isinstance(file, str)
+ self.lockfile = lock_file(file + '.lck')
+ else:
+ self.lockfile = None
+@@ -46,7 +46,7 @@ class ZipFile(zipfile.ZipFile):
+ 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
++ zinfo.external_attr = (0x81a4 & 0xFFFF) << 16
+ else:
+ zinfo = zinfo_or_arcname
+
+@@ -58,7 +58,7 @@ class ZipFile(zipfile.ZipFile):
+ # 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):
++ if zinfo.filename in self.NameToInfo:
+ # Find the last ZipInfo with our name.
+ # Last, because that's catching multiple overwrites
+ i = len(self.filelist)
+@@ -109,14 +109,14 @@ class ZipFile(zipfile.ZipFile):
+ # 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 = [(zi, True) for zi in self.filelist] + \
++ [(zi, False) for zi in 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)]
++ for i in range(len(all)-1)]
+ lengths.append(self.end - all[-1][0].header_offset)
+ to_pos = 0
+ for (zi, keep), length in zip(all, lengths):
+diff --git a/config/expandlibs.py b/config/expandlibs.py
+index ac06c432f..df1fed15d 100644
+--- a/config/expandlibs.py
++++ b/config/expandlibs.py
+@@ -26,7 +26,7 @@ ${LIB_PREFIX}${ROOT}.${LIB_SUFFIX} following these rules:
+ 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
+
+@@ -36,7 +36,7 @@ def ensureParentDir(file):
+ if dir and not os.path.exists(dir):
+ try:
+ os.makedirs(dir)
+- except OSError, error:
++ except OSError as error:
+ if error.errno != errno.EEXIST:
+ raise
+
+@@ -140,4 +140,4 @@ class ExpandArgs(list):
+ return [relativize(arg)]
+
+ if __name__ == '__main__':
+- print " ".join(ExpandArgs(sys.argv[1:]))
++ print(" ".join(ExpandArgs(sys.argv[1:])))
+diff --git a/config/expandlibs_exec.py b/config/expandlibs_exec.py
+index df656016c..fb786a6a8 100644
+--- a/config/expandlibs_exec.py
++++ b/config/expandlibs_exec.py
+@@ -20,7 +20,7 @@ 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 (
+@@ -304,11 +304,11 @@ class SectionFinder(object):
+ return syms
+
+ def print_command(out, args):
+- print >>out, "Executing: " + " ".join(args)
++ print("Executing: " + " ".join(args), file=out)
+ for tmp in [f for f in args.tmp if os.path.isfile(f)]:
+- print >>out, tmp + ":"
++ print(tmp + ":", file=out)
+ with open(tmp) as file:
+- print >>out, "".join([" " + l for l in file.readlines()])
++ print("".join([" " + l for l in file.readlines()]), file=out)
+ out.flush()
+
+ def main(args, proc_callback=None):
+@@ -338,13 +338,13 @@ def main(args, proc_callback=None):
+ 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
++ except Exception as e:
++ print('error: Launching', args, ':', e, file=sys.stderr)
+ raise e
+ (stdout, stderr) = proc.communicate()
+ if proc.returncode and not options.verbose:
+ print_command(sys.stderr, args)
+- sys.stderr.write(stdout)
++ sys.stderr.write(stdout.decode("utf-8"))
+ sys.stderr.flush()
+ if proc.returncode:
+ return proc.returncode
+diff --git a/config/expandlibs_gen.py b/config/expandlibs_gen.py
+index b1de63cd0..dc62bd184 100644
+--- a/config/expandlibs_gen.py
++++ b/config/expandlibs_gen.py
+@@ -5,7 +5,7 @@
+ '''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
+@@ -38,4 +38,4 @@ if __name__ == '__main__':
+
+ ensureParentDir(options.output)
+ with open(options.output, 'w') as outfile:
+- print >>outfile, generate(args)
++ print(generate(args), file=outfile)
+diff --git a/configure.py b/configure.py
+index 771e34e38..bee329d7c 100644
+--- a/configure.py
++++ b/configure.py
+@@ -2,10 +2,11 @@
+ # License, v. 2.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, unicode_literals
++
+
+ import codecs
+ import itertools
++import logging
+ import os
+ import sys
+ import textwrap
+@@ -34,7 +35,9 @@ from mozbuild.util import (
+ def main(argv):
+ config = {}
+ sandbox = ConfigureSandbox(config, os.environ, argv)
++ print('sandbox.run started')
+ sandbox.run(os.path.join(os.path.dirname(__file__), 'moz.configure'))
++ print('sandbox.run finished')
+
+ if sandbox._help:
+ return 0
+@@ -56,12 +59,21 @@ def config_status(config):
+
+ sanitized_config = {}
+ sanitized_config['substs'] = {
+- k: sanitized_bools(v) for k, v in config.iteritems()
++ k: sanitized_bools(v) for k, v in config.items()
+ if k not in ('DEFINES', 'non_global_defines', 'TOPSRCDIR', 'TOPOBJDIR',
+ 'ALL_CONFIGURE_PATHS')
+ }
++
++ # Hack around OptionValue entries unknown during compile
++ for opt in ('BUILD_BACKENDS', 'MOZ_UI_LOCALE', 'RUSTFLAGS' ):
++ old = sanitized_config['substs'][opt]
++ new = []
++ for setting in old:
++ new.append(setting)
++ sanitized_config['substs'][opt] = new
++
+ sanitized_config['defines'] = {
+- k: sanitized_bools(v) for k, v in config['DEFINES'].iteritems()
++ k: sanitized_bools(v) for k, v in config['DEFINES'].items()
+ }
+ sanitized_config['non_global_defines'] = config['non_global_defines']
+ sanitized_config['topsrcdir'] = config['TOPSRCDIR']
+@@ -71,20 +83,17 @@ def config_status(config):
+ # Create config.status. Eventually, we'll want to just do the work it does
+ # here, when we're able to skip configure tests/use cached results/not rely
+ # on autoconf.
+- print("Creating config.status", file=sys.stderr)
+- encoding = 'mbcs' if sys.platform == 'win32' else 'utf-8'
+- with codecs.open('config.status', 'w', encoding) as fh:
++ logging.getLogger('moz.configure').info('Creating config.status')
++ with codecs.open('config.status', 'w', 'utf-8') as fh:
+ fh.write(textwrap.dedent('''\
+ #!%(python)s
+- # coding=%(encoding)s
+- from __future__ import unicode_literals
+- from mozbuild.util import encode
+- encoding = '%(encoding)s'
+- ''') % {'python': config['PYTHON'], 'encoding': encoding})
++ # coding=utf-8
++ print("config.status started")
++ ''') % {'python': config['PYTHON']})
+ # A lot of the build backend code is currently expecting byte
+ # strings and breaks in subtle ways with unicode strings. (bug 1296508)
+- for k, v in sanitized_config.iteritems():
+- fh.write('%s = encode(%s, encoding)\n' % (k, indented_repr(v)))
++ for k, v in sanitized_config.items():
++ fh.write('%s = %s\n' % (k, indented_repr(v)))
+ fh.write("__all__ = ['topobjdir', 'topsrcdir', 'defines', "
+ "'non_global_defines', 'substs', 'mozconfig']")
+
+@@ -97,6 +106,9 @@ def config_status(config):
+ args = dict([(name, globals()[name]) for name in __all__])
+ config_status(**args)
+ '''))
++ fh.write(textwrap.dedent('''
++ print("config.status finished")
++ '''))
+
+ partial_config = PartialConfigEnvironment(config['TOPOBJDIR'])
+ partial_config.write_vars(sanitized_config)
+@@ -116,7 +128,7 @@ def config_status(config):
+ # executable permissions.
+ os.chmod('config.status', 0o755)
+ if config.get('MOZ_BUILD_APP') != 'js' or config.get('JS_STANDALONE'):
+- os.environ[b'WRITE_MOZINFO'] = b'1'
++ os.environ['WRITE_MOZINFO'] = '1'
+ from mozbuild.config_status import config_status
+
+ # Some values in sanitized_config also have more complex types, such as
+@@ -127,7 +139,7 @@ def config_status(config):
+
+ # A lot of the build backend code is currently expecting byte strings
+ # and breaks in subtle ways with unicode strings.
+- return config_status(args=[], **encode(sanitized_config, encoding))
++ return config_status(args=[], **sanitized_config)
+ return 0
+
+
+diff --git a/js/src/build/moz.build b/js/src/build/moz.build
+index a7f5fa4ce..856cae32d 100644
+--- a/js/src/build/moz.build
++++ b/js/src/build/moz.build
+@@ -47,22 +47,22 @@ USE_LIBS += [
+ 'zlib',
+ ]
+
+-if CONFIG['OS_ARCH'] not in ('WINNT', 'HP-UX'):
++if str(CONFIG['OS_ARCH']) not in ('WINNT', 'HP-UX'):
+ OS_LIBS += [
+ 'm',
+ ]
+
+-if CONFIG['OS_ARCH'] == 'FreeBSD':
++if str(CONFIG['OS_ARCH']) == 'FreeBSD':
+ OS_LIBS += [
+ '-pthread',
+ ]
+
+-if CONFIG['OS_ARCH'] == 'Linux':
++if str(CONFIG['OS_ARCH']) == 'Linux':
+ OS_LIBS += [
+ 'dl',
+ ]
+
+-if CONFIG['OS_ARCH'] == 'SunOS':
++if str(CONFIG['OS_ARCH']) == 'SunOS':
+ OS_LIBS += [
+ 'posix4',
+ 'dl',
+diff --git a/js/src/builtin/embedjs.py b/js/src/builtin/embedjs.py
+index ba25e71c1..d4f2de122 100644
+--- a/js/src/builtin/embedjs.py
++++ b/js/src/builtin/embedjs.py
+@@ -36,7 +36,7 @@
+ #
+ # It uses the C preprocessor to process its inputs.
+
+-from __future__ import with_statement
++
+ import re, sys, os, subprocess
+ import shlex
+ import which
+@@ -52,8 +52,8 @@ def ToCAsciiArray(lines):
+
+ def ToCArray(lines):
+ result = []
+- for chr in lines:
+- result.append(str(ord(chr)))
++ for char in lines:
++ result.append("0x%0.2X" % char)
+ return ", ".join(result)
+
+ HEADER_TEMPLATE = """\
+@@ -87,7 +87,7 @@ def embed(cxx, preprocessorOption, cppflags, msgs, sources, c_out, js_out, names
+
+ js_out.write(processed)
+ import zlib
+- compressed = zlib.compress(processed)
++ compressed = zlib.compress(processed.encode('utf-8'))
+ data = ToCArray(compressed)
+ c_out.write(HEADER_TEMPLATE % {
+ 'sources_type': 'unsigned char',
+@@ -107,7 +107,7 @@ def preprocess(cxx, preprocessorOption, source, args = []):
+ tmpOut = 'self-hosting-preprocessed.pp';
+ outputArg = shlex.split(preprocessorOption + tmpOut)
+
+- with open(tmpIn, 'wb') as input:
++ with open(tmpIn, 'w') as input:
+ input.write(source)
+ print(' '.join(cxx + outputArg + args + [tmpIn]))
+ result = subprocess.Popen(cxx + outputArg + args + [tmpIn]).wait()
+diff --git a/js/src/configure b/js/src/configure
+index 3b3a39af3..8f5ea41d0 100755
+--- a/js/src/configure
++++ b/js/src/configure
+@@ -24,4 +24,4 @@ export OLD_CONFIGURE="$SRCDIR"/old-configure
+
+ set -- "$@" --enable-project=js
+
+-which python2.7 > /dev/null && exec python2.7 "$TOPSRCDIR/configure.py" "$@" || exec python "$TOPSRCDIR/configure.py" "$@"
++which python3 > /dev/null && exec python3 "$TOPSRCDIR/configure.py" "$@" || exec python "$TOPSRCDIR/configure.py" "$@"
+diff --git a/js/src/frontend/GenerateReservedWords.py b/js/src/frontend/GenerateReservedWords.py
+index 3aa2307b9..381c8e2b4 100644
+--- a/js/src/frontend/GenerateReservedWords.py
++++ b/js/src/frontend/GenerateReservedWords.py
+@@ -80,14 +80,14 @@ def split_list_per_column(reserved_word_list, column):
+ per_column = column_dict.setdefault(word[column], [])
+ per_column.append(item)
+
+- return sorted(column_dict.items(), key=lambda (char, word): ord(char))
++ return sorted(list(column_dict.items()), key=lambda char_word: ord(char_word[0]))
+
+ def generate_letter_switch(opt, unprocessed_columns, reserved_word_list,
+ columns=None):
+ assert(len(reserved_word_list) != 0);
+
+ if not columns:
+- columns = range(0, unprocessed_columns)
++ columns = list(range(0, unprocessed_columns))
+
+ if len(reserved_word_list) == 1:
+ index, word = reserved_word_list[0]
+@@ -161,7 +161,7 @@ def split_list_per_length(reserved_word_list):
+ per_length = length_dict.setdefault(len(word), [])
+ per_length.append(item)
+
+- return sorted(length_dict.items(), key=lambda (length, word): length)
++ return sorted(list(length_dict.items()), key=lambda length_word: length_word[0])
+
+ def generate_switch(opt, reserved_word_list):
+ assert(len(reserved_word_list) != 0);
+diff --git a/js/src/gc/GenerateStatsPhases.py b/js/src/gc/GenerateStatsPhases.py
+index 2daf83555..e39a26a4b 100644
+--- a/js/src/gc/GenerateStatsPhases.py
++++ b/js/src/gc/GenerateStatsPhases.py
+@@ -267,7 +267,7 @@ def generateHeader(out):
+ #
+ # Generate PhaseKind enum.
+ #
+- phaseKindNames = map(lambda phaseKind: phaseKind.name, AllPhaseKinds)
++ phaseKindNames = [phaseKind.name for phaseKind in AllPhaseKinds]
+ extraPhaseKinds = [
+ "NONE = LIMIT",
+ "EXPLICIT_SUSPENSION = LIMIT",
+@@ -279,7 +279,7 @@ def generateHeader(out):
+ #
+ # Generate Phase enum.
+ #
+- phaseNames = map(lambda phase: phase.name, AllPhases)
++ phaseNames = [phase.name for phase in AllPhases]
+ extraPhases = [
+ "NONE = LIMIT",
+ "EXPLICIT_SUSPENSION = LIMIT",
+diff --git a/js/src/old-configure.in b/js/src/old-configure.in
+index 11c3d5a2e..389265404 100644
+--- a/js/src/old-configure.in
++++ b/js/src/old-configure.in
+@@ -1884,3 +1884,5 @@ if test "$JS_STANDALONE"; then
+ fi
+
+ rm -fr confdefs* $ac_clean_files
++echo confdefs* $ac_clean_files removed
++echo "old-configure done"
+diff --git a/memory/build/moz.build b/memory/build/moz.build
+index e2c715271..f09ce7935 100644
+--- a/memory/build/moz.build
++++ b/memory/build/moz.build
+@@ -30,7 +30,7 @@ else:
+ 'fallback.cpp',
+ ]
+
+-if CONFIG['OS_TARGET'] == 'Darwin' and (CONFIG['MOZ_REPLACE_MALLOC'] or
++if str(CONFIG['OS_TARGET']) == 'Darwin' and (CONFIG['MOZ_REPLACE_MALLOC'] or
+ CONFIG['MOZ_MEMORY']):
+ SOURCES += [
+ 'zone.c',
+@@ -38,15 +38,15 @@ if CONFIG['OS_TARGET'] == 'Darwin' and (CONFIG['MOZ_REPLACE_MALLOC'] or
+
+ Library('memory')
+
+-if CONFIG['OS_TARGET'] == 'Android' and CONFIG['CC_TYPE'] == 'clang':
++if str(CONFIG['OS_TARGET']) == 'Android' and str(CONFIG['CC_TYPE']) == 'clang':
+ CXXFLAGS += [
+ '-Wno-tautological-pointer-compare',
+ ]
+
+-if CONFIG['MOZ_BUILD_APP'] != 'memory':
++if str(CONFIG['MOZ_BUILD_APP']) != 'memory':
+ FINAL_LIBRARY = 'mozglue'
+
+-if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'):
++if str(CONFIG['CC_TYPE']) in ('msvc', 'clang-cl'):
+ CXXFLAGS += ['-wd4273'] # inconsistent dll linkage (bug 558163)
+
+ if CONFIG['MOZ_REPLACE_MALLOC_STATIC']:
+diff --git a/mozglue/build/moz.build b/mozglue/build/moz.build
+index 53758485a..5e9308802 100644
+--- a/mozglue/build/moz.build
++++ b/mozglue/build/moz.build
+@@ -9,12 +9,12 @@
+ # If this is ever changed, update MOZ_SHARED_MOZGLUE in browser/installer/Makefile.in
+ if CONFIG['JS_STANDALONE'] and not CONFIG['MOZ_MEMORY']:
+ Library('mozglue')
+-elif CONFIG['OS_TARGET'] in ('WINNT', 'Darwin', 'Android'):
++elif str(CONFIG['OS_TARGET']) in ('WINNT', 'Darwin', 'Android'):
+ SharedLibrary('mozglue')
+ else:
+ Library('mozglue')
+
+-if CONFIG['OS_TARGET'] == 'Android':
++if str(CONFIG['OS_TARGET']) == 'Android':
+ SOURCES += [
+ 'BionicGlue.cpp',
+ ]
+@@ -24,14 +24,14 @@ if CONFIG['MOZ_ASAN']:
+ 'AsanOptions.cpp',
+ ]
+
+-if CONFIG['OS_TARGET'] == 'WINNT':
++if str(CONFIG['OS_TARGET']) == 'WINNT':
+ DEFFILE = 'mozglue.def'
+ # We'll break the DLL blocklist if we immediately load user32.dll
+ DELAYLOAD_DLLS += [
+ 'user32.dll',
+ ]
+
+- if CONFIG['CC_TYPE'] == "msvc":
++ if str(CONFIG['CC_TYPE']) == "msvc":
+ CFLAGS += ['-guard:cf']
+ CXXFLAGS += ['-guard:cf']
+ LDFLAGS += ['-guard:cf']
+@@ -48,12 +48,12 @@ if CONFIG['MOZ_WIDGET_TOOLKIT']:
+ 'dummy.cpp',
+ ]
+
+- if CONFIG['OS_TARGET'] == 'WINNT':
++ if str(CONFIG['OS_TARGET']) == 'WINNT':
+ LOCAL_INCLUDES += [
+ '/memory/build',
+ ]
+
+- if CONFIG['CC_TYPE'] == "msvc":
++ if str(CONFIG['CC_TYPE']) == "msvc":
+ SOURCES += ['WindowsCFGStatus.cpp']
+ SOURCES += [
+ 'Authenticode.cpp',
+@@ -85,17 +85,17 @@ if CONFIG['MOZ_WIDGET_TOOLKIT']:
+ 'WindowsDllBlocklist.h',
+ ]
+
+- if CONFIG['CPU_ARCH'].startswith('x86'):
++ if str(CONFIG['CPU_ARCH']).startswith('x86'):
+ SOURCES += [
+ 'SSE.cpp',
+ ]
+
+- if CONFIG['CPU_ARCH'] == 'arm':
++ if str(CONFIG['CPU_ARCH']) == 'arm':
+ SOURCES += [
+ 'arm.cpp',
+ ]
+
+- if CONFIG['CPU_ARCH'].startswith('mips'):
++ if str(CONFIG['CPU_ARCH']).startswith('mips'):
+ SOURCES += [
+ 'mips.cpp',
+ ]
+@@ -114,7 +114,7 @@ LIBRARY_DEFINES['MOZ_HAS_MOZGLUE'] = True
+
+ LDFLAGS += CONFIG['MOZ_GLUE_WRAP_LDFLAGS']
+
+-if CONFIG['OS_TARGET'] == 'Darwin':
++if str(CONFIG['OS_TARGET']) == 'Darwin':
+ # On OSX 10.10.3, a dead lock happens in some cases involving dynamic
+ # symbol resolution for symbols that jemalloc itself uses. While it
+ # might be possible to find a way to avoid all such symbol resolutions,
+@@ -124,7 +124,7 @@ if CONFIG['OS_TARGET'] == 'Darwin':
+ # for TLS.
+ LDFLAGS += ['-Wl,-bind_at_load']
+
+-if CONFIG['MOZ_LINKER'] and CONFIG['TARGET_CPU'] == 'arm':
++if CONFIG['MOZ_LINKER'] and str(CONFIG['TARGET_CPU']) == 'arm':
+ LDFLAGS += ['-Wl,-version-script,%s/arm-eabi-filter' % SRCDIR]
+
+ DIST_INSTALL = True
+diff --git a/python/mozbuild/mozbuild/action/check_binary.py b/python/mozbuild/mozbuild/action/check_binary.py
+index 5665ef053..b696f73d6 100644
+--- a/python/mozbuild/mozbuild/action/check_binary.py
++++ b/python/mozbuild/mozbuild/action/check_binary.py
+@@ -104,6 +104,8 @@ def iter_readelf_symbols(target, binary):
+
+ def iter_readelf_dynamic(target, binary):
+ for line in get_output(target['readelf'], '-d', binary):
++ if isinstance(line, bytes):
++ line=line.decode('utf-8')
+ data = line.split(None, 2)
+ if data and len(data) == 3 and data[0].startswith('0x'):
+ yield data[1].rstrip(')').lstrip('('), data[2]
+diff --git a/python/mozbuild/mozbuild/action/process_define_files.py b/python/mozbuild/mozbuild/action/process_define_files.py
+index 563fbb8fa..c3df2869b 100644
+--- a/python/mozbuild/mozbuild/action/process_define_files.py
++++ b/python/mozbuild/mozbuild/action/process_define_files.py
+@@ -2,7 +2,7 @@
+ # License, v. 2.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 absolute_import, print_function, unicode_literals
++
+
+ import argparse
+ import os
+@@ -53,7 +53,7 @@ def process_define_file(output, input):
+ 'CONFIGURE_DEFINE_FILE')
+ defines = '\n'.join(sorted(
+ '#define %s %s' % (name, val)
+- for name, val in config.defines['ALLDEFINES'].iteritems()))
++ for name, val in config.defines['ALLDEFINES'].items()))
+ l = l[:m.start('cmd') - 1] \
+ + defines + l[m.end('name'):]
+ elif cmd == 'define':
+diff --git a/python/mozbuild/mozbuild/backend/base.py b/python/mozbuild/mozbuild/backend/base.py
+index a8d5c94e0..7cda63475 100644
+--- a/python/mozbuild/mozbuild/backend/base.py
++++ b/python/mozbuild/mozbuild/backend/base.py
+@@ -2,7 +2,7 @@
+ # License, v. 2.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 absolute_import, unicode_literals
++
+
+ from abc import (
+ ABCMeta,
+@@ -31,7 +31,7 @@ from .configenvironment import ConfigEnvironment
+ from mozbuild.base import ExecutionSummary
+
+
+-class BuildBackend(LoggingMixin):
++class BuildBackend(LoggingMixin, metaclass=ABCMeta):
+ """Abstract base class for build backends.
+
+ A build backend is merely a consumer of the build configuration (the output
+@@ -39,8 +39,6 @@ class BuildBackend(LoggingMixin):
+ is the discretion of the specific implementation.
+ """
+
+- __metaclass__ = ABCMeta
+-
+ def __init__(self, environment):
+ assert isinstance(environment, (ConfigEnvironment, EmptyConfig))
+ self.populate_logger()
+@@ -311,7 +309,7 @@ class BuildBackend(LoggingMixin):
+ srcdir = mozpath.dirname(obj.input_path)
+ pp.context.update({
+ k: ' '.join(v) if isinstance(v, list) else v
+- for k, v in obj.config.substs.iteritems()
++ for k, v in obj.config.substs.items()
+ })
+ pp.context.update(
+ top_srcdir=obj.topsrcdir,
+diff --git a/python/mozbuild/mozbuild/backend/common.py b/python/mozbuild/mozbuild/backend/common.py
+index d00cbbcaf..f747df446 100644
+--- a/python/mozbuild/mozbuild/backend/common.py
++++ b/python/mozbuild/mozbuild/backend/common.py
+@@ -2,7 +2,7 @@
+ # License, v. 2.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 absolute_import, unicode_literals
++
+
+ import json
+ import os
+@@ -174,7 +174,7 @@ class CommonBackend(BuildBackend):
+ if len(self._idl_manager.idls):
+ self._write_rust_xpidl_summary(self._idl_manager)
+ self._handle_idl_manager(self._idl_manager)
+- self._handle_generated_sources(mozpath.join(self.environment.topobjdir, 'dist/include/%s.h' % idl['root']) for idl in self._idl_manager.idls.values())
++ self._handle_generated_sources(mozpath.join(self.environment.topobjdir, 'dist/include/%s.h' % idl['root']) for idl in list(self._idl_manager.idls.values()))
+
+
+ for config in self._configs:
+@@ -372,14 +372,14 @@ class CommonBackend(BuildBackend):
+
+ with self._write_file(mozpath.join(topobjdir, 'dist', 'xpcrs', 'rt', 'all.rs')) as fh:
+ fh.write("// THIS FILE IS GENERATED - DO NOT EDIT\n\n")
+- for idl in manager.idls.values():
++ for idl in list(manager.idls.values()):
+ fh.write(include_tmpl % ("rt", idl['root']))
+ fh.write(";\n")
+
+ with self._write_file(mozpath.join(topobjdir, 'dist', 'xpcrs', 'bt', 'all.rs')) as fh:
+ fh.write("// THIS FILE IS GENERATED - DO NOT EDIT\n\n")
+ fh.write("&[\n")
+- for idl in manager.idls.values():
++ for idl in list(manager.idls.values()):
+ fh.write(include_tmpl % ("bt", idl['root']))
+ fh.write(",\n")
+ fh.write("]\n")
+diff --git a/python/mozbuild/mozbuild/backend/configenvironment.py b/python/mozbuild/mozbuild/backend/configenvironment.py
+index 3676a7d18..f0896cea4 100644
+--- a/python/mozbuild/mozbuild/backend/configenvironment.py
++++ b/python/mozbuild/mozbuild/backend/configenvironment.py
+@@ -2,14 +2,14 @@
+ # License, v. 2.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 absolute_import
++
+
+ import os
+ import sys
+ import json
+
+ from collections import Iterable, OrderedDict
+-from types import StringTypes, ModuleType
++from types import ModuleType
+
+ import mozpack.path as mozpath
+
+@@ -22,7 +22,7 @@ from mozbuild.shellutil import quote as shell_quote
+
+
+ if sys.version_info.major == 2:
+- text_type = unicode
++ text_type = str
+ else:
+ text_type = str
+
+@@ -151,7 +151,7 @@ class ConfigEnvironment(object):
+ shell_quote(self.defines[name]).replace('$', '$$'))
+ for name in sorted(global_defines)])
+ def serialize(name, obj):
+- if isinstance(obj, StringTypes):
++ if isinstance(obj, str):
+ return obj
+ if isinstance(obj, Iterable):
+ return ' '.join(obj)
+@@ -185,8 +185,8 @@ class ConfigEnvironment(object):
+ except UnicodeDecodeError:
+ return v.decode('utf-8', 'replace')
+
+- for k, v in self.substs.items():
+- if not isinstance(v, StringTypes):
++ for k, v in list(self.substs.items()):
++ if not isinstance(v, str):
+ if isinstance(v, Iterable):
+ type(v)(decode(i) for i in v)
+ elif not isinstance(v, text_type):
+@@ -255,7 +255,7 @@ class PartialConfigDict(object):
+ existing_files = self._load_config_track()
+
+ new_files = set()
+- for k, v in values.iteritems():
++ for k, v in values.items():
+ new_files.add(self._write_file(k, v))
+
+ for filename in existing_files - new_files:
+diff --git a/python/mozbuild/mozbuild/backend/fastermake.py b/python/mozbuild/mozbuild/backend/fastermake.py
+index b029aa10f..b66ade64f 100644
+--- a/python/mozbuild/mozbuild/backend/fastermake.py
++++ b/python/mozbuild/mozbuild/backend/fastermake.py
+@@ -2,7 +2,7 @@
+ # License, v. 2.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 absolute_import, unicode_literals, print_function
++
+
+ from mozbuild.backend.base import PartialBackend
+ from mozbuild.backend.common import CommonBackend
+@@ -140,7 +140,7 @@ class FasterMakeBackend(CommonBackend, PartialBackend):
+ # Add information for chrome manifest generation
+ manifest_targets = []
+
+- for target, entries in self._manifest_entries.iteritems():
++ for target, entries in self._manifest_entries.items():
+ manifest_targets.append(target)
+ install_target = mozpath.basedir(target, install_manifests_bases)
+ self._install_manifests[install_target].add_content(
+@@ -152,13 +152,13 @@ class FasterMakeBackend(CommonBackend, PartialBackend):
+ % ' '.join(self._install_manifests.keys()))
+
+ # Add dependencies we infered:
+- for target, deps in self._dependencies.iteritems():
++ for target, deps in self._dependencies.items():
+ mk.create_rule([target]).add_dependencies(
+ '$(TOPOBJDIR)/%s' % d for d in deps)
+
+ mk.add_statement('include $(TOPSRCDIR)/config/faster/rules.mk')
+
+- for base, install_manifest in self._install_manifests.iteritems():
++ for base, install_manifest in self._install_manifests.items():
+ with self._write_file(
+ mozpath.join(self.environment.topobjdir, 'faster',
+ 'install_%s' % base.replace('/', '_'))) as fh:
+@@ -167,7 +167,7 @@ class FasterMakeBackend(CommonBackend, PartialBackend):
+ # For artifact builds only, write a single unified manifest for consumption by |mach watch|.
+ if self.environment.is_artifact_build:
+ unified_manifest = InstallManifest()
+- for base, install_manifest in self._install_manifests.iteritems():
++ for base, install_manifest in self._install_manifests.items():
+ # Expect 'dist/bin/**', which includes 'dist/bin' with no trailing slash.
+ assert base.startswith('dist/bin')
+ base = base[len('dist/bin'):]
+diff --git a/python/mozbuild/mozbuild/backend/recursivemake.py b/python/mozbuild/mozbuild/backend/recursivemake.py
+index dd9020d62..aa89cc297 100644
+--- a/python/mozbuild/mozbuild/backend/recursivemake.py
++++ b/python/mozbuild/mozbuild/backend/recursivemake.py
+@@ -2,7 +2,7 @@
+ # License, v. 2.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 absolute_import, unicode_literals
++
+
+ import logging
+ import os
+@@ -12,7 +12,7 @@ from collections import (
+ defaultdict,
+ namedtuple,
+ )
+-from StringIO import StringIO
++from io import StringIO
+ from itertools import chain
+
+ from mozpack.manifests import (
+@@ -80,75 +80,76 @@ from ..util import (
+ )
+ from ..makeutil import Makefile
+ from mozbuild.shellutil import quote as shell_quote
++from functools import reduce
+
+ MOZBUILD_VARIABLES = [
+- b'ASFLAGS',
+- b'CMSRCS',
+- b'CMMSRCS',
+- b'CPP_UNIT_TESTS',
+- b'DIRS',
+- b'DIST_INSTALL',
+- b'EXTRA_DSO_LDOPTS',
+- b'EXTRA_JS_MODULES',
+- b'EXTRA_PP_COMPONENTS',
+- b'EXTRA_PP_JS_MODULES',
+- b'FORCE_SHARED_LIB',
+- b'FORCE_STATIC_LIB',
+- b'FINAL_LIBRARY',
+- b'HOST_CFLAGS',
+- b'HOST_CSRCS',
+- b'HOST_CMMSRCS',
+- b'HOST_CXXFLAGS',
+- b'HOST_EXTRA_LIBS',
+- b'HOST_LIBRARY_NAME',
+- b'HOST_PROGRAM',
+- b'HOST_SIMPLE_PROGRAMS',
+- b'JAR_MANIFEST',
+- b'JAVA_JAR_TARGETS',
+- b'LIBRARY_NAME',
+- b'LIBS',
+- b'MAKE_FRAMEWORK',
+- b'MODULE',
+- b'NO_DIST_INSTALL',
+- b'NO_EXPAND_LIBS',
+- b'NO_INTERFACES_MANIFEST',
+- b'NO_JS_MANIFEST',
+- b'OS_LIBS',
+- b'PARALLEL_DIRS',
+- b'PREF_JS_EXPORTS',
+- b'PROGRAM',
+- b'RESOURCE_FILES',
+- b'SHARED_LIBRARY_LIBS',
+- b'SHARED_LIBRARY_NAME',
+- b'SIMPLE_PROGRAMS',
+- b'SONAME',
+- b'STATIC_LIBRARY_NAME',
+- b'TEST_DIRS',
+- b'TOOL_DIRS',
++ 'ASFLAGS',
++ 'CMSRCS',
++ 'CMMSRCS',
++ 'CPP_UNIT_TESTS',
++ 'DIRS',
++ 'DIST_INSTALL',
++ 'EXTRA_DSO_LDOPTS',
++ 'EXTRA_JS_MODULES',
++ 'EXTRA_PP_COMPONENTS',
++ 'EXTRA_PP_JS_MODULES',
++ 'FORCE_SHARED_LIB',
++ 'FORCE_STATIC_LIB',
++ 'FINAL_LIBRARY',
++ 'HOST_CFLAGS',
++ 'HOST_CSRCS',
++ 'HOST_CMMSRCS',
++ 'HOST_CXXFLAGS',
++ 'HOST_EXTRA_LIBS',
++ 'HOST_LIBRARY_NAME',
++ 'HOST_PROGRAM',
++ 'HOST_SIMPLE_PROGRAMS',
++ 'JAR_MANIFEST',
++ 'JAVA_JAR_TARGETS',
++ 'LIBRARY_NAME',
++ 'LIBS',
++ 'MAKE_FRAMEWORK',
++ 'MODULE',
++ 'NO_DIST_INSTALL',
++ 'NO_EXPAND_LIBS',
++ 'NO_INTERFACES_MANIFEST',
++ 'NO_JS_MANIFEST',
++ 'OS_LIBS',
++ 'PARALLEL_DIRS',
++ 'PREF_JS_EXPORTS',
++ 'PROGRAM',
++ 'RESOURCE_FILES',
++ 'SHARED_LIBRARY_LIBS',
++ 'SHARED_LIBRARY_NAME',
++ 'SIMPLE_PROGRAMS',
++ 'SONAME',
++ 'STATIC_LIBRARY_NAME',
++ 'TEST_DIRS',
++ 'TOOL_DIRS',
+ # XXX config/Makefile.in specifies this in a make invocation
+ #'USE_EXTENSION_MANIFEST',
+- b'XPCSHELL_TESTS',
+- b'XPIDL_MODULE',
++ 'XPCSHELL_TESTS',
++ 'XPIDL_MODULE',
+ ]
+
+ DEPRECATED_VARIABLES = [
+- b'EXPORT_LIBRARY',
+- b'EXTRA_LIBS',
+- b'HOST_LIBS',
+- b'LIBXUL_LIBRARY',
+- b'MOCHITEST_A11Y_FILES',
+- b'MOCHITEST_BROWSER_FILES',
+- b'MOCHITEST_BROWSER_FILES_PARTS',
+- b'MOCHITEST_CHROME_FILES',
+- b'MOCHITEST_FILES',
+- b'MOCHITEST_FILES_PARTS',
+- b'MOCHITEST_METRO_FILES',
+- b'MOCHITEST_ROBOCOP_FILES',
+- b'MODULE_OPTIMIZE_FLAGS',
+- b'MOZ_CHROME_FILE_FORMAT',
+- b'SHORT_LIBNAME',
+- b'TESTING_JS_MODULES',
+- b'TESTING_JS_MODULE_DIR',
++ 'EXPORT_LIBRARY',
++ 'EXTRA_LIBS',
++ 'HOST_LIBS',
++ 'LIBXUL_LIBRARY',
++ 'MOCHITEST_A11Y_FILES',
++ 'MOCHITEST_BROWSER_FILES',
++ 'MOCHITEST_BROWSER_FILES_PARTS',
++ 'MOCHITEST_CHROME_FILES',
++ 'MOCHITEST_FILES',
++ 'MOCHITEST_FILES_PARTS',
++ 'MOCHITEST_METRO_FILES',
++ 'MOCHITEST_ROBOCOP_FILES',
++ 'MODULE_OPTIMIZE_FLAGS',
++ 'MOZ_CHROME_FILE_FORMAT',
++ 'SHORT_LIBNAME',
++ 'TESTING_JS_MODULES',
++ 'TESTING_JS_MODULE_DIR',
+ ]
+
+ MOZBUILD_VARIABLES_MESSAGE = 'It should only be defined in moz.build files.'
+@@ -207,7 +208,7 @@ class BackendMakeFile(object):
+ self.fh.write(buf)
+
+ def write_once(self, buf):
+- if isinstance(buf, unicode):
++ if isinstance(buf, str):
+ buf = buf.encode('utf-8')
+ if b'\n' + buf not in self.fh.getvalue():
+ self.write(buf)
+@@ -280,7 +281,7 @@ class RecursiveMakeTraversal(object):
+ Helper function to call a filter from compute_dependencies and
+ traverse.
+ """
+- return filter(current, self.get_subdirs(current))
++ return list(filter(current, self.get_subdirs(current)))
+
+ def compute_dependencies(self, filter=None):
+ """
+@@ -710,7 +711,7 @@ class RecursiveMakeBackend(CommonBackend):
+ convenience variables, and the other dependency definitions for a
+ hopefully proper directory traversal.
+ """
+- for tier, no_skip in self._no_skip.items():
++ for tier, no_skip in list(self._no_skip.items()):
+ self.log(logging.DEBUG, 'fill_root_mk', {
+ 'number': len(no_skip), 'tier': tier
+ }, 'Using {number} directories during {tier}')
+@@ -757,7 +758,7 @@ class RecursiveMakeBackend(CommonBackend):
+ for tier, filter in filters:
+ main, all_deps = \
+ self._traversal.compute_dependencies(filter)
+- for dir, deps in all_deps.items():
++ for dir, deps in list(all_deps.items()):
+ if deps is not None or (dir in self._idl_dirs \
+ and tier == 'export'):
+ rule = root_deps_mk.create_rule(['%s/%s' % (dir, tier)])
+@@ -770,7 +771,7 @@ class RecursiveMakeBackend(CommonBackend):
+ rule.add_dependencies('%s/%s' % (d, tier) for d in main)
+
+ all_compile_deps = reduce(lambda x,y: x|y,
+- self._compile_graph.values()) if self._compile_graph else set()
++ list(self._compile_graph.values())) if self._compile_graph else set()
+ # Include the following as dependencies of the top recursion target for
+ # compilation:
+ # - nodes that are not dependended upon by anything. Typically, this
+@@ -783,7 +784,7 @@ class RecursiveMakeBackend(CommonBackend):
+ # as direct dependencies of the top recursion target, to somehow
+ # prioritize them.
+ # 1. See bug 1262241 comment 5.
+- compile_roots = [t for t, deps in self._compile_graph.iteritems()
++ compile_roots = [t for t, deps in list(self._compile_graph.items())
+ if not deps or t not in all_compile_deps]
+
+ rule = root_deps_mk.create_rule(['recurse_compile'])
+@@ -845,14 +846,14 @@ class RecursiveMakeBackend(CommonBackend):
+ rule.add_dependencies(['$(CURDIR)/%: %'])
+
+ def _check_blacklisted_variables(self, makefile_in, makefile_content):
+- if b'EXTERNALLY_MANAGED_MAKE_FILE' in makefile_content:
++ if 'EXTERNALLY_MANAGED_MAKE_FILE' in makefile_content:
+ # Bypass the variable restrictions for externally managed makefiles.
+ return
+
+ for l in makefile_content.splitlines():
+ l = l.strip()
+ # Don't check comments
+- if l.startswith(b'#'):
++ if l.startswith('#'):
+ continue
+ for x in chain(MOZBUILD_VARIABLES, DEPRECATED_VARIABLES):
+ if x not in l:
+@@ -909,11 +910,11 @@ class RecursiveMakeBackend(CommonBackend):
+ # Directories with a Makefile containing a tools target, or
+ # XPI_PKGNAME or INSTALL_EXTENSION_ID can't be skipped and
+ # must run during the 'tools' tier.
+- for t in (b'XPI_PKGNAME', b'INSTALL_EXTENSION_ID',
+- b'tools'):
++ for t in ('XPI_PKGNAME', 'INSTALL_EXTENSION_ID',
++ 'tools'):
+ if t not in content:
+ continue
+- if t == b'tools' and not re.search('(?:^|\s)tools.*::', content, re.M):
++ if t == 'tools' and not re.search('(?:^|\s)tools.*::', content, re.M):
+ continue
+ if objdir == self.environment.topobjdir:
+ continue
+@@ -933,7 +934,7 @@ class RecursiveMakeBackend(CommonBackend):
+ self._fill_root_mk()
+
+ # Make the master test manifest files.
+- for flavor, t in self._test_manifests.items():
++ for flavor, t in list(self._test_manifests.items()):
+ install_prefix, manifests = t
+ manifest_stem = mozpath.join(install_prefix, '%s.ini' % flavor)
+ self._write_master_test_manifest(mozpath.join(
+@@ -1039,7 +1040,7 @@ class RecursiveMakeBackend(CommonBackend):
+ for p in ('Makefile', 'backend.mk', '.deps/.mkdir.done'):
+ build_files.add_optional_exists(p)
+
+- for idl in manager.idls.values():
++ for idl in list(manager.idls.values()):
+ self._install_manifests['dist_idl'].add_link(idl['source'],
+ idl['basename'])
+ self._install_manifests['dist_include'].add_optional_exists('%s.h'
+@@ -1086,7 +1087,7 @@ class RecursiveMakeBackend(CommonBackend):
+
+ interfaces_manifests = []
+ dist_dir = mozpath.join(self.environment.topobjdir, 'dist')
+- for manifest, entries in manager.interface_manifests.items():
++ for manifest, entries in list(manager.interface_manifests.items()):
+ interfaces_manifests.append(mozpath.join('$(DEPTH)', manifest))
+ for xpt in sorted(entries):
+ registered_xpt_files.add(mozpath.join(
+@@ -1194,7 +1195,7 @@ class RecursiveMakeBackend(CommonBackend):
+ # Don't allow files to be defined multiple times unless it is allowed.
+ # We currently allow duplicates for non-test files or test files if
+ # the manifest is listed as a duplicate.
+- for source, (dest, is_test) in obj.installs.items():
++ for source, (dest, is_test) in list(obj.installs.items()):
+ try:
+ self._install_manifests['_test_files'].add_link(source, dest)
+ except ValueError:
+@@ -1558,7 +1559,7 @@ class RecursiveMakeBackend(CommonBackend):
+ man_dir = mozpath.join(self.environment.topobjdir, '_build_manifests',
+ dest)
+
+- for k, manifest in manifests.items():
++ for k, manifest in list(manifests.items()):
+ with self._write_file(mozpath.join(man_dir, k)) as fh:
+ manifest.write(fileobj=fh)
+
+@@ -1593,20 +1594,20 @@ class RecursiveMakeBackend(CommonBackend):
+ pp.context.update(extra)
+ if not pp.context.get('autoconfmk', ''):
+ pp.context['autoconfmk'] = 'autoconf.mk'
+- pp.handleLine(b'# THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT MODIFY BY HAND.\n');
+- pp.handleLine(b'DEPTH := @DEPTH@\n')
+- pp.handleLine(b'topobjdir := @topobjdir@\n')
+- pp.handleLine(b'topsrcdir := @top_srcdir@\n')
+- pp.handleLine(b'srcdir := @srcdir@\n')
+- pp.handleLine(b'VPATH := @srcdir@\n')
+- pp.handleLine(b'relativesrcdir := @relativesrcdir@\n')
+- pp.handleLine(b'include $(DEPTH)/config/@autoconfmk@\n')
++ pp.handleLine('# THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT MODIFY BY HAND.\n');
++ pp.handleLine('DEPTH := @DEPTH@\n')
++ pp.handleLine('topobjdir := @topobjdir@\n')
++ pp.handleLine('topsrcdir := @top_srcdir@\n')
++ pp.handleLine('srcdir := @srcdir@\n')
++ pp.handleLine('VPATH := @srcdir@\n')
++ pp.handleLine('relativesrcdir := @relativesrcdir@\n')
++ pp.handleLine('include $(DEPTH)/config/@autoconfmk@\n')
+ if not stub:
+ pp.do_include(obj.input_path)
+ # Empty line to avoid failures when last line in Makefile.in ends
+ # with a backslash.
+- pp.handleLine(b'\n')
+- pp.handleLine(b'include $(topsrcdir)/config/recurse.mk\n')
++ pp.handleLine('\n')
++ pp.handleLine('include $(topsrcdir)/config/recurse.mk\n')
+ if not stub:
+ # Adding the Makefile.in here has the desired side-effect
+ # that if the Makefile.in disappears, this will force
+diff --git a/python/mozbuild/mozbuild/config_status.py b/python/mozbuild/mozbuild/config_status.py
+index d46f1332d..a9a27a699 100644
+--- a/python/mozbuild/mozbuild/config_status.py
++++ b/python/mozbuild/mozbuild/config_status.py
+@@ -77,6 +77,7 @@ def config_status(topobjdir='.', topsrcdir='.', defines=None,
+ See build/autoconf/config.status.m4.
+ '''
+
++ print("config_status started")
+ if 'CONFIG_FILES' in os.environ:
+ raise Exception('Using the CONFIG_FILES environment variable is not '
+ 'supported.')
+@@ -119,7 +120,7 @@ def config_status(topobjdir='.', topsrcdir='.', defines=None,
+ if 'WRITE_MOZINFO' in os.environ:
+ write_mozinfo(os.path.join(topobjdir, 'mozinfo.json'), env, os.environ)
+
+- cpu_start = time.clock()
++ cpu_start = time.perf_counter()
+ time_start = time.time()
+
+ # Make appropriate backend instances, defaulting to RecursiveMakeBackend,
+@@ -155,7 +156,7 @@ def config_status(topobjdir='.', topsrcdir='.', defines=None,
+ summary = obj.gyp_summary()
+ print(summary, file=sys.stderr)
+
+- cpu_time = time.clock() - cpu_start
++ cpu_time = time.perf_counter() - cpu_start
+ wall_time = time.time() - time_start
+ efficiency = cpu_time / wall_time if wall_time else 100
+ untracked = wall_time - execution_time
+@@ -179,3 +180,5 @@ def config_status(topobjdir='.', topsrcdir='.', defines=None,
+ # Advertise Android Studio if it is appropriate.
+ if MachCommandConditions.is_android(env):
+ print(ANDROID_IDE_ADVERTISEMENT)
++
++ print("config_status finished")
+diff --git a/python/mozbuild/mozbuild/configure/__init__.py b/python/mozbuild/mozbuild/configure/__init__.py
+index d03615707..13d623d4f 100644
+--- a/python/mozbuild/mozbuild/configure/__init__.py
++++ b/python/mozbuild/mozbuild/configure/__init__.py
+@@ -2,9 +2,9 @@
+ # License, v. 2.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 absolute_import, print_function, unicode_literals
+
+-import __builtin__
++
++import builtins
+ import inspect
+ import logging
+ import os
+@@ -38,6 +38,8 @@ from mozbuild.util import (
+
+ import mozpack.path as mozpath
+
++import traceback
++
+
+ class ConfigureError(Exception):
+ pass
+@@ -69,7 +71,7 @@ class SandboxDependsFunction(object):
+ def __getattr__(self, key):
+ return self._getattr(key).sandboxed
+
+- def __nonzero__(self):
++ def __bool__(self):
+ raise ConfigureError(
+ 'Cannot do boolean operations on @depends functions.')
+
+@@ -96,6 +98,7 @@ class DependsFunction(object):
+ sandbox._value_for(self)
+ elif not sandbox._help:
+ sandbox._execution_queue.append((sandbox._value_for, (self,)))
++ sandbox.tasks_debug_out("DependsFunction.__init %s" % func.__name__)
+
+ @property
+ def name(self):
+@@ -206,6 +209,15 @@ class CombinedDependsFunction(DependsFunction):
+ def __ne__(self, other):
+ return not self == other
+
++ def __hash__(self):
++ # This was one was taken from [1] initially. Should not have done that:
++ # it causes explosion of ConfigureSandbox._execution_queue with 100%
++ # CPU load and eating all avaliable memory...
++ #
++ # [1] https://code.foxkit.us/adelie/packages/blob/f2b5773da19ab397fbe64fd32dacc383cfe4cd77/user/mozjs/python3.patch#L8068
++ return hash((self._name, tuple(self.dependencies)))
++
++
+ class SandboxedGlobal(dict):
+ '''Identifiable dict type for use as function global'''
+
+@@ -253,11 +265,12 @@ class ConfigureSandbox(dict):
+ # The default set of builtins. We expose unicode as str to make sandboxed
+ # files more python3-ready.
+ BUILTINS = ReadOnlyDict({
+- b: getattr(__builtin__, b)
++ b: getattr(builtins, b)
+ for b in ('None', 'False', 'True', 'int', 'bool', 'any', 'all', 'len',
+ 'list', 'tuple', 'set', 'dict', 'isinstance', 'getattr',
+- 'hasattr', 'enumerate', 'range', 'zip')
+- }, __import__=forbidden_import, str=unicode)
++ 'hasattr', 'enumerate', 'range', 'zip', '__build_class__',
++ 'bytes', 'exec')
++ }, __import__=forbidden_import, str=str)
+
+ # Expose a limited set of functions from os.path
+ OS = ReadOnlyNamespace(path=ReadOnlyNamespace(**{
+@@ -294,6 +307,11 @@ class ConfigureSandbox(dict):
+ # Queue of functions to execute, with their arguments
+ self._execution_queue = []
+
++ # For debugging: Show number of tasks started in run() / added elsewhere
++ # and some additional info
++ self.task_debug = False # set True to enable
++ self.tasks_started = 0
++
+ # Store the `when`s associated to some options.
+ self._conditions = {}
+
+@@ -331,7 +349,7 @@ class ConfigureSandbox(dict):
+ return method
+ def wrapped(*args, **kwargs):
+ out_args = [
+- arg.decode(encoding) if isinstance(arg, str) else arg
++ arg.decode(encoding) if isinstance(arg, bytes) else arg
+ for arg in args
+ ]
+ return method(*out_args, **kwargs)
+@@ -360,6 +378,14 @@ class ConfigureSandbox(dict):
+ handler.setFormatter(formatter)
+ logger.addHandler(handler)
+
++ def tasks_debug_out(self, text):
++ if self.task_debug:
++ print("%s / queued %i / done %i" %(text, len(self._execution_queue), self.tasks_started))
++ #if len(self._execution_queue) > 5000:
++ # traceback.print_stack(file=sys.stdout)
++ #if len(self._execution_queue) > 5010:
++ # raise Exception("Too many tasks")
++
+ def include_file(self, path):
+ '''Include one file in the sandbox. Users of this class probably want
+ to use `run` instead.
+@@ -380,6 +406,9 @@ class ConfigureSandbox(dict):
+ if path in self._all_paths:
+ raise ConfigureError(
+ 'Cannot include `%s` because it was included already.' % path)
++
++ if self.task_debug:
++ print("include_file", path)
+ self._paths.append(path)
+ self._all_paths.add(path)
+
+@@ -398,7 +427,7 @@ class ConfigureSandbox(dict):
+ if path:
+ self.include_file(path)
+
+- for option in self._options.itervalues():
++ for option in self._options.values():
+ # All options must be referenced by some @depends function
+ if option not in self._seen:
+ raise ConfigureError(
+@@ -425,6 +454,8 @@ class ConfigureSandbox(dict):
+
+ # Run the execution queue
+ for func, args in self._execution_queue:
++ self.tasks_started += 1
++ self.tasks_debug_out("ConfigureSandbox.run(%s)" % func.__name__)
+ func(*args)
+
+ if self._help:
+@@ -504,7 +535,7 @@ class ConfigureSandbox(dict):
+ value = PositiveOptionValue()
+ elif value is False or value == ():
+ value = NegativeOptionValue()
+- elif isinstance(value, types.StringTypes):
++ elif isinstance(value, (str,)):
+ value = PositiveOptionValue((value,))
+ elif isinstance(value, tuple):
+ value = PositiveOptionValue(value)
+@@ -544,7 +575,7 @@ class ConfigureSandbox(dict):
+ return value
+
+ def _dependency(self, arg, callee_name, arg_name=None):
+- if isinstance(arg, types.StringTypes):
++ if isinstance(arg, (str,)):
+ prefix, name, values = Option.split_option(arg)
+ if values != ():
+ raise ConfigureError("Option must not contain an '='")
+@@ -608,7 +639,7 @@ class ConfigureSandbox(dict):
+ '''
+ when = self._normalize_when(kwargs.get('when'), 'option')
+ args = [self._resolve(arg) for arg in args]
+- kwargs = {k: self._resolve(v) for k, v in kwargs.iteritems()
++ kwargs = {k: self._resolve(v) for k, v in kwargs.items()
+ if k != 'when'}
+ option = Option(*args, **kwargs)
+ if when:
+@@ -689,7 +720,7 @@ class ConfigureSandbox(dict):
+ with self.only_when_impl(when):
+ what = self._resolve(what)
+ if what:
+- if not isinstance(what, types.StringTypes):
++ if not isinstance(what, (str,)):
+ raise TypeError("Unexpected type: '%s'" % type(what).__name__)
+ self.include_file(what)
+
+@@ -707,7 +738,7 @@ class ConfigureSandbox(dict):
+ (k[:-len('_impl')], getattr(self, k))
+ for k in dir(self) if k.endswith('_impl') and k != 'template_impl'
+ )
+- glob.update((k, v) for k, v in self.iteritems() if k not in glob)
++ glob.update((k, v) for k, v in self.items() if k not in glob)
+
+ # Any function argument to the template must be prepared to be sandboxed.
+ # If the template itself returns a function (in which case, it's very
+@@ -731,7 +762,7 @@ class ConfigureSandbox(dict):
+ def wrapper(*args, **kwargs):
+ args = [maybe_prepare_function(arg) for arg in args]
+ kwargs = {k: maybe_prepare_function(v)
+- for k, v in kwargs.iteritems()}
++ for k, v in kwargs.items()}
+ ret = template(*args, **kwargs)
+ if isfunction(ret):
+ # We can't expect the sandboxed code to think about all the
+@@ -766,7 +797,7 @@ class ConfigureSandbox(dict):
+ for value, required in (
+ (_import, True), (_from, False), (_as, False)):
+
+- if not isinstance(value, types.StringTypes) and (
++ if not isinstance(value, (str,)) and (
+ required or value is not None):
+ raise TypeError("Unexpected type: '%s'" % type(value).__name__)
+ if value is not None and not self.RE_MODULE.match(value):
+@@ -807,7 +838,7 @@ class ConfigureSandbox(dict):
+ # Special case for the open() builtin, because otherwise, using it
+ # fails with "IOError: file() constructor not accessible in
+ # restricted mode"
+- if what == '__builtin__.open':
++ if what == 'builtins.open':
+ return lambda *args, **kwargs: open(*args, **kwargs)
+ # Until this proves to be a performance problem, just construct an
+ # import statement and execute it.
+@@ -829,7 +860,7 @@ class ConfigureSandbox(dict):
+ name = self._resolve(name, need_help_dependency=False)
+ if name is None:
+ return
+- if not isinstance(name, types.StringTypes):
++ if not isinstance(name, (str,)):
+ raise TypeError("Unexpected type: '%s'" % type(name).__name__)
+ if name in data:
+ raise ConfigureError(
+@@ -850,6 +881,7 @@ class ConfigureSandbox(dict):
+
+ self._execution_queue.append((
+ self._resolve_and_set, (self._config, name, value, when)))
++ self.tasks_debug_out("ConfigureSandbox.set_config_impl / %s(%s" % (name, value))
+
+ def set_define_impl(self, name, value, when=None):
+ '''Implementation of set_define().
+@@ -864,6 +896,7 @@ class ConfigureSandbox(dict):
+ defines = self._config.setdefault('DEFINES', {})
+ self._execution_queue.append((
+ self._resolve_and_set, (defines, name, value, when)))
++ self.tasks_debug_out("ConfigureSandbox.set_define_impl / %s(%s)" % (name, value))
+
+ def imply_option_impl(self, option, value, reason=None, when=None):
+ '''Implementation of imply_option().
+@@ -922,7 +955,7 @@ class ConfigureSandbox(dict):
+ if isinstance(possible_reasons[0], Option):
+ reason = possible_reasons[0]
+ if not reason and (isinstance(value, (bool, tuple)) or
+- isinstance(value, types.StringTypes)):
++ isinstance(value, (str,))):
+ # A reason can be provided automatically when imply_option
+ # is called with an immediate value.
+ _, filename, line, _, _, _ = inspect.stack()[1]
+@@ -955,10 +988,10 @@ class ConfigureSandbox(dict):
+ if not inspect.isfunction(func):
+ raise TypeError("Unexpected type: '%s'" % type(func).__name__)
+ if func in self._prepared_functions:
+- return func, func.func_globals
++ return func, func.__globals__
+
+ glob = SandboxedGlobal(
+- (k, v) for k, v in func.func_globals.iteritems()
++ (k, v) for k, v in func.__globals__.items()
+ if (inspect.isfunction(v) and v not in self._templates) or (
+ inspect.isclass(v) and issubclass(v, Exception))
+ )
+@@ -979,20 +1012,20 @@ class ConfigureSandbox(dict):
+ # Note this is not entirely bullet proof (if the value is e.g. a list,
+ # the list contents could have changed), but covers the bases.
+ closure = None
+- if func.func_closure:
++ if func.__closure__:
+ def makecell(content):
+ def f():
+ content
+- return f.func_closure[0]
++ return f.__closure__[0]
+
+ closure = tuple(makecell(cell.cell_contents)
+- for cell in func.func_closure)
++ for cell in func.__closure__)
+
+ new_func = self.wraps(func)(types.FunctionType(
+- func.func_code,
++ func.__code__,
+ glob,
+ func.__name__,
+- func.func_defaults,
++ func.__defaults__,
+ closure
+ ))
+ @self.wraps(new_func)
+diff --git a/python/mozbuild/mozbuild/configure/check_debug_ranges.py b/python/mozbuild/mozbuild/configure/check_debug_ranges.py
+index c0caa9cc5..a3e1f37e1 100644
+--- a/python/mozbuild/mozbuild/configure/check_debug_ranges.py
++++ b/python/mozbuild/mozbuild/configure/check_debug_ranges.py
+@@ -6,7 +6,7 @@
+ # to a given compilation unit. This is used as a helper to find a bug in some
+ # versions of GNU ld.
+
+-from __future__ import absolute_import
++
+
+ import subprocess
+ import sys
+@@ -45,6 +45,8 @@ def get_range_length(range, debug_ranges):
+ def main(bin, compilation_unit):
+ p = subprocess.Popen(['objdump', '-W', bin], stdout = subprocess.PIPE, stderr = subprocess.PIPE)
+ (out, err) = p.communicate()
++ if isinstance(out, bytes):
++ out = out.decode('utf-8')
+ sections = re.split('\n(Contents of the|The section) ', out)
+ debug_info = [s for s in sections if s.startswith('.debug_info')]
+ debug_ranges = [s for s in sections if s.startswith('.debug_ranges')]
+@@ -59,4 +61,4 @@ def main(bin, compilation_unit):
+
+
+ if __name__ == '__main__':
+- print(main(*sys.argv[1:]))
++ print((main(*sys.argv[1:])))
+diff --git a/python/mozbuild/mozbuild/configure/options.py b/python/mozbuild/mozbuild/configure/options.py
+index 53ae2ae6d..4d80cad86 100644
+--- a/python/mozbuild/mozbuild/configure/options.py
++++ b/python/mozbuild/mozbuild/configure/options.py
+@@ -2,7 +2,7 @@
+ # License, v. 2.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 absolute_import, print_function, unicode_literals
++
+
+ import os
+ import sys
+@@ -12,7 +12,7 @@ from collections import OrderedDict
+
+ def istupleofstrings(obj):
+ return isinstance(obj, tuple) and len(obj) and all(
+- isinstance(o, types.StringTypes) for o in obj)
++ isinstance(o, (str,)) for o in obj)
+
+
+ class OptionValue(tuple):
+@@ -88,7 +88,7 @@ class PositiveOptionValue(OptionValue):
+ in the form of a tuple for when values are given to the option (in the form
+ --option=value[,value2...].
+ '''
+- def __nonzero__(self):
++ def __bool__(self):
+ return True
+
+
+@@ -113,7 +113,7 @@ class ConflictingOptionError(InvalidOptionError):
+ if format_data:
+ message = message.format(**format_data)
+ super(ConflictingOptionError, self).__init__(message)
+- for k, v in format_data.iteritems():
++ for k, v in format_data.items():
+ setattr(self, k, v)
+
+
+@@ -149,7 +149,7 @@ class Option(object):
+ 'At least an option name or an environment variable name must '
+ 'be given')
+ if name:
+- if not isinstance(name, types.StringTypes):
++ if not isinstance(name, (str,)):
+ raise InvalidOptionError('Option must be a string')
+ if not name.startswith('--'):
+ raise InvalidOptionError('Option must start with `--`')
+@@ -158,7 +158,7 @@ class Option(object):
+ if not name.islower():
+ raise InvalidOptionError('Option must be all lowercase')
+ if env:
+- if not isinstance(env, types.StringTypes):
++ if not isinstance(env, (str,)):
+ raise InvalidOptionError(
+ 'Environment variable name must be a string')
+ if not env.isupper():
+@@ -168,8 +168,8 @@ class Option(object):
+ isinstance(nargs, int) and nargs >= 0):
+ raise InvalidOptionError(
+ "nargs must be a positive integer, '?', '*' or '+'")
+- if (not isinstance(default, types.StringTypes) and
+- not isinstance(default, (bool, types.NoneType)) and
++ if (not isinstance(default, (str,)) and
++ not isinstance(default, (bool, type(None))) and
+ not istupleofstrings(default)):
+ raise InvalidOptionError(
+ 'default must be a bool, a string or a tuple of strings')
+@@ -241,7 +241,7 @@ class Option(object):
+ ', '.join("'%s'" % c for c in choices))
+ elif has_choices:
+ maxargs = self.maxargs
+- if len(choices) < maxargs and maxargs != sys.maxint:
++ if len(choices) < maxargs and maxargs != sys.maxsize:
+ raise InvalidOptionError('Not enough `choices` for `nargs`')
+ self.choices = choices
+ self.help = help
+@@ -255,7 +255,7 @@ class Option(object):
+ where prefix is one of 'with', 'without', 'enable' or 'disable'.
+ The '=values' part is optional. Values are separated with commas.
+ '''
+- if not isinstance(option, types.StringTypes):
++ if not isinstance(option, (str,)):
+ raise InvalidOptionError('Option must be a string')
+
+ elements = option.split('=', 1)
+@@ -308,7 +308,7 @@ class Option(object):
+ def maxargs(self):
+ if isinstance(self.nargs, int):
+ return self.nargs
+- return 1 if self.nargs == '?' else sys.maxint
++ return 1 if self.nargs == '?' else sys.maxsize
+
+ def _validate_nargs(self, num):
+ minargs, maxargs = self.minargs, self.maxargs
+@@ -499,5 +499,5 @@ class CommandLineHelper(object):
+
+ def __iter__(self):
+ for d in (self._args, self._extra_args):
+- for arg, pos in d.itervalues():
++ for arg, pos in d.values():
+ yield arg
+diff --git a/python/mozbuild/mozbuild/configure/util.py b/python/mozbuild/mozbuild/configure/util.py
+index 9d8b2eb0e..a12986e48 100644
+--- a/python/mozbuild/mozbuild/configure/util.py
++++ b/python/mozbuild/mozbuild/configure/util.py
+@@ -77,15 +77,7 @@ class ConfigureOutputHandler(logging.Handler):
+ # Python has this feature where it sets the encoding of pipes to
+ # ascii, which blatantly fails when trying to print out non-ascii.
+ def fix_encoding(fh):
+- try:
+- isatty = fh.isatty()
+- except AttributeError:
+- isatty = True
+-
+- if not isatty:
+- encoding = getpreferredencoding()
+- if encoding:
+- return codecs.getwriter(encoding)(fh)
++ # no magic on oe / python3
+ return fh
+
+ self._stdout = fix_encoding(stdout)
+@@ -200,7 +192,7 @@ class LineIO(object):
+ self._errors = errors
+
+ def write(self, buf):
+- if self._encoding and isinstance(buf, str):
++ if self._encoding and isinstance(buf, bytes):
+ buf = buf.decode(self._encoding, self._errors)
+ lines = buf.splitlines()
+ if not lines:
+diff --git a/python/mozbuild/mozbuild/controller/building.py b/python/mozbuild/mozbuild/controller/building.py
+index d5af532f7..e9810fe58 100644
+--- a/python/mozbuild/mozbuild/controller/building.py
++++ b/python/mozbuild/mozbuild/controller/building.py
+@@ -2,7 +2,7 @@
+ # License, v. 2.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 absolute_import, unicode_literals
++
+
+ import errno
+ import getpass
+@@ -146,7 +146,7 @@ class TierStatus(object):
+ """
+ o = []
+
+- for tier, state in self.tiers.items():
++ for tier, state in list(self.tiers.items()):
+ t_entry = dict(
+ name=tier,
+ start=state['begin_time'],
+@@ -574,7 +574,7 @@ class BuildProgressFooter(Footer):
+
+ def __init__(self, terminal, monitor):
+ Footer.__init__(self, terminal)
+- self.tiers = monitor.tiers.tier_status.viewitems()
++ self.tiers = monitor.tiers.tier_status.items()
+
+ def draw(self):
+ """Draws this footer in the terminal."""
+@@ -911,8 +911,8 @@ class CCacheStats(object):
+
+ return '\n'.join(lines)
+
+- def __nonzero__(self):
+- relative_values = [v for k, v in self._values.items()
++ def __bool__(self):
++ relative_values = [v for k, v in list(self._values.items())
+ if k not in self.ABSOLUTE_KEYS]
+ return (all(v >= 0 for v in relative_values) and
+ any(v > 0 for v in relative_values))
+@@ -1156,7 +1156,7 @@ class BuildDriver(MozbuildObject):
+
+ high_finder, finder_percent = monitor.have_high_finder_usage()
+ if high_finder:
+- print(FINDER_SLOW_MESSAGE % finder_percent)
++ print((FINDER_SLOW_MESSAGE % finder_percent))
+
+ ccache_end = monitor.ccache_stats()
+
+@@ -1276,8 +1276,8 @@ class BuildDriver(MozbuildObject):
+ """Install test files."""
+
+ if self.is_clobber_needed():
+- print(INSTALL_TESTS_CLOBBER.format(
+- clobber_file=os.path.join(self.topobjdir, 'CLOBBER')))
++ print((INSTALL_TESTS_CLOBBER.format(
++ clobber_file=os.path.join(self.topobjdir, 'CLOBBER'))))
+ sys.exit(1)
+
+ if not test_objs:
+diff --git a/python/mozbuild/mozbuild/frontend/context.py b/python/mozbuild/mozbuild/frontend/context.py
+index fbdbefc1d..1aef6a65a 100644
+--- a/python/mozbuild/mozbuild/frontend/context.py
++++ b/python/mozbuild/mozbuild/frontend/context.py
+@@ -14,7 +14,7 @@ If you are looking for the absolute authority on what moz.build files can
+ contain, you've come to the right place.
+ """
+
+-from __future__ import absolute_import, unicode_literals
++
+
+ import os
+
+@@ -237,15 +237,15 @@ class Context(KeyedDefaultDict):
+ This function is transactional: if setitem fails for one of the values,
+ the context is not updated at all."""
+ if isinstance(iterable, dict):
+- iterable = iterable.items()
++ iterable = list(iterable.items())
+
+ update = {}
+- for key, value in itertools.chain(iterable, kwargs.items()):
++ for key, value in itertools.chain(iterable, list(kwargs.items())):
+ stored_type = self._validate(key, value)
+ # Don't create an instance of stored_type if coercion is needed,
+ # until all values are validated.
+ update[key] = (value, stored_type)
+- for key, (value, stored_type) in update.items():
++ for key, (value, stored_type) in list(update.items()):
+ if not isinstance(value, stored_type):
+ update[key] = stored_type(value)
+ else:
+@@ -311,7 +311,7 @@ class BaseCompileFlags(ContextDerivedValue, dict):
+ # a template were set and which were provided as defaults.
+ template_name = getattr(context, 'template', None)
+ if template_name in (None, 'Gyp'):
+- dict.__init__(self, ((k, v if v is None else TypedList(unicode)(v))
++ dict.__init__(self, ((k, v if v is None else TypedList(str)(v))
+ for k, v, _ in self.flag_variables))
+ else:
+ dict.__init__(self)
+@@ -520,13 +520,13 @@ class CompileFlags(BaseCompileFlags):
+ if key in self and self[key] is None:
+ raise ValueError('`%s` may not be set in COMPILE_FLAGS from moz.build, this '
+ 'value is resolved from the emitter.' % key)
+- if not (isinstance(value, list) and all(isinstance(v, basestring) for v in value)):
++ if not (isinstance(value, list) and all(isinstance(v, str) for v in value)):
+ raise ValueError('A list of strings must be provided as a value for a '
+ 'compile flags category.')
+ dict.__setitem__(self, key, value)
+
+
+-class FinalTargetValue(ContextDerivedValue, unicode):
++class FinalTargetValue(ContextDerivedValue, str):
+ def __new__(cls, context, value=""):
+ if not value:
+ value = 'dist/'
+@@ -536,7 +536,7 @@ class FinalTargetValue(ContextDerivedValue, unicode):
+ value += 'bin'
+ if context['DIST_SUBDIR']:
+ value += '/' + context['DIST_SUBDIR']
+- return unicode.__new__(cls, value)
++ return str.__new__(cls, value)
+
+
+ def Enum(*values):
+@@ -584,7 +584,7 @@ class PathMeta(type):
+ cls = SourcePath
+ return super(PathMeta, cls).__call__(context, value)
+
+-class Path(ContextDerivedValue, unicode):
++class Path(ContextDerivedValue, str, metaclass=PathMeta):
+ """Stores and resolves a source path relative to a given context
+
+ This class is used as a backing type for some of the sandbox variables.
+@@ -595,7 +595,6 @@ class Path(ContextDerivedValue, unicode):
+ - '!objdir/relative/paths'
+ - '%/filesystem/absolute/paths'
+ """
+- __metaclass__ = PathMeta
+
+ def __new__(cls, context, value=None):
+ return super(Path, cls).__new__(cls, value)
+@@ -612,10 +611,14 @@ class Path(ContextDerivedValue, unicode):
+ """
+ return Path(self.context, mozpath.join(self, *p))
+
++ @staticmethod
++ def cmp(a, b):
++ return (a > b) - (a < b)
++
+ def __cmp__(self, other):
+ if isinstance(other, Path) and self.srcdir != other.srcdir:
+- return cmp(self.full_path, other.full_path)
+- return cmp(unicode(self), other)
++ return self.cmp(self.full_path, other.full_path)
++ return self.cmp(str(self), other)
+
+ # __cmp__ is not enough because unicode has __eq__, __ne__, etc. defined
+ # and __cmp__ is only used for those when they don't exist.
+@@ -773,7 +776,7 @@ def ContextDerivedTypedRecord(*fields):
+ __slots__ = tuple([name for name, _ in fields])
+
+ def __init__(self, context):
+- for fname, ftype in self._fields.items():
++ for fname, ftype in list(self._fields.items()):
+ if issubclass(ftype, ContextDerivedValue):
+ setattr(self, fname, self._fields[fname](context))
+ else:
+@@ -909,8 +912,8 @@ def TypedListWithAction(typ, action):
+ return _TypedListWithAction
+
+ WebPlatformTestManifest = TypedNamedTuple("WebPlatformTestManifest",
+- [("manifest_path", unicode),
+- ("test_root", unicode)])
++ [("manifest_path", str),
++ ("test_root", str)])
+ ManifestparserManifestList = OrderedPathListWithAction(read_manifestparser_manifest)
+ ReftestManifestList = OrderedPathListWithAction(read_reftest_manifest)
+ WptManifestList = TypedListWithAction(WebPlatformTestManifest, read_wpt_manifest)
+@@ -918,18 +921,18 @@ WptManifestList = TypedListWithAction(WebPlatformTestManifest, read_wpt_manifest
+ OrderedSourceList = ContextDerivedTypedList(SourcePath, StrictOrderingOnAppendList)
+ OrderedTestFlavorList = TypedList(Enum(*all_test_flavors()),
+ StrictOrderingOnAppendList)
+-OrderedStringList = TypedList(unicode, StrictOrderingOnAppendList)
++OrderedStringList = TypedList(str, StrictOrderingOnAppendList)
+ DependentTestsEntry = ContextDerivedTypedRecord(('files', OrderedSourceList),
+ ('tags', OrderedStringList),
+ ('flavors', OrderedTestFlavorList))
+ BugzillaComponent = TypedNamedTuple('BugzillaComponent',
+- [('product', unicode), ('component', unicode)])
++ [('product', str), ('component', str)])
+ SchedulingComponents = ContextDerivedTypedRecord(
+- ('inclusive', TypedList(unicode, StrictOrderingOnAppendList)),
+- ('exclusive', TypedList(unicode, StrictOrderingOnAppendList)))
++ ('inclusive', TypedList(str, StrictOrderingOnAppendList)),
++ ('exclusive', TypedList(str, StrictOrderingOnAppendList)))
+
+ GeneratedFilesList = StrictOrderingOnAppendListWithFlagsFactory({
+- 'script': unicode,
++ 'script': str,
+ 'inputs': list,
+ 'flags': list, })
+
+@@ -1096,7 +1099,7 @@ class Files(SubContext):
+ self.test_tags |= other.test_tags
+ self.test_flavors |= other.test_flavors
+
+- for k, v in other.items():
++ for k, v in list(other.items()):
+ if k == 'IMPACTED_TESTS':
+ self.test_files |= set(mozpath.relpath(e.full_path, e.context.config.topsrcdir)
+ for e in v.files)
+@@ -1154,7 +1157,7 @@ class Files(SubContext):
+
+ bug_components = Counter()
+
+- for f in files.values():
++ for f in list(files.values()):
+ bug_component = f.get('BUG_COMPONENT')
+ if bug_component:
+ bug_components[bug_component] += 1
+@@ -1232,7 +1235,7 @@ VARIABLES = {
+ RustLibrary template instead.
+ """),
+
+- 'RUST_LIBRARY_TARGET_DIR': (unicode, unicode,
++ 'RUST_LIBRARY_TARGET_DIR': (str, str,
+ """Where CARGO_TARGET_DIR should point when compiling this library. If
+ not set, it defaults to the current objdir. It should be a relative path
+ to the current objdir; absolute paths should not be used.
+@@ -1248,7 +1251,7 @@ VARIABLES = {
+ HostRustLibrary template instead.
+ """),
+
+- 'RUST_TEST': (unicode, unicode,
++ 'RUST_TEST': (str, str,
+ """Name of a Rust test to build and run via `cargo test`.
+
+ This variable should not be used directly; you should be using the
+@@ -1487,7 +1490,7 @@ VARIABLES = {
+ """Like ``OBJDIR_FILES``, with preprocessing. Use sparingly.
+ """),
+
+- 'FINAL_LIBRARY': (unicode, unicode,
++ 'FINAL_LIBRARY': (str, str,
+ """Library in which the objects of the current directory will be linked.
+
+ This variable contains the name of a library, defined elsewhere with
+@@ -1528,7 +1531,7 @@ VARIABLES = {
+ with the host compiler.
+ """),
+
+- 'HOST_LIBRARY_NAME': (unicode, unicode,
++ 'HOST_LIBRARY_NAME': (str, str,
+ """Name of target library generated when cross compiling.
+ """),
+
+@@ -1546,7 +1549,7 @@ VARIABLES = {
+ libraries that link into this library via FINAL_LIBRARY.
+ """),
+
+- 'LIBRARY_NAME': (unicode, unicode,
++ 'LIBRARY_NAME': (str, str,
+ """The code name of the library generated for a directory.
+
+ By default STATIC_LIBRARY_NAME and SHARED_LIBRARY_NAME take this name.
+@@ -1558,7 +1561,7 @@ VARIABLES = {
+ ``example/components/xpcomsample.lib`` on Windows.
+ """),
+
+- 'SHARED_LIBRARY_NAME': (unicode, unicode,
++ 'SHARED_LIBRARY_NAME': (str, str,
+ """The name of the static library generated for a directory, if it needs to
+ differ from the library code name.
+
+@@ -1572,7 +1575,7 @@ VARIABLES = {
+ Implies FORCE_SHARED_LIB.
+ """),
+
+- 'STATIC_LIBRARY_NAME': (unicode, unicode,
++ 'STATIC_LIBRARY_NAME': (str, str,
+ """The name of the static library generated for a directory, if it needs to
+ differ from the library code name.
+
+@@ -1604,31 +1607,31 @@ VARIABLES = {
+
+ This variable contains a list of system libaries to link against.
+ """),
+- 'RCFILE': (unicode, unicode,
++ 'RCFILE': (str, str,
+ """The program .rc file.
+
+ This variable can only be used on Windows.
+ """),
+
+- 'RESFILE': (unicode, unicode,
++ 'RESFILE': (str, str,
+ """The program .res file.
+
+ This variable can only be used on Windows.
+ """),
+
+- 'RCINCLUDE': (unicode, unicode,
++ 'RCINCLUDE': (str, str,
+ """The resource script file to be included in the default .res file.
+
+ This variable can only be used on Windows.
+ """),
+
+- 'DEFFILE': (unicode, unicode,
++ 'DEFFILE': (str, str,
+ """The program .def (module definition) file.
+
+ This variable can only be used on Windows.
+ """),
+
+- 'SYMBOLS_FILE': (Path, unicode,
++ 'SYMBOLS_FILE': (Path, str,
+ """A file containing a list of symbols to export from a shared library.
+
+ The given file contains a list of symbols to be exported, and is
+@@ -1649,7 +1652,7 @@ VARIABLES = {
+ ``BIN_SUFFIX``, the name will remain unchanged.
+ """),
+
+- 'SONAME': (unicode, unicode,
++ 'SONAME': (str, str,
+ """The soname of the shared object currently being linked
+
+ soname is the "logical name" of a shared object, often used to provide
+@@ -1719,7 +1722,7 @@ VARIABLES = {
+ ``GENERATED_FILES``.
+ """),
+
+- 'PROGRAM' : (unicode, unicode,
++ 'PROGRAM' : (str, str,
+ """Compiled executable name.
+
+ If the configuration token ``BIN_SUFFIX`` is set, its value will be
+@@ -1727,7 +1730,7 @@ VARIABLES = {
+ ``BIN_SUFFIX``, ``PROGRAM`` will remain unchanged.
+ """),
+
+- 'HOST_PROGRAM' : (unicode, unicode,
++ 'HOST_PROGRAM' : (str, str,
+ """Compiled host executable name.
+
+ If the configuration token ``HOST_BIN_SUFFIX`` is set, its value will be
+@@ -1765,7 +1768,7 @@ VARIABLES = {
+ files.
+ """),
+
+- 'XPIDL_MODULE': (unicode, unicode,
++ 'XPIDL_MODULE': (str, str,
+ """XPCOM Interface Definition Module Name.
+
+ This is the name of the ``.xpt`` file that is created by linking
+@@ -1924,14 +1927,14 @@ VARIABLES = {
+
+
+ # The following variables are used to control the target of installed files.
+- 'XPI_NAME': (unicode, unicode,
++ 'XPI_NAME': (str, str,
+ """The name of an extension XPI to generate.
+
+ When this variable is present, the results of this directory will end up
+ being packaged into an extension instead of the main dist/bin results.
+ """),
+
+- 'DIST_SUBDIR': (unicode, unicode,
++ 'DIST_SUBDIR': (str, str,
+ """The name of an alternate directory to install files to.
+
+ When this variable is present, the results of this directory will end up
+@@ -1939,7 +1942,7 @@ VARIABLES = {
+ otherwise be placed.
+ """),
+
+- 'FINAL_TARGET': (FinalTargetValue, unicode,
++ 'FINAL_TARGET': (FinalTargetValue, str,
+ """The name of the directory to install targets to.
+
+ The directory is relative to the top of the object directory. The
+@@ -1970,7 +1973,7 @@ VARIABLES = {
+
+ 'GYP_DIRS': (StrictOrderingOnAppendListWithFlagsFactory({
+ 'variables': dict,
+- 'input': unicode,
++ 'input': str,
+ 'sandbox_vars': dict,
+ 'no_chromium': bool,
+ 'no_unified': bool,
+@@ -2194,7 +2197,7 @@ VARIABLES = {
+ }
+
+ # Sanity check: we don't want any variable above to have a list as storage type.
+-for name, (storage_type, input_types, docs) in VARIABLES.items():
++for name, (storage_type, input_types, docs) in list(VARIABLES.items()):
+ if storage_type == list:
+ raise RuntimeError('%s has a "list" storage type. Use "List" instead.'
+ % name)
+diff --git a/python/mozbuild/mozbuild/frontend/data.py b/python/mozbuild/mozbuild/frontend/data.py
+index 442fc9e0a..837453a9f 100644
+--- a/python/mozbuild/mozbuild/frontend/data.py
++++ b/python/mozbuild/mozbuild/frontend/data.py
+@@ -15,7 +15,7 @@ contains the code for converting executed mozbuild files into these data
+ structures.
+ """
+
+-from __future__ import absolute_import, unicode_literals
++
+
+ from mozbuild.util import StrictOrderingOnAppendList
+ from mozpack.chrome.manifest import ManifestEntry
+@@ -182,7 +182,7 @@ class ComputedFlags(ContextDerived):
+ if value:
+ for dest_var in dest_vars:
+ flags[dest_var].extend(value)
+- return flags.items()
++ return list(flags.items())
+
+ class XPIDLFile(ContextDerived):
+ """Describes an XPIDL file to be compiled."""
+@@ -213,7 +213,7 @@ class BaseDefines(ContextDerived):
+ self.defines = defines
+
+ def get_defines(self):
+- for define, value in self.defines.iteritems():
++ for define, value in self.defines.items():
+ if value is True:
+ yield('-D%s' % define)
+ elif value is False:
+@@ -494,7 +494,7 @@ class SimpleProgram(BaseProgram):
+ KIND = 'target'
+
+ def source_files(self):
+- for srcs in self.sources.values():
++ for srcs in list(self.sources.values()):
+ for f in srcs:
+ if mozpath.basename(mozpath.splitext(f)[0]) == mozpath.splitext(self.program)[0]:
+ return [f]
+diff --git a/python/mozbuild/mozbuild/frontend/emitter.py b/python/mozbuild/mozbuild/frontend/emitter.py
+index 642b381c0..c28344a75 100644
+--- a/python/mozbuild/mozbuild/frontend/emitter.py
++++ b/python/mozbuild/mozbuild/frontend/emitter.py
+@@ -2,7 +2,7 @@
+ # License, v. 2.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 absolute_import, unicode_literals
++
+
+ import itertools
+ import logging
+@@ -116,8 +116,8 @@ class TreeMetadataEmitter(LoggingMixin):
+ # arguments. This gross hack works around the problem until we
+ # rid ourselves of 2.6.
+ self.info = {}
+- for k, v in mozinfo.info.items():
+- if isinstance(k, unicode):
++ for k, v in list(mozinfo.info.items()):
++ if isinstance(k, str):
+ k = k.encode('ascii')
+ self.info[k] = v
+
+@@ -234,7 +234,7 @@ class TreeMetadataEmitter(LoggingMixin):
+
+
+ # Next do FINAL_LIBRARY linkage.
+- for lib in (l for libs in self._libs.values() for l in libs):
++ for lib in (l for libs in list(self._libs.values()) for l in libs):
+ if not isinstance(lib, (StaticLibrary, RustLibrary)) or not lib.link_into:
+ continue
+ if lib.link_into not in self._libs:
+@@ -294,13 +294,13 @@ class TreeMetadataEmitter(LoggingMixin):
+ lib.link_into == outerlib.basename):
+ propagate_defines(lib, defines)
+
+- for lib in (l for libs in self._libs.values() for l in libs):
++ for lib in (l for libs in list(self._libs.values()) for l in libs):
+ if isinstance(lib, Library):
+ propagate_defines(lib, lib.lib_defines)
+ yield lib
+
+
+- for lib in (l for libs in self._libs.values() for l in libs):
++ for lib in (l for libs in list(self._libs.values()) for l in libs):
+ lib_defines = list(lib.lib_defines.get_defines())
+ if lib_defines:
+ objdir_flags = self._compile_flags[lib.objdir]
+@@ -310,13 +310,13 @@ class TreeMetadataEmitter(LoggingMixin):
+ if objdir_flags:
+ objdir_flags.resolve_flags('LIBRARY_DEFINES', lib_defines)
+
+- for flags_obj in self._compile_flags.values():
++ for flags_obj in list(self._compile_flags.values()):
+ yield flags_obj
+
+- for flags_obj in self._compile_as_flags.values():
++ for flags_obj in list(self._compile_as_flags.values()):
+ yield flags_obj
+
+- for obj in self._binaries.values():
++ for obj in list(self._binaries.values()):
+ yield obj
+
+
+@@ -409,7 +409,7 @@ class TreeMetadataEmitter(LoggingMixin):
+ libs[key] = l
+ if key not in libs:
+ libs[key] = l
+- candidates = libs.values()
++ candidates = list(libs.values())
+ if force_static and not candidates:
+ if dir:
+ raise SandboxValidationError(
+@@ -473,9 +473,9 @@ class TreeMetadataEmitter(LoggingMixin):
+
+ def _verify_deps(self, context, crate_dir, crate_name, dependencies, description='Dependency'):
+ """Verify that a crate's dependencies all specify local paths."""
+- for dep_crate_name, values in dependencies.iteritems():
++ for dep_crate_name, values in dependencies.items():
+ # A simple version number.
+- if isinstance(values, (str, unicode)):
++ if isinstance(values, str):
+ raise SandboxValidationError(
+ '%s %s of crate %s does not list a path' % (description, dep_crate_name, crate_name),
+ context)
+@@ -529,7 +529,7 @@ class TreeMetadataEmitter(LoggingMixin):
+
+ cargo_target_dir = context.get('RUST_LIBRARY_TARGET_DIR', '.')
+
+- dependencies = set(config.get('dependencies', {}).iterkeys())
++ dependencies = set(config.get('dependencies', {}).keys())
+
+ features = context.get(cls.FEATURES_VAR, [])
+ unique_features = set(features)
+@@ -863,7 +863,7 @@ class TreeMetadataEmitter(LoggingMixin):
+ assert not gen_sources['UNIFIED_SOURCES']
+
+ no_pgo = context.get('NO_PGO')
+- no_pgo_sources = [f for f, flags in all_flags.iteritems()
++ no_pgo_sources = [f for f, flags in all_flags.items()
+ if flags.no_pgo]
+ if no_pgo:
+ if no_pgo_sources:
+@@ -890,7 +890,7 @@ class TreeMetadataEmitter(LoggingMixin):
+
+ # The inverse of the above, mapping suffixes to their canonical suffix.
+ canonicalized_suffix_map = {}
+- for suffix, alternatives in suffix_map.iteritems():
++ for suffix, alternatives in suffix_map.items():
+ alternatives.add(suffix)
+ for a in alternatives:
+ canonicalized_suffix_map[a] = suffix
+@@ -914,7 +914,7 @@ class TreeMetadataEmitter(LoggingMixin):
+ # Source files to track for linkables associated with this context.
+ ctxt_sources = defaultdict(lambda: defaultdict(list))
+
+- for variable, (klass, gen_klass, suffixes) in varmap.items():
++ for variable, (klass, gen_klass, suffixes) in list(varmap.items()):
+ allowed_suffixes = set().union(*[suffix_map[s] for s in suffixes])
+
+ # First ensure that we haven't been given filetypes that we don't
+@@ -941,20 +941,20 @@ class TreeMetadataEmitter(LoggingMixin):
+ obj = cls(*arglist)
+ srcs = obj.files
+ if isinstance(obj, UnifiedSources) and obj.have_unified_mapping:
+- srcs = dict(obj.unified_source_mapping).keys()
++ srcs = list(dict(obj.unified_source_mapping).keys())
+ ctxt_sources[variable][canonical_suffix] += sorted(srcs)
+ yield obj
+
+ if ctxt_sources:
+ for linkable in linkables:
+ for target_var in ('SOURCES', 'UNIFIED_SOURCES'):
+- for suffix, srcs in ctxt_sources[target_var].items():
++ for suffix, srcs in list(ctxt_sources[target_var].items()):
+ linkable.sources[suffix] += srcs
+ for host_linkable in host_linkables:
+- for suffix, srcs in ctxt_sources['HOST_SOURCES'].items():
++ for suffix, srcs in list(ctxt_sources['HOST_SOURCES'].items()):
+ host_linkable.sources[suffix] += srcs
+
+- for f, flags in all_flags.iteritems():
++ for f, flags in all_flags.items():
+ if flags.flags:
+ ext = mozpath.splitext(f)[1]
+ yield PerSourceFlag(context, f, flags.flags)
+@@ -1143,7 +1143,7 @@ class TreeMetadataEmitter(LoggingMixin):
+ for obj in self._handle_linkables(context, passthru, generated_files):
+ yield obj
+
+- generated_files.update(['%s%s' % (k, self.config.substs.get('BIN_SUFFIX', '')) for k in self._binaries.keys()])
++ generated_files.update(['%s%s' % (k, self.config.substs.get('BIN_SUFFIX', '')) for k in list(self._binaries.keys())])
+
+ components = []
+ for var, cls in (
+@@ -1277,7 +1277,7 @@ class TreeMetadataEmitter(LoggingMixin):
+ for obj in self._process_jar_manifests(context):
+ yield obj
+
+- for name, jar in context.get('JAVA_JAR_TARGETS', {}).items():
++ for name, jar in list(context.get('JAVA_JAR_TARGETS', {}).items()):
+ yield ContextWrapped(context, jar)
+
+ computed_as_flags.resolve_flags('MOZBUILD',
+@@ -1346,7 +1346,7 @@ class TreeMetadataEmitter(LoggingMixin):
+ script = mozpath.join(mozpath.dirname(mozpath.dirname(__file__)),
+ 'action', 'process_define_files.py')
+ yield GeneratedFile(context, script, 'process_define_file',
+- unicode(path),
++ str(path),
+ [Path(context, path + '.in')])
+
+ generated_files = context.get('GENERATED_FILES') or []
+@@ -1393,7 +1393,7 @@ class TreeMetadataEmitter(LoggingMixin):
+ flags.flags, localized=localized)
+
+ def _process_test_manifests(self, context):
+- for prefix, info in TEST_MANIFESTS.items():
++ for prefix, info in list(TEST_MANIFESTS.items()):
+ for path, manifest in context.get('%s_MANIFESTS' % prefix, []):
+ for obj in self._process_test_manifest(context, info, path, manifest):
+ yield obj
+@@ -1479,7 +1479,7 @@ class TreeMetadataEmitter(LoggingMixin):
+
+ process_support_files(test)
+
+- for path, m_defaults in mpmanifest.manifest_defaults.items():
++ for path, m_defaults in list(mpmanifest.manifest_defaults.items()):
+ process_support_files(m_defaults)
+
+ # We also copy manifests into the output directory,
+diff --git a/python/mozbuild/mozbuild/frontend/reader.py b/python/mozbuild/mozbuild/frontend/reader.py
+index c1efc1c3d..0cdf8b8db 100644
+--- a/python/mozbuild/mozbuild/frontend/reader.py
++++ b/python/mozbuild/mozbuild/frontend/reader.py
+@@ -16,7 +16,7 @@ The BuildReader contains basic logic for traversing a tree of mozbuild files.
+ It does this by examining specific variables populated during execution.
+ """
+
+-from __future__ import absolute_import, print_function, unicode_literals
++
+
+ import ast
+ import inspect
+@@ -81,12 +81,13 @@ from .context import (
+
+ from mozbuild.base import ExecutionSummary
+ from concurrent.futures.process import ProcessPoolExecutor
++from functools import reduce
+
+
+
+ if sys.version_info.major == 2:
+- text_type = unicode
+- type_type = types.TypeType
++ text_type = str
++ type_type = type
+ else:
+ text_type = str
+ type_type = type
+@@ -127,7 +128,7 @@ class EmptyConfig(object):
+
+ self.substs = self.PopulateOnGetDict(EmptyValue, substs or self.default_substs)
+ udict = {}
+- for k, v in self.substs.items():
++ for k, v in list(self.substs.items()):
+ if isinstance(v, str):
+ udict[k.decode('utf-8')] = v.decode('utf-8')
+ else:
+@@ -311,7 +312,7 @@ class MozbuildSandbox(Sandbox):
+ raise Exception('`template` is a function decorator. You must '
+ 'use it as `@template` preceding a function declaration.')
+
+- name = func.func_name
++ name = func.__name__
+
+ if name in self.templates:
+ raise KeyError(
+@@ -390,7 +391,7 @@ class MozbuildSandbox(Sandbox):
+ klass = self._context.__class__
+ self._context.__class__ = TemplateContext
+ # The sandbox will do all the necessary checks for these merges.
+- for key, value in context.items():
++ for key, value in list(context.items()):
+ if isinstance(value, dict):
+ self[key].update(value)
+ elif isinstance(value, (list, HierarchicalStringList)):
+@@ -407,12 +408,14 @@ class MozbuildSandbox(Sandbox):
+
+ class TemplateFunction(object):
+ def __init__(self, func, sandbox):
+- self.path = func.func_code.co_filename
+- self.name = func.func_name
++ self.path = func.__code__.co_filename
++ self.name = func.__name__
+
+- code = func.func_code
++ code = func.__code__
+ firstlineno = code.co_firstlineno
+ lines = sandbox._current_source.splitlines(True)
++ if len(lines) and isinstance(lines[0], bytes):
++ lines = [l.decode('utf-8') for l in lines]
+ lines = inspect.getblock(lines[firstlineno - 1:])
+
+ # The code lines we get out of inspect.getsourcelines look like
+@@ -430,7 +433,7 @@ class TemplateFunction(object):
+ # actually never calls __getitem__ and __setitem__, so we need to
+ # modify the AST so that accesses to globals are properly directed
+ # to a dict.
+- self._global_name = b'_data' # AST wants str for this, not unicode
++ self._global_name = '_data'
+ # In case '_data' is a name used for a variable in the function code,
+ # prepend more underscores until we find an unused name.
+ while (self._global_name in code.co_names or
+@@ -449,8 +452,8 @@ class TemplateFunction(object):
+ compile(func_ast, self.path, 'exec'),
+ glob,
+ self.name,
+- func.func_defaults,
+- func.func_closure,
++ func.__defaults__,
++ func.__closure__,
+ )
+ func()
+
+@@ -464,11 +467,11 @@ class TemplateFunction(object):
+ '__builtins__': sandbox._builtins
+ }
+ func = types.FunctionType(
+- self._func.func_code,
++ self._func.__code__,
+ glob,
+ self.name,
+- self._func.func_defaults,
+- self._func.func_closure
++ self._func.__defaults__,
++ self._func.__closure__
+ )
+ sandbox.exec_function(func, args, kwargs, self.path,
+ becomes_current_path=False)
+@@ -484,7 +487,7 @@ class TemplateFunction(object):
+ def visit_Str(self, node):
+ # String nodes we got from the AST parser are str, but we want
+ # unicode literals everywhere, so transform them.
+- node.s = unicode(node.s)
++ node.s = str(node.s)
+ return node
+
+ def visit_Name(self, node):
+@@ -617,7 +620,7 @@ class BuildReaderError(Exception):
+
+ for l in traceback.format_exception(type(self.other), self.other,
+ self.trace):
+- s.write(unicode(l))
++ s.write(str(l))
+
+ return s.getvalue()
+
+@@ -767,7 +770,7 @@ class BuildReaderError(Exception):
+ s.write(' %s\n' % inner.args[2])
+ s.write('\n')
+ close_matches = difflib.get_close_matches(inner.args[2],
+- VARIABLES.keys(), 2)
++ list(VARIABLES.keys()), 2)
+ if close_matches:
+ s.write('Maybe you meant %s?\n' % ' or '.join(close_matches))
+ s.write('\n')
+@@ -1152,7 +1155,7 @@ class BuildReader(object):
+ context)
+ non_unified_sources.add(source)
+ action_overrides = {}
+- for action, script in gyp_dir.action_overrides.iteritems():
++ for action, script in gyp_dir.action_overrides.items():
+ action_overrides[action] = SourcePath(context, script)
+
+ gyp_processor = GypProcessor(context.config,
+@@ -1188,7 +1191,7 @@ class BuildReader(object):
+
+ recurse_info[d][key] = dict(sandbox.metadata[key])
+
+- for path, child_metadata in recurse_info.items():
++ for path, child_metadata in list(recurse_info.items()):
+ child_path = path.join('moz.build').full_path
+
+ # Ensure we don't break out of the topsrcdir. We don't do realpath
+@@ -1279,7 +1282,7 @@ class BuildReader(object):
+ # There is room to improve this code (and the code in
+ # _find_relevant_mozbuilds) to better handle multiple files in the same
+ # directory. Bug 1136966 tracks.
+- for path, mbpaths in relevants.items():
++ for path, mbpaths in list(relevants.items()):
+ path_mozbuilds[path] = [mozpath.join(topsrcdir, p) for p in mbpaths]
+
+ for i, mbpath in enumerate(mbpaths[0:-1]):
+@@ -1316,7 +1319,7 @@ class BuildReader(object):
+ all_contexts.append(context)
+
+ result = {}
+- for path, paths in path_mozbuilds.items():
++ for path, paths in list(path_mozbuilds.items()):
+ result[path] = reduce(lambda x, y: x + y, (contexts[p] for p in paths), [])
+
+ return result, all_contexts
+@@ -1356,7 +1359,7 @@ class BuildReader(object):
+
+ r = {}
+
+- for path, ctxs in paths.items():
++ for path, ctxs in list(paths.items()):
+ # Should be normalized by read_relevant_mozbuilds.
+ assert '\\' not in path
+
+diff --git a/python/mozbuild/mozbuild/frontend/sandbox.py b/python/mozbuild/mozbuild/frontend/sandbox.py
+index b2090802e..6d94291ea 100644
+--- a/python/mozbuild/mozbuild/frontend/sandbox.py
++++ b/python/mozbuild/mozbuild/frontend/sandbox.py
+@@ -17,7 +17,7 @@ KeyError are machine parseable. This machine-friendly data is used to present
+ user-friendly error messages in the case of errors.
+ """
+
+-from __future__ import absolute_import, unicode_literals
++
+
+ import os
+ import sys
+@@ -112,6 +112,7 @@ class Sandbox(dict):
+ 'int': int,
+ 'set': set,
+ 'tuple': tuple,
++ 'str': str,
+ })
+
+ def __init__(self, context, finder=default_finder):
+diff --git a/python/mozbuild/mozbuild/jar.py b/python/mozbuild/mozbuild/jar.py
+index 47a2eff63..96aea63ce 100644
+--- a/python/mozbuild/mozbuild/jar.py
++++ b/python/mozbuild/mozbuild/jar.py
+@@ -8,7 +8,7 @@ processing jar.mn files.
+ See the documentation for jar.mn on MDC for further details on the format.
+ '''
+
+-from __future__ import absolute_import
++
+
+ import sys
+ import os
+@@ -17,7 +17,7 @@ import re
+ import logging
+ from time import localtime
+ from MozZipFile import ZipFile
+-from cStringIO import StringIO
++from io import StringIO
+ from collections import defaultdict
+
+ from mozbuild.preprocessor import Preprocessor
+@@ -302,9 +302,9 @@ class JarMaker(object):
+ '''updateManifest replaces the % in the chrome registration entries
+ with the given chrome base path, and updates the given manifest file.
+ '''
+- myregister = dict.fromkeys(map(lambda s: s.replace('%',
+- chromebasepath), register))
+- addEntriesToListFile(manifestPath, myregister.iterkeys())
++ myregister = dict.fromkeys([s.replace('%',
++ chromebasepath) for s in register])
++ addEntriesToListFile(manifestPath, iter(myregister.keys()))
+
+ def makeJar(self, infile, jardir):
+ '''makeJar is the main entry point to JarMaker.
+@@ -322,7 +322,7 @@ class JarMaker(object):
+ elif self.relativesrcdir:
+ self.localedirs = \
+ self.generateLocaleDirs(self.relativesrcdir)
+- if isinstance(infile, basestring):
++ if isinstance(infile, str):
+ logging.info('processing ' + infile)
+ self.sourcedirs.append(_normpath(os.path.dirname(infile)))
+ pp = self.pp.clone()
+diff --git a/python/mozbuild/mozbuild/makeutil.py b/python/mozbuild/mozbuild/makeutil.py
+index fcd45bed2..f77c5d2c3 100644
+--- a/python/mozbuild/mozbuild/makeutil.py
++++ b/python/mozbuild/mozbuild/makeutil.py
+@@ -2,11 +2,10 @@
+ # License, v. 2.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 absolute_import
++
+
+ import os
+ import re
+-from types import StringTypes
+ from collections import Iterable
+
+
+@@ -66,7 +65,7 @@ class _SimpleOrderedSet(object):
+ self._list = []
+ self._set = set()
+
+- def __nonzero__(self):
++ def __bool__(self):
+ return bool(self._set)
+
+ def __iter__(self):
+@@ -103,19 +102,19 @@ class Rule(object):
+
+ def add_targets(self, targets):
+ '''Add additional targets to the rule.'''
+- assert isinstance(targets, Iterable) and not isinstance(targets, StringTypes)
++ assert isinstance(targets, Iterable) and not isinstance(targets, str)
+ self._targets.update(targets)
+ return self
+
+ def add_dependencies(self, deps):
+ '''Add dependencies to the rule.'''
+- assert isinstance(deps, Iterable) and not isinstance(deps, StringTypes)
++ assert isinstance(deps, Iterable) and not isinstance(deps, str)
+ self._dependencies.update(deps)
+ return self
+
+ def add_commands(self, commands):
+ '''Add commands to the rule.'''
+- assert isinstance(commands, Iterable) and not isinstance(commands, StringTypes)
++ assert isinstance(commands, Iterable) and not isinstance(commands, str)
+ self._commands.extend(commands)
+ return self
+
+@@ -139,13 +138,16 @@ class Rule(object):
+ '''
+ if not self._targets:
+ return
+- fh.write('%s:' % ' '.join(self._targets))
++ wstring = '%s:' % ' '.join(self._targets)
+ if self._dependencies:
+- fh.write(' %s' % ' '.join(self.dependencies()))
+- fh.write('\n')
++ wstring += ' %s' % ' '.join(self.dependencies())
++ wstring += '\n'
+ for cmd in self._commands:
+- fh.write('\t%s\n' % cmd)
+-
++ wstring += '\t%s\n' % cmd
++ try:
++ fh.write(wstring.encode('utf-8'))
++ except TypeError:
++ fh.write(wstring)
+
+ # colon followed by anything except a slash (Windows path detection)
+ _depfilesplitter = re.compile(r':(?![\\/])')
+diff --git a/python/mozbuild/mozbuild/mozinfo.py b/python/mozbuild/mozbuild/mozinfo.py
+index 7e7ad1b2a..f03f20ba3 100755
+--- a/python/mozbuild/mozbuild/mozinfo.py
++++ b/python/mozbuild/mozbuild/mozinfo.py
+@@ -5,7 +5,7 @@
+ # This module produces a JSON file that provides basic build info and
+ # configuration metadata.
+
+-from __future__ import absolute_import
++
+
+ import os
+ import re
+@@ -33,7 +33,7 @@ def build_dict(config, env=os.environ):
+ d['mozconfig'] = config.mozconfig
+
+ # os
+- o = substs["OS_TARGET"]
++ o = str(substs["OS_TARGET"])
+ known_os = {"Linux": "linux",
+ "WINNT": "win",
+ "Darwin": "mac",
+@@ -148,7 +148,7 @@ def write_mozinfo(file, config, env=os.environ):
+ and what keys are produced.
+ """
+ build_conf = build_dict(config, env)
+- if isinstance(file, basestring):
+- file = open(file, 'wb')
++ if isinstance(file, str):
++ file = open(file, 'w')
+
+ json.dump(build_conf, file, sort_keys=True, indent=4)
+diff --git a/python/mozbuild/mozbuild/preprocessor.py b/python/mozbuild/mozbuild/preprocessor.py
+index 6780b8b72..19e59884e 100644
+--- a/python/mozbuild/mozbuild/preprocessor.py
++++ b/python/mozbuild/mozbuild/preprocessor.py
+@@ -27,7 +27,8 @@ import os
+ import re
+ from optparse import OptionParser
+ import errno
+-from makeutil import Makefile
++from .makeutil import Makefile
++from functools import reduce
+
+ # hack around win32 mangling our line endings
+ # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65443
+@@ -230,7 +231,7 @@ class Expression:
+ def __repr__(self):
+ return self.value.__repr__()
+
+- class ParseError(StandardError):
++ class ParseError(Exception):
+ """
+ Error raised when parsing fails.
+ It has two members, offset and content, which give the offset of the
+@@ -278,7 +279,7 @@ class Preprocessor:
+ self.context = Context()
+ for k,v in {'FILE': '',
+ 'LINE': 0,
+- 'DIRECTORY': os.path.abspath('.')}.iteritems():
++ 'DIRECTORY': os.path.abspath('.')}.items():
+ self.context[k] = v
+ self.actionLevel = 0
+ self.disableLevel = 0
+@@ -292,21 +293,21 @@ class Preprocessor:
+ self.cmds = {}
+ for cmd, level in {'define': 0,
+ 'undef': 0,
+- 'if': sys.maxint,
+- 'ifdef': sys.maxint,
+- 'ifndef': sys.maxint,
++ 'if': sys.maxsize,
++ 'ifdef': sys.maxsize,
++ 'ifndef': sys.maxsize,
+ 'else': 1,
+ 'elif': 1,
+ 'elifdef': 1,
+ 'elifndef': 1,
+- 'endif': sys.maxint,
++ 'endif': sys.maxsize,
+ 'expand': 0,
+ 'literal': 0,
+ 'filter': 0,
+ 'unfilter': 0,
+ 'include': 0,
+ 'includesubst': 0,
+- 'error': 0}.iteritems():
++ 'error': 0}.items():
+ self.cmds[cmd] = (level, getattr(self, 'do_' + cmd))
+ self.out = sys.stdout
+ self.setMarker(marker)
+@@ -434,7 +435,7 @@ class Preprocessor:
+ filteredLine = self.applyFilters(aLine)
+ if filteredLine != aLine:
+ self.actionLevel = 2
+- self.out.write(filteredLine)
++ self.out.write(filteredLine.encode('utf-8'))
+
+ def handleCommandLine(self, args, defaultToStdin = False):
+ """
+@@ -468,7 +469,7 @@ class Preprocessor:
+ raise Preprocessor.Error(self, "--depend doesn't work with stdout",
+ None)
+ try:
+- from makeutil import Makefile
++ from .makeutil import Makefile
+ except:
+ raise Preprocessor.Error(self, "--depend requires the "
+ "mozbuild.makeutil module", None)
+@@ -683,7 +684,7 @@ class Preprocessor:
+ current = dict(self.filters)
+ for f in filters:
+ current[f] = getattr(self, 'filter_' + f)
+- filterNames = current.keys()
++ filterNames = list(current.keys())
+ filterNames.sort()
+ self.filters = [(fn, current[fn]) for fn in filterNames]
+ return
+@@ -693,7 +694,7 @@ class Preprocessor:
+ for f in filters:
+ if f in current:
+ del current[f]
+- filterNames = current.keys()
++ filterNames = list(current.keys())
+ filterNames.sort()
+ self.filters = [(fn, current[fn]) for fn in filterNames]
+ return
+@@ -738,7 +739,7 @@ class Preprocessor:
+ args can either be a file name, or a file-like object.
+ Files should be opened, and will be closed after processing.
+ """
+- isName = type(args) == str or type(args) == unicode
++ isName = type(args) == str or type(args) == str
+ oldCheckLineNumbers = self.checkLineNumbers
+ self.checkLineNumbers = False
+ if isName:
+diff --git a/python/mozbuild/mozbuild/shellutil.py b/python/mozbuild/mozbuild/shellutil.py
+index 185a970ee..c0c15f8f2 100644
+--- a/python/mozbuild/mozbuild/shellutil.py
++++ b/python/mozbuild/mozbuild/shellutil.py
+@@ -15,7 +15,7 @@ def _tokens2re(**tokens):
+ # which matches the pattern and captures it in a named match group.
+ # The group names and patterns are given as arguments.
+ all_tokens = '|'.join('(?P<%s>%s)' % (name, value)
+- for name, value in tokens.iteritems())
++ for name, value in tokens.items())
+ nonescaped = r'(?<!\\)(?:%s)' % all_tokens
+
+ # The final pattern matches either the above pattern, or an escaped
+@@ -96,7 +96,7 @@ class _ClineSplitter(object):
+ self.cline = self.cline[m.end():]
+
+ match = {name: value
+- for name, value in m.groupdict().items() if value}
++ for name, value in list(m.groupdict().items()) if value}
+ if 'quote' in match:
+ # " or ' start a quoted string
+ if match['quote'] == '"':
+@@ -144,7 +144,7 @@ class _ClineSplitter(object):
+ self._push(self.cline[:m.start()])
+ self.cline = self.cline[m.end():]
+ match = {name: value
+- for name, value in m.groupdict().items() if value}
++ for name, value in list(m.groupdict().items()) if value}
+ if 'quote' in match:
+ # a double quote ends the quoted string, so go back to
+ # unquoted parsing
+diff --git a/python/mozbuild/mozbuild/test/backend/test_recursivemake.py b/python/mozbuild/mozbuild/test/backend/test_recursivemake.py
+index a05059f8a..355a96165 100644
+--- a/python/mozbuild/mozbuild/test/backend/test_recursivemake.py
++++ b/python/mozbuild/mozbuild/test/backend/test_recursivemake.py
+@@ -2,9 +2,9 @@
+ # License, v. 2.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 cPickle as pickle
++
++import pickle as pickle
+ import json
+ import os
+ import unittest
+@@ -333,7 +333,7 @@ class TestRecursiveMakeBackend(BackendTester):
+ ],
+ }
+
+- for var, val in expected.items():
++ for var, val in list(expected.items()):
+ # print("test_variable_passthru[%s]" % (var))
+ found = [str for str in lines if str.startswith(var)]
+ self.assertEqual(found, val)
+@@ -372,7 +372,7 @@ class TestRecursiveMakeBackend(BackendTester):
+ ],
+ }
+
+- for var, val in expected.items():
++ for var, val in list(expected.items()):
+ found = [str for str in lines if str.startswith(var)]
+ self.assertEqual(found, val)
+
+@@ -563,7 +563,7 @@ class TestRecursiveMakeBackend(BackendTester):
+
+ # This is not the most robust test in the world, but it gets the job
+ # done.
+- entries = [e for e in m._dests.keys() if '**' in e]
++ entries = [e for e in list(m._dests.keys()) if '**' in e]
+ self.assertEqual(len(entries), 1)
+ self.assertIn('support/**', entries[0])
+
+@@ -590,11 +590,11 @@ class TestRecursiveMakeBackend(BackendTester):
+ set(['child/test_sub.js',
+ 'child/data/**',
+ 'child/another-file.sjs']))
+- for key in test_installs.keys():
++ for key in list(test_installs.keys()):
+ self.assertIn(key, test_installs)
+
+ synthesized_manifest = InstallManifest()
+- for item, installs in test_installs.items():
++ for item, installs in list(test_installs.items()):
+ for install_info in installs:
+ if len(install_info) == 3:
+ synthesized_manifest.add_pattern_link(*install_info)
+@@ -602,7 +602,7 @@ class TestRecursiveMakeBackend(BackendTester):
+ synthesized_manifest.add_link(*install_info)
+
+ self.assertEqual(len(synthesized_manifest), 3)
+- for item, info in synthesized_manifest._dests.items():
++ for item, info in list(synthesized_manifest._dests.items()):
+ self.assertIn(item, m)
+ self.assertEqual(info, m._dests[item])
+
+@@ -864,7 +864,7 @@ class TestRecursiveMakeBackend(BackendTester):
+ expected[mozpath.join(env.topobjdir, 'final-target')] = [
+ 'FINAL_TARGET = $(DEPTH)/random-final-target'
+ ]
+- for key, expected_rules in expected.iteritems():
++ for key, expected_rules in expected.items():
+ backend_path = mozpath.join(key, 'backend.mk')
+ lines = [l.strip() for l in open(backend_path, 'rt').readlines()[2:]]
+ found = [str for str in lines if
+diff --git a/python/mozbuild/mozbuild/test/configure/common.py b/python/mozbuild/mozbuild/test/configure/common.py
+index 150c6e393..5e2c2afaa 100644
+--- a/python/mozbuild/mozbuild/test/configure/common.py
++++ b/python/mozbuild/mozbuild/test/configure/common.py
+@@ -2,7 +2,7 @@
+ # License, v. 2.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 absolute_import, print_function, unicode_literals
++
+
+ import copy
+ import errno
+@@ -16,7 +16,7 @@ from mozbuild.configure import ConfigureSandbox
+ from mozbuild.util import ReadOnlyNamespace
+ from mozpack import path as mozpath
+
+-from StringIO import StringIO
++from io import StringIO
+ from which import WhichError
+
+ from buildconfig import (
+@@ -77,10 +77,10 @@ class ConfigureTestSandbox(ConfigureSandbox):
+ self._search_path = environ.get('PATH', '').split(os.pathsep)
+
+ self._subprocess_paths = {
+- mozpath.abspath(k): v for k, v in paths.iteritems() if v
++ mozpath.abspath(k): v for k, v in paths.items() if v
+ }
+
+- paths = paths.keys()
++ paths = list(paths.keys())
+
+ environ = dict(environ)
+ if 'CONFIG_SHELL' not in environ:
+diff --git a/python/mozbuild/mozbuild/test/configure/lint.py b/python/mozbuild/mozbuild/test/configure/lint.py
+index 98f5f4fe7..a549b4bcf 100644
+--- a/python/mozbuild/mozbuild/test/configure/lint.py
++++ b/python/mozbuild/mozbuild/test/configure/lint.py
+@@ -2,11 +2,11 @@
+ # License, v. 2.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 absolute_import, print_function, unicode_literals
++
+
+ import os
+ import unittest
+-from StringIO import StringIO
++from io import StringIO
+ from mozunit import main
+ from buildconfig import (
+ topobjdir,
+@@ -40,9 +40,7 @@ class LintMeta(type):
+ return type.__new__(mcs, name, bases, attrs)
+
+
+-class Lint(unittest.TestCase):
+- __metaclass__ = LintMeta
+-
++class Lint(unittest.TestCase, metaclass=LintMeta):
+ def setUp(self):
+ self._curdir = os.getcwd()
+ os.chdir(topobjdir)
+diff --git a/python/mozbuild/mozbuild/test/configure/test_checks_configure.py b/python/mozbuild/mozbuild/test/configure/test_checks_configure.py
+index c60000bb2..07091c077 100644
+--- a/python/mozbuild/mozbuild/test/configure/test_checks_configure.py
++++ b/python/mozbuild/mozbuild/test/configure/test_checks_configure.py
+@@ -2,9 +2,9 @@
+ # License, v. 2.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 absolute_import, print_function, unicode_literals
+
+-from StringIO import StringIO
++
++from io import StringIO
+ import os
+ import sys
+ import textwrap
+@@ -447,7 +447,7 @@ class TestChecksConfigure(unittest.TestCase):
+ checking for a... %s
+ ''' % self.OTHER_A))
+
+- dirs = map(mozpath.dirname, (self.OTHER_A, self.KNOWN_A))
++ dirs = list(map(mozpath.dirname, (self.OTHER_A, self.KNOWN_A)))
+ config, out, status = self.get_result(textwrap.dedent('''\
+ check_prog("A", ("known-a",), paths=["%s"])
+ ''' % os.pathsep.join(dirs)))
+@@ -457,7 +457,7 @@ class TestChecksConfigure(unittest.TestCase):
+ checking for a... %s
+ ''' % self.OTHER_A))
+
+- dirs = map(mozpath.dirname, (self.KNOWN_A, self.KNOWN_B))
++ dirs = list(map(mozpath.dirname, (self.KNOWN_A, self.KNOWN_B)))
+ config, out, status = self.get_result(textwrap.dedent('''\
+ check_prog("A", ("known-a",), paths=["%s", "%s"])
+ ''' % (os.pathsep.join(dirs), self.OTHER_A)))
+diff --git a/python/mozbuild/mozbuild/test/configure/test_compile_checks.py b/python/mozbuild/mozbuild/test/configure/test_compile_checks.py
+index b5be3bf2e..282000bb2 100644
+--- a/python/mozbuild/mozbuild/test/configure/test_compile_checks.py
++++ b/python/mozbuild/mozbuild/test/configure/test_compile_checks.py
+@@ -2,14 +2,14 @@
+ # License, v. 2.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 absolute_import, print_function, unicode_literals
++
+
+ import os
+ import textwrap
+ import unittest
+ import mozpack.path as mozpath
+
+-from StringIO import StringIO
++from io import StringIO
+
+ from buildconfig import topsrcdir
+ from common import ConfigureTestSandbox
+diff --git a/python/mozbuild/mozbuild/test/configure/test_configure.py b/python/mozbuild/mozbuild/test/configure/test_configure.py
+index f37e2701f..eb0ca84fb 100644
+--- a/python/mozbuild/mozbuild/test/configure/test_configure.py
++++ b/python/mozbuild/mozbuild/test/configure/test_configure.py
+@@ -2,9 +2,9 @@
+ # License, v. 2.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 absolute_import, print_function, unicode_literals
+
+-from StringIO import StringIO
++
++from io import StringIO
+ import os
+ import sys
+ import textwrap
+@@ -43,7 +43,7 @@ class TestConfigure(unittest.TestCase):
+
+ if '--help' in options:
+ return out.getvalue(), config
+- self.assertEquals('', out.getvalue())
++ self.assertEqual('', out.getvalue())
+ return config
+
+ def moz_configure(self, source):
+@@ -55,7 +55,7 @@ class TestConfigure(unittest.TestCase):
+ def test_defaults(self):
+ config = self.get_config()
+ self.maxDiff = None
+- self.assertEquals({
++ self.assertEqual({
+ 'CHOICES': NegativeOptionValue(),
+ 'DEFAULTED': PositiveOptionValue(('not-simple',)),
+ 'IS_GCC': NegativeOptionValue(),
+@@ -71,9 +71,9 @@ class TestConfigure(unittest.TestCase):
+ def test_help(self):
+ help, config = self.get_config(['--help'], prog='configure')
+
+- self.assertEquals({}, config)
++ self.assertEqual({}, config)
+ self.maxDiff = None
+- self.assertEquals(
++ self.assertEqual(
+ 'Usage: configure [options]\n'
+ '\n'
+ 'Options: [defaults in brackets after descriptions]\n'
+@@ -109,7 +109,7 @@ class TestConfigure(unittest.TestCase):
+ ):
+ self.assertNotIn('ENABLED_SIMPLE', config)
+ self.assertIn('SIMPLE', config)
+- self.assertEquals(NegativeOptionValue(), config['SIMPLE'])
++ self.assertEqual(NegativeOptionValue(), config['SIMPLE'])
+
+ for config in (
+ self.get_config(['--enable-simple']),
+@@ -117,7 +117,7 @@ class TestConfigure(unittest.TestCase):
+ ):
+ self.assertIn('ENABLED_SIMPLE', config)
+ self.assertIn('SIMPLE', config)
+- self.assertEquals(PositiveOptionValue(), config['SIMPLE'])
++ self.assertEqual(PositiveOptionValue(), config['SIMPLE'])
+ self.assertIs(config['SIMPLE'], config['ENABLED_SIMPLE'])
+
+ # --enable-simple doesn't take values.
+@@ -135,7 +135,7 @@ class TestConfigure(unittest.TestCase):
+ env={'MOZ_WITH_ENV': '1'}),
+ ):
+ self.assertIn('WITH_ENV', config)
+- self.assertEquals(NegativeOptionValue(), config['WITH_ENV'])
++ self.assertEqual(NegativeOptionValue(), config['WITH_ENV'])
+
+ for config in (
+ self.get_config(['--enable-with-env']),
+@@ -145,7 +145,7 @@ class TestConfigure(unittest.TestCase):
+ env={'MOZ_WITH_ENV': ''}),
+ ):
+ self.assertIn('WITH_ENV', config)
+- self.assertEquals(PositiveOptionValue(), config['WITH_ENV'])
++ self.assertEqual(PositiveOptionValue(), config['WITH_ENV'])
+
+ with self.assertRaises(InvalidOptionError):
+ self.get_config(['--enable-with-env=value'])
+@@ -160,23 +160,23 @@ class TestConfigure(unittest.TestCase):
+ self.get_config(['--enable-values', '--disable-values']),
+ ):
+ self.assertIn(name, config)
+- self.assertEquals(NegativeOptionValue(), config[name])
++ self.assertEqual(NegativeOptionValue(), config[name])
+
+ for config in (
+ self.get_config(['--enable-values']),
+ self.get_config(['--disable-values', '--enable-values']),
+ ):
+ self.assertIn(name, config)
+- self.assertEquals(PositiveOptionValue(), config[name])
++ self.assertEqual(PositiveOptionValue(), config[name])
+
+ config = self.get_config(['--enable-values=foo'])
+ self.assertIn(name, config)
+- self.assertEquals(PositiveOptionValue(('foo',)), config[name])
++ self.assertEqual(PositiveOptionValue(('foo',)), config[name])
+
+ config = self.get_config(['--enable-values=foo,bar'])
+ self.assertIn(name, config)
+ self.assertTrue(config[name])
+- self.assertEquals(PositiveOptionValue(('foo', 'bar')), config[name])
++ self.assertEqual(PositiveOptionValue(('foo', 'bar')), config[name])
+
+ def test_values2(self):
+ self.test_values('VALUES2')
+@@ -187,12 +187,12 @@ class TestConfigure(unittest.TestCase):
+ def test_returned_default(self):
+ config = self.get_config(['--enable-simple'])
+ self.assertIn('DEFAULTED', config)
+- self.assertEquals(
++ self.assertEqual(
+ PositiveOptionValue(('simple',)), config['DEFAULTED'])
+
+ config = self.get_config(['--disable-simple'])
+ self.assertIn('DEFAULTED', config)
+- self.assertEquals(
++ self.assertEqual(
+ PositiveOptionValue(('not-simple',)), config['DEFAULTED'])
+
+ def test_returned_choices(self):
+@@ -200,13 +200,13 @@ class TestConfigure(unittest.TestCase):
+ config = self.get_config(
+ ['--enable-values=alpha', '--returned-choices=%s' % val])
+ self.assertIn('CHOICES', config)
+- self.assertEquals(PositiveOptionValue((val,)), config['CHOICES'])
++ self.assertEqual(PositiveOptionValue((val,)), config['CHOICES'])
+
+ for val in ('0', '1', '2'):
+ config = self.get_config(
+ ['--enable-values=numeric', '--returned-choices=%s' % val])
+ self.assertIn('CHOICES', config)
+- self.assertEquals(PositiveOptionValue((val,)), config['CHOICES'])
++ self.assertEqual(PositiveOptionValue((val,)), config['CHOICES'])
+
+ with self.assertRaises(InvalidOptionError):
+ self.get_config(['--enable-values=numeric',
+@@ -218,12 +218,12 @@ class TestConfigure(unittest.TestCase):
+ def test_included(self):
+ config = self.get_config(env={'CC': 'gcc'})
+ self.assertIn('IS_GCC', config)
+- self.assertEquals(config['IS_GCC'], True)
++ self.assertEqual(config['IS_GCC'], True)
+
+ config = self.get_config(
+ ['--enable-include=extra.configure', '--extra'])
+ self.assertIn('EXTRA', config)
+- self.assertEquals(PositiveOptionValue(), config['EXTRA'])
++ self.assertEqual(PositiveOptionValue(), config['EXTRA'])
+
+ with self.assertRaises(InvalidOptionError):
+ self.get_config(['--extra'])
+@@ -231,7 +231,7 @@ class TestConfigure(unittest.TestCase):
+ def test_template(self):
+ config = self.get_config(env={'CC': 'gcc'})
+ self.assertIn('CFLAGS', config)
+- self.assertEquals(config['CFLAGS'], ['-Werror=foobar'])
++ self.assertEqual(config['CFLAGS'], ['-Werror=foobar'])
+
+ config = self.get_config(env={'CC': 'clang'})
+ self.assertNotIn('CFLAGS', config)
+@@ -288,7 +288,7 @@ class TestConfigure(unittest.TestCase):
+ sandbox
+ )
+
+- import __builtin__
++ import builtins
+ self.assertIs(sandbox['foo'](), __builtin__)
+
+ exec_(textwrap.dedent('''
+@@ -300,7 +300,7 @@ class TestConfigure(unittest.TestCase):
+ )
+
+ f = sandbox['foo']()
+- self.assertEquals(f.name, os.devnull)
++ self.assertEqual(f.name, os.devnull)
+ f.close()
+
+ # This unlocks the sandbox
+@@ -336,8 +336,8 @@ class TestConfigure(unittest.TestCase):
+ self.assertIs(sandbox['foo'](), sandbox)
+
+ # Nothing leaked from the function being executed
+- self.assertEquals(sandbox.keys(), ['__builtins__', 'foo'])
+- self.assertEquals(sandbox['__builtins__'], ConfigureSandbox.BUILTINS)
++ self.assertEqual(list(sandbox.keys()), ['__builtins__', 'foo'])
++ self.assertEqual(sandbox['__builtins__'], ConfigureSandbox.BUILTINS)
+
+ exec_(textwrap.dedent('''
+ @template
+@@ -354,7 +354,7 @@ class TestConfigure(unittest.TestCase):
+ with self.assertRaises(NameError) as e:
+ sandbox._depends[sandbox['bar']].result()
+
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ "global name 'sys' is not defined")
+
+ def test_apply_imports(self):
+@@ -380,28 +380,28 @@ class TestConfigure(unittest.TestCase):
+ sandbox
+ )
+
+- self.assertEquals(len(imports), 1)
++ self.assertEqual(len(imports), 1)
+
+ def test_os_path(self):
+ config = self.get_config(['--with-imports=%s' % __file__])
+ self.assertIn('HAS_ABSPATH', config)
+- self.assertEquals(config['HAS_ABSPATH'], True)
++ self.assertEqual(config['HAS_ABSPATH'], True)
+ self.assertIn('HAS_GETATIME', config)
+- self.assertEquals(config['HAS_GETATIME'], True)
++ self.assertEqual(config['HAS_GETATIME'], True)
+ self.assertIn('HAS_GETATIME2', config)
+- self.assertEquals(config['HAS_GETATIME2'], False)
++ self.assertEqual(config['HAS_GETATIME2'], False)
+
+ def test_template_call(self):
+ config = self.get_config(env={'CC': 'gcc'})
+ self.assertIn('TEMPLATE_VALUE', config)
+- self.assertEquals(config['TEMPLATE_VALUE'], 42)
++ self.assertEqual(config['TEMPLATE_VALUE'], 42)
+ self.assertIn('TEMPLATE_VALUE_2', config)
+- self.assertEquals(config['TEMPLATE_VALUE_2'], 21)
++ self.assertEqual(config['TEMPLATE_VALUE_2'], 21)
+
+ def test_template_imports(self):
+ config = self.get_config(['--enable-imports-in-template'])
+ self.assertIn('PLATFORM', config)
+- self.assertEquals(config['PLATFORM'], sys.platform)
++ self.assertEqual(config['PLATFORM'], sys.platform)
+
+ def test_decorators(self):
+ config = {}
+@@ -419,27 +419,27 @@ class TestConfigure(unittest.TestCase):
+ return self.get_config(*args, configure='set_config.configure')
+
+ help, config = get_config(['--help'])
+- self.assertEquals(config, {})
++ self.assertEqual(config, {})
+
+ config = get_config(['--set-foo'])
+ self.assertIn('FOO', config)
+- self.assertEquals(config['FOO'], True)
++ self.assertEqual(config['FOO'], True)
+
+ config = get_config(['--set-bar'])
+ self.assertNotIn('FOO', config)
+ self.assertIn('BAR', config)
+- self.assertEquals(config['BAR'], True)
++ self.assertEqual(config['BAR'], True)
+
+ config = get_config(['--set-value=qux'])
+ self.assertIn('VALUE', config)
+- self.assertEquals(config['VALUE'], 'qux')
++ self.assertEqual(config['VALUE'], 'qux')
+
+ config = get_config(['--set-name=hoge'])
+ self.assertIn('hoge', config)
+- self.assertEquals(config['hoge'], True)
++ self.assertEqual(config['hoge'], True)
+
+ config = get_config([])
+- self.assertEquals(config, {'BAR': False})
++ self.assertEqual(config, {'BAR': False})
+
+ with self.assertRaises(ConfigureError):
+ # Both --set-foo and --set-name=FOO are going to try to
+@@ -454,11 +454,11 @@ class TestConfigure(unittest.TestCase):
+ set_config('QUX', 'qux', when='--with-qux')
+ '''):
+ config = self.get_config()
+- self.assertEquals(config, {
++ self.assertEqual(config, {
+ 'FOO': 'foo',
+ })
+ config = self.get_config(['--with-qux'])
+- self.assertEquals(config, {
++ self.assertEqual(config, {
+ 'FOO': 'foo',
+ 'QUX': 'qux',
+ })
+@@ -468,27 +468,27 @@ class TestConfigure(unittest.TestCase):
+ return self.get_config(*args, configure='set_define.configure')
+
+ help, config = get_config(['--help'])
+- self.assertEquals(config, {'DEFINES': {}})
++ self.assertEqual(config, {'DEFINES': {}})
+
+ config = get_config(['--set-foo'])
+ self.assertIn('FOO', config['DEFINES'])
+- self.assertEquals(config['DEFINES']['FOO'], True)
++ self.assertEqual(config['DEFINES']['FOO'], True)
+
+ config = get_config(['--set-bar'])
+ self.assertNotIn('FOO', config['DEFINES'])
+ self.assertIn('BAR', config['DEFINES'])
+- self.assertEquals(config['DEFINES']['BAR'], True)
++ self.assertEqual(config['DEFINES']['BAR'], True)
+
+ config = get_config(['--set-value=qux'])
+ self.assertIn('VALUE', config['DEFINES'])
+- self.assertEquals(config['DEFINES']['VALUE'], 'qux')
++ self.assertEqual(config['DEFINES']['VALUE'], 'qux')
+
+ config = get_config(['--set-name=hoge'])
+ self.assertIn('hoge', config['DEFINES'])
+- self.assertEquals(config['DEFINES']['hoge'], True)
++ self.assertEqual(config['DEFINES']['hoge'], True)
+
+ config = get_config([])
+- self.assertEquals(config['DEFINES'], {'BAR': False})
++ self.assertEqual(config['DEFINES'], {'BAR': False})
+
+ with self.assertRaises(ConfigureError):
+ # Both --set-foo and --set-name=FOO are going to try to
+@@ -503,11 +503,11 @@ class TestConfigure(unittest.TestCase):
+ set_define('QUX', 'qux', when='--with-qux')
+ '''):
+ config = self.get_config()
+- self.assertEquals(config['DEFINES'], {
++ self.assertEqual(config['DEFINES'], {
+ 'FOO': 'foo',
+ })
+ config = self.get_config(['--with-qux'])
+- self.assertEquals(config['DEFINES'], {
++ self.assertEqual(config['DEFINES'], {
+ 'FOO': 'foo',
+ 'QUX': 'qux',
+ })
+@@ -518,19 +518,19 @@ class TestConfigure(unittest.TestCase):
+ *args, configure='imply_option/simple.configure')
+
+ help, config = get_config(['--help'])
+- self.assertEquals(config, {})
++ self.assertEqual(config, {})
+
+ config = get_config([])
+- self.assertEquals(config, {})
++ self.assertEqual(config, {})
+
+ config = get_config(['--enable-foo'])
+ self.assertIn('BAR', config)
+- self.assertEquals(config['BAR'], PositiveOptionValue())
++ self.assertEqual(config['BAR'], PositiveOptionValue())
+
+ with self.assertRaises(InvalidOptionError) as e:
+ get_config(['--enable-foo', '--disable-bar'])
+
+- self.assertEquals(
++ self.assertEqual(
+ e.exception.message,
+ "'--enable-bar' implied by '--enable-foo' conflicts with "
+ "'--disable-bar' from the command-line")
+@@ -541,31 +541,31 @@ class TestConfigure(unittest.TestCase):
+ *args, configure='imply_option/negative.configure')
+
+ help, config = get_config(['--help'])
+- self.assertEquals(config, {})
++ self.assertEqual(config, {})
+
+ config = get_config([])
+- self.assertEquals(config, {})
++ self.assertEqual(config, {})
+
+ config = get_config(['--enable-foo'])
+ self.assertIn('BAR', config)
+- self.assertEquals(config['BAR'], NegativeOptionValue())
++ self.assertEqual(config['BAR'], NegativeOptionValue())
+
+ with self.assertRaises(InvalidOptionError) as e:
+ get_config(['--enable-foo', '--enable-bar'])
+
+- self.assertEquals(
++ self.assertEqual(
+ e.exception.message,
+ "'--disable-bar' implied by '--enable-foo' conflicts with "
+ "'--enable-bar' from the command-line")
+
+ config = get_config(['--disable-hoge'])
+ self.assertIn('BAR', config)
+- self.assertEquals(config['BAR'], NegativeOptionValue())
++ self.assertEqual(config['BAR'], NegativeOptionValue())
+
+ with self.assertRaises(InvalidOptionError) as e:
+ get_config(['--disable-hoge', '--enable-bar'])
+
+- self.assertEquals(
++ self.assertEqual(
+ e.exception.message,
+ "'--disable-bar' implied by '--disable-hoge' conflicts with "
+ "'--enable-bar' from the command-line")
+@@ -576,23 +576,23 @@ class TestConfigure(unittest.TestCase):
+ *args, configure='imply_option/values.configure')
+
+ help, config = get_config(['--help'])
+- self.assertEquals(config, {})
++ self.assertEqual(config, {})
+
+ config = get_config([])
+- self.assertEquals(config, {})
++ self.assertEqual(config, {})
+
+ config = get_config(['--enable-foo=a'])
+ self.assertIn('BAR', config)
+- self.assertEquals(config['BAR'], PositiveOptionValue(('a',)))
++ self.assertEqual(config['BAR'], PositiveOptionValue(('a',)))
+
+ config = get_config(['--enable-foo=a,b'])
+ self.assertIn('BAR', config)
+- self.assertEquals(config['BAR'], PositiveOptionValue(('a','b')))
++ self.assertEqual(config['BAR'], PositiveOptionValue(('a','b')))
+
+ with self.assertRaises(InvalidOptionError) as e:
+ get_config(['--enable-foo=a,b', '--disable-bar'])
+
+- self.assertEquals(
++ self.assertEqual(
+ e.exception.message,
+ "'--enable-bar=a,b' implied by '--enable-foo' conflicts with "
+ "'--disable-bar' from the command-line")
+@@ -603,15 +603,15 @@ class TestConfigure(unittest.TestCase):
+ *args, configure='imply_option/infer.configure')
+
+ help, config = get_config(['--help'])
+- self.assertEquals(config, {})
++ self.assertEqual(config, {})
+
+ config = get_config([])
+- self.assertEquals(config, {})
++ self.assertEqual(config, {})
+
+ with self.assertRaises(InvalidOptionError) as e:
+ get_config(['--enable-foo', '--disable-bar'])
+
+- self.assertEquals(
++ self.assertEqual(
+ e.exception.message,
+ "'--enable-bar' implied by '--enable-foo' conflicts with "
+ "'--disable-bar' from the command-line")
+@@ -619,7 +619,7 @@ class TestConfigure(unittest.TestCase):
+ with self.assertRaises(ConfigureError) as e:
+ self.get_config([], configure='imply_option/infer_ko.configure')
+
+- self.assertEquals(
++ self.assertEqual(
+ e.exception.message,
+ "Cannot infer what implies '--enable-bar'. Please add a `reason` "
+ "to the `imply_option` call.")
+@@ -630,25 +630,25 @@ class TestConfigure(unittest.TestCase):
+ *args, configure='imply_option/imm.configure')
+
+ help, config = get_config(['--help'])
+- self.assertEquals(config, {})
++ self.assertEqual(config, {})
+
+ config = get_config([])
+- self.assertEquals(config, {})
++ self.assertEqual(config, {})
+
+ config_path = mozpath.abspath(
+ mozpath.join(test_data_path, 'imply_option', 'imm.configure'))
+
+- with self.assertRaisesRegexp(InvalidOptionError,
++ with self.assertRaisesRegex(InvalidOptionError,
+ "--enable-foo' implied by 'imply_option at %s:7' conflicts with "
+ "'--disable-foo' from the command-line" % config_path):
+ get_config(['--disable-foo'])
+
+- with self.assertRaisesRegexp(InvalidOptionError,
++ with self.assertRaisesRegex(InvalidOptionError,
+ "--enable-bar=foo,bar' implied by 'imply_option at %s:16' conflicts"
+ " with '--enable-bar=a,b,c' from the command-line" % config_path):
+ get_config(['--enable-bar=a,b,c'])
+
+- with self.assertRaisesRegexp(InvalidOptionError,
++ with self.assertRaisesRegex(InvalidOptionError,
+ "--enable-baz=BAZ' implied by 'imply_option at %s:25' conflicts"
+ " with '--enable-baz=QUUX' from the command-line" % config_path):
+ get_config(['--enable-baz=QUUX'])
+@@ -660,7 +660,7 @@ class TestConfigure(unittest.TestCase):
+ '''):
+ self.get_config()
+
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ "`--with-foo`, emitted from `%s` line 2, is unknown."
+ % mozpath.join(test_data_path, 'moz.configure'))
+
+@@ -675,7 +675,7 @@ class TestConfigure(unittest.TestCase):
+ '''):
+ self.get_config()
+
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ "Unexpected type: 'int'")
+
+ def test_imply_option_when(self):
+@@ -686,12 +686,12 @@ class TestConfigure(unittest.TestCase):
+ set_config('QUX', depends('--with-qux')(lambda x: x))
+ '''):
+ config = self.get_config()
+- self.assertEquals(config, {
++ self.assertEqual(config, {
+ 'QUX': NegativeOptionValue(),
+ })
+
+ config = self.get_config(['--with-foo'])
+- self.assertEquals(config, {
++ self.assertEqual(config, {
+ 'QUX': PositiveOptionValue(),
+ })
+
+@@ -700,7 +700,7 @@ class TestConfigure(unittest.TestCase):
+ with self.moz_configure('option("--with-foo", help="foo")'):
+ self.get_config()
+
+- self.assertEquals(
++ self.assertEqual(
+ e.exception.message,
+ 'Option `--with-foo` is not handled ; reference it with a @depends'
+ )
+@@ -712,7 +712,7 @@ class TestConfigure(unittest.TestCase):
+ '''):
+ self.get_config()
+
+- self.assertEquals(
++ self.assertEqual(
+ e.exception.message,
+ 'Option `--with-foo` already defined'
+ )
+@@ -724,7 +724,7 @@ class TestConfigure(unittest.TestCase):
+ '''):
+ self.get_config()
+
+- self.assertEquals(
++ self.assertEqual(
+ e.exception.message,
+ 'Option `MOZ_FOO` already defined'
+ )
+@@ -736,7 +736,7 @@ class TestConfigure(unittest.TestCase):
+ '''):
+ self.get_config()
+
+- self.assertEquals(
++ self.assertEqual(
+ e.exception.message,
+ 'Option `MOZ_FOO` already defined'
+ )
+@@ -748,7 +748,7 @@ class TestConfigure(unittest.TestCase):
+ '''):
+ self.get_config()
+
+- self.assertEquals(
++ self.assertEqual(
+ e.exception.message,
+ 'Option `MOZ_FOO` already defined'
+ )
+@@ -760,7 +760,7 @@ class TestConfigure(unittest.TestCase):
+ '''):
+ self.get_config()
+
+- self.assertEquals(
++ self.assertEqual(
+ e.exception.message,
+ 'Option `--with-foo` already defined'
+ )
+@@ -776,18 +776,18 @@ class TestConfigure(unittest.TestCase):
+ set_config('QUX', depends('--with-qux', when='--with-foo')(lambda x: x))
+ '''):
+ config = self.get_config()
+- self.assertEquals(config, {
++ self.assertEqual(config, {
+ 'FOO': NegativeOptionValue(),
+ })
+
+ config = self.get_config(['--with-foo'])
+- self.assertEquals(config, {
++ self.assertEqual(config, {
+ 'FOO': PositiveOptionValue(),
+ 'QUX': NegativeOptionValue(),
+ })
+
+ config = self.get_config(['--with-foo', '--with-qux'])
+- self.assertEquals(config, {
++ self.assertEqual(config, {
+ 'FOO': PositiveOptionValue(),
+ 'QUX': PositiveOptionValue(),
+ })
+@@ -795,7 +795,7 @@ class TestConfigure(unittest.TestCase):
+ with self.assertRaises(InvalidOptionError) as e:
+ self.get_config(['--with-bar'])
+
+- self.assertEquals(
++ self.assertEqual(
+ e.exception.message,
+ '--with-bar is not available in this configuration'
+ )
+@@ -803,7 +803,7 @@ class TestConfigure(unittest.TestCase):
+ with self.assertRaises(InvalidOptionError) as e:
+ self.get_config(['--with-qux'])
+
+- self.assertEquals(
++ self.assertEqual(
+ e.exception.message,
+ '--with-qux is not available in this configuration'
+ )
+@@ -811,18 +811,18 @@ class TestConfigure(unittest.TestCase):
+ with self.assertRaises(InvalidOptionError) as e:
+ self.get_config(['QUX=1'])
+
+- self.assertEquals(
++ self.assertEqual(
+ e.exception.message,
+ 'QUX is not available in this configuration'
+ )
+
+ config = self.get_config(env={'QUX': '1'})
+- self.assertEquals(config, {
++ self.assertEqual(config, {
+ 'FOO': NegativeOptionValue(),
+ })
+
+ help, config = self.get_config(['--help'])
+- self.assertEquals(help, textwrap.dedent('''\
++ self.assertEqual(help, textwrap.dedent('''\
+ Usage: configure [options]
+
+ Options: [defaults in brackets after descriptions]
+@@ -833,7 +833,7 @@ class TestConfigure(unittest.TestCase):
+ '''))
+
+ help, config = self.get_config(['--help', '--with-foo'])
+- self.assertEquals(help, textwrap.dedent('''\
++ self.assertEqual(help, textwrap.dedent('''\
+ Usage: configure [options]
+
+ Options: [defaults in brackets after descriptions]
+@@ -851,7 +851,7 @@ class TestConfigure(unittest.TestCase):
+ with self.assertRaises(ConfigureError) as e:
+ self.get_config()
+
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ '@depends function needs the same `when` as '
+ 'options it depends on')
+
+@@ -868,7 +868,7 @@ class TestConfigure(unittest.TestCase):
+ with self.assertRaises(ConfigureError) as e:
+ self.get_config()
+
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ '@depends function needs the same `when` as '
+ 'options it depends on')
+
+@@ -896,7 +896,7 @@ class TestConfigure(unittest.TestCase):
+ with self.moz_configure('include("../foo.configure")'):
+ self.get_config()
+
+- self.assertEquals(
++ self.assertEqual(
+ e.exception.message,
+ 'Cannot include `%s` because it is not in a subdirectory of `%s`'
+ % (mozpath.normpath(mozpath.join(test_data_path, '..',
+@@ -911,7 +911,7 @@ class TestConfigure(unittest.TestCase):
+ '''):
+ self.get_config()
+
+- self.assertEquals(
++ self.assertEqual(
+ e.exception.message,
+ 'Cannot include `%s` because it was included already.'
+ % mozpath.normpath(mozpath.join(test_data_path,
+@@ -924,7 +924,7 @@ class TestConfigure(unittest.TestCase):
+ '''):
+ self.get_config()
+
+- self.assertEquals(e.exception.message, "Unexpected type: 'int'")
++ self.assertEqual(e.exception.message, "Unexpected type: 'int'")
+
+ def test_include_when(self):
+ with MockedOpen({
+@@ -967,26 +967,26 @@ class TestConfigure(unittest.TestCase):
+ '''),
+ }):
+ config = self.get_config()
+- self.assertEquals(config, {})
++ self.assertEqual(config, {})
+
+ config = self.get_config(['--with-foo'])
+- self.assertEquals(config, {})
++ self.assertEqual(config, {})
+
+ config = self.get_config(['--with-bar'])
+- self.assertEquals(config, {
++ self.assertEqual(config, {
+ 'BAR': 'bar',
+ })
+
+ with self.assertRaises(InvalidOptionError) as e:
+ self.get_config(['--with-qux'])
+
+- self.assertEquals(
++ self.assertEqual(
+ e.exception.message,
+ '--with-qux is not available in this configuration'
+ )
+
+ config = self.get_config(['--with-foo', '--with-foo-really'])
+- self.assertEquals(config, {
++ self.assertEqual(config, {
+ 'FOO': 'foo',
+ 'FOO2': True,
+ })
+@@ -998,7 +998,7 @@ class TestConfigure(unittest.TestCase):
+ '''):
+ self.get_config()
+
+- self.assertEquals(e.exception.message, 'Cannot reassign builtins')
++ self.assertEqual(e.exception.message, 'Cannot reassign builtins')
+
+ with self.assertRaises(KeyError) as e:
+ with self.moz_configure('''
+@@ -1006,7 +1006,7 @@ class TestConfigure(unittest.TestCase):
+ '''):
+ self.get_config()
+
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ 'Cannot assign `foo` because it is neither a '
+ '@depends nor a @template')
+
+@@ -1019,7 +1019,7 @@ class TestConfigure(unittest.TestCase):
+ '''):
+ self.get_config()
+
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ "@depends needs at least one argument")
+
+ with self.assertRaises(ConfigureError) as e:
+@@ -1030,7 +1030,7 @@ class TestConfigure(unittest.TestCase):
+ '''):
+ self.get_config()
+
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ "'--with-foo' is not a known option. Maybe it's "
+ "declared too late?")
+
+@@ -1042,7 +1042,7 @@ class TestConfigure(unittest.TestCase):
+ '''):
+ self.get_config()
+
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ "Option must not contain an '='")
+
+ with self.assertRaises(TypeError) as e:
+@@ -1053,7 +1053,7 @@ class TestConfigure(unittest.TestCase):
+ '''):
+ self.get_config()
+
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ "Cannot use object of type 'int' as argument "
+ "to @depends")
+
+@@ -1065,7 +1065,7 @@ class TestConfigure(unittest.TestCase):
+ '''):
+ self.get_config()
+
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ "Cannot decorate generator functions with @depends")
+
+ with self.assertRaises(TypeError) as e:
+@@ -1074,7 +1074,7 @@ class TestConfigure(unittest.TestCase):
+ '''):
+ self.get_config()
+
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ "Unexpected type: 'int'")
+
+ with self.assertRaises(ConfigureError) as e:
+@@ -1088,7 +1088,7 @@ class TestConfigure(unittest.TestCase):
+ '''):
+ self.get_config()
+
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ "The `foo` function may not be called")
+
+ with self.assertRaises(TypeError) as e:
+@@ -1099,7 +1099,7 @@ class TestConfigure(unittest.TestCase):
+ '''):
+ self.get_config()
+
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ "depends_impl() got an unexpected keyword argument 'foo'")
+
+ def test_depends_when(self):
+@@ -1124,12 +1124,12 @@ class TestConfigure(unittest.TestCase):
+ set_config('QUX', qux)
+ '''):
+ config = self.get_config()
+- self.assertEquals(config, {
++ self.assertEqual(config, {
+ 'FOO': 'foo',
+ })
+
+ config = self.get_config(['--with-qux'])
+- self.assertEquals(config, {
++ self.assertEqual(config, {
+ 'FOO': 'foo',
+ 'QUX': 'qux',
+ })
+@@ -1144,7 +1144,7 @@ class TestConfigure(unittest.TestCase):
+ '''):
+ self.get_config()
+
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ '@imports must appear after @template')
+
+ with self.assertRaises(ConfigureError) as e:
+@@ -1157,7 +1157,7 @@ class TestConfigure(unittest.TestCase):
+ '''):
+ self.get_config()
+
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ '@imports must appear after @depends')
+
+ for import_ in (
+@@ -1174,7 +1174,7 @@ class TestConfigure(unittest.TestCase):
+ ''' % import_):
+ self.get_config()
+
+- self.assertEquals(e.exception.message, "Unexpected type: 'int'")
++ self.assertEqual(e.exception.message, "Unexpected type: 'int'")
+
+ with self.assertRaises(TypeError) as e:
+ with self.moz_configure('''
+@@ -1185,7 +1185,7 @@ class TestConfigure(unittest.TestCase):
+ '''):
+ self.get_config()
+
+- self.assertEquals(e.exception.message, "Unexpected type: 'int'")
++ self.assertEqual(e.exception.message, "Unexpected type: 'int'")
+
+ with self.assertRaises(ValueError) as e:
+ with self.moz_configure('''
+@@ -1195,7 +1195,7 @@ class TestConfigure(unittest.TestCase):
+ '''):
+ self.get_config()
+
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ "Invalid argument to @imports: 'os*'")
+
+ def test_only_when(self):
+@@ -1250,7 +1250,7 @@ class TestConfigure(unittest.TestCase):
+ with self.assertRaises(InvalidOptionError) as e:
+ self.get_config(['--foo'])
+
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ '--foo is not available in this configuration')
+
+ # Cannot depend on an option defined in a only_when block, because we
+@@ -1261,7 +1261,7 @@ class TestConfigure(unittest.TestCase):
+ with self.assertRaises(ConfigureError) as e:
+ self.get_config()
+
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ '@depends function needs the same `when` as '
+ 'options it depends on')
+
+@@ -1278,7 +1278,7 @@ class TestConfigure(unittest.TestCase):
+ with self.assertRaises(InvalidOptionError) as e:
+ self.get_config()
+
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ '--foo is not available in this configuration')
+
+ # And similarly doesn't fail when the condition is true.
+diff --git a/python/mozbuild/mozbuild/test/configure/test_lint.py b/python/mozbuild/mozbuild/test/configure/test_lint.py
+index 6d8d4c49f..6ad897839 100644
+--- a/python/mozbuild/mozbuild/test/configure/test_lint.py
++++ b/python/mozbuild/mozbuild/test/configure/test_lint.py
+@@ -2,9 +2,9 @@
+ # License, v. 2.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 absolute_import, print_function, unicode_literals
+
+-from StringIO import StringIO
++
++from io import StringIO
+ import os
+ import textwrap
+ import unittest
+@@ -62,7 +62,7 @@ class TestLint(unittest.TestCase):
+ '''):
+ self.lint_test()
+
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ "`bar` depends on '--help' and `foo`. "
+ "`foo` must depend on '--help'")
+
+@@ -85,7 +85,7 @@ class TestLint(unittest.TestCase):
+ '''):
+ self.lint_test()
+
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ "`bar` depends on '--help' and `foo`. "
+ "`foo` must depend on '--help'")
+
+@@ -111,7 +111,7 @@ class TestLint(unittest.TestCase):
+ '''):
+ self.lint_test()
+
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ "Missing @depends for `foo`: '--help'")
+
+ with self.assertRaises(ConfigureError) as e:
+@@ -130,7 +130,7 @@ class TestLint(unittest.TestCase):
+ '''):
+ self.lint_test()
+
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ "Missing @depends for `foo`: '--help'")
+
+ with self.assertRaises(ConfigureError) as e:
+@@ -145,7 +145,7 @@ class TestLint(unittest.TestCase):
+ '''):
+ self.lint_test()
+
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ "Missing @depends for `foo`: '--help'")
+
+ # This would have failed with "Missing @depends for `foo`: '--help'"
+@@ -178,7 +178,7 @@ class TestLint(unittest.TestCase):
+ '''):
+ self.lint_test()
+
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ "Missing @depends for `foo`: '--help'")
+
+ # There is a default restricted `os` module when there is no explicit
+@@ -205,7 +205,7 @@ class TestLint(unittest.TestCase):
+ '''):
+ self.lint_test()
+
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ "%s:3: The dependency on `--foo` is unused."
+ % mozpath.join(test_data_path, 'moz.configure'))
+
+@@ -222,7 +222,7 @@ class TestLint(unittest.TestCase):
+ '''):
+ self.lint_test()
+
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ "%s:5: The dependency on `bar` is unused."
+ % mozpath.join(test_data_path, 'moz.configure'))
+
+@@ -236,7 +236,7 @@ class TestLint(unittest.TestCase):
+ '''):
+ self.lint_test()
+
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ "%s:2: The dependency on `<lambda>` is unused."
+ % mozpath.join(test_data_path, 'moz.configure'))
+
+@@ -257,7 +257,7 @@ class TestLint(unittest.TestCase):
+ '''):
+ self.lint_test()
+
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ "%s:9: The dependency on `qux` is unused."
+ % mozpath.join(test_data_path, 'moz.configure'))
+
+diff --git a/python/mozbuild/mozbuild/test/configure/test_moz_configure.py b/python/mozbuild/mozbuild/test/configure/test_moz_configure.py
+index b3342e268..7a26e9e09 100644
+--- a/python/mozbuild/mozbuild/test/configure/test_moz_configure.py
++++ b/python/mozbuild/mozbuild/test/configure/test_moz_configure.py
+@@ -2,7 +2,7 @@
+ # License, v. 2.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 absolute_import, print_function, unicode_literals
++
+
+ from mozunit import main
+ from mozpack import path as mozpath
+@@ -27,10 +27,10 @@ class TestMozConfigure(BaseConfigureTest):
+ shell = mozpath.abspath('/bin/sh')
+ return result.replace('CONFIG_SHELL=%s ' % shell, '')
+
+- self.assertEquals('--enable-application=browser',
++ self.assertEqual('--enable-application=browser',
+ get_value_for(['--enable-application=browser']))
+
+- self.assertEquals('--enable-application=browser '
++ self.assertEqual('--enable-application=browser '
+ 'MOZ_VTUNE=1',
+ get_value_for(['--enable-application=browser',
+ 'MOZ_VTUNE=1']))
+@@ -39,25 +39,25 @@ class TestMozConfigure(BaseConfigureTest):
+ environ={'MOZ_VTUNE': '1'},
+ mozconfig='ac_add_options --enable-project=js')
+
+- self.assertEquals('--enable-project=js MOZ_VTUNE=1',
++ self.assertEqual('--enable-project=js MOZ_VTUNE=1',
+ value)
+
+ # --disable-js-shell is the default, so it's filtered out.
+- self.assertEquals('--enable-application=browser',
++ self.assertEqual('--enable-application=browser',
+ get_value_for(['--enable-application=browser',
+ '--disable-js-shell']))
+
+ # Normally, --without-foo would be filtered out because that's the
+ # default, but since it is a (fake) old-configure option, it always
+ # appears.
+- self.assertEquals('--enable-application=browser --without-foo',
++ self.assertEqual('--enable-application=browser --without-foo',
+ get_value_for(['--enable-application=browser',
+ '--without-foo']))
+- self.assertEquals('--enable-application=browser --with-foo',
++ self.assertEqual('--enable-application=browser --with-foo',
+ get_value_for(['--enable-application=browser',
+ '--with-foo']))
+
+- self.assertEquals("--enable-application=browser '--with-foo=foo bar'",
++ self.assertEqual("--enable-application=browser '--with-foo=foo bar'",
+ get_value_for(['--enable-application=browser',
+ '--with-foo=foo bar']))
+
+@@ -69,7 +69,7 @@ class TestMozConfigure(BaseConfigureTest):
+ self.version = version
+
+ def __call__(self, stdin, args):
+- this.assertEquals(args, ('-version',))
++ this.assertEqual(args, ('-version',))
+ return 0, self.version, ''
+
+ def check_nsis_version(version):
+@@ -84,13 +84,13 @@ class TestMozConfigure(BaseConfigureTest):
+ with self.assertRaises(SystemExit) as e:
+ check_nsis_version('v3.0a2')
+
+- self.assertEquals(check_nsis_version('v3.0b1'), '3.0b1')
+- self.assertEquals(check_nsis_version('v3.0b2'), '3.0b2')
+- self.assertEquals(check_nsis_version('v3.0rc1'), '3.0rc1')
+- self.assertEquals(check_nsis_version('v3.0'), '3.0')
+- self.assertEquals(check_nsis_version('v3.0-2'), '3.0')
+- self.assertEquals(check_nsis_version('v3.0.1'), '3.0')
+- self.assertEquals(check_nsis_version('v3.1'), '3.1')
++ self.assertEqual(check_nsis_version('v3.0b1'), '3.0b1')
++ self.assertEqual(check_nsis_version('v3.0b2'), '3.0b2')
++ self.assertEqual(check_nsis_version('v3.0rc1'), '3.0rc1')
++ self.assertEqual(check_nsis_version('v3.0'), '3.0')
++ self.assertEqual(check_nsis_version('v3.0-2'), '3.0')
++ self.assertEqual(check_nsis_version('v3.0.1'), '3.0')
++ self.assertEqual(check_nsis_version('v3.1'), '3.1')
+
+
+ if __name__ == '__main__':
+diff --git a/python/mozbuild/mozbuild/test/configure/test_options.py b/python/mozbuild/mozbuild/test/configure/test_options.py
+index 9defccb2c..330ce3b1f 100644
+--- a/python/mozbuild/mozbuild/test/configure/test_options.py
++++ b/python/mozbuild/mozbuild/test/configure/test_options.py
+@@ -2,7 +2,7 @@
+ # License, v. 2.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 absolute_import, print_function, unicode_literals
++
+
+ import unittest
+
+@@ -28,139 +28,139 @@ class Option(Option):
+ class TestOption(unittest.TestCase):
+ def test_option(self):
+ option = Option('--option')
+- self.assertEquals(option.prefix, '')
+- self.assertEquals(option.name, 'option')
+- self.assertEquals(option.env, None)
++ self.assertEqual(option.prefix, '')
++ self.assertEqual(option.name, 'option')
++ self.assertEqual(option.env, None)
+ self.assertFalse(option.default)
+
+ option = Option('--enable-option')
+- self.assertEquals(option.prefix, 'enable')
+- self.assertEquals(option.name, 'option')
+- self.assertEquals(option.env, None)
++ self.assertEqual(option.prefix, 'enable')
++ self.assertEqual(option.name, 'option')
++ self.assertEqual(option.env, None)
+ self.assertFalse(option.default)
+
+ option = Option('--disable-option')
+- self.assertEquals(option.prefix, 'disable')
+- self.assertEquals(option.name, 'option')
+- self.assertEquals(option.env, None)
++ self.assertEqual(option.prefix, 'disable')
++ self.assertEqual(option.name, 'option')
++ self.assertEqual(option.env, None)
+ self.assertTrue(option.default)
+
+ option = Option('--with-option')
+- self.assertEquals(option.prefix, 'with')
+- self.assertEquals(option.name, 'option')
+- self.assertEquals(option.env, None)
++ self.assertEqual(option.prefix, 'with')
++ self.assertEqual(option.name, 'option')
++ self.assertEqual(option.env, None)
+ self.assertFalse(option.default)
+
+ option = Option('--without-option')
+- self.assertEquals(option.prefix, 'without')
+- self.assertEquals(option.name, 'option')
+- self.assertEquals(option.env, None)
++ self.assertEqual(option.prefix, 'without')
++ self.assertEqual(option.name, 'option')
++ self.assertEqual(option.env, None)
+ self.assertTrue(option.default)
+
+ option = Option('--without-option-foo', env='MOZ_OPTION')
+- self.assertEquals(option.env, 'MOZ_OPTION')
++ self.assertEqual(option.env, 'MOZ_OPTION')
+
+ option = Option(env='MOZ_OPTION')
+- self.assertEquals(option.prefix, '')
+- self.assertEquals(option.name, None)
+- self.assertEquals(option.env, 'MOZ_OPTION')
++ self.assertEqual(option.prefix, '')
++ self.assertEqual(option.name, None)
++ self.assertEqual(option.env, 'MOZ_OPTION')
+ self.assertFalse(option.default)
+
+ with self.assertRaises(InvalidOptionError) as e:
+ Option('--option', nargs=0, default=('a',))
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ "The given `default` doesn't satisfy `nargs`")
+
+ with self.assertRaises(InvalidOptionError) as e:
+ Option('--option', nargs=1, default=())
+- self.assertEquals(
++ self.assertEqual(
+ e.exception.message,
+ 'default must be a bool, a string or a tuple of strings')
+
+ with self.assertRaises(InvalidOptionError) as e:
+ Option('--option', nargs=1, default=True)
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ "The given `default` doesn't satisfy `nargs`")
+
+ with self.assertRaises(InvalidOptionError) as e:
+ Option('--option', nargs=1, default=('a', 'b'))
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ "The given `default` doesn't satisfy `nargs`")
+
+ with self.assertRaises(InvalidOptionError) as e:
+ Option('--option', nargs=2, default=())
+- self.assertEquals(
++ self.assertEqual(
+ e.exception.message,
+ 'default must be a bool, a string or a tuple of strings')
+
+ with self.assertRaises(InvalidOptionError) as e:
+ Option('--option', nargs=2, default=True)
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ "The given `default` doesn't satisfy `nargs`")
+
+ with self.assertRaises(InvalidOptionError) as e:
+ Option('--option', nargs=2, default=('a',))
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ "The given `default` doesn't satisfy `nargs`")
+
+ with self.assertRaises(InvalidOptionError) as e:
+ Option('--option', nargs='?', default=('a', 'b'))
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ "The given `default` doesn't satisfy `nargs`")
+
+ with self.assertRaises(InvalidOptionError) as e:
+ Option('--option', nargs='+', default=())
+- self.assertEquals(
++ self.assertEqual(
+ e.exception.message,
+ 'default must be a bool, a string or a tuple of strings')
+
+ with self.assertRaises(InvalidOptionError) as e:
+ Option('--option', nargs='+', default=True)
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ "The given `default` doesn't satisfy `nargs`")
+
+ # --disable options with a nargs value that requires at least one
+ # argument need to be given a default.
+ with self.assertRaises(InvalidOptionError) as e:
+ Option('--disable-option', nargs=1)
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ "The given `default` doesn't satisfy `nargs`")
+
+ with self.assertRaises(InvalidOptionError) as e:
+ Option('--disable-option', nargs='+')
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ "The given `default` doesn't satisfy `nargs`")
+
+ # Test nargs inference from default value
+ option = Option('--with-foo', default=True)
+- self.assertEquals(option.nargs, 0)
++ self.assertEqual(option.nargs, 0)
+
+ option = Option('--with-foo', default=False)
+- self.assertEquals(option.nargs, 0)
++ self.assertEqual(option.nargs, 0)
+
+ option = Option('--with-foo', default='a')
+- self.assertEquals(option.nargs, '?')
++ self.assertEqual(option.nargs, '?')
+
+ option = Option('--with-foo', default=('a',))
+- self.assertEquals(option.nargs, '?')
++ self.assertEqual(option.nargs, '?')
+
+ option = Option('--with-foo', default=('a', 'b'))
+- self.assertEquals(option.nargs, '*')
++ self.assertEqual(option.nargs, '*')
+
+ option = Option(env='FOO', default=True)
+- self.assertEquals(option.nargs, 0)
++ self.assertEqual(option.nargs, 0)
+
+ option = Option(env='FOO', default=False)
+- self.assertEquals(option.nargs, 0)
++ self.assertEqual(option.nargs, 0)
+
+ option = Option(env='FOO', default='a')
+- self.assertEquals(option.nargs, '?')
++ self.assertEqual(option.nargs, '?')
+
+ option = Option(env='FOO', default=('a',))
+- self.assertEquals(option.nargs, '?')
++ self.assertEqual(option.nargs, '?')
+
+ option = Option(env='FOO', default=('a', 'b'))
+- self.assertEquals(option.nargs, '*')
++ self.assertEqual(option.nargs, '*')
+
+ def test_option_option(self):
+ for option in (
+@@ -170,70 +170,70 @@ class TestOption(unittest.TestCase):
+ '--with-option',
+ '--without-option',
+ ):
+- self.assertEquals(Option(option).option, option)
+- self.assertEquals(Option(option, env='FOO').option, option)
++ self.assertEqual(Option(option).option, option)
++ self.assertEqual(Option(option, env='FOO').option, option)
+
+ opt = Option(option, default=False)
+- self.assertEquals(opt.option,
++ self.assertEqual(opt.option,
+ option.replace('-disable-', '-enable-')
+ .replace('-without-', '-with-'))
+
+ opt = Option(option, default=True)
+- self.assertEquals(opt.option,
++ self.assertEqual(opt.option,
+ option.replace('-enable-', '-disable-')
+ .replace('-with-', '-without-'))
+
+- self.assertEquals(Option(env='FOO').option, 'FOO')
++ self.assertEqual(Option(env='FOO').option, 'FOO')
+
+ def test_option_choices(self):
+ with self.assertRaises(InvalidOptionError) as e:
+ Option('--option', nargs=3, choices=('a', 'b'))
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ 'Not enough `choices` for `nargs`')
+
+ with self.assertRaises(InvalidOptionError) as e:
+ Option('--without-option', nargs=1, choices=('a', 'b'))
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ 'A `default` must be given along with `choices`')
+
+ with self.assertRaises(InvalidOptionError) as e:
+ Option('--without-option', nargs='+', choices=('a', 'b'))
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ 'A `default` must be given along with `choices`')
+
+ with self.assertRaises(InvalidOptionError) as e:
+ Option('--without-option', default='c', choices=('a', 'b'))
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ "The `default` value must be one of 'a', 'b'")
+
+ with self.assertRaises(InvalidOptionError) as e:
+ Option('--without-option', default=('a', 'c',), choices=('a', 'b'))
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ "The `default` value must be one of 'a', 'b'")
+
+ with self.assertRaises(InvalidOptionError) as e:
+ Option('--without-option', default=('c',), choices=('a', 'b'))
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ "The `default` value must be one of 'a', 'b'")
+
+ option = Option('--with-option', nargs='+', choices=('a', 'b'))
+ with self.assertRaises(InvalidOptionError) as e:
+ option.get_value('--with-option=c')
+- self.assertEquals(e.exception.message, "'c' is not one of 'a', 'b'")
++ self.assertEqual(e.exception.message, "'c' is not one of 'a', 'b'")
+
+ value = option.get_value('--with-option=b,a')
+ self.assertTrue(value)
+- self.assertEquals(PositiveOptionValue(('b', 'a')), value)
++ self.assertEqual(PositiveOptionValue(('b', 'a')), value)
+
+ option = Option('--without-option', nargs='*', default='a',
+ choices=('a', 'b'))
+ with self.assertRaises(InvalidOptionError) as e:
+ option.get_value('--with-option=c')
+- self.assertEquals(e.exception.message, "'c' is not one of 'a', 'b'")
++ self.assertEqual(e.exception.message, "'c' is not one of 'a', 'b'")
+
+ value = option.get_value('--with-option=b,a')
+ self.assertTrue(value)
+- self.assertEquals(PositiveOptionValue(('b', 'a')), value)
++ self.assertEqual(PositiveOptionValue(('b', 'a')), value)
+
+ # Test nargs inference from choices
+ option = Option('--with-option', choices=('a', 'b'))
+@@ -244,37 +244,37 @@ class TestOption(unittest.TestCase):
+ choices=('a', 'b', 'c', 'd'))
+
+ value = option.get_value('--with-option=+d')
+- self.assertEquals(PositiveOptionValue(('b', 'c', 'd')), value)
++ self.assertEqual(PositiveOptionValue(('b', 'c', 'd')), value)
+
+ value = option.get_value('--with-option=-b')
+- self.assertEquals(PositiveOptionValue(('c',)), value)
++ self.assertEqual(PositiveOptionValue(('c',)), value)
+
+ value = option.get_value('--with-option=-b,+d')
+- self.assertEquals(PositiveOptionValue(('c','d')), value)
++ self.assertEqual(PositiveOptionValue(('c','d')), value)
+
+ # Adding something that is in the default is fine
+ value = option.get_value('--with-option=+b')
+- self.assertEquals(PositiveOptionValue(('b', 'c')), value)
++ self.assertEqual(PositiveOptionValue(('b', 'c')), value)
+
+ # Removing something that is not in the default is fine, as long as it
+ # is one of the choices
+ value = option.get_value('--with-option=-a')
+- self.assertEquals(PositiveOptionValue(('b', 'c')), value)
++ self.assertEqual(PositiveOptionValue(('b', 'c')), value)
+
+ with self.assertRaises(InvalidOptionError) as e:
+ option.get_value('--with-option=-e')
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ "'e' is not one of 'a', 'b', 'c', 'd'")
+
+ # Other "not a choice" errors.
+ with self.assertRaises(InvalidOptionError) as e:
+ option.get_value('--with-option=+e')
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ "'e' is not one of 'a', 'b', 'c', 'd'")
+
+ with self.assertRaises(InvalidOptionError) as e:
+ option.get_value('--with-option=e')
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ "'e' is not one of 'a', 'b', 'c', 'd'")
+
+ def test_option_value_compare(self):
+@@ -294,7 +294,7 @@ class TestOption(unittest.TestCase):
+
+ # For usability reasons, we raise TypeError when attempting to compare
+ # against a non-tuple.
+- with self.assertRaisesRegexp(TypeError, 'cannot compare a'):
++ with self.assertRaisesRegex(TypeError, 'cannot compare a'):
+ val == 'foo'
+
+ # But we allow empty option values to compare otherwise we can't
+@@ -313,36 +313,36 @@ class TestOption(unittest.TestCase):
+
+ def test_option_value_format(self):
+ val = PositiveOptionValue()
+- self.assertEquals('--with-value', val.format('--with-value'))
+- self.assertEquals('--with-value', val.format('--without-value'))
+- self.assertEquals('--enable-value', val.format('--enable-value'))
+- self.assertEquals('--enable-value', val.format('--disable-value'))
+- self.assertEquals('--value', val.format('--value'))
+- self.assertEquals('VALUE=1', val.format('VALUE'))
++ self.assertEqual('--with-value', val.format('--with-value'))
++ self.assertEqual('--with-value', val.format('--without-value'))
++ self.assertEqual('--enable-value', val.format('--enable-value'))
++ self.assertEqual('--enable-value', val.format('--disable-value'))
++ self.assertEqual('--value', val.format('--value'))
++ self.assertEqual('VALUE=1', val.format('VALUE'))
+
+ val = PositiveOptionValue(('a',))
+- self.assertEquals('--with-value=a', val.format('--with-value'))
+- self.assertEquals('--with-value=a', val.format('--without-value'))
+- self.assertEquals('--enable-value=a', val.format('--enable-value'))
+- self.assertEquals('--enable-value=a', val.format('--disable-value'))
+- self.assertEquals('--value=a', val.format('--value'))
+- self.assertEquals('VALUE=a', val.format('VALUE'))
++ self.assertEqual('--with-value=a', val.format('--with-value'))
++ self.assertEqual('--with-value=a', val.format('--without-value'))
++ self.assertEqual('--enable-value=a', val.format('--enable-value'))
++ self.assertEqual('--enable-value=a', val.format('--disable-value'))
++ self.assertEqual('--value=a', val.format('--value'))
++ self.assertEqual('VALUE=a', val.format('VALUE'))
+
+ val = PositiveOptionValue(('a', 'b'))
+- self.assertEquals('--with-value=a,b', val.format('--with-value'))
+- self.assertEquals('--with-value=a,b', val.format('--without-value'))
+- self.assertEquals('--enable-value=a,b', val.format('--enable-value'))
+- self.assertEquals('--enable-value=a,b', val.format('--disable-value'))
+- self.assertEquals('--value=a,b', val.format('--value'))
+- self.assertEquals('VALUE=a,b', val.format('VALUE'))
++ self.assertEqual('--with-value=a,b', val.format('--with-value'))
++ self.assertEqual('--with-value=a,b', val.format('--without-value'))
++ self.assertEqual('--enable-value=a,b', val.format('--enable-value'))
++ self.assertEqual('--enable-value=a,b', val.format('--disable-value'))
++ self.assertEqual('--value=a,b', val.format('--value'))
++ self.assertEqual('VALUE=a,b', val.format('VALUE'))
+
+ val = NegativeOptionValue()
+- self.assertEquals('--without-value', val.format('--with-value'))
+- self.assertEquals('--without-value', val.format('--without-value'))
+- self.assertEquals('--disable-value', val.format('--enable-value'))
+- self.assertEquals('--disable-value', val.format('--disable-value'))
+- self.assertEquals('', val.format('--value'))
+- self.assertEquals('VALUE=', val.format('VALUE'))
++ self.assertEqual('--without-value', val.format('--with-value'))
++ self.assertEqual('--without-value', val.format('--without-value'))
++ self.assertEqual('--disable-value', val.format('--enable-value'))
++ self.assertEqual('--disable-value', val.format('--disable-value'))
++ self.assertEqual('', val.format('--value'))
++ self.assertEqual('VALUE=', val.format('VALUE'))
+
+ def test_option_value(self, name='option', nargs=0, default=None):
+ disabled = name.startswith(('disable-', 'without-'))
+@@ -359,28 +359,28 @@ class TestOption(unittest.TestCase):
+
+ if nargs in (0, '?', '*') or disabled:
+ value = option.get_value('--%s' % name, 'option')
+- self.assertEquals(value, posOptionValue())
+- self.assertEquals(value.origin, 'option')
++ self.assertEqual(value, posOptionValue())
++ self.assertEqual(value.origin, 'option')
+ else:
+ with self.assertRaises(InvalidOptionError) as e:
+ option.get_value('--%s' % name)
+ if nargs == 1:
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ '--%s takes 1 value' % name)
+ elif nargs == '+':
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ '--%s takes 1 or more values' % name)
+ else:
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ '--%s takes 2 values' % name)
+
+ value = option.get_value('')
+- self.assertEquals(value, defaultValue)
+- self.assertEquals(value.origin, 'default')
++ self.assertEqual(value, defaultValue)
++ self.assertEqual(value.origin, 'default')
+
+ value = option.get_value(None)
+- self.assertEquals(value, defaultValue)
+- self.assertEquals(value.origin, 'default')
++ self.assertEqual(value, defaultValue)
++ self.assertEqual(value.origin, 'default')
+
+ with self.assertRaises(AssertionError):
+ value = option.get_value('MOZ_OPTION=', 'environment')
+@@ -393,47 +393,47 @@ class TestOption(unittest.TestCase):
+
+ if nargs in (1, '?', '*', '+') and not disabled:
+ value = option.get_value('--%s=' % name, 'option')
+- self.assertEquals(value, PositiveOptionValue(('',)))
+- self.assertEquals(value.origin, 'option')
++ self.assertEqual(value, PositiveOptionValue(('',)))
++ self.assertEqual(value.origin, 'option')
+ else:
+ with self.assertRaises(InvalidOptionError) as e:
+ option.get_value('--%s=' % name)
+ if disabled:
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ 'Cannot pass a value to --%s' % name)
+ else:
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ '--%s takes %d values' % (name, nargs))
+
+ if nargs in (1, '?', '*', '+') and not disabled:
+ value = option.get_value('--%s=foo' % name, 'option')
+- self.assertEquals(value, PositiveOptionValue(('foo',)))
+- self.assertEquals(value.origin, 'option')
++ self.assertEqual(value, PositiveOptionValue(('foo',)))
++ self.assertEqual(value.origin, 'option')
+ else:
+ with self.assertRaises(InvalidOptionError) as e:
+ option.get_value('--%s=foo' % name)
+ if disabled:
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ 'Cannot pass a value to --%s' % name)
+ else:
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ '--%s takes %d values' % (name, nargs))
+
+ if nargs in (2, '*', '+') and not disabled:
+ value = option.get_value('--%s=foo,bar' % name, 'option')
+- self.assertEquals(value, PositiveOptionValue(('foo', 'bar')))
+- self.assertEquals(value.origin, 'option')
++ self.assertEqual(value, PositiveOptionValue(('foo', 'bar')))
++ self.assertEqual(value.origin, 'option')
+ else:
+ with self.assertRaises(InvalidOptionError) as e:
+ option.get_value('--%s=foo,bar' % name, 'option')
+ if disabled:
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ 'Cannot pass a value to --%s' % name)
+ elif nargs == '?':
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ '--%s takes 0 or 1 values' % name)
+ else:
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ '--%s takes %d value%s'
+ % (name, nargs, 's' if nargs != 1 else ''))
+
+@@ -441,59 +441,59 @@ class TestOption(unittest.TestCase):
+ default=default)
+ if nargs in (0, '?', '*') or disabled:
+ value = option.get_value('--%s' % name, 'option')
+- self.assertEquals(value, posOptionValue())
+- self.assertEquals(value.origin, 'option')
++ self.assertEqual(value, posOptionValue())
++ self.assertEqual(value.origin, 'option')
+ else:
+ with self.assertRaises(InvalidOptionError) as e:
+ option.get_value('--%s' % name)
+ if disabled:
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ 'Cannot pass a value to --%s' % name)
+ elif nargs == '+':
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ '--%s takes 1 or more values' % name)
+ else:
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ '--%s takes %d value%s'
+ % (name, nargs, 's' if nargs != 1 else ''))
+
+ value = option.get_value('')
+- self.assertEquals(value, defaultValue)
+- self.assertEquals(value.origin, 'default')
++ self.assertEqual(value, defaultValue)
++ self.assertEqual(value.origin, 'default')
+
+ value = option.get_value(None)
+- self.assertEquals(value, defaultValue)
+- self.assertEquals(value.origin, 'default')
++ self.assertEqual(value, defaultValue)
++ self.assertEqual(value.origin, 'default')
+
+ value = option.get_value('MOZ_OPTION=', 'environment')
+- self.assertEquals(value, NegativeOptionValue())
+- self.assertEquals(value.origin, 'environment')
++ self.assertEqual(value, NegativeOptionValue())
++ self.assertEqual(value.origin, 'environment')
+
+ if nargs in (0, '?', '*'):
+ value = option.get_value('MOZ_OPTION=1', 'environment')
+- self.assertEquals(value, PositiveOptionValue())
+- self.assertEquals(value.origin, 'environment')
++ self.assertEqual(value, PositiveOptionValue())
++ self.assertEqual(value.origin, 'environment')
+ elif nargs in (1, '+'):
+ value = option.get_value('MOZ_OPTION=1', 'environment')
+- self.assertEquals(value, PositiveOptionValue(('1',)))
+- self.assertEquals(value.origin, 'environment')
++ self.assertEqual(value, PositiveOptionValue(('1',)))
++ self.assertEqual(value.origin, 'environment')
+ else:
+ with self.assertRaises(InvalidOptionError) as e:
+ option.get_value('MOZ_OPTION=1', 'environment')
+- self.assertEquals(e.exception.message, 'MOZ_OPTION takes 2 values')
++ self.assertEqual(e.exception.message, 'MOZ_OPTION takes 2 values')
+
+ if nargs in (1, '?', '*', '+') and not disabled:
+ value = option.get_value('--%s=' % name, 'option')
+- self.assertEquals(value, PositiveOptionValue(('',)))
+- self.assertEquals(value.origin, 'option')
++ self.assertEqual(value, PositiveOptionValue(('',)))
++ self.assertEqual(value.origin, 'option')
+ else:
+ with self.assertRaises(InvalidOptionError) as e:
+ option.get_value('--%s=' % name, 'option')
+ if disabled:
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ 'Cannot pass a value to --%s' % name)
+ else:
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ '--%s takes %d values' % (name, nargs))
+
+ with self.assertRaises(AssertionError):
+@@ -501,26 +501,26 @@ class TestOption(unittest.TestCase):
+
+ if nargs in (1, '?', '*', '+'):
+ value = option.get_value('MOZ_OPTION=foo', 'environment')
+- self.assertEquals(value, PositiveOptionValue(('foo',)))
+- self.assertEquals(value.origin, 'environment')
++ self.assertEqual(value, PositiveOptionValue(('foo',)))
++ self.assertEqual(value.origin, 'environment')
+ else:
+ with self.assertRaises(InvalidOptionError) as e:
+ option.get_value('MOZ_OPTION=foo', 'environment')
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ 'MOZ_OPTION takes %d values' % nargs)
+
+ if nargs in (2, '*', '+'):
+ value = option.get_value('MOZ_OPTION=foo,bar', 'environment')
+- self.assertEquals(value, PositiveOptionValue(('foo', 'bar')))
+- self.assertEquals(value.origin, 'environment')
++ self.assertEqual(value, PositiveOptionValue(('foo', 'bar')))
++ self.assertEqual(value.origin, 'environment')
+ else:
+ with self.assertRaises(InvalidOptionError) as e:
+ option.get_value('MOZ_OPTION=foo,bar', 'environment')
+ if nargs == '?':
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ 'MOZ_OPTION takes 0 or 1 values')
+ else:
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ 'MOZ_OPTION takes %d value%s'
+ % (nargs, 's' if nargs != 1 else ''))
+
+@@ -532,26 +532,26 @@ class TestOption(unittest.TestCase):
+ env_option.get_value('--%s' % name)
+
+ value = env_option.get_value('')
+- self.assertEquals(value, defaultValue)
+- self.assertEquals(value.origin, 'default')
++ self.assertEqual(value, defaultValue)
++ self.assertEqual(value.origin, 'default')
+
+ value = env_option.get_value('MOZ_OPTION=', 'environment')
+- self.assertEquals(value, negOptionValue())
+- self.assertEquals(value.origin, 'environment')
++ self.assertEqual(value, negOptionValue())
++ self.assertEqual(value.origin, 'environment')
+
+ if nargs in (0, '?', '*'):
+ value = env_option.get_value('MOZ_OPTION=1', 'environment')
+- self.assertEquals(value, posOptionValue())
++ self.assertEqual(value, posOptionValue())
+ self.assertTrue(value)
+- self.assertEquals(value.origin, 'environment')
++ self.assertEqual(value.origin, 'environment')
+ elif nargs in (1, '+'):
+ value = env_option.get_value('MOZ_OPTION=1', 'environment')
+- self.assertEquals(value, PositiveOptionValue(('1',)))
+- self.assertEquals(value.origin, 'environment')
++ self.assertEqual(value, PositiveOptionValue(('1',)))
++ self.assertEqual(value.origin, 'environment')
+ else:
+ with self.assertRaises(InvalidOptionError) as e:
+ env_option.get_value('MOZ_OPTION=1', 'environment')
+- self.assertEquals(e.exception.message, 'MOZ_OPTION takes 2 values')
++ self.assertEqual(e.exception.message, 'MOZ_OPTION takes 2 values')
+
+ with self.assertRaises(AssertionError) as e:
+ env_option.get_value('--%s' % name)
+@@ -561,26 +561,26 @@ class TestOption(unittest.TestCase):
+
+ if nargs in (1, '?', '*', '+'):
+ value = env_option.get_value('MOZ_OPTION=foo', 'environment')
+- self.assertEquals(value, PositiveOptionValue(('foo',)))
+- self.assertEquals(value.origin, 'environment')
++ self.assertEqual(value, PositiveOptionValue(('foo',)))
++ self.assertEqual(value.origin, 'environment')
+ else:
+ with self.assertRaises(InvalidOptionError) as e:
+ env_option.get_value('MOZ_OPTION=foo', 'environment')
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ 'MOZ_OPTION takes %d values' % nargs)
+
+ if nargs in (2, '*', '+'):
+ value = env_option.get_value('MOZ_OPTION=foo,bar', 'environment')
+- self.assertEquals(value, PositiveOptionValue(('foo', 'bar')))
+- self.assertEquals(value.origin, 'environment')
++ self.assertEqual(value, PositiveOptionValue(('foo', 'bar')))
++ self.assertEqual(value.origin, 'environment')
+ else:
+ with self.assertRaises(InvalidOptionError) as e:
+ env_option.get_value('MOZ_OPTION=foo,bar', 'environment')
+ if nargs == '?':
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ 'MOZ_OPTION takes 0 or 1 values')
+ else:
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ 'MOZ_OPTION takes %d value%s'
+ % (nargs, 's' if nargs != 1 else ''))
+
+@@ -592,28 +592,28 @@ class TestOption(unittest.TestCase):
+ default=default)
+
+ value = option.get_value('--%s-option' % disable, 'option')
+- self.assertEquals(value, NegativeOptionValue())
+- self.assertEquals(value.origin, 'option')
++ self.assertEqual(value, NegativeOptionValue())
++ self.assertEqual(value.origin, 'option')
+
+ option = self.test_option_value('%s-option' % disable, nargs=nargs,
+ default=default)
+
+ if nargs in (0, '?', '*'):
+ value = option.get_value('--%s-option' % enable, 'option')
+- self.assertEquals(value, PositiveOptionValue())
+- self.assertEquals(value.origin, 'option')
++ self.assertEqual(value, PositiveOptionValue())
++ self.assertEqual(value.origin, 'option')
+ else:
+ with self.assertRaises(InvalidOptionError) as e:
+ option.get_value('--%s-option' % enable, 'option')
+ if nargs == 1:
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ '--%s-option takes 1 value' % enable)
+ elif nargs == '+':
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ '--%s-option takes 1 or more values'
+ % enable)
+ else:
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ '--%s-option takes 2 values' % enable)
+
+ def test_option_value_with(self):
+@@ -622,12 +622,12 @@ class TestOption(unittest.TestCase):
+ def test_option_value_invalid_nargs(self):
+ with self.assertRaises(InvalidOptionError) as e:
+ Option('--option', nargs='foo')
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ "nargs must be a positive integer, '?', '*' or '+'")
+
+ with self.assertRaises(InvalidOptionError) as e:
+ Option('--option', nargs=-2)
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ "nargs must be a positive integer, '?', '*' or '+'")
+
+ def test_option_value_nargs_1(self):
+@@ -638,7 +638,7 @@ class TestOption(unittest.TestCase):
+ # A default is required
+ with self.assertRaises(InvalidOptionError) as e:
+ Option('--disable-option', nargs=1)
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ "The given `default` doesn't satisfy `nargs`")
+
+ def test_option_value_nargs_2(self):
+@@ -649,7 +649,7 @@ class TestOption(unittest.TestCase):
+ # A default is required
+ with self.assertRaises(InvalidOptionError) as e:
+ Option('--disable-option', nargs=2)
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ "The given `default` doesn't satisfy `nargs`")
+
+ def test_option_value_nargs_0_or_1(self):
+@@ -676,7 +676,7 @@ class TestOption(unittest.TestCase):
+ # A default is required
+ with self.assertRaises(InvalidOptionError) as e:
+ Option('--disable-option', nargs='+')
+- self.assertEquals(e.exception.message,
++ self.assertEqual(e.exception.message,
+ "The given `default` doesn't satisfy `nargs`")
+
+
+@@ -684,21 +684,21 @@ class TestCommandLineHelper(unittest.TestCase):
+ def test_basic(self):
+ helper = CommandLineHelper({}, ['cmd', '--foo', '--bar'])
+
+- self.assertEquals(['--foo', '--bar'], list(helper))
++ self.assertEqual(['--foo', '--bar'], list(helper))
+
+ helper.add('--enable-qux')
+
+- self.assertEquals(['--foo', '--bar', '--enable-qux'], list(helper))
++ self.assertEqual(['--foo', '--bar', '--enable-qux'], list(helper))
+
+ value, option = helper.handle(Option('--bar'))
+- self.assertEquals(['--foo', '--enable-qux'], list(helper))
+- self.assertEquals(PositiveOptionValue(), value)
+- self.assertEquals('--bar', option)
++ self.assertEqual(['--foo', '--enable-qux'], list(helper))
++ self.assertEqual(PositiveOptionValue(), value)
++ self.assertEqual('--bar', option)
+
+ value, option = helper.handle(Option('--baz'))
+- self.assertEquals(['--foo', '--enable-qux'], list(helper))
+- self.assertEquals(NegativeOptionValue(), value)
+- self.assertEquals(None, option)
++ self.assertEqual(['--foo', '--enable-qux'], list(helper))
++ self.assertEqual(NegativeOptionValue(), value)
++ self.assertEqual(None, option)
+
+ with self.assertRaises(AssertionError):
+ CommandLineHelper({}, ['--foo', '--bar'])
+@@ -707,89 +707,89 @@ class TestCommandLineHelper(unittest.TestCase):
+ foo = Option('--with-foo', nargs='*')
+ helper = CommandLineHelper({}, ['cmd', '--with-foo=a,b'])
+ value, option = helper.handle(foo)
+- self.assertEquals(PositiveOptionValue(('a', 'b')), value)
+- self.assertEquals('command-line', value.origin)
+- self.assertEquals('--with-foo=a,b', option)
++ self.assertEqual(PositiveOptionValue(('a', 'b')), value)
++ self.assertEqual('command-line', value.origin)
++ self.assertEqual('--with-foo=a,b', option)
+
+ helper = CommandLineHelper({}, ['cmd', '--with-foo=a,b',
+ '--without-foo'])
+ value, option = helper.handle(foo)
+- self.assertEquals(NegativeOptionValue(), value)
+- self.assertEquals('command-line', value.origin)
+- self.assertEquals('--without-foo', option)
++ self.assertEqual(NegativeOptionValue(), value)
++ self.assertEqual('command-line', value.origin)
++ self.assertEqual('--without-foo', option)
+
+ helper = CommandLineHelper({}, ['cmd', '--without-foo',
+ '--with-foo=a,b'])
+ value, option = helper.handle(foo)
+- self.assertEquals(PositiveOptionValue(('a', 'b')), value)
+- self.assertEquals('command-line', value.origin)
+- self.assertEquals('--with-foo=a,b', option)
++ self.assertEqual(PositiveOptionValue(('a', 'b')), value)
++ self.assertEqual('command-line', value.origin)
++ self.assertEqual('--with-foo=a,b', option)
+
+ foo = Option('--with-foo', env='FOO', nargs='*')
+ helper = CommandLineHelper({'FOO': ''}, ['cmd', '--with-foo=a,b'])
+ value, option = helper.handle(foo)
+- self.assertEquals(PositiveOptionValue(('a', 'b')), value)
+- self.assertEquals('command-line', value.origin)
+- self.assertEquals('--with-foo=a,b', option)
++ self.assertEqual(PositiveOptionValue(('a', 'b')), value)
++ self.assertEqual('command-line', value.origin)
++ self.assertEqual('--with-foo=a,b', option)
+
+ helper = CommandLineHelper({'FOO': 'a,b'}, ['cmd', '--without-foo'])
+ value, option = helper.handle(foo)
+- self.assertEquals(NegativeOptionValue(), value)
+- self.assertEquals('command-line', value.origin)
+- self.assertEquals('--without-foo', option)
++ self.assertEqual(NegativeOptionValue(), value)
++ self.assertEqual('command-line', value.origin)
++ self.assertEqual('--without-foo', option)
+
+ helper = CommandLineHelper({'FOO': ''}, ['cmd', '--with-bar=a,b'])
+ value, option = helper.handle(foo)
+- self.assertEquals(NegativeOptionValue(), value)
+- self.assertEquals('environment', value.origin)
+- self.assertEquals('FOO=', option)
++ self.assertEqual(NegativeOptionValue(), value)
++ self.assertEqual('environment', value.origin)
++ self.assertEqual('FOO=', option)
+
+ helper = CommandLineHelper({'FOO': 'a,b'}, ['cmd', '--without-bar'])
+ value, option = helper.handle(foo)
+- self.assertEquals(PositiveOptionValue(('a', 'b')), value)
+- self.assertEquals('environment', value.origin)
+- self.assertEquals('FOO=a,b', option)
++ self.assertEqual(PositiveOptionValue(('a', 'b')), value)
++ self.assertEqual('environment', value.origin)
++ self.assertEqual('FOO=a,b', option)
+
+ helper = CommandLineHelper({}, ['cmd', '--with-foo=a,b', 'FOO='])
+ value, option = helper.handle(foo)
+- self.assertEquals(NegativeOptionValue(), value)
+- self.assertEquals('command-line', value.origin)
+- self.assertEquals('FOO=', option)
++ self.assertEqual(NegativeOptionValue(), value)
++ self.assertEqual('command-line', value.origin)
++ self.assertEqual('FOO=', option)
+
+ helper = CommandLineHelper({}, ['cmd', '--without-foo', 'FOO=a,b'])
+ value, option = helper.handle(foo)
+- self.assertEquals(PositiveOptionValue(('a', 'b')), value)
+- self.assertEquals('command-line', value.origin)
+- self.assertEquals('FOO=a,b', option)
++ self.assertEqual(PositiveOptionValue(('a', 'b')), value)
++ self.assertEqual('command-line', value.origin)
++ self.assertEqual('FOO=a,b', option)
+
+ helper = CommandLineHelper({}, ['cmd', 'FOO=', '--with-foo=a,b'])
+ value, option = helper.handle(foo)
+- self.assertEquals(PositiveOptionValue(('a', 'b')), value)
+- self.assertEquals('command-line', value.origin)
+- self.assertEquals('--with-foo=a,b', option)
++ self.assertEqual(PositiveOptionValue(('a', 'b')), value)
++ self.assertEqual('command-line', value.origin)
++ self.assertEqual('--with-foo=a,b', option)
+
+ helper = CommandLineHelper({}, ['cmd', 'FOO=a,b', '--without-foo'])
+ value, option = helper.handle(foo)
+- self.assertEquals(NegativeOptionValue(), value)
+- self.assertEquals('command-line', value.origin)
+- self.assertEquals('--without-foo', option)
++ self.assertEqual(NegativeOptionValue(), value)
++ self.assertEqual('command-line', value.origin)
++ self.assertEqual('--without-foo', option)
+
+ def test_extra_args(self):
+ foo = Option('--with-foo', env='FOO', nargs='*')
+ helper = CommandLineHelper({}, ['cmd'])
+ helper.add('FOO=a,b,c', 'other-origin')
+ value, option = helper.handle(foo)
+- self.assertEquals(PositiveOptionValue(('a', 'b', 'c')), value)
+- self.assertEquals('other-origin', value.origin)
+- self.assertEquals('FOO=a,b,c', option)
++ self.assertEqual(PositiveOptionValue(('a', 'b', 'c')), value)
++ self.assertEqual('other-origin', value.origin)
++ self.assertEqual('FOO=a,b,c', option)
+
+ helper = CommandLineHelper({}, ['cmd'])
+ helper.add('FOO=a,b,c', 'other-origin')
+ helper.add('--with-foo=a,b,c', 'other-origin')
+ value, option = helper.handle(foo)
+- self.assertEquals(PositiveOptionValue(('a', 'b', 'c')), value)
+- self.assertEquals('other-origin', value.origin)
+- self.assertEquals('--with-foo=a,b,c', option)
++ self.assertEqual(PositiveOptionValue(('a', 'b', 'c')), value)
++ self.assertEqual('other-origin', value.origin)
++ self.assertEqual('--with-foo=a,b,c', option)
+
+ # Adding conflicting options is not allowed.
+ helper = CommandLineHelper({}, ['cmd'])
+@@ -809,9 +809,9 @@ class TestCommandLineHelper(unittest.TestCase):
+ # But adding the same is allowed.
+ helper.add('FOO=a,b,c', 'other-origin')
+ value, option = helper.handle(foo)
+- self.assertEquals(PositiveOptionValue(('a', 'b', 'c')), value)
+- self.assertEquals('other-origin', value.origin)
+- self.assertEquals('FOO=a,b,c', option)
++ self.assertEqual(PositiveOptionValue(('a', 'b', 'c')), value)
++ self.assertEqual('other-origin', value.origin)
++ self.assertEqual('FOO=a,b,c', option)
+
+ # The same rule as above applies when using the option form vs. the
+ # variable form. But we can't detect it when .add is called.
+@@ -837,9 +837,9 @@ class TestCommandLineHelper(unittest.TestCase):
+ helper.add('FOO=a,b,c', 'other-origin')
+ helper.add('--with-foo=a,b,c', 'other-origin')
+ value, option = helper.handle(foo)
+- self.assertEquals(PositiveOptionValue(('a', 'b', 'c')), value)
+- self.assertEquals('other-origin', value.origin)
+- self.assertEquals('--with-foo=a,b,c', option)
++ self.assertEqual(PositiveOptionValue(('a', 'b', 'c')), value)
++ self.assertEqual('other-origin', value.origin)
++ self.assertEqual('--with-foo=a,b,c', option)
+
+ # Conflicts are also not allowed against what is in the
+ # environment/on the command line.
+@@ -869,19 +869,19 @@ class TestCommandLineHelper(unittest.TestCase):
+ foo = Option('--foo',
+ possible_origins=('command-line',))
+ value, option = helper.handle(foo)
+- self.assertEquals(PositiveOptionValue(), value)
+- self.assertEquals('command-line', value.origin)
+- self.assertEquals('--foo', option)
++ self.assertEqual(PositiveOptionValue(), value)
++ self.assertEqual('command-line', value.origin)
++ self.assertEqual('--foo', option)
+
+ bar = Option('--bar',
+ possible_origins=('mozconfig',))
+- with self.assertRaisesRegexp(InvalidOptionError,
++ with self.assertRaisesRegex(InvalidOptionError,
+ "--bar can not be set by command-line. Values are accepted from: mozconfig"):
+ helper.handle(bar)
+
+ baz = Option(env='BAZ',
+ possible_origins=('implied',))
+- with self.assertRaisesRegexp(InvalidOptionError,
++ with self.assertRaisesRegex(InvalidOptionError,
+ "BAZ=1 can not be set by environment. Values are accepted from: implied"):
+ helper.handle(baz)
+
+diff --git a/python/mozbuild/mozbuild/test/configure/test_toolchain_configure.py b/python/mozbuild/mozbuild/test/configure/test_toolchain_configure.py
+index cb7ff709e..c339a32bf 100755
+--- a/python/mozbuild/mozbuild/test/configure/test_toolchain_configure.py
++++ b/python/mozbuild/mozbuild/test/configure/test_toolchain_configure.py
+@@ -2,12 +2,12 @@
+ # License, v. 2.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 absolute_import, print_function, unicode_literals
++
+
+ import logging
+ import os
+
+-from StringIO import StringIO
++from io import StringIO
+
+ from mozunit import main
+
+@@ -366,9 +366,9 @@ class BaseToolchainTest(BaseConfigureTest):
+ compiler = sandbox._value_for(sandbox[var])
+ # Add var on both ends to make it clear which of the
+ # variables is failing the test when that happens.
+- self.assertEquals((var, compiler), (var, result))
++ self.assertEqual((var, compiler), (var, result))
+ except SystemExit:
+- self.assertEquals((var, result),
++ self.assertEqual((var, result),
+ (var, self.out.getvalue().strip()))
+ return
+
+@@ -407,7 +407,7 @@ class BaseToolchainTest(BaseConfigureTest):
+ 'RUST_LIB_SUFFIX',
+ 'OBJ_SUFFIX',
+ ):
+- self.assertEquals('%s=%s' % (k, sandbox.get_config(k)),
++ self.assertEqual('%s=%s' % (k, sandbox.get_config(k)),
+ '%s=%s' % (k, library_name_info[k]))
+
+
+@@ -584,7 +584,7 @@ class LinuxToolchainTest(BaseToolchainTest):
+ # We'll try gcc and clang, but since there is no gcc (gcc-x.y doesn't
+ # count), find clang.
+ paths = {
+- k: v for k, v in self.PATHS.iteritems()
++ k: v for k, v in self.PATHS.items()
+ if os.path.basename(k) not in ('gcc', 'g++')
+ }
+ self.do_toolchain_test(paths, {
+@@ -619,7 +619,7 @@ class LinuxToolchainTest(BaseToolchainTest):
+ # Even if there are gcc-x.y or clang-x.y compilers available, we
+ # don't try them. This could be considered something to improve.
+ paths = {
+- k: v for k, v in self.PATHS.iteritems()
++ k: v for k, v in self.PATHS.items()
+ if os.path.basename(k) not in ('gcc', 'g++', 'clang', 'clang++')
+ }
+ self.do_toolchain_test(paths, {
+@@ -800,7 +800,7 @@ class OSXToolchainTest(BaseToolchainTest):
+ def test_not_gcc(self):
+ # We won't pick GCC if it's the only thing available.
+ paths = {
+- k: v for k, v in self.PATHS.iteritems()
++ k: v for k, v in self.PATHS.items()
+ if os.path.basename(k) not in ('clang', 'clang++')
+ }
+ self.do_toolchain_test(paths, {
+@@ -976,7 +976,7 @@ class WindowsToolchainTest(BaseToolchainTest):
+ def test_clang_cl(self):
+ # We'll pick clang-cl if msvc can't be found.
+ paths = {
+- k: v for k, v in self.PATHS.iteritems()
++ k: v for k, v in self.PATHS.items()
+ if os.path.basename(k) != 'cl'
+ }
+ self.do_toolchain_test(paths, {
+@@ -987,7 +987,7 @@ class WindowsToolchainTest(BaseToolchainTest):
+ def test_gcc(self):
+ # We'll pick GCC if msvc and clang-cl can't be found.
+ paths = {
+- k: v for k, v in self.PATHS.iteritems()
++ k: v for k, v in self.PATHS.items()
+ if os.path.basename(k) not in ('cl', 'clang-cl')
+ }
+ self.do_toolchain_test(paths, {
+@@ -1006,7 +1006,7 @@ class WindowsToolchainTest(BaseToolchainTest):
+ def test_clang(self):
+ # We'll pick clang if nothing else is found.
+ paths = {
+- k: v for k, v in self.PATHS.iteritems()
++ k: v for k, v in self.PATHS.items()
+ if os.path.basename(k) not in ('cl', 'clang-cl', 'gcc')
+ }
+ self.do_toolchain_test(paths, {
+diff --git a/python/mozbuild/mozbuild/test/configure/test_toolchain_helpers.py b/python/mozbuild/mozbuild/test/configure/test_toolchain_helpers.py
+index 8ec33a8b7..ba046ed12 100644
+--- a/python/mozbuild/mozbuild/test/configure/test_toolchain_helpers.py
++++ b/python/mozbuild/mozbuild/test/configure/test_toolchain_helpers.py
+@@ -2,7 +2,7 @@
+ # License, v. 2.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 absolute_import, print_function, unicode_literals
++
+
+ import copy
+ import re
+@@ -10,7 +10,7 @@ import types
+ import unittest
+
+ from fnmatch import fnmatch
+-from StringIO import StringIO
++from io import StringIO
+ from textwrap import dedent
+
+ from mozunit import (
+@@ -43,7 +43,7 @@ class CompilerPreprocessor(Preprocessor):
+ # Hack around it enough that the configure tests work properly.
+ context = self.context
+ def normalize_numbers(value):
+- if isinstance(value, types.StringTypes):
++ if isinstance(value, (str,)):
+ if value[-1:] == 'L' and value[:-1].isdigit():
+ value = int(value[:-1])
+ return value
+@@ -53,7 +53,7 @@ class CompilerPreprocessor(Preprocessor):
+ return self.HAS_FEATURE.sub(r'\1\2', expr)
+ self.context = self.Context(
+ (normalize_has_feature(k), normalize_numbers(v))
+- for k, v in context.iteritems()
++ for k, v in context.items()
+ )
+ try:
+ return Preprocessor.do_if(self, normalize_has_feature(expression),
+@@ -95,7 +95,7 @@ class TestCompilerPreprocessor(unittest.TestCase):
+ input.name = 'foo'
+ pp.do_include(input)
+
+- self.assertEquals(pp.out.getvalue(), '1 . 2 . c "D"')
++ self.assertEqual(pp.out.getvalue(), '1 . 2 . c "D"')
+
+ def test_condition(self):
+ pp = CompilerPreprocessor({
+@@ -125,7 +125,7 @@ class TestCompilerPreprocessor(unittest.TestCase):
+ input.name = 'foo'
+ pp.do_include(input)
+
+- self.assertEquals('IFDEF_A\nIF_A\nIF_B\nIF_NOT_C\n', pp.out.getvalue())
++ self.assertEqual('IFDEF_A\nIF_A\nIF_B\nIF_NOT_C\n', pp.out.getvalue())
+
+
+ class FakeCompiler(dict):
+@@ -164,9 +164,9 @@ class FakeCompiler(dict):
+ '''
+ def __init__(self, *definitions):
+ for definition in definitions:
+- if all(not isinstance(d, dict) for d in definition.itervalues()):
++ if all(not isinstance(d, dict) for d in definition.values()):
+ definition = {None: definition}
+- for key, value in definition.iteritems():
++ for key, value in definition.items():
+ self.setdefault(key, {}).update(value)
+
+ def __call__(self, stdin, args):
+@@ -178,14 +178,14 @@ class FakeCompiler(dict):
+ pp = CompilerPreprocessor(self[None])
+
+ def apply_defn(defn):
+- for k, v in defn.iteritems():
++ for k, v in defn.items():
+ if v is False:
+ if k in pp.context:
+ del pp.context[k]
+ else:
+ pp.context[k] = v
+
+- for glob, defn in self.iteritems():
++ for glob, defn in self.items():
+ if glob and not glob.startswith('-') and fnmatch(file, glob):
+ apply_defn(defn)
+
+@@ -216,7 +216,7 @@ class TestFakeCompiler(unittest.TestCase):
+ 'A': '1',
+ 'B': '2',
+ })
+- self.assertEquals(compiler(None, ['-E', 'file']),
++ self.assertEqual(compiler(None, ['-E', 'file']),
+ (0, '1 2 C', ''))
+
+ compiler = FakeCompiler({
+@@ -238,25 +238,25 @@ class TestFakeCompiler(unittest.TestCase):
+ 'B': '42',
+ },
+ })
+- self.assertEquals(compiler(None, ['-E', 'file']),
++ self.assertEqual(compiler(None, ['-E', 'file']),
+ (0, '1 2 C', ''))
+- self.assertEquals(compiler(None, ['-E', '-foo', 'file']),
++ self.assertEqual(compiler(None, ['-E', '-foo', 'file']),
+ (0, '1 2 foo', ''))
+- self.assertEquals(compiler(None, ['-E', '-bar', 'file']),
++ self.assertEqual(compiler(None, ['-E', '-bar', 'file']),
+ (0, '1 bar bar', ''))
+- self.assertEquals(compiler(None, ['-E', '-qux', 'file']),
++ self.assertEqual(compiler(None, ['-E', '-qux', 'file']),
+ (0, '1 B C', ''))
+- self.assertEquals(compiler(None, ['-E', '-foo', '-bar', 'file']),
++ self.assertEqual(compiler(None, ['-E', '-foo', '-bar', 'file']),
+ (0, '1 bar bar', ''))
+- self.assertEquals(compiler(None, ['-E', '-bar', '-foo', 'file']),
++ self.assertEqual(compiler(None, ['-E', '-bar', '-foo', 'file']),
+ (0, '1 bar foo', ''))
+- self.assertEquals(compiler(None, ['-E', '-bar', '-qux', 'file']),
++ self.assertEqual(compiler(None, ['-E', '-bar', '-qux', 'file']),
+ (0, '1 B bar', ''))
+- self.assertEquals(compiler(None, ['-E', '-qux', '-bar', 'file']),
++ self.assertEqual(compiler(None, ['-E', '-qux', '-bar', 'file']),
+ (0, '1 bar bar', ''))
+- self.assertEquals(compiler(None, ['-E', 'file.c']),
++ self.assertEqual(compiler(None, ['-E', 'file.c']),
+ (0, '1 42 C', ''))
+- self.assertEquals(compiler(None, ['-E', '-bar', 'file.c']),
++ self.assertEqual(compiler(None, ['-E', '-bar', 'file.c']),
+ (0, '1 bar bar', ''))
+
+ def test_multiple_definitions(self):
+@@ -267,7 +267,7 @@ class TestFakeCompiler(unittest.TestCase):
+ 'C': 3,
+ })
+
+- self.assertEquals(compiler, {
++ self.assertEqual(compiler, {
+ None: {
+ 'A': 1,
+ 'B': 2,
+@@ -282,7 +282,7 @@ class TestFakeCompiler(unittest.TestCase):
+ 'C': 3,
+ })
+
+- self.assertEquals(compiler, {
++ self.assertEqual(compiler, {
+ None: {
+ 'A': 1,
+ 'B': 4,
+@@ -302,7 +302,7 @@ class TestFakeCompiler(unittest.TestCase):
+ },
+ })
+
+- self.assertEquals(compiler, {
++ self.assertEqual(compiler, {
+ None: {
+ 'A': 1,
+ 'B': 4,
+@@ -330,7 +330,7 @@ class TestFakeCompiler(unittest.TestCase):
+ },
+ })
+
+- self.assertEquals(compiler, {
++ self.assertEqual(compiler, {
+ None: {
+ 'A': 1,
+ 'B': 2,
+@@ -370,7 +370,7 @@ class CompilerResult(ReadOnlyNamespace):
+ def __add__(self, other):
+ assert isinstance(other, dict)
+ result = copy.deepcopy(self.__dict__)
+- for k, v in other.iteritems():
++ for k, v in other.items():
+ if k == 'flags':
+ result.setdefault(k, []).extend(v)
+ else:
+@@ -381,7 +381,7 @@ class CompilerResult(ReadOnlyNamespace):
+ class TestCompilerResult(unittest.TestCase):
+ def test_compiler_result(self):
+ result = CompilerResult()
+- self.assertEquals(result.__dict__, {
++ self.assertEqual(result.__dict__, {
+ 'wrapper': [],
+ 'compiler': mozpath.abspath(''),
+ 'version': '',
+@@ -397,7 +397,7 @@ class TestCompilerResult(unittest.TestCase):
+ language='C',
+ flags=['-std=gnu99'],
+ )
+- self.assertEquals(result.__dict__, {
++ self.assertEqual(result.__dict__, {
+ 'wrapper': [],
+ 'compiler': mozpath.abspath('/usr/bin/gcc'),
+ 'version': '4.2.1',
+@@ -407,7 +407,7 @@ class TestCompilerResult(unittest.TestCase):
+ })
+
+ result2 = result + {'flags': ['-m32']}
+- self.assertEquals(result2.__dict__, {
++ self.assertEqual(result2.__dict__, {
+ 'wrapper': [],
+ 'compiler': mozpath.abspath('/usr/bin/gcc'),
+ 'version': '4.2.1',
+@@ -416,14 +416,14 @@ class TestCompilerResult(unittest.TestCase):
+ 'flags': ['-std=gnu99', '-m32'],
+ })
+ # Original flags are untouched.
+- self.assertEquals(result.flags, ['-std=gnu99'])
++ self.assertEqual(result.flags, ['-std=gnu99'])
+
+ result3 = result + {
+ 'compiler': '/usr/bin/gcc-4.7',
+ 'version': '4.7.3',
+ 'flags': ['-m32'],
+ }
+- self.assertEquals(result3.__dict__, {
++ self.assertEqual(result3.__dict__, {
+ 'wrapper': [],
+ 'compiler': mozpath.abspath('/usr/bin/gcc-4.7'),
+ 'version': '4.7.3',
+diff --git a/python/mozbuild/mozbuild/test/configure/test_toolkit_moz_configure.py b/python/mozbuild/mozbuild/test/configure/test_toolkit_moz_configure.py
+index ac35d745f..cdd8ece1b 100644
+--- a/python/mozbuild/mozbuild/test/configure/test_toolkit_moz_configure.py
++++ b/python/mozbuild/mozbuild/test/configure/test_toolkit_moz_configure.py
+@@ -2,7 +2,7 @@
+ # License, v. 2.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 absolute_import, print_function, unicode_literals
++
+
+ import os
+
+diff --git a/python/mozbuild/mozbuild/test/configure/test_util.py b/python/mozbuild/mozbuild/test/configure/test_util.py
+index 9f9575fd0..c2db1a628 100644
+--- a/python/mozbuild/mozbuild/test/configure/test_util.py
++++ b/python/mozbuild/mozbuild/test/configure/test_util.py
+@@ -2,7 +2,7 @@
+ # License, v. 2.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 absolute_import, print_function, unicode_literals
++
+
+ import logging
+ import os
+@@ -11,7 +11,7 @@ import textwrap
+ import unittest
+ import sys
+
+-from StringIO import StringIO
++from io import StringIO
+
+ from mozunit import main
+ from mozpack import path as mozpath
+@@ -434,11 +434,11 @@ class TestLogSubprocessOutput(unittest.TestCase):
+ except SystemExit as e:
+ status = e.code
+
+- self.assertEquals(status, 0)
++ self.assertEqual(status, 0)
+ quote_char = "'"
+ if getpreferredencoding().lower() == 'utf-8':
+ quote_char = '\u00B4'.encode('utf-8')
+- self.assertEquals(out.getvalue().strip(), quote_char)
++ self.assertEqual(out.getvalue().strip(), quote_char)
+
+
+ class TestVersion(unittest.TestCase):
+diff --git a/python/mozbuild/mozbuild/testing.py b/python/mozbuild/mozbuild/testing.py
+index 3229c3f77..82d250fab 100644
+--- a/python/mozbuild/mozbuild/testing.py
++++ b/python/mozbuild/mozbuild/testing.py
+@@ -2,9 +2,9 @@
+ # License, v. 2.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 absolute_import, unicode_literals
+
+-import cPickle as pickle
++
++import pickle as pickle
+ import os
+ import sys
+
+@@ -70,7 +70,7 @@ REFTEST_FLAVORS = ('crashtest', 'reftest')
+ WEB_PLATFORM_TESTS_FLAVORS = ('web-platform-tests',)
+
+ def all_test_flavors():
+- return ([v[0] for v in TEST_MANIFESTS.values()] +
++ return ([v[0] for v in list(TEST_MANIFESTS.values())] +
+ list(REFTEST_FLAVORS) +
+ list(WEB_PLATFORM_TESTS_FLAVORS))
+
+@@ -210,7 +210,7 @@ def install_test_files(topsrcdir, topobjdir, tests_root, test_objs):
+ only a few tests need to be run.
+ """
+ flavor_info = {flavor: (root, prefix, install)
+- for (flavor, root, prefix, install) in TEST_MANIFESTS.values()}
++ for (flavor, root, prefix, install) in list(TEST_MANIFESTS.values())}
+ objdir_dest = mozpath.join(topobjdir, tests_root)
+
+ converter = SupportFilesConverter()
+@@ -292,7 +292,7 @@ def read_wpt_manifest(context, paths):
+ paths_file = os.path.join(context.config.topsrcdir, "testing",
+ "web-platform", "tests", "tools", "localpaths.py")
+ _globals = {"__file__": paths_file}
+- execfile(paths_file, _globals)
++ exec(compile(open(paths_file, "rb").read(), paths_file, 'exec'), _globals)
+ import manifest as wptmanifest
+ finally:
+ sys.path = old_path
+diff --git a/python/mozbuild/mozbuild/util.py b/python/mozbuild/mozbuild/util.py
+index 4ea227dc0..79cb15713 100644
+--- a/python/mozbuild/mozbuild/util.py
++++ b/python/mozbuild/mozbuild/util.py
+@@ -5,7 +5,7 @@
+ # This file contains miscellaneous utility functions that don't belong anywhere
+ # in particular.
+
+-from __future__ import absolute_import, unicode_literals, print_function
++
+
+ import argparse
+ import collections
+@@ -21,6 +21,9 @@ import stat
+ import sys
+ import time
+ import types
++import pprint
++import six
++import subprocess
+
+ from collections import (
+ defaultdict,
+@@ -36,7 +39,7 @@ from io import (
+ if sys.version_info[0] == 3:
+ str_type = str
+ else:
+- str_type = basestring
++ str_type = str
+
+ if sys.platform == 'win32':
+ _kernel32 = ctypes.windll.kernel32
+@@ -78,7 +81,7 @@ def hash_file(path, hasher=None):
+ return h.hexdigest()
+
+
+-class EmptyValue(unicode):
++class EmptyValue(str):
+ """A dummy type that behaves like an empty string and sequence.
+
+ This type exists in order to support
+@@ -92,7 +95,7 @@ class EmptyValue(unicode):
+ class ReadOnlyNamespace(object):
+ """A class for objects with immutable attributes set at initialization."""
+ def __init__(self, **kwargs):
+- for k, v in kwargs.iteritems():
++ for k, v in kwargs.items():
+ super(ReadOnlyNamespace, self).__setattr__(k, v)
+
+ def __delattr__(self, key):
+@@ -224,7 +227,7 @@ class FileAvoidWrite(BytesIO):
+ self.mode = mode
+
+ def write(self, buf):
+- if isinstance(buf, unicode):
++ if isinstance(buf, str):
+ buf = buf.encode('utf-8')
+ BytesIO.write(self, buf)
+
+@@ -267,6 +270,10 @@ class FileAvoidWrite(BytesIO):
+ if 'b' in self.mode:
+ writemode += 'b'
+ with open(self.name, writemode) as file:
++ if 'b' in self.mode and isinstance(buf, str):
++ buf = buf.encode('utf-8')
++ elif 'b' not in self.mode and isinstance(buf, bytes):
++ buf = buf.decode('utf-8')
+ file.write(buf)
+
+ if self._capture_diff:
+@@ -381,7 +388,7 @@ class ListMixin(object):
+ def __add__(self, other):
+ # Allow None and EmptyValue is a special case because it makes undefined
+ # variable references in moz.build behave better.
+- other = [] if isinstance(other, (types.NoneType, EmptyValue)) else other
++ other = [] if isinstance(other, (type(None), EmptyValue)) else other
+ if not isinstance(other, list):
+ raise ValueError('Only lists can be appended to lists.')
+
+@@ -390,7 +397,7 @@ class ListMixin(object):
+ return new_list
+
+ def __iadd__(self, other):
+- other = [] if isinstance(other, (types.NoneType, EmptyValue)) else other
++ other = [] if isinstance(other, (type(None), EmptyValue)) else other
+ if not isinstance(other, list):
+ raise ValueError('Only lists can be appended to lists.')
+
+@@ -561,14 +568,14 @@ def FlagsFactory(flags):
+ functions below.
+ """
+ assert isinstance(flags, dict)
+- assert all(isinstance(v, type) for v in flags.values())
++ assert all(isinstance(v, type) for v in list(flags.values()))
+
+ class Flags(object):
+- __slots__ = flags.keys()
++ __slots__ = list(flags.keys())
+ _flags = flags
+
+ def update(self, **kwargs):
+- for k, v in kwargs.iteritems():
++ for k, v in kwargs.items():
+ setattr(self, k, v)
+
+ def __getattr__(self, name):
+@@ -1006,8 +1013,6 @@ def TypedNamedTuple(name, fields):
+ 'got %s, expected %s' % (fname,
+ type(value), ftype))
+
+- super(TypedTuple, self).__init__(*args, **kwargs)
+-
+ TypedTuple._fields = fields
+
+ return TypedTuple
+@@ -1099,14 +1104,14 @@ def group_unified_files(files, unified_prefix, unified_suffix,
+ # issue. So we do a little dance to filter it out ourselves.
+ dummy_fill_value = ("dummy",)
+ def filter_out_dummy(iterable):
+- return itertools.ifilter(lambda x: x != dummy_fill_value,
++ return filter(lambda x: x != dummy_fill_value,
+ iterable)
+
+ # From the itertools documentation, slightly modified:
+ def grouper(n, iterable):
+ "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
+ args = [iter(iterable)] * n
+- return itertools.izip_longest(fillvalue=dummy_fill_value, *args)
++ return itertools.zip_longest(fillvalue=dummy_fill_value, *args)
+
+ for i, unified_group in enumerate(grouper(files_per_unified_file,
+ files)):
+@@ -1123,7 +1128,7 @@ def pair(iterable):
+ [(1,2), (3,4), (5,6)]
+ '''
+ i = iter(iterable)
+- return itertools.izip_longest(i, i)
++ return itertools.zip_longest(i, i)
+
+
+ VARIABLES_RE = re.compile('\$\((\w+)\)')
+@@ -1141,7 +1146,7 @@ def expand_variables(s, variables):
+ value = variables.get(name)
+ if not value:
+ continue
+- if not isinstance(value, types.StringTypes):
++ if not isinstance(value, (str,)):
+ value = ' '.join(value)
+ result += value
+ return result
+@@ -1168,7 +1173,7 @@ class EnumStringComparisonError(Exception):
+ pass
+
+
+-class EnumString(unicode):
++class EnumString(str):
+ '''A string type that only can have a limited set of values, similarly to
+ an Enum, and can only be compared against that set of values.
+
+@@ -1185,8 +1190,8 @@ class EnumString(unicode):
+ def __eq__(self, other):
+ if other not in self.POSSIBLE_VALUES:
+ raise EnumStringComparisonError(
+- 'Can only compare with %s'
+- % ', '.join("'%s'" % v for v in self.POSSIBLE_VALUES))
++ '%s is not in %s'
++ % (other, ', '.join("'%s'" % v for v in self.POSSIBLE_VALUES)))
+ return super(EnumString, self).__eq__(other)
+
+ def __ne__(self, other):
+@@ -1204,14 +1209,14 @@ def _escape_char(c):
+ # quoting could be done with either ' or ".
+ if c == "'":
+ return "\\'"
+- return unicode(c.encode('unicode_escape'))
++ return str(c.encode('unicode_escape'))
+
+ # Mapping table between raw characters below \x80 and their escaped
+ # counterpart, when they differ
+ _INDENTED_REPR_TABLE = {
+ c: e
+ for c, e in map(lambda x: (x, _escape_char(x)),
+- map(unichr, range(128)))
++ map(chr, range(128)))
+ if c != e
+ }
+ # Regexp matching all characters to escape.
+@@ -1219,7 +1224,33 @@ _INDENTED_REPR_RE = re.compile(
+ '([' + ''.join(_INDENTED_REPR_TABLE.values()) + ']+)')
+
+
++# Stolen from gecko master [1]
++# [1] https://github.com/mozilla/gecko-dev/blob/4165a2e843c494bfb3e35d8a1fbf9c61209e3675/python/mozbuild/mozbuild/util.py#L1286
++
++# The default PrettyPrinter has some issues with UTF-8, so we need to override
++# some stuff here.
++class _PrettyPrinter(pprint.PrettyPrinter):
++ def format(self, object, context, maxlevels, level):
++ if not (isinstance(object, six.text_type) or
++ isinstance(object, six.binary_type)):
++ return super(_PrettyPrinter, self).format(
++ object, context, maxlevels, level)
++ # This is super hacky and weird, but the output of 'repr' actually
++ # varies based on the default I/O encoding of the process, which isn't
++ # necessarily utf-8. Instead we open a new shell and ask what the repr
++ # WOULD be assuming the default encoding is utf-8. If you can come up
++ # with a better way of doing this without simply re-implementing the
++ # logic of "repr", please replace this.
++ env = dict(os.environ)
++ env['PYTHONIOENCODING'] = 'utf-8'
++ ret = six.ensure_text(subprocess.check_output(
++ [sys.executable], input='print(repr(%s))' % repr(object),
++ universal_newlines=True, env=env, encoding='utf-8')).strip()
++ return (ret, True, False)
++
+ def indented_repr(o, indent=4):
++ return _PrettyPrinter(indent=indent).pformat(o)
++
+ '''Similar to repr(), but returns an indented representation of the object
+
+ One notable difference with repr is that the returned representation
+@@ -1242,7 +1273,7 @@ def indented_repr(o, indent=4):
+ elif isinstance(o, bytes):
+ yield 'b'
+ yield repr(o)
+- elif isinstance(o, unicode):
++ elif isinstance(o, str):
+ yield "'"
+ # We want a readable string (non escaped unicode), but some
+ # special characters need escaping (e.g. \n, \t, etc.)
+@@ -1272,11 +1303,11 @@ def encode(obj, encoding='utf-8'):
+ if isinstance(obj, dict):
+ return {
+ encode(k, encoding): encode(v, encoding)
+- for k, v in obj.iteritems()
++ for k, v in obj.items()
+ }
+ if isinstance(obj, bytes):
+ return obj
+- if isinstance(obj, unicode):
++ if isinstance(obj, str):
+ return obj.encode(encoding)
+ if isinstance(obj, Iterable):
+ return [encode(i, encoding) for i in obj]
+diff --git a/python/mozbuild/mozbuild/virtualenv.py b/python/mozbuild/mozbuild/virtualenv.py
+index 38d06d71d..c67c046f3 100644
+--- a/python/mozbuild/mozbuild/virtualenv.py
++++ b/python/mozbuild/mozbuild/virtualenv.py
+@@ -531,9 +531,9 @@ def verify_python_version(log_handle):
+
+ our = LooseVersion('%d.%d.%d' % (major, minor, micro))
+
+- if major != MINIMUM_PYTHON_MAJOR or our < MINIMUM_PYTHON_VERSION:
+- log_handle.write('Python %s or greater (but not Python 3) is '
+- 'required to build. ' % MINIMUM_PYTHON_VERSION)
++ if our < MINIMUM_PYTHON_VERSION:
++ log_handle.write('Python %s or greater is required to build. '
++ % MINIMUM_PYTHON_VERSION)
+ log_handle.write('You are running Python %s.\n' % our)
+
+ if os.name in ('nt', 'ce'):
+diff --git a/python/mozbuild/mozpack/chrome/manifest.py b/python/mozbuild/mozpack/chrome/manifest.py
+index c91b99cf1..02eac0dbb 100644
+--- a/python/mozbuild/mozpack/chrome/manifest.py
++++ b/python/mozbuild/mozpack/chrome/manifest.py
+@@ -2,11 +2,11 @@
+ # License, v. 2.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 absolute_import
++
+
+ import re
+ import os
+-from urlparse import urlparse
++from urllib.parse import urlparse
+ import mozpack.path as mozpath
+ from mozpack.chrome.flags import Flags
+ from mozpack.errors import errors
+@@ -316,7 +316,7 @@ class ManifestContract(ManifestEntry):
+ return self.serialize(self.contractID, self.cid)
+
+ # All manifest classes by their type name.
+-MANIFESTS_TYPES = dict([(c.type, c) for c in globals().values()
++MANIFESTS_TYPES = dict([(c.type, c) for c in list(globals().values())
+ if type(c) == type and issubclass(c, ManifestEntry)
+ and hasattr(c, 'type') and c.type])
+
+diff --git a/python/mozbuild/mozpack/copier.py b/python/mozbuild/mozpack/copier.py
+index 1e521e52b..43ed9be4a 100644
+--- a/python/mozbuild/mozpack/copier.py
++++ b/python/mozbuild/mozpack/copier.py
+@@ -2,7 +2,7 @@
+ # License, v. 2.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 absolute_import
++
+
+ import os
+ import stat
+@@ -113,7 +113,7 @@ class FileRegistry(object):
+ '''
+ Return all paths stored in the container, in the order they were added.
+ '''
+- return self._files.keys()
++ return list(self._files.keys())
+
+ def __len__(self):
+ '''
+@@ -146,7 +146,7 @@ class FileRegistry(object):
+ for path, file in registry:
+ (...)
+ '''
+- return self._files.iteritems()
++ return iter(self._files.items())
+
+ def required_directories(self):
+ '''
+@@ -155,7 +155,7 @@ class FileRegistry(object):
+ unspecified (virtual) root directory (and do not include said root
+ directory).
+ '''
+- return set(k for k, v in self._required_directories.items() if v > 0)
++ return set(k for k, v in list(self._required_directories.items()) if v > 0)
+
+ def output_to_inputs_tree(self):
+ '''
+@@ -295,7 +295,7 @@ class FileCopier(FileRegistry):
+
+ Returns a FileCopyResult that details what changed.
+ '''
+- assert isinstance(destination, basestring)
++ assert isinstance(destination, str)
+ assert not os.path.exists(destination) or os.path.isdir(destination)
+
+ result = FileCopyResult()
+@@ -563,7 +563,7 @@ class Jarrer(FileRegistry, BaseFile):
+ def exists(self):
+ return self.deflater is not None
+
+- if isinstance(dest, basestring):
++ if isinstance(dest, str):
+ dest = Dest(dest)
+ assert isinstance(dest, Dest)
+
+diff --git a/python/mozbuild/mozpack/files.py b/python/mozbuild/mozpack/files.py
+index 8ce353375..bf35e39b8 100644
+--- a/python/mozbuild/mozpack/files.py
++++ b/python/mozbuild/mozpack/files.py
+@@ -2,7 +2,7 @@
+ # License, v. 2.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 absolute_import
++
+
+ import errno
+ import os
+@@ -57,7 +57,7 @@ else:
+
+ def _copyfile(src, dest):
+ # False indicates `dest` should be overwritten if it exists already.
+- if isinstance(src, unicode) and isinstance(dest, unicode):
++ if isinstance(src, str) and isinstance(dest, str):
+ _CopyFileW(src, dest, False)
+ elif isinstance(src, str) and isinstance(dest, str):
+ _CopyFileA(src, dest, False)
+@@ -164,7 +164,7 @@ class BaseFile(object):
+ disabled when skip_if_older is False.
+ Returns whether a copy was actually performed (True) or not (False).
+ '''
+- if isinstance(dest, basestring):
++ if isinstance(dest, str):
+ dest = Dest(dest)
+ else:
+ assert isinstance(dest, Dest)
+@@ -278,11 +278,11 @@ class ExecutableFile(File):
+ '''
+ def copy(self, dest, skip_if_older=True):
+ real_dest = dest
+- if not isinstance(dest, basestring):
++ if not isinstance(dest, str):
+ fd, dest = mkstemp()
+ os.close(fd)
+ os.remove(dest)
+- assert isinstance(dest, basestring)
++ assert isinstance(dest, str)
+ # If File.copy didn't actually copy because dest is newer, check the
+ # file sizes. If dest is smaller, it means it is already stripped and
+ # elfhacked, so we can skip.
+@@ -319,7 +319,7 @@ class AbsoluteSymlinkFile(File):
+ File.__init__(self, path)
+
+ def copy(self, dest, skip_if_older=True):
+- assert isinstance(dest, basestring)
++ assert isinstance(dest, str)
+
+ # The logic in this function is complicated by the fact that symlinks
+ # aren't universally supported. So, where symlinks aren't supported, we
+@@ -410,7 +410,7 @@ class HardlinkFile(File):
+ '''
+
+ def copy(self, dest, skip_if_older=True):
+- assert isinstance(dest, basestring)
++ assert isinstance(dest, str)
+
+ if not hasattr(os, 'link'):
+ return super(HardlinkFile, self).copy(
+@@ -471,7 +471,7 @@ class ExistingFile(BaseFile):
+ self.required = required
+
+ def copy(self, dest, skip_if_older=True):
+- if isinstance(dest, basestring):
++ if isinstance(dest, str):
+ dest = Dest(dest)
+ else:
+ assert isinstance(dest, Dest)
+@@ -517,7 +517,7 @@ class PreprocessedFile(BaseFile):
+ '''
+ Invokes the preprocessor to create the destination file.
+ '''
+- if isinstance(dest, basestring):
++ if isinstance(dest, str):
+ dest = Dest(dest)
+ else:
+ assert isinstance(dest, Dest)
+@@ -657,7 +657,7 @@ class XPTFile(GeneratedFile):
+ the individual XPTs to link.
+ skip_if_older is ignored.
+ '''
+- if isinstance(dest, basestring):
++ if isinstance(dest, str):
+ dest = Dest(dest)
+ assert isinstance(dest, Dest)
+
+@@ -1108,7 +1108,7 @@ class ComposedFinder(BaseFinder):
+ from mozpack.copier import FileRegistry
+ self.files = FileRegistry()
+
+- for base, finder in sorted(finders.iteritems()):
++ for base, finder in sorted(finders.items()):
+ if self.files.contains(base):
+ self.files.remove(base)
+ for p, f in finder.find(''):
+diff --git a/python/mozbuild/mozpack/manifests.py b/python/mozbuild/mozpack/manifests.py
+index 27c66634b..f79b40086 100644
+--- a/python/mozbuild/mozpack/manifests.py
++++ b/python/mozbuild/mozpack/manifests.py
+@@ -2,8 +2,6 @@
+ # License, v. 2.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 absolute_import, unicode_literals
+-
+ from contextlib import contextmanager
+ import json
+
+@@ -116,7 +114,7 @@ class InstallManifest(object):
+ self._source_files = set()
+
+ if path or fileobj:
+- with _auto_fileobj(path, fileobj, 'rb') as fh:
++ with _auto_fileobj(path, fileobj, 'r') as fh:
+ self._source_files.add(fh.name)
+ self._load_from_fileobj(fh)
+
+@@ -175,7 +173,7 @@ class InstallManifest(object):
+ dest, content = fields[1:]
+
+ self.add_content(
+- self._decode_field_entry(content).encode('utf-8'), dest)
++ self._decode_field_entry(content), dest)
+ continue
+
+ # Don't fail for non-actionable items, allowing
+@@ -228,7 +226,7 @@ class InstallManifest(object):
+
+ It is an error if both are specified.
+ """
+- with _auto_fileobj(path, fileobj, 'wb') as fh:
++ with _auto_fileobj(path, fileobj, 'w') as fh:
+ fh.write('%d\n' % self.CURRENT_VERSION)
+
+ for dest in sorted(self._dests):
+@@ -242,13 +240,11 @@ class InstallManifest(object):
+ for path in paths:
+ source = mozpath.join(base, path)
+ parts = ['%d' % type, mozpath.join(dest, path), source]
+- fh.write('%s\n' % self.FIELD_SEPARATOR.join(
+- p.encode('utf-8') for p in parts))
++ fh.write('%s\n' % self.FIELD_SEPARATOR.join(parts))
+ else:
+ parts = ['%d' % entry[0], dest]
+ parts.extend(entry[1:])
+- fh.write('%s\n' % self.FIELD_SEPARATOR.join(
+- p.encode('utf-8') for p in parts))
++ fh.write('%s\n' % self.FIELD_SEPARATOR.join(parts))
+
+ def add_link(self, source, dest):
+ """Add a link to this manifest.
+@@ -439,7 +435,7 @@ class InstallManifest(object):
+ if install_type == self.CONTENT:
+ # GeneratedFile expect the buffer interface, which the unicode
+ # type doesn't have, so encode to a str.
+- content = self._decode_field_entry(entry[1]).encode('utf-8')
++ content = self._decode_field_entry(entry[1])
+ registry.add(dest, GeneratedFile(content))
+ continue
+
+diff --git a/python/mozbuild/mozpack/mozjar.py b/python/mozbuild/mozpack/mozjar.py
+index a723fd2c0..0b04d233c 100644
+--- a/python/mozbuild/mozpack/mozjar.py
++++ b/python/mozbuild/mozpack/mozjar.py
+@@ -2,7 +2,7 @@
+ # License, v. 2.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 absolute_import
++
+
+ from io import BytesIO
+ import struct
+@@ -14,9 +14,10 @@ from zipfile import (
+ ZIP_DEFLATED,
+ )
+ from collections import OrderedDict
+-from urlparse import urlparse, ParseResult
++from urllib.parse import urlparse, ParseResult
+ import mozpack.path as mozpath
+ from mozbuild.util import memoize
++from functools import reduce
+
+
+ JAR_STORED = ZIP_STORED
+@@ -72,7 +73,7 @@ class JarStruct(object):
+ an instance with empty fields.
+ '''
+ assert self.MAGIC and isinstance(self.STRUCT, OrderedDict)
+- self.size_fields = set(t for t in self.STRUCT.itervalues()
++ self.size_fields = set(t for t in self.STRUCT.values()
+ if not t in JarStruct.TYPE_MAPPING)
+ self._values = {}
+ if data:
+@@ -94,7 +95,7 @@ class JarStruct(object):
+ # For all fields used as other fields sizes, keep track of their value
+ # separately.
+ sizes = dict((t, 0) for t in self.size_fields)
+- for name, t in self.STRUCT.iteritems():
++ for name, t in self.STRUCT.items():
+ if t in JarStruct.TYPE_MAPPING:
+ value, size = JarStruct.get_data(t, data[offset:])
+ else:
+@@ -113,7 +114,7 @@ class JarStruct(object):
+ Initialize an instance with empty fields.
+ '''
+ self.signature = self.MAGIC
+- for name, t in self.STRUCT.iteritems():
++ for name, t in self.STRUCT.items():
+ if name in self.size_fields:
+ continue
+ self._values[name] = 0 if t in JarStruct.TYPE_MAPPING else ''
+@@ -138,9 +139,9 @@ class JarStruct(object):
+ from self.STRUCT.
+ '''
+ serialized = struct.pack('<I', self.signature)
+- sizes = dict((t, name) for name, t in self.STRUCT.iteritems()
++ sizes = dict((t, name) for name, t in self.STRUCT.items()
+ if not t in JarStruct.TYPE_MAPPING)
+- for name, t in self.STRUCT.iteritems():
++ for name, t in self.STRUCT.items():
+ if t in JarStruct.TYPE_MAPPING:
+ format, size = JarStruct.TYPE_MAPPING[t]
+ if name in sizes:
+@@ -159,7 +160,7 @@ class JarStruct(object):
+ variable length fields.
+ '''
+ size = JarStruct.TYPE_MAPPING['uint32'][1]
+- for name, type in self.STRUCT.iteritems():
++ for name, type in self.STRUCT.items():
+ if type in JarStruct.TYPE_MAPPING:
+ size += JarStruct.TYPE_MAPPING[type][1]
+ else:
+@@ -180,7 +181,7 @@ class JarStruct(object):
+ return key in self._values
+
+ def __iter__(self):
+- return self._values.iteritems()
++ return iter(self._values.items())
+
+ def __repr__(self):
+ return "<%s %s>" % (self.__class__.__name__,
+@@ -374,7 +375,7 @@ class JarReader(object):
+ entries = self.entries
+ if not entries:
+ return JAR_STORED
+- return max(f['compression'] for f in entries.itervalues())
++ return max(f['compression'] for f in entries.values())
+
+ @property
+ def entries(self):
+@@ -390,7 +391,7 @@ class JarReader(object):
+ preload = JarStruct.get_data('uint32', self._data)[0]
+ entries = OrderedDict()
+ offset = self._cdir_end['cdir_offset']
+- for e in xrange(self._cdir_end['cdir_entries']):
++ for e in range(self._cdir_end['cdir_entries']):
+ entry = JarCdirEntry(self._data[offset:])
+ offset += entry.size
+ # Creator host system. 0 is MSDOS, 3 is Unix
+@@ -452,7 +453,7 @@ class JarReader(object):
+ for file in jarReader:
+ ...
+ '''
+- for entry in self.entries.itervalues():
++ for entry in self.entries.values():
+ yield self._getreader(entry)
+
+ def __getitem__(self, name):
+@@ -547,7 +548,7 @@ class JarWriter(object):
+ headers = {}
+ preload_size = 0
+ # Prepare central directory entries
+- for entry, content in self._contents.itervalues():
++ for entry, content in self._contents.values():
+ header = JarLocalFileHeader()
+ for name in entry.STRUCT:
+ if name in header:
+@@ -562,7 +563,7 @@ class JarWriter(object):
+ end['disk_entries'] = len(self._contents)
+ end['cdir_entries'] = end['disk_entries']
+ end['cdir_size'] = reduce(lambda x, y: x + y[0].size,
+- self._contents.values(), 0)
++ list(self._contents.values()), 0)
+ # On optimized archives, store the preloaded size and the central
+ # directory entries, followed by the first end of central directory.
+ if self._optimize:
+@@ -571,18 +572,18 @@ class JarWriter(object):
+ if preload_size:
+ preload_size += offset
+ self._data.write(struct.pack('<I', preload_size))
+- for entry, _ in self._contents.itervalues():
++ for entry, _ in self._contents.values():
+ entry['offset'] += offset
+ self._data.write(entry.serialize())
+ self._data.write(end.serialize())
+ # Store local file entries followed by compressed data
+- for entry, content in self._contents.itervalues():
++ for entry, content in self._contents.values():
+ self._data.write(headers[entry].serialize())
+ self._data.write(content)
+ # On non optimized archives, store the central directory entries.
+ if not self._optimize:
+ end['cdir_offset'] = offset
+- for entry, _ in self._contents.itervalues():
++ for entry, _ in self._contents.values():
+ self._data.write(entry.serialize())
+ # Store the end of central directory.
+ self._data.write(end.serialize())
+@@ -622,7 +623,7 @@ class JarWriter(object):
+ deflater = data
+ else:
+ deflater = Deflater(compress, compress_level=self._compress_level)
+- if isinstance(data, basestring):
++ if isinstance(data, str):
+ deflater.write(data)
+ elif hasattr(data, 'read'):
+ if hasattr(data, 'seek'):
+diff --git a/testing/mozbase/manifestparser/manifestparser/ini.py b/testing/mozbase/manifestparser/manifestparser/ini.py
+index e5ba249c1..c141a18b7 100644
+--- a/testing/mozbase/manifestparser/manifestparser/ini.py
++++ b/testing/mozbase/manifestparser/manifestparser/ini.py
+@@ -2,7 +2,7 @@
+ # License, v. 2.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 absolute_import
++
+
+ import os
+ import sys
+@@ -12,7 +12,7 @@ __all__ = ['read_ini', 'combine_fields']
+
+ class IniParseError(Exception):
+ def __init__(self, fp, linenum, msg):
+- if isinstance(fp, basestring):
++ if isinstance(fp, str):
+ path = fp
+ elif hasattr(fp, 'name'):
+ path = fp.name
+@@ -43,12 +43,15 @@ def read_ini(fp, variables=None, default='DEFAULT', defaults_only=False,
+ sections = []
+ key = value = None
+ section_names = set()
+- if isinstance(fp, basestring):
++ if isinstance(fp, str):
+ fp = file(fp)
+
+ # read the lines
+ for (linenum, line) in enumerate(fp.read().splitlines(), start=1):
+
++ if isinstance(line, bytes):
++ line = line.decode('utf-8')
++
+ stripped = line.strip()
+
+ # ignore blank lines
+@@ -66,7 +69,7 @@ def read_ini(fp, variables=None, default='DEFAULT', defaults_only=False,
+ inline_prefixes = {p: -1 for p in comments}
+ while comment_start == sys.maxsize and inline_prefixes:
+ next_prefixes = {}
+- for prefix, index in inline_prefixes.items():
++ for prefix, index in list(inline_prefixes.items()):
+ index = line.find(prefix, index+1)
+ if index == -1:
+ continue
+@@ -163,7 +166,7 @@ def combine_fields(global_vars, local_vars):
+ 'support-files': '%s %s',
+ }
+ final_mapping = global_vars.copy()
+- for field_name, value in local_vars.items():
++ for field_name, value in list(local_vars.items()):
+ if field_name not in field_patterns or field_name not in global_vars:
+ final_mapping[field_name] = value
+ continue
+diff --git a/testing/mozbase/manifestparser/manifestparser/manifestparser.py b/testing/mozbase/manifestparser/manifestparser/manifestparser.py
+index 921369fd2..5b2f4c453 100755
+--- a/testing/mozbase/manifestparser/manifestparser/manifestparser.py
++++ b/testing/mozbase/manifestparser/manifestparser/manifestparser.py
+@@ -2,9 +2,9 @@
+ # License, v. 2.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 absolute_import, print_function
+
+-from StringIO import StringIO
++
++from io import StringIO
+ import json
+ import fnmatch
+ import os
+@@ -23,7 +23,7 @@ from .filters import (
+ __all__ = ['ManifestParser', 'TestManifest', 'convert']
+
+ relpath = os.path.relpath
+-string = (basestring,)
++string = (str,)
+
+
+ # path normalization
+@@ -195,7 +195,7 @@ class ManifestParser(object):
+
+ # otherwise an item
+ # apply ancestor defaults, while maintaining current file priority
+- data = dict(self._ancestor_defaults.items() + data.items())
++ data = dict(list(self._ancestor_defaults.items()) + list(data.items()))
+
+ test = data
+ test['name'] = section
+@@ -323,19 +323,19 @@ class ManifestParser(object):
+ # make some check functions
+ if inverse:
+ def has_tags(test):
+- return not tags.intersection(test.keys())
++ return not tags.intersection(list(test.keys()))
+
+ def dict_query(test):
+- for key, value in kwargs.items():
++ for key, value in list(kwargs.items()):
+ if test.get(key) == value:
+ return False
+ return True
+ else:
+ def has_tags(test):
+- return tags.issubset(test.keys())
++ return tags.issubset(list(test.keys()))
+
+ def dict_query(test):
+- for key, value in kwargs.items():
++ for key, value in list(kwargs.items()):
+ if test.get(key) != value:
+ return False
+ return True
+@@ -359,7 +359,7 @@ class ManifestParser(object):
+ if tests is None:
+ manifests = []
+ # Make sure to return all the manifests, even ones without tests.
+- for manifest in self.manifest_defaults.keys():
++ for manifest in list(self.manifest_defaults.keys()):
+ if isinstance(manifest, tuple):
+ parentmanifest, manifest = manifest
+ if manifest not in manifests:
+@@ -409,7 +409,7 @@ class ManifestParser(object):
+ """
+
+ files = set([])
+- if isinstance(directories, basestring):
++ if isinstance(directories, str):
+ directories = [directories]
+
+ # get files in directories
+@@ -476,7 +476,7 @@ class ManifestParser(object):
+ print('[DEFAULT]', file=fp)
+ for tag in global_tags:
+ print('%s =' % tag, file=fp)
+- for key, value in global_kwargs.items():
++ for key, value in list(global_kwargs.items()):
+ print('%s = %s' % (key, value), file=fp)
+ print(file=fp)
+
+@@ -602,7 +602,7 @@ class ManifestParser(object):
+ internal function to import directories
+ """
+
+- if isinstance(pattern, basestring):
++ if isinstance(pattern, str):
+ patterns = [pattern]
+ else:
+ patterns = pattern
+diff --git a/testing/mozbase/mozinfo/mozinfo/mozinfo.py b/testing/mozbase/mozinfo/mozinfo/mozinfo.py
+index 90c187568..6c5a1f322 100755
+--- a/testing/mozbase/mozinfo/mozinfo/mozinfo.py
++++ b/testing/mozbase/mozinfo/mozinfo/mozinfo.py
+@@ -8,7 +8,7 @@
+ # linux) to the information; I certainly wouldn't want anyone parsing this
+ # information and having behaviour depend on it
+
+-from __future__ import absolute_import, print_function
++
+
+ import os
+ import platform
+@@ -24,7 +24,7 @@ _os = os
+ class unknown(object):
+ """marker class for unknown information"""
+
+- def __nonzero__(self):
++ def __bool__(self):
+ return False
+
+ def __str__(self):
+@@ -96,20 +96,17 @@ elif system.startswith(('MINGW', 'MSYS_NT')):
+ info['os'] = 'win'
+ os_version = version = unknown
+ elif system == "Linux":
+- if hasattr(platform, "linux_distribution"):
+- (distro, os_version, codename) = platform.linux_distribution()
+- else:
+- (distro, os_version, codename) = platform.dist()
+ if not processor:
+ processor = machine
+- version = "%s %s" % (distro, os_version)
++
++ distro = 'OE/Yocto'
++ os_version = version = unknown
+
+ # Bug in Python 2's `platform` library:
+ # It will return a triple of empty strings if the distribution is not supported.
+ # It works on Python 3. If we don't have an OS version,
+ # the unit tests fail to run.
+ if not distro and not os_version and not codename:
+- distro = 'lfs'
+ version = release
+ os_version = release
+
+@@ -131,7 +128,7 @@ else:
+ os_version = version = unknown
+
+ info['version'] = version
+-info['os_version'] = StringVersion(os_version)
++info['os_version'] = version
+
+ # processor type and bits
+ if processor in ["i386", "i686"]:
+@@ -188,12 +185,7 @@ def update(new_info):
+ to a json file containing the new info.
+ """
+
+- PY3 = sys.version_info[0] == 3
+- if PY3:
+- string_types = str,
+- else:
+- string_types = basestring,
+- if isinstance(new_info, string_types):
++ if isinstance(new_info, str):
+ # lazy import
+ import mozfile
+ import json
+@@ -295,7 +287,7 @@ def main(args=None):
+
+ # print out choices if requested
+ flag = False
+- for key, value in options.__dict__.items():
++ for key, value in list(options.__dict__.items()):
+ if value is True:
+ print('%s choices: %s' % (key, ' '.join([str(choice)
+ for choice in choices[key]])))
+@@ -304,7 +296,7 @@ def main(args=None):
+ return
+
+ # otherwise, print out all info
+- for key, value in info.items():
++ for key, value in list(info.items()):
+ print('%s: %s' % (key, value))
+
+
+diff --git a/testing/mozbase/mozprocess/mozprocess/processhandler.py b/testing/mozbase/mozprocess/mozprocess/processhandler.py
+index 3efb650b7..2575a4702 100644
+--- a/testing/mozbase/mozprocess/mozprocess/processhandler.py
++++ b/testing/mozbase/mozprocess/mozprocess/processhandler.py
+@@ -2,7 +2,7 @@
+ # License, v. 2.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 absolute_import, print_function
++
+
+ import errno
+ import os
+@@ -13,7 +13,7 @@ import threading
+ import time
+ import traceback
+
+-from Queue import Queue, Empty
++from queue import Queue, Empty
+ from datetime import datetime
+
+
+@@ -124,14 +124,14 @@ class ProcessHandlerMixin(object):
+ thread = threading.current_thread().name
+ print("DBG::MOZPROC PID:{} ({}) | {}".format(self.pid, thread, msg))
+
+- def __del__(self, _maxint=sys.maxint):
++ def __del__(self, _maxint=sys.maxsize):
+ if isWin:
+ handle = getattr(self, '_handle', None)
+ if handle:
+ if hasattr(self, '_internal_poll'):
+ self._internal_poll(_deadstate=_maxint)
+ else:
+- self.poll(_deadstate=sys.maxint)
++ self.poll(_deadstate=sys.maxsize)
+ if handle or self._job or self._io_port:
+ self._cleanup()
+ else:
+@@ -243,7 +243,7 @@ class ProcessHandlerMixin(object):
+ p2cread, p2cwrite,
+ c2pread, c2pwrite,
+ errread, errwrite) = args_tuple
+- if not isinstance(args, basestring):
++ if not isinstance(args, str):
+ args = subprocess.list2cmdline(args)
+
+ # Always or in the create new process group
+diff --git a/third_party/python/which/which.py b/third_party/python/which/which.py
+index 9c7d10835..f02b2616e 100644
+--- a/third_party/python/which/which.py
++++ b/third_party/python/which/which.py
+@@ -90,13 +90,13 @@ def _getRegisteredExecutable(exeName):
+ if sys.platform.startswith('win'):
+ if os.path.splitext(exeName)[1].lower() != '.exe':
+ exeName += '.exe'
+- import _winreg
++ import winreg
+ try:
+ key = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\" +\
+ exeName
+- value = _winreg.QueryValue(_winreg.HKEY_LOCAL_MACHINE, key)
++ value = winreg.QueryValue(winreg.HKEY_LOCAL_MACHINE, key)
+ registered = (value, "from HKLM\\"+key)
+- except _winreg.error:
++ except winreg.error:
+ pass
+ if registered and not os.path.exists(registered[0]):
+ registered = None
+@@ -244,7 +244,7 @@ def which(command, path=None, verbose=0, exts=None):
+ If no match is found for the command, a WhichError is raised.
+ """
+ try:
+- match = whichgen(command, path, verbose, exts).next()
++ match = next(whichgen(command, path, verbose, exts))
+ except StopIteration:
+ raise WhichError("Could not find '%s' on the path." % command)
+ return match
+@@ -281,17 +281,17 @@ def main(argv):
+ try:
+ optlist, args = getopt.getopt(argv[1:], 'haVvqp:e:',
+ ['help', 'all', 'version', 'verbose', 'quiet', 'path=', 'exts='])
+- except getopt.GetoptError, msg:
++ except getopt.GetoptError as msg:
+ sys.stderr.write("which: error: %s. Your invocation was: %s\n"\
+ % (msg, argv))
+ sys.stderr.write("Try 'which --help'.\n")
+ return 1
+ for opt, optarg in optlist:
+ if opt in ('-h', '--help'):
+- print _cmdlnUsage
++ print(_cmdlnUsage)
+ return 0
+ elif opt in ('-V', '--version'):
+- print "which %s" % __version__
++ print("which %s" % __version__)
+ return 0
+ elif opt in ('-a', '--all'):
+ all = 1
+@@ -319,9 +319,9 @@ def main(argv):
+ nmatches = 0
+ for match in whichgen(arg, path=altpath, verbose=verbose, exts=exts):
+ if verbose:
+- print "%s (%s)" % match
++ print("%s (%s)" % match)
+ else:
+- print match
++ print(match)
+ nmatches += 1
+ if not all:
+ break
+--
+2.21.0
+
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0002-js.pc.in-do-not-include-RequiredDefines.h-for-depend.patch b/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0002-js.pc.in-do-not-include-RequiredDefines.h-for-depend.patch
new file mode 100644
index 0000000000..e3f1883a99
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0002-js.pc.in-do-not-include-RequiredDefines.h-for-depend.patch
@@ -0,0 +1,33 @@
+From 0a61b0b98c152f10404ccbdeeac583a486638a7a Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Andreas=20M=C3=BCller?= <schnitzeltony@googlemail.com>
+Date: Thu, 6 Jun 2013 18:36:01 +0200
+Subject: [PATCH] js.pc.in: do not include RequiredDefines.h for depending
+ packages
+
+in our cross environment the would fail with:
+
+| cc1: fatal error: /usr/include/js-17.0/js/RequiredDefines.h: No such file or directory
+
+and currently it only defines __STDC_LIMIT_MACROS
+Upstream-Status: Inappropriate [embedded specific]
+Signed-off-by: Andreas Müller <schnitzeltony@googlemail.com>
+
+Rebase to 52.8.1
+Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
+---
+ js/src/build/js.pc.in | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/js/src/build/js.pc.in b/js/src/build/js.pc.in
+index 2eae393..c2dea62 100644
+--- a/js/src/build/js.pc.in
++++ b/js/src/build/js.pc.in
+@@ -8,4 +8,4 @@ Description: The Mozilla library for JavaScript
+ Version: @MOZILLA_VERSION@
+ @PKGCONF_REQUIRES_PRIVATE@
+ Libs: -L${libdir} -l@JS_LIBRARY_NAME@
+-Cflags: -include ${includedir}/@JS_LIBRARY_NAME@/js/RequiredDefines.h -I${includedir}/@JS_LIBRARY_NAME@
++Cflags: -I${includedir}/@JS_LIBRARY_NAME@
+--
+2.7.4
+
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0003-fix-cross-compilation-on-i586-targets.patch b/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0003-fix-cross-compilation-on-i586-targets.patch
new file mode 100644
index 0000000000..e0929a8a8f
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0003-fix-cross-compilation-on-i586-targets.patch
@@ -0,0 +1,38 @@
+From a452138a1dd274bfad381a701729783360dc86fb Mon Sep 17 00:00:00 2001
+From: Maciej Borzecki <maciej.borzecki@open-rnd.pl>
+Date: Tue, 5 Jan 2016 22:04:17 +0100
+Subject: [PATCH] fix cross compilation on i586 targets
+
+Remove offending -Wl,-rpath-link that may cause host libraries to be picked
+during linking. The patch applies a fix to configure.in. So as not to
+regenerate configure, similar fix is applied there.
+
+Upstream-Status: Inappropriate [embedded specific]
+
+Signed-off-by: Maciej Borzecki <maciej.borzecki@open-rnd.pl>
+
+Rebase to 52.8.1
+Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
+
+Rebase to 60.9.0 (firefox-esr sources)
+Signed-off-by: Andreas Müller <schnitzeltony@gmail.com>
+---
+ js/src/old-configure.in | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/js/src/old-configure.in b/js/src/old-configure.in
+index 3d53ee1..11c3d5a 100644
+--- a/js/src/old-configure.in
++++ b/js/src/old-configure.in
+@@ -405,7 +405,7 @@ AS='$(CC)'
+ AS_DASH_C_FLAG='-c'
+ MOZ_USER_DIR=".mozilla"
+
+-MOZ_FIX_LINK_PATHS="-Wl,-rpath-link,${DIST}/bin -Wl,-rpath-link,${prefix}/lib"
++MOZ_FIX_LINK_PATHS="-Wl,-rpath-link,${DIST}/bin"
+
+ dnl Configure platform-specific CPU architecture compiler options.
+ dnl ==============================================================
+--
+2.21.0
+
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0004-do-not-create-python-environment.patch b/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0004-do-not-create-python-environment.patch
new file mode 100644
index 0000000000..985fc36c18
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0004-do-not-create-python-environment.patch
@@ -0,0 +1,64 @@
+From 5028d1cd669c179ed49061316d04c8e8862a5bd8 Mon Sep 17 00:00:00 2001
+From: Hongxu Jia <hongxu.jia@windriver.com>
+Date: Thu, 12 Jul 2018 15:04:47 +0800
+Subject: [PATCH 1/5] do not create python environment
+
+Use oe's python environment rather than create one of host
+
+Upstream-Status: Inappropriate [oe specific]
+
+Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
+
+Rebase to 60.9.0 (firefox-esr sources)
+Signed-off-by: Andreas Müller <schnitzeltony@gmail.com>
+---
+ build/moz.configure/init.configure | 18 ------------------
+ configure.py | 10 +++++++++-
+ 3 files changed, 11 insertions(+), 21 deletions(-)
+
+--- a/build/moz.configure/init.configure
++++ b/build/moz.configure/init.configure
+@@ -250,24 +250,6 @@ def virtualenv_python(env_python, build_
+ else:
+ python = sys.executable
+
+- if not manager.up_to_date(python):
+- log.info('Creating Python environment')
+- manager.build(python)
+-
+- python = normsep(manager.python_path)
+-
+- if python != normsep(sys.executable):
+- log.info('Reexecuting in the virtualenv')
+- if env_python:
+- del os.environ['PYTHON']
+- # One would prefer to use os.execl, but that's completely borked on
+- # Windows.
+- sys.exit(subprocess.call([python] + sys.argv))
+-
+- # We are now in the virtualenv
+- if not distutils.sysconfig.get_python_lib():
+- die('Could not determine python site packages directory')
+-
+ return python
+
+
+--- a/configure.py
++++ b/configure.py
+@@ -12,7 +12,15 @@ import textwrap
+
+
+ base_dir = os.path.abspath(os.path.dirname(__file__))
+-sys.path.insert(0, os.path.join(base_dir, 'python', 'mozbuild'))
++sys.path.insert(0, os.path.join(base_dir, 'config'))
++def get_immediate_subdirectories(a_dir):
++ return [name for name in os.listdir(a_dir)
++ if os.path.isdir(os.path.join(a_dir, name))]
++for s in ["python", "testing/mozbase"]:
++ sub_dir = os.path.join(base_dir, s)
++ for module_dir in get_immediate_subdirectories(sub_dir):
++ sys.path.insert(0, os.path.join(sub_dir, module_dir))
++
+ from mozbuild.configure import ConfigureSandbox
+ from mozbuild.makeutil import Makefile
+ from mozbuild.pythonutil import iter_modules_in_path
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0005-fix-cannot-find-link.patch b/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0005-fix-cannot-find-link.patch
new file mode 100644
index 0000000000..4f7ebc68d7
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0005-fix-cannot-find-link.patch
@@ -0,0 +1,34 @@
+From e6dcee5f8a0f80ce99946b81fa1233611a149fe6 Mon Sep 17 00:00:00 2001
+From: Hongxu Jia <hongxu.jia@windriver.com>
+Date: Thu, 12 Jul 2018 18:00:52 +0800
+Subject: [PATCH 2/5] fix cannot find link
+
+..
+|DEBUG: link: Trying 'mips64-wrs-linux-ld --sysroot=tmp-glibc/work/
+mips64-wrs-linux/mozjs/52.8.1-r0/recipe-sysroot '
+|ERROR: Cannot find link
+...
+
+Upstream-Status: Inappropriate [oe specific]
+
+Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
+---
+ build/moz.configure/checks.configure | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/build/moz.configure/checks.configure b/build/moz.configure/checks.configure
+index 8c2dbc0..83bffc3 100644
+--- a/build/moz.configure/checks.configure
++++ b/build/moz.configure/checks.configure
+@@ -128,7 +128,7 @@ def check_prog(var, progs, what=None, input=None, allow_missing=False,
+
+ for prog in value or progs:
+ log.debug('%s: Trying %s', var.lower(), quote(prog))
+- result = find_program(prog, paths)
++ result = find_program(prog.split()[0], paths)
+ if result:
+ return result
+
+--
+2.7.4
+
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0006-workaround-autoconf-2.13-detection-failed.patch b/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0006-workaround-autoconf-2.13-detection-failed.patch
new file mode 100644
index 0000000000..a754ff16cf
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0006-workaround-autoconf-2.13-detection-failed.patch
@@ -0,0 +1,28 @@
+From 646a78262b18e19721cd41ee515215221dd241b6 Mon Sep 17 00:00:00 2001
+From: Hongxu Jia <hongxu.jia@windriver.com>
+Date: Thu, 12 Jul 2018 18:12:42 +0800
+Subject: [PATCH 3/5] workaround autoconf 2.13 detection failed
+
+Upstream-Status: Inappropriate [oe specific]
+
+Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
+---
+ build/moz.configure/old.configure | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/build/moz.configure/old.configure b/build/moz.configure/old.configure
+index b32c3f7..ece47f4 100644
+--- a/build/moz.configure/old.configure
++++ b/build/moz.configure/old.configure
+@@ -31,7 +31,7 @@ def autoconf(mozconfig, autoconf):
+ autoconf = autoconf[0] if autoconf else None
+
+ for ac in (mozconfig_autoconf, autoconf, 'autoconf-2.13', 'autoconf2.13',
+- 'autoconf213'):
++ 'autoconf213', 'autoconf'):
+ if ac:
+ autoconf = find_program(ac)
+ if autoconf:
+--
+2.7.4
+
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0007-fix-do_compile-failed-on-mips.patch b/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0007-fix-do_compile-failed-on-mips.patch
new file mode 100644
index 0000000000..d1da109720
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0007-fix-do_compile-failed-on-mips.patch
@@ -0,0 +1,33 @@
+From 55d833dc3c194f1eb7841f308ad3b9ec3800d3b3 Mon Sep 17 00:00:00 2001
+From: Hongxu Jia <hongxu.jia@windriver.com>
+Date: Fri, 13 Jul 2018 15:48:32 +0800
+Subject: [PATCH 5/5] fix do_compile failed on mips
+
+Link with var-OS_LDFLAGS to fix the issue.
+Such as on mips:
+...
+|mips-wrsmllib32-linux-g++ -meb -mabi=32 -mhard-float ... -o libmozjs-52.so
+|/usr/include/c++/8.1.0/bits/atomic_base.h:514: error: undefined
+reference to '__atomic_fetch_add_8'
+...
+
+In recipe, set OS_LDFLAGS="-Wl,-latomic" could fix the issue.
+
+Upstream-Status: Inappropriate [oe specific]
+
+Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
+---
+ config/config.mk | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/config/config.mk
++++ b/config/config.mk
+@@ -423,7 +423,7 @@ EXPAND_MKSHLIB_ARGS = --uselist
+ ifdef SYMBOL_ORDER
+ EXPAND_MKSHLIB_ARGS += --symbol-order $(SYMBOL_ORDER)
+ endif
+-EXPAND_MKSHLIB = $(EXPAND_LIBS_EXEC) $(EXPAND_MKSHLIB_ARGS) -- $(MKSHLIB)
++EXPAND_MKSHLIB = $(EXPAND_LIBS_EXEC) $(EXPAND_MKSHLIB_ARGS) -- $(MKSHLIB) $(OS_LDFLAGS)
+
+ # autoconf.mk sets OBJ_SUFFIX to an error to avoid use before including
+ # this file
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0008-add-riscv-support.patch b/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0008-add-riscv-support.patch
new file mode 100644
index 0000000000..0a41485610
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0008-add-riscv-support.patch
@@ -0,0 +1,50 @@
+Add RISC-V support
+
+Upstream-Status: Submitted [https://bugzilla.mozilla.org/show_bug.cgi?id=1318905]
+
+Signed-off-by: Ricardo Salveti <ricardo@foundries.io>
+
+--- a/build/autoconf/config.guess
++++ b/build/autoconf/config.guess
+@@ -1029,6 +1029,9 @@ EOF
+ ppcle:Linux:*:*)
+ echo powerpcle-unknown-linux-${LIBC}
+ exit ;;
++ riscv32:Linux:*:* | riscv64:Linux:*:*)
++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
++ exit ;;
+ s390:Linux:*:* | s390x:Linux:*:*)
+ echo ${UNAME_MACHINE}-ibm-linux-${LIBC}
+ exit ;;
+--- a/build/moz.configure/init.configure
++++ b/build/moz.configure/init.configure
+@@ -658,6 +658,9 @@ def split_triplet(triplet, allow_unknown
+ elif cpu == 'sh4':
+ canonical_cpu = 'sh4'
+ endianness = 'little'
++ elif cpu in ('riscv32', 'riscv64'):
++ canonical_cpu = cpu
++ endianness = 'little'
+ elif allow_unknown:
+ canonical_cpu = cpu
+ endianness = 'unknown'
+--- a/python/mozbuild/mozbuild/configure/constants.py
++++ b/python/mozbuild/mozbuild/configure/constants.py
+@@ -50,6 +50,8 @@ CPU_bitness = {
+ 'mips64': 64,
+ 'ppc': 32,
+ 'ppc64': 64,
++ 'riscv32': 32,
++ 'riscv64': 64,
+ 's390': 32,
+ 's390x': 64,
+ 'sh4': 32,
+@@ -82,6 +84,8 @@ CPU_preprocessor_checks = OrderedDict((
+ ('s390', '__s390__'),
+ ('ppc64', '__powerpc64__'),
+ ('ppc', '__powerpc__'),
++ ('riscv32', '__riscv && __SIZEOF_POINTER__ == 4'),
++ ('riscv64', '__riscv && __SIZEOF_POINTER__ == 8'),
+ ('Alpha', '__alpha__'),
+ ('hppa', '__hppa__'),
+ ('sparc64', '__sparc__ && __arch64__'),
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0009-mozjs-fix-coredump-caused-by-getenv.patch b/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0009-mozjs-fix-coredump-caused-by-getenv.patch
new file mode 100644
index 0000000000..477f73a2f7
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0009-mozjs-fix-coredump-caused-by-getenv.patch
@@ -0,0 +1,27 @@
+From 20b639b7364f9953fdacb058f9ba800bcbf029b4 Mon Sep 17 00:00:00 2001
+From: Changqing Li <changqing.li@windriver.com>
+Date: Thu, 2 Aug 2018 09:40:48 +0800
+Subject: [PATCH] mozjs: fix coredump caused by getenv
+
+Upstream-Status: Submitted [https://bugzilla.mozilla.org/show_bug.cgi?id=1480315]
+
+Signed-off-by: Changqing Li <changqing.li@windriver.com>
+---
+ mozglue/misc/TimeStamp.cpp | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/mozglue/misc/TimeStamp.cpp b/mozglue/misc/TimeStamp.cpp
+index 932b75c..7a4d71b 100644
+--- a/mozglue/misc/TimeStamp.cpp
++++ b/mozglue/misc/TimeStamp.cpp
+@@ -11,6 +11,7 @@
+ #include "mozilla/TimeStamp.h"
+ #include <stdio.h>
+ #include <string.h>
++#include <stdlib.h>
+
+ namespace mozilla {
+
+--
+2.7.4
+
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0010-format-overflow.patch b/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0010-format-overflow.patch
new file mode 100644
index 0000000000..e257fc6f62
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0010-format-overflow.patch
@@ -0,0 +1,21 @@
+Drop enable format string warnings to help gcc9
+
+Fixes
+| /mnt/a/yoe/build/tmp/work/core2-64-yoe-linux-musl/mozjs/52.9.1-r0/mozjs-52.9.1/js/src/jit/x64/BaseAssembler-x64.h:596:13: error: '%s' directive argument is null [-Werror=format-overflow=]
+| 596 | spew("movq " MEM_obs ", %s", ADDR_obs(offset, base, index, scale), GPReg64Name(dst));
+| | ~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Upstream-Status: Inappropriate [Workaround for gcc9]
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+
+--- a/js/src/moz.build
++++ b/js/src/moz.build
+@@ -785,7 +785,7 @@ if CONFIG['JS_HAS_CTYPES']:
+ if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
+ # Also disable strict-aliasing for GCC compiler, that is enabled by default
+ # starting with version 7.1, see Bug 1363009
+- CXXFLAGS += ['-Wno-shadow', '-Werror=format', '-fno-strict-aliasing']
++ CXXFLAGS += ['-Wno-shadow', '-fno-strict-aliasing']
+
+ # Suppress warnings in third-party code.
+ if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0011-To-fix-build-error-on-arm32BE.patch b/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0011-To-fix-build-error-on-arm32BE.patch
new file mode 100644
index 0000000000..056f74a529
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0011-To-fix-build-error-on-arm32BE.patch
@@ -0,0 +1,28 @@
+From 9afb0e4d3b9209ea198052cea0401bef7ee25ad8 Mon Sep 17 00:00:00 2001
+From: Lei Maohui <leimaohui@cn.fujitsu.com>
+Date: Thu, 9 May 2019 12:23:40 +0900
+Subject: [PATCH] To fix build error on arm32BE.
+
+error: #error Target architecture was not detected as supported by Double-Conversion.
+
+Signed-off-by: Lei Maohui <leimaohui@cn.fujitsu.com>
+---
+ mfbt/double-conversion/double-conversion/utils.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/mfbt/double-conversion/double-conversion/utils.h b/mfbt/double-conversion/double-conversion/utils.h
+index 4f37218..93575cb 100644
+--- a/mfbt/double-conversion/double-conversion/utils.h
++++ b/mfbt/double-conversion/double-conversion/utils.h
+@@ -53,7 +53,7 @@
+ // disabled.)
+ // On Linux,x86 89255e-22 != Div_double(89255.0/1e22)
+ #if defined(_M_X64) || defined(__x86_64__) || \
+- defined(__ARMEL__) || defined(__avr32__) || \
++ defined(__arm__) || defined(__avr32__) || \
+ defined(__hppa__) || defined(__ia64__) || \
+ defined(__mips__) || \
+ defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__) || \
+--
+2.7.4
+
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0012-JS_PUBLIC_API.patch b/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0012-JS_PUBLIC_API.patch
new file mode 100644
index 0000000000..56b18ba8c6
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0012-JS_PUBLIC_API.patch
@@ -0,0 +1,55 @@
+patch from https://bugzilla.mozilla.org/show_bug.cgi?id=1426865
+
+Upstream-Status: Submitted [https://bugzilla.mozilla.org/show_bug.cgi?id=1426865]
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+--- a/js/public/TypeDecls.h
++++ b/js/public/TypeDecls.h
+@@ -21,31 +21,32 @@
+ #include <stdint.h>
+
+ #include "js-config.h"
++#include "jstypes.h"
+
+ typedef uint8_t jsbytecode;
+
+-class JSAtom;
+-struct JSCompartment;
+-struct JSContext;
+-class JSFunction;
+-class JSObject;
+-struct JSRuntime;
+-class JSScript;
+-class JSString;
+-class JSAddonId;
+-struct JSFreeOp;
++class JS_PUBLIC_API JSAtom;
++struct JS_PUBLIC_API JSCompartment;
++struct JS_PUBLIC_API JSContext;
++class JS_PUBLIC_API JSFunction;
++class JS_PUBLIC_API JSObject;
++struct JS_PUBLIC_API JSRuntime;
++class JS_PUBLIC_API JSScript;
++class JS_PUBLIC_API JSString;
++class JS_PUBLIC_API JSAddonId;
++struct JS_PUBLIC_API JSFreeOp;
+
+-struct jsid;
++struct JS_PUBLIC_API jsid;
+
+ namespace JS {
+
+ typedef unsigned char Latin1Char;
+
+-class Symbol;
+-class Value;
+-class Realm;
+-struct Runtime;
+-struct Zone;
++class JS_PUBLIC_API Symbol;
++class JS_PUBLIC_API Value;
++class JS_PUBLIC_API Realm;
++struct JS_PUBLIC_API Runtime;
++struct JS_PUBLIC_API Zone;
+
+ template <typename T>
+ class Handle;
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0013-riscv-Disable-atomic-operations.patch b/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0013-riscv-Disable-atomic-operations.patch
new file mode 100644
index 0000000000..2e810c87f9
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0013-riscv-Disable-atomic-operations.patch
@@ -0,0 +1,38 @@
+From 64ad80e6d95871f17be4cd01da15581f41ac0b2b Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Mon, 27 May 2019 21:10:34 -0700
+Subject: [PATCH] riscv: Disable atomic operations
+
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ js/src/jit/AtomicOperations.h | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/js/src/jit/AtomicOperations.h
++++ b/js/src/jit/AtomicOperations.h
+@@ -393,6 +393,8 @@ inline bool AtomicOperations::isLockfree
+ #include "jit/none/AtomicOperations-feeling-lucky.h"
+ #elif defined(__s390__) || defined(__s390x__)
+ #include "jit/none/AtomicOperations-feeling-lucky.h"
++#elif defined(__riscv)
++#include "jit/none/AtomicOperations-feeling-lucky.h"
+ #else
+ #error "No AtomicOperations support provided for this platform"
+ #endif
+--- a/js/src/jit/none/AtomicOperations-feeling-lucky.h
++++ b/js/src/jit/none/AtomicOperations-feeling-lucky.h
+@@ -80,6 +80,14 @@
+ #define GNUC_COMPATIBLE
+ #endif
+
++#ifdef __riscv
++#define GNUC_COMPATIBLE
++#ifdef __riscv_xlen == 64
++#define HAS_64BIT_ATOMICS
++#define HAS_64BIT_LOCKFREE
++#endif
++#endif
++
+ // The default implementation tactic for gcc/clang is to use the newer
+ // __atomic intrinsics added for use in C++11 <atomic>. Where that
+ // isn't available, we use GCC's older __sync functions instead.
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0014-fallback-to-2011-C++-standard.patch b/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0014-fallback-to-2011-C++-standard.patch
new file mode 100644
index 0000000000..7a0d286e14
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/0014-fallback-to-2011-C++-standard.patch
@@ -0,0 +1,42 @@
+Option '-std=gnu++14' has been supported from gcc 4.9. But on some build hosts
+such as CentOS 7.6 which only has gcc 4.8.5 and fails to configure:
+
+| checking whether the host C compiler can be used... no
+| ERROR: Only GCC 4.9 or newer is supported (found version 4.8.5).
+
+Fallback to 2011 C++ standard and lower required gcc version to 4.8.0 which is
+the same as in previous version 52.9.1 of mozjs.
+
+Upstream-Status: Inappropriate [Workaround]
+
+Signed-off-by: Kai Kang <kai.kang@windriver.com>
+---
+diff --git a/build/moz.configure/toolchain.configure b/build/moz.configure/toolchain.configure
+index 9c772a8..fc640c7 100755
+--- a/build/moz.configure/toolchain.configure
++++ b/build/moz.configure/toolchain.configure
+@@ -502,10 +502,8 @@ def check_compiler(compiler, language, target):
+ append_flag('-std=c++14')
+ # GCC 4.9 indicates that it implements draft C++14 features
+ # instead of the full language.
+- elif info.type == 'gcc' and \
+- info.language_version not in (draft_cxx14_version,
+- cxx14_version):
+- append_flag('-std=gnu++14')
++ elif info.type == 'gcc' and info.language_version != 201103:
++ append_flag('-std=gnu++11')
+
+ # We force clang-cl to emulate Visual C++ 2017 version 15.4
+ if info.type == 'clang-cl' and info.version != '19.11.25547':
+@@ -903,9 +901,9 @@ def compiler(language, host_or_target, c_compiler=None, other_compiler=None,
+ # Check the compiler version here instead of in `compiler_version` so
+ # that the `checking` message doesn't pretend the compiler can be used
+ # to then bail out one line later.
+- if info.type == 'gcc' and info.version < '4.9.0':
++ if info.type == 'gcc' and info.version < '4.8.0':
+ raise FatalCheckError(
+- 'Only GCC 4.9 or newer is supported (found version %s).'
++ 'Only GCC 4.8 or newer is supported (found version %s).'
+ % info.version)
+
+ if info.type == 'gcc' and host_or_target.os == 'Android':
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/mipsarchn32/0001-fix-compiling-failure-on-mips64-n32-bsp.patch b/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/mipsarchn32/0001-fix-compiling-failure-on-mips64-n32-bsp.patch
new file mode 100644
index 0000000000..b882d76ec2
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/mipsarchn32/0001-fix-compiling-failure-on-mips64-n32-bsp.patch
@@ -0,0 +1,80 @@
+From f2f8be496c8e34b4d909b688a95c6f8565201081 Mon Sep 17 00:00:00 2001
+From: Hongxu Jia <hongxu.jia@windriver.com>
+Date: Wed, 19 Jun 2019 14:30:44 +0800
+Subject: [PATCH] fix compiling failure on mips64-n32 bsp
+
+- Tweak mips64-n32 with mips32
+
+- The toolchain of mips64-n32 supports both of macro
+ `__mips64' and `__mips__', but 32bit is required here.
+
+- N32 uses 64-bit registers but restricts addresses to 32 bits.
+ https://www.linux-mips.org/pub/linux/mips/doc/ABI/MIPS-N32-ABI-Handbook.pdf
+ Table 2-1 specifies the use of registers in n32 and native 64-bit mode.
+ From the table, N32 and N64 have the same registers
+
+Upstream-Status: Inappropriate [oe specific]
+
+Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
+Signed-off-by: Mingli Yu <Mingli.Yu@windriver.com>
+---
+ build/moz.configure/init.configure | 5 ++++-
+ js/src/jit/mips-shared/Architecture-mips-shared.h | 4 +++-
+ python/mozbuild/mozbuild/configure/constants.py | 2 +-
+ 3 files changed, 8 insertions(+), 3 deletions(-)
+
+diff --git a/build/moz.configure/init.configure b/build/moz.configure/init.configure
+index 648ac2d..d0bcaf8 100644
+--- a/build/moz.configure/init.configure
++++ b/build/moz.configure/init.configure
+@@ -650,7 +650,10 @@ def split_triplet(triplet, allow_unknown=False):
+ canonical_cpu = 'mips32'
+ endianness = 'little' if 'el' in cpu else 'big'
+ elif cpu in ('mips64', 'mips64el'):
+- canonical_cpu = 'mips64'
++ if 'n32' in triplet:
++ canonical_cpu = 'mips32'
++ else:
++ canonical_cpu = 'mips64'
+ endianness = 'little' if 'el' in cpu else 'big'
+ elif cpu.startswith('aarch64'):
+ canonical_cpu = 'aarch64'
+diff --git a/js/src/jit/mips-shared/Architecture-mips-shared.h b/js/src/jit/mips-shared/Architecture-mips-shared.h
+index e95ffd4..caf83f7 100644
+--- a/js/src/jit/mips-shared/Architecture-mips-shared.h
++++ b/js/src/jit/mips-shared/Architecture-mips-shared.h
+@@ -28,6 +28,8 @@
+ #elif (defined(_MIPS_SIM) && (_MIPS_SIM == _ABI64)) || \
+ defined(JS_SIMULATOR_MIPS64)
+ #define USES_N64_ABI
++#elif (defined(_MIPS_SIM) && (_MIPS_SIM == _ABIN32))
++#define USES_N32_ABI
+ #else
+ #error "Unsupported ABI"
+ #endif
+@@ -94,7 +96,7 @@ class Registers {
+ ta1 = t5,
+ ta2 = t6,
+ ta3 = t7,
+-#elif defined(USES_N64_ABI)
++#elif defined(USES_N64_ABI) || defined(USES_N32_ABI)
+ a4 = r8,
+ a5 = r9,
+ a6 = r10,
+diff --git a/python/mozbuild/mozbuild/configure/constants.py b/python/mozbuild/mozbuild/configure/constants.py
+index 1067b6a..e0f0405 100644
+--- a/python/mozbuild/mozbuild/configure/constants.py
++++ b/python/mozbuild/mozbuild/configure/constants.py
+@@ -90,8 +90,8 @@ CPU_preprocessor_checks = OrderedDict((
+ ('hppa', '__hppa__'),
+ ('sparc64', '__sparc__ && __arch64__'),
+ ('sparc', '__sparc__'),
+- ('mips64', '__mips64'),
+ ('mips32', '__mips__'),
++ ('mips64', '__mips64'),
+ ('sh4', '__sh__'),
+ ))
+
+--
+2.7.4
+
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/musl/0001-support-musl.patch b/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/musl/0001-support-musl.patch
new file mode 100644
index 0000000000..770d5e0aaa
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/musl/0001-support-musl.patch
@@ -0,0 +1,98 @@
+From 04e8a611e958f0da1ccac61acae3a6f1a5168b20 Mon Sep 17 00:00:00 2001
+From: Hongxu Jia <hongxu.jia@windriver.com>
+Date: Fri, 13 Jul 2018 18:08:14 +0800
+Subject: [PATCH] support musl
+
+Upstream-Status: Pending
+
+Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
+---
+ mozglue/misc/TimeStamp_darwin.cpp | 1 -
+ mozglue/misc/TimeStamp_posix.cpp | 1 -
+ nsprpub/pr/src/misc/prsystem.c | 1 -
+ python/psutil/psutil/_psutil_bsd.c | 1 -
+ python/psutil/psutil/_psutil_osx.c | 1 -
+ python/psutil/psutil/arch/bsd/process_info.c | 1 -
+ python/psutil/psutil/arch/osx/process_info.c | 1 -
+ 9 files changed, 3 insertions(+), 12 deletions(-)
+
+--- a/mozglue/misc/TimeStamp_darwin.cpp
++++ b/mozglue/misc/TimeStamp_darwin.cpp
+@@ -19,7 +19,6 @@
+
+ #include <mach/mach_time.h>
+ #include <sys/time.h>
+-#include <sys/sysctl.h>
+ #include <time.h>
+ #include <unistd.h>
+
+--- a/mozglue/misc/TimeStamp_posix.cpp
++++ b/mozglue/misc/TimeStamp_posix.cpp
+@@ -21,7 +21,6 @@
+ #if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || \
+ defined(__OpenBSD__)
+ #include <sys/param.h>
+-#include <sys/sysctl.h>
+ #endif
+
+ #if defined(__DragonFly__) || defined(__FreeBSD__)
+--- a/nsprpub/pr/src/misc/prsystem.c
++++ b/nsprpub/pr/src/misc/prsystem.c
+@@ -27,7 +27,6 @@
+ || defined(OPENBSD) || defined(DRAGONFLY) || defined(DARWIN)
+ #define _PR_HAVE_SYSCTL
+ #include <sys/param.h>
+-#include <sys/sysctl.h>
+ #endif
+
+ #if defined(DARWIN)
+--- a/third_party/python/psutil/psutil/_psutil_bsd.c
++++ b/third_party/python/psutil/psutil/_psutil_bsd.c
+@@ -29,7 +29,6 @@
+ #include <paths.h>
+ #include <sys/types.h>
+ #include <sys/param.h>
+-#include <sys/sysctl.h>
+ #include <sys/user.h>
+ #include <sys/proc.h>
+ #include <sys/file.h>
+--- a/third_party/python/psutil/psutil/_psutil_osx.c
++++ b/third_party/python/psutil/psutil/_psutil_osx.c
+@@ -13,7 +13,6 @@
+ #include <stdlib.h>
+ #include <stdio.h>
+ #include <utmpx.h>
+-#include <sys/sysctl.h>
+ #include <sys/vmmeter.h>
+ #include <libproc.h>
+ #include <sys/proc_info.h>
+--- a/third_party/python/psutil/psutil/arch/osx/process_info.c
++++ b/third_party/python/psutil/psutil/arch/osx/process_info.c
+@@ -16,7 +16,6 @@
+ #include <stdlib.h>
+ #include <stdio.h>
+ #include <signal.h>
+-#include <sys/sysctl.h>
+ #include <libproc.h>
+
+ #include "process_info.h"
+--- a/memory/build/Mutex.h
++++ b/memory/build/Mutex.h
+@@ -42,7 +42,7 @@ struct Mutex {
+ if (pthread_mutexattr_init(&attr) != 0) {
+ return false;
+ }
+- pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ADAPTIVE_NP);
++ pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_STALLED);
+ if (pthread_mutex_init(&mMutex, &attr) != 0) {
+ pthread_mutexattr_destroy(&attr);
+ return false;
+@@ -102,7 +102,7 @@ typedef Mutex StaticMutex;
+
+ #if defined(XP_DARWIN)
+ #define STATIC_MUTEX_INIT OS_SPINLOCK_INIT
+-#elif defined(XP_LINUX) && !defined(ANDROID)
++#elif defined(XP_LINUX) && !defined(ANDROID) && defined(__GLIBC__)
+ #define STATIC_MUTEX_INIT PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
+ #else
+ #define STATIC_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/musl/0002-js-Fix-build-with-musl.patch b/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/musl/0002-js-Fix-build-with-musl.patch
new file mode 100644
index 0000000000..f4c6e2768d
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs/musl/0002-js-Fix-build-with-musl.patch
@@ -0,0 +1,31 @@
+From 0c9e8f586ba52a9aef5ed298e8315b2598b8fb72 Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Sat, 25 May 2019 16:54:45 -0700
+Subject: [PATCH] js: Fix build with musl
+
+The MIPS specific header <sgidefs.h> is not provided by musl
+linux kernel headers provide <asm/sgidefs.h> which has same definitions
+
+Upstream-Status: Pending
+
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ js/src/jsmath.cpp | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/js/src/jsmath.cpp b/js/src/jsmath.cpp
+index a28968be..8facaa81 100644
+--- a/js/src/jsmath.cpp
++++ b/js/src/jsmath.cpp
+@@ -71,7 +71,7 @@
+ #elif defined(__s390__)
+ #define GETRANDOM_NR 349
+ #elif defined(__mips__)
+-#include <sgidefs.h>
++#include <asm/sgidefs.h>
+ #if _MIPS_SIM == _MIPS_SIM_ABI32
+ #define GETRANDOM_NR 4353
+ #elif _MIPS_SIM == _MIPS_SIM_ABI64
+--
+2.21.0
+
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs_60.9.0.bb b/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs_60.9.0.bb
new file mode 100644
index 0000000000..9466c62aac
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-extended/mozjs/mozjs_60.9.0.bb
@@ -0,0 +1,135 @@
+SUMMARY = "SpiderMonkey is Mozilla's JavaScript engine written in C/C++"
+HOMEPAGE = "https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey"
+LICENSE = "MPL-2.0"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=dc9b6ecd19a14a54a628edaaf23733bf"
+
+SRC_URI = " \
+ https://archive.mozilla.org/pub/firefox/releases/${PV}esr/source/firefox-${PV}esr.source.tar.xz \
+ file://0001-Port-build-to-python3.patch \
+ file://0002-js.pc.in-do-not-include-RequiredDefines.h-for-depend.patch \
+ file://0003-fix-cross-compilation-on-i586-targets.patch \
+ file://0004-do-not-create-python-environment.patch \
+ file://0005-fix-cannot-find-link.patch \
+ file://0006-workaround-autoconf-2.13-detection-failed.patch \
+ file://0007-fix-do_compile-failed-on-mips.patch \
+ file://0008-add-riscv-support.patch \
+ file://0009-mozjs-fix-coredump-caused-by-getenv.patch \
+ file://0010-format-overflow.patch \
+ file://0011-To-fix-build-error-on-arm32BE.patch \
+ file://0012-JS_PUBLIC_API.patch \
+ file://0013-riscv-Disable-atomic-operations.patch \
+ file://0014-fallback-to-2011-C++-standard.patch \
+"
+SRC_URI_append_libc-musl = " \
+ file://musl/0001-support-musl.patch \
+ file://musl/0002-js-Fix-build-with-musl.patch \
+"
+SRC_URI_append_mipsarchn32 = " \
+ file://mipsarchn32/0001-fix-compiling-failure-on-mips64-n32-bsp.patch \
+"
+SRC_URI[md5sum] = "69a0be9ce695e5dc4941ed0c78ef00c2"
+SRC_URI[sha256sum] = "9f453c8cc5669e46e38f977764d49a36295bf0d023619d9aac782e6bb3e8c53f"
+
+S = "${WORKDIR}/firefox-${@d.getVar("PV").replace("esr", "")}"
+
+inherit autotools pkgconfig perlnative python3native
+
+inherit features_check
+CONFLICT_DISTRO_FEATURES_mipsarchn32 = "ld-is-gold"
+
+DEPENDS += " \
+ nspr zlib autoconf-2.13-native \
+ python3-six-native python3-pytoml-native \
+ python3-jsmin-native python3-six \
+"
+
+# Disable null pointer optimization in gcc >= 6
+# https://bugzilla.redhat.com/show_bug.cgi?id=1328045
+CFLAGS += "-fno-tree-vrp -fno-strict-aliasing -fno-delete-null-pointer-checks"
+CXXFLAGS += "-fno-tree-vrp -fno-strict-aliasing -fno-delete-null-pointer-checks"
+
+# nspr's package-config is ignored so set libs manually
+EXTRA_OECONF = " \
+ --target=${TARGET_SYS} \
+ --host=${BUILD_SYS} \
+ --prefix=${prefix} \
+ --libdir=${libdir} \
+ --disable-tests --disable-strip --disable-optimize \
+ --disable-jemalloc \
+ --with-nspr-cflags='-I${STAGING_INCDIR}/nspr -I${STAGING_INCDIR}/nss3' \
+ --with-nspr-libs='-lplds4 -lplc4 -lnspr4' \
+ ${@bb.utils.contains('DISTRO_FEATURES', 'ld-is-gold', "--enable-gold", '--disable-gold', d)} \
+"
+
+# Without this, JS_Init() will fail for mips64.
+EXTRA_OECONF_append_mipsarch = " --with-intl-api=build"
+EXTRA_OECONF_append_powerpc = " --with-intl-api=build"
+
+EXTRA_OECONF_append_mipsarch = " --disable-ion"
+EXTRA_OECONF_append_riscv64 = " --disable-ion"
+EXTRA_OECONF_append_riscv32 = " --disable-ion"
+
+PACKAGECONFIG ??= "${@bb.utils.filter('DISTRO_FEATURES', 'x11', d)}"
+PACKAGECONFIG[x11] = "--x-includes=${STAGING_INCDIR} --x-libraries=${STAGING_LIBDIR},--x-includes=no --x-libraries=no,virtual/libx11"
+
+EXTRA_OEMAKE_task-compile += "BUILD_OPT=1 OS_LDFLAGS='-Wl,-latomic ${LDFLAGS}'"
+EXTRA_OEMAKE_task-install += "STATIC_LIBRARY_NAME=js_static"
+
+export HOST_CC = "${BUILD_CC}"
+export HOST_CXX = "${BUILD_CXX}"
+export HOST_CFLAGS = "${BUILD_CFLAGS}"
+export HOST_CPPFLAGS = "${BUILD_CPPFLAGS}"
+export HOST_CXXFLAGS = "${BUILD_CXXFLAGS}"
+
+do_configure() {
+ export SHELL="/bin/sh"
+ cd ${S}
+ # Add mozjs python-modules necessary
+ PYTHONPATH="${S}/third_party/python/which:${S}/config:${S}/build"
+ for sub_dir in python testing/mozbase; do
+ for module_dir in `ls $sub_dir -1`;do
+ [ $module_dir = "virtualenv" ] && continue
+ if [ -d "${S}/$sub_dir/$module_dir" ];then
+ PYTHONPATH="$PYTHONPATH:${S}/$sub_dir/$module_dir"
+ fi
+ done
+ done
+ echo "$PYTHONPATH" > ${B}/PYTHONPATH
+ export PYTHONPATH=`cat ${B}/PYTHONPATH`
+
+ cd ${S}/js/src
+ autoconf213 --macrodir=${STAGING_DATADIR_NATIVE}/autoconf213 old-configure.in > old-configure
+
+ cd ${B}
+ ${S}/js/src/configure ${EXTRA_OECONF}
+
+ # Make standard Makefile checks pass
+ touch ${S}/js/src/configure
+ touch ${B}/config.status
+}
+
+do_compile_prepend() {
+ export SHELL="/bin/sh"
+ export PYTHONPATH=`cat ${B}/PYTHONPATH`
+}
+
+do_install_prepend() {
+ export SHELL="/bin/sh"
+ export PYTHONPATH=`cat ${B}/PYTHONPATH`
+}
+
+PACKAGES =+ "lib${BPN}"
+FILES_lib${BPN} += "${libdir}/lib*.so"
+FILES_${PN}-dev += "${bindir}/js60-config"
+
+# Fails to build with thumb-1 (qemuarm)
+#| {standard input}: Assembler messages:
+#| {standard input}:2172: Error: shifts in CMP/MOV instructions are only supported in unified syntax -- `mov r2,r1,LSR#20'
+#| {standard input}:2173: Error: unshifted register required -- `bic r2,r2,#(1<<11)'
+#| {standard input}:2174: Error: unshifted register required -- `orr r1,r1,#(1<<20)'
+#| {standard input}:2176: Error: instruction not supported in Thumb16 mode -- `subs r2,r2,#0x300'
+#| {standard input}:2178: Error: instruction not supported in Thumb16 mode -- `subs r5,r2,#52'
+ARM_INSTRUCTION_SET_armv5 = "arm"
+ARM_INSTRUCTION_SET_armv4 = "arm"
+
+DISABLE_STATIC = ""
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-support/smem/smem/0001-smem-fix-support-for-source-option-python3.patch b/meta-oe/dynamic-layers/meta-python/recipes-support/smem/smem/0001-smem-fix-support-for-source-option-python3.patch
new file mode 100644
index 0000000000..5c1be5a0a2
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-support/smem/smem/0001-smem-fix-support-for-source-option-python3.patch
@@ -0,0 +1,53 @@
+From 3ff78f1f00973393d1a7ee4e467a2bacf1c807f3 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Andr=C3=A9=20Draszik?= <git@andred.net>
+Date: Wed, 5 Feb 2020 16:14:21 +0000
+Subject: [PATCH] smem: fix support for --source option (python3)
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Using --source doesn't work without this patch:
+Traceback (most recent call last):
+ File "./smem", line 727, in <module>
+ showpids()
+ File "./smem", line 299, in showpids
+ showtable(pt.keys(), fields, columns.split(), options.sort or 'pss')
+ File "./smem", line 519, in showtable
+ mt = totalmem()
+ File "./smem", line 118, in totalmem
+ _totalmem = memory()['memtotal']
+ File "./smem", line 193, in memory
+ m = f.match(l)
+TypeError: cannot use a string pattern on a bytes-like object
+
+python3's tarfile returns bytes, whereas all of the rest of
+the code assumes str.
+
+Fix the tarfile usage to convert to str before returning the
+results.
+
+Signed-off-by: André Draszik <git@andred.net>
+Upstream-Status: Inappropriate [upstream wants to support python2 & python3]
+---
+ smem | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/smem b/smem
+index 46a3189..54d40dd 100755
+--- a/smem
++++ b/smem
+@@ -90,9 +90,9 @@ class tardata(procdata):
+ d,f = ti.name.split('/')
+ yield d
+ def _read(self, f):
+- return self.tar.extractfile(f).read()
++ return self.tar.extractfile(f).read().decode()
+ def _readlines(self, f):
+- return self.tar.extractfile(f).readlines()
++ return [l.decode() for l in self.tar.extractfile(f).readlines()]
+ def piduser(self, p):
+ t = self.tar.getmember("%d" % p)
+ if t.uname:
+--
+2.23.0.rc1
+
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-support/smem/smem_1.5.bb b/meta-oe/dynamic-layers/meta-python/recipes-support/smem/smem_1.5.bb
new file mode 100644
index 0000000000..90db9c3f3e
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-support/smem/smem_1.5.bb
@@ -0,0 +1,43 @@
+SUMMARY = "Report application memory usage in a meaningful way"
+DESCRIPTION = "smem is a tool that can give numerous reports on memory usage on Linux \
+systems. Unlike existing tools, smem can report proportional set size (PSS), \
+which is a more meaningful representation of the amount of memory used by \
+libraries and applications in a virtual memory system."
+HOMEPAGE = "http://www.selenic.com/smem/"
+SECTION = "Applications/System"
+
+LICENSE = "GPLv2+"
+LIC_FILES_CHKSUM = "file://COPYING;md5=b234ee4d69f5fce4486a80fdaf4a4263"
+
+HG_CHANGESET = "98273ce331bb"
+SRC_URI = "https://selenic.com/repo/${BPN}/archive/${HG_CHANGESET}.tar.bz2;downloadfilename=${BP}.tar.bz2 \
+ file://0001-smem-fix-support-for-source-option-python3.patch"
+SRC_URI[md5sum] = "51c3989779360f42b42ef46b2831be3a"
+SRC_URI[sha256sum] = "161131c686a6d9962a0e96912526dd46308e022d62e3f8acaed5a56fda8e08ce"
+
+UPSTREAM_CHECK_URI = "https://selenic.com/repo/smem/tags"
+UPSTREAM_CHECK_REGEX = "(?P<pver>\d+(\.\d+)+)"
+
+S = "${WORKDIR}/${BPN}-${HG_CHANGESET}"
+
+do_compile() {
+ ${CC} ${CFLAGS} ${LDFLAGS} smemcap.c -o smemcap
+}
+
+do_install() {
+ install -d ${D}/${bindir}/
+ install -d ${D}/${mandir}/man8
+ install -m 0755 ${S}/smem ${D}${bindir}/
+ sed -i -e '1s,#!.*python.*,#!${USRBINPATH}/env python3,' ${D}${bindir}/smem
+ install -m 0755 ${S}/smemcap ${D}${bindir}/
+ install -m 0644 ${S}/smem.8 ${D}/${mandir}/man8/
+}
+
+RDEPENDS_${PN} = "python3-core python3-compression"
+RRECOMMENDS_${PN} = "python3-matplotlib python3-numpy"
+
+PACKAGE_BEFORE_PN = "smemcap"
+
+FILES_smemcap = "${bindir}/smemcap"
+
+BBCLASSEXTEND = "native"