Bug 778236 - Treat gyp files as if their content was defined in moz.build files. r=gps
authorMike Hommey <mh+mozilla@glandium.org>
Thu, 12 Dec 2013 23:41:05 +0900
changeset 160235 688d526f93134dd6f2a6e6dd011c28ef535bb0bb
parent 160234 a0522e28d9700ea00fb061fb718689767fc4f3c8
child 160236 f5bb944954a5dfa7d56b6ee531e83d2f978cc724
push id25827
push userkwierso@gmail.com
push dateFri, 13 Dec 2013 03:13:04 +0000
treeherdermozilla-central@1bc33fa19b24 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgps
bugs778236
milestone29.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 778236 - Treat gyp files as if their content was defined in moz.build files. r=gps
build/autoconf/arch.m4
build/gyp.mozbuild
build/virtualenv_packages.txt
config/config.mk
configure.in
js/src/build/autoconf/arch.m4
js/src/config/config.mk
media/mtransport/third_party/moz.build
media/mtransport/third_party/nICEr/nicer.gyp
media/mtransport/third_party/nrappkit/nrappkit.gyp
media/webrtc/moz.build
media/webrtc/trunk/tools/gyp/pylib/gyp/generator/mozmake.py
media/webrtc/trunk/tools/gyp/pylib/gyp/input.py
media/webrtc/trunk/webrtc/modules/audio_coding/codecs/opus/opus.gypi
media/webrtc/trunk/webrtc/modules/audio_device/audio_device.gypi
media/webrtc/webrtc_config.gypi
python/mozbuild/mozbuild/backend/recursivemake.py
python/mozbuild/mozbuild/frontend/emitter.py
python/mozbuild/mozbuild/frontend/gyp_reader.py
python/mozbuild/mozbuild/frontend/reader.py
python/mozbuild/mozbuild/frontend/sandbox_symbols.py
python/mozbuild/mozbuild/test/backend/test_recursivemake.py
--- a/build/autoconf/arch.m4
+++ b/build/autoconf/arch.m4
@@ -242,16 +242,17 @@ if test "$CPU_ARCH" = "arm"; then
       fi
   fi
 
 fi # CPU_ARCH = arm
 
 AC_SUBST(HAVE_ARM_SIMD)
 AC_SUBST(HAVE_ARM_NEON)
 AC_SUBST(BUILD_ARM_NEON)
+AC_SUBST(ARM_ARCH)
 
 if test -n "$MOZ_ARCH"; then
   NSPR_CONFIGURE_ARGS="$NSPR_CONFIGURE_ARGS --with-arch=$MOZ_ARCH"
   NSPR_CONFIGURE_ARGS="$NSPR_CONFIGURE_ARGS --with-thumb=$MOZ_THUMB"
   NSPR_CONFIGURE_ARGS="$NSPR_CONFIGURE_ARGS --with-thumb-interwork=$MOZ_THUMB_INTERWORK"
   NSPR_CONFIGURE_ARGS="$NSPR_CONFIGURE_ARGS --with-fpu=$MOZ_FPU"
   NSPR_CONFIGURE_ARGS="$NSPR_CONFIGURE_ARGS --with-float-abi=$MOZ_FLOAT_ABI"
   NSPR_CONFIGURE_ARGS="$NSPR_CONFIGURE_ARGS --with-soft-float=$MOZ_SOFT_FLOAT"
new file mode 100644
--- /dev/null
+++ b/build/gyp.mozbuild
@@ -0,0 +1,109 @@
+# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+gyp_vars = {
+    'build_with_mozilla': 1,
+    'build_with_chromium': 0,
+    'have_clock_monotonic': 1 if CONFIG['HAVE_CLOCK_MONOTONIC'] else 0,
+    'have_ethtool_cmd_speed_hi': 1 if CONFIG['MOZ_WEBRTC_HAVE_ETHTOOL_SPEED_HI'] else 0,
+    'include_alsa_audio': 1 if CONFIG['MOZ_ALSA'] else 0,
+    'include_pulse_audio': 1 if CONFIG['MOZ_PULSEAUDIO'] else 0,
+    # basic stuff for everything
+    'include_internal_video_render': 0,
+    'clang_use_chrome_plugins': 0,
+    'enable_protobuf': 0,
+    'include_tests': 0,
+    'enable_android_opensl': 1,
+    # use_system_lib* still seems to be in use in trunk/build
+    'use_system_libjpeg': 0,
+    'use_system_libvpx': 0,
+    'build_libjpeg': 0,
+    'build_libvpx': 0,
+    # saves 4MB when webrtc_trace is off
+    'enable_lazy_trace_alloc': 1,
+
+     # turn off mandatory use of NEON and instead use NEON detection
+    'arm_neon': 0,
+
+    'moz_widget_toolkit_gonk': 0,
+
+    # (for vp8) chromium sets to 0 also
+    'use_temporal_layers': 0,
+    # Creates AEC internal sample dump files in current directory
+    # 'aec_debug_dump': 1,
+
+    # codec enable/disables:
+    # Note: if you change one here, you must modify layout/media/webrtc/Makefile.in!
+    'include_g711': 1,
+    'include_opus': 1,
+    'include_g722': 0,
+    'include_ilbc': 0,
+    'include_isac': 0,
+    'include_pcm16b': 1,
+}
+
+os = CONFIG['OS_TARGET']
+
+if os == 'WINNT':
+    gyp_vars.update(
+        MSVS_VERSION=CONFIG['_MSVS_VERSION'],
+        MSVS_OS_BITS=64 if CONFIG['HAVE_64BIT_OS'] else 32,
+    )
+elif os == 'Android':
+    if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
+        gyp_vars['build_with_gonk'] = 1
+        gyp_vars['moz_widget_toolkit_gonk'] = 1
+    else:
+        gyp_vars.update(
+            gtest_target_type='executable',
+            android_toolchain=CONFIG['ANDROID_TOOLCHAIN'],
+        )
+
+flavors = {
+    'WINNT': 'win',
+    'Android': 'linux' if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' else 'android',
+    'Linux': 'linux',
+    'Darwin': 'mac' if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa' else 'ios',
+    'SunOS': 'solaris',
+    'GNU_kFreeBSD': 'freebsd',
+    'DragonFly': 'dragonfly',
+    'FreeBSD': 'freebsd',
+    'NetBSD': 'netbsd',
+    'OpenBSD': 'openbsd',
+}
+gyp_vars['OS'] = flavors[os]
+
+arches = {
+    'x86_64': 'x64',
+    'arm': 'arm',
+    'x86': 'ia32',
+    'ppc': 'ppc',
+    'ppc64': 'ppc',
+    'ia64': 'ia64',
+}
+
+gyp_vars['target_arch'] = arches[CONFIG['CPU_ARCH']]
+
+if CONFIG['ARM_ARCH']:
+    # We currently don't have a way to convert a string to an int in moz.build.
+    # As of writing, ARM_ARCH is not going to be over 8, so a string comparison
+    # works.
+    if CONFIG['ARM_ARCH'] < '7':
+        gyp_vars['armv7'] = 0
+    elif os == 'Android':
+        gyp_vars['armv7'] = 1
+    else:
+        # CPU detection for ARM works on Android only.  armv7 always uses CPU
+        # detection, so we have to set armv7=0 for non-Android target
+        gyp_vars['armv7'] = 0
+
+# Don't try to compile ssse3/sse4.1 code if toolchain doesn't support
+if CONFIG['INTEL_ARCHITECTURE']:
+    if not CONFIG['HAVE_TOOLCHAIN_SUPPORT_MSSSE3'] or not CONFIG['HAVE_TOOLCHAIN_SUPPORT_MSSE4_1']:
+        gyp_vars['yuv_disable_asm'] = 1
+
+if CONFIG['MACOS_SDK_DIR']:
+    gyp_vars['mac_sdk_path'] = CONFIG['MACOS_SDK_DIR']
--- a/build/virtualenv_packages.txt
+++ b/build/virtualenv_packages.txt
@@ -12,8 +12,9 @@ codegen.pth:python/codegen/
 mock.pth:python/mock-1.0.0
 mozilla.pth:build
 mozilla.pth:config
 mozilla.pth:xpcom/typelib/xpt/tools
 moztreedocs.pth:tools/docs
 copy:build/buildconfig.py
 packages.txt:testing/mozbase/packages.txt
 objdir:build
+gyp.pth:media/webrtc/trunk/tools/gyp/pylib
--- a/config/config.mk
+++ b/config/config.mk
@@ -582,20 +582,21 @@ HOST_CMMFLAGS += -fobjc-exceptions
 OS_COMPILE_CMFLAGS += -fobjc-exceptions
 OS_COMPILE_CMMFLAGS += -fobjc-exceptions
 ifeq ($(MOZ_WIDGET_TOOLKIT),uikit)
 OS_COMPILE_CMFLAGS += -fobjc-abi-version=2 -fobjc-legacy-dispatch
 OS_COMPILE_CMMFLAGS += -fobjc-abi-version=2 -fobjc-legacy-dispatch
 endif
 endif
 
-COMPILE_CFLAGS	= $(VISIBILITY_FLAGS) $(DEFINES) $(INCLUDES) $(DSO_CFLAGS) $(DSO_PIC_CFLAGS) $(RTL_FLAGS) $(OS_CPPFLAGS) $(OS_COMPILE_CFLAGS) $(CFLAGS)
-COMPILE_CXXFLAGS = $(STL_FLAGS) $(VISIBILITY_FLAGS) $(DEFINES) $(INCLUDES) $(DSO_CFLAGS) $(DSO_PIC_CFLAGS) $(RTL_FLAGS) $(OS_CPPFLAGS) $(OS_COMPILE_CXXFLAGS) $(CXXFLAGS)
-COMPILE_CMFLAGS = $(OS_COMPILE_CMFLAGS)
-COMPILE_CMMFLAGS = $(OS_COMPILE_CMMFLAGS)
+COMPILE_CFLAGS	= $(VISIBILITY_FLAGS) $(DEFINES) $(INCLUDES) $(DSO_CFLAGS) $(DSO_PIC_CFLAGS) $(RTL_FLAGS) $(OS_CPPFLAGS) $(OS_COMPILE_CFLAGS) $(CFLAGS) $(EXTRA_COMPILE_FLAGS)
+COMPILE_CXXFLAGS = $(STL_FLAGS) $(VISIBILITY_FLAGS) $(DEFINES) $(INCLUDES) $(DSO_CFLAGS) $(DSO_PIC_CFLAGS) $(RTL_FLAGS) $(OS_CPPFLAGS) $(OS_COMPILE_CXXFLAGS) $(CXXFLAGS) $(EXTRA_COMPILE_FLAGS)
+COMPILE_CMFLAGS = $(OS_COMPILE_CMFLAGS) $(EXTRA_COMPILE_FLAGS)
+COMPILE_CMMFLAGS = $(OS_COMPILE_CMMFLAGS) $(EXTRA_COMPILE_FLAGS)
+ASFLAGS += $(EXTRA_ASSEMBLER_FLAGS)
 
 ifndef CROSS_COMPILE
 HOST_CFLAGS += $(RTL_FLAGS)
 endif
 
 #
 # Name of the binary code directories
 #
@@ -879,8 +880,26 @@ PLY_INCLUDE = -I$(topsrcdir)/other-licen
 
 export CL_INCLUDES_PREFIX
 
 ifdef MOZ_GTK2_CFLAGS
 MOZ_GTK2_CFLAGS := -I$(topsrcdir)/widget/gtk/compat $(MOZ_GTK2_CFLAGS)
 endif
 
 DEFINES += -DNO_NSPR_10_SUPPORT
+
+ifdef IS_GYP_DIR
+LOCAL_INCLUDES += \
+  -I$(topsrcdir)/ipc/chromium/src \
+  -I$(topsrcdir)/ipc/glue \
+  -I$(DEPTH)/ipc/ipdl/_ipdlheaders \
+  $(NULL)
+
+ifeq (WINNT,$(OS_TARGET))
+# These get set via VC project file settings for normal GYP builds.
+DEFINES += -DUNICODE -D_UNICODE
+LOCAL_INCLUDES += -I'$(MOZ_DIRECTX_SDK_PATH)/include'
+endif
+
+STL_FLAGS=
+# Skip most Mozilla-specific include locations.
+INCLUDES = -I. $(LOCAL_INCLUDES) -I$(DEPTH)/dist/include
+endif
--- a/configure.in
+++ b/configure.in
@@ -451,26 +451,27 @@ case "$target" in
             AC_MSG_ERROR([The major versions of \$CC and \$CXX do not match.])
         fi
 
         AC_DEFINE(_CRT_SECURE_NO_WARNINGS)
         AC_DEFINE(_CRT_NONSTDC_NO_WARNINGS)
 
         if test "$_CC_MAJOR_VERSION" = "16"; then
             _CC_SUITE=10
-            _MSVS_VERSION=2010
+            MSVS_VERSION=2010
         elif test "$_CC_MAJOR_VERSION" = "17"; then
             _CC_SUITE=11
-            _MSVS_VERSION=2012
+            MSVS_VERSION=2012
         elif test "$_CC_MAJOR_VERSION" = "18"; then
             _CC_SUITE=12
-            _MSVS_VERSION=2013
+            MSVS_VERSION=2013
         else
             AC_MSG_ERROR([This version ($CC_VERSION) of the MSVC compiler is unsupported. See https://developer.mozilla.org/en/Windows_Build_Prerequisites.])
         fi
+	AC_SUBST(MSVS_VERSION)
 
         AC_DEFINE(HAVE_SEH_EXCEPTIONS)
 
         if test -n "$WIN32_REDIST_DIR"; then
           if test ! -d "$WIN32_REDIST_DIR"; then
             AC_MSG_ERROR([Invalid Win32 Redist directory: ${WIN32_REDIST_DIR}])
           fi
           WIN32_REDIST_DIR=`cd "$WIN32_REDIST_DIR" && pwd`
@@ -5063,39 +5064,25 @@ if test -n "$MOZ_WEBRTC"; then
         ;;
     esac
 fi
 
 AC_TRY_COMPILE([#include <linux/ethtool.h>],
                [ struct ethtool_cmd cmd; cmd.speed_hi = 0; ],
                MOZ_WEBRTC_HAVE_ETHTOOL_SPEED_HI=1)
 
+AC_SUBST(MOZ_WEBRTC_HAVE_ETHTOOL_SPEED_HI)
+
 # target_arch is from {ia32|x64|arm|ppc}
 case "$CPU_ARCH" in
-x86_64)
-    WEBRTC_TARGET_ARCH=x64
-    ;;
-
-arm*)
-    WEBRTC_TARGET_ARCH=arm
-    ;;
-
-x86)
-    WEBRTC_TARGET_ARCH=ia32
-    ;;
-
-ppc*)
-    WEBRTC_TARGET_ARCH=ppc
-    ;;
-ia64)
-    WEBRTC_TARGET_ARCH=ia64
+x86_64 | arm | x86 | ppc* | ia64)
+    :
     ;;
 *)
 # unsupported arch for webrtc
-    WEBRTC_TARGET_ARCH=unknown
     MOZ_WEBRTC=
     ;;
 
 esac
 
 dnl ========================================================
 dnl = Disable WebRTC code
 dnl ========================================================
@@ -8833,171 +8820,16 @@ case "$host" in
 *-apple-darwin11*)
     FIXED_EGREP="env ARCHPREFERENCE=i386,x86_64 arch egrep"
     ;;
 *)
     FIXED_EGREP="egrep"
     ;;
 esac
 
-# Generate Makefiles for WebRTC directly from .gyp files
-if test "${OS_TARGET}" = "WINNT"; then
-   if test "$HAVE_64BIT_OS"; then
-      OS_BITS=64
-   else
-      OS_BITS=32
-   fi
-   EXTRA_GYP_DEFINES="-D MSVS_VERSION=${_MSVS_VERSION} -D MSVS_OS_BITS=${OS_BITS}"
-
-elif test "${OS_TARGET}" = "Android"; then
-   if test "${MOZ_WIDGET_TOOLKIT}" = "gonk"; then
-      EXTRA_GYP_DEFINES="-G os=linux "
-   else
-      EXTRA_GYP_DEFINES="-D gtest_target_type=executable -D android_toolchain=${android_toolchain} -G os=android "
-   fi
-fi
-
-if test -n "$ARM_ARCH"; then
-    if test "$ARM_ARCH" -lt 7; then
-        EXTRA_GYP_DEFINES="${EXTRA_GYP_DEFINES} -D armv7=0 "
-    else
-        if test "${OS_TARGET}" = "Android"; then
-            EXTRA_GYP_DEFINES="${EXTRA_GYP_DEFINES} -D armv7=1 "
-        else
-            dnl CPU detection for ARM works on Android only.  armv7 always uses CPU detection, so
-            dnl we have to set armv7=0 for non-Android target
-            EXTRA_GYP_DEFINES="${EXTRA_GYP_DEFINES} -D armv7=0 "
-        fi
-    fi
-fi
-
-# Keep libcubeb and audio_device backends in sync
-if test -n "$MOZ_ALSA"; then
-   EXTRA_GYP_DEFINES="$EXTRA_GYP_DEFINES -D include_alsa_audio=1"
-else
-   EXTRA_GYP_DEFINES="$EXTRA_GYP_DEFINES -D include_alsa_audio=0"
-fi
-if test -n "$MOZ_PULSEAUDIO"; then
-   EXTRA_GYP_DEFINES="$EXTRA_GYP_DEFINES -D include_pulse_audio=1"
-else
-   EXTRA_GYP_DEFINES="$EXTRA_GYP_DEFINES -D include_pulse_audio=0"
-fi
-
-# Don't try to compile ssse3/sse4.1 code if toolchain doesn't support
-if test -n "$INTEL_ARCHITECTURE"; then
-  if test -z "$HAVE_TOOLCHAIN_SUPPORT_MSSSE3" -o -z "$HAVE_TOOLCHAIN_SUPPORT_MSSE4_1"; then
-    EXTRA_GYP_DEFINES="$EXTRA_GYP_DEFINES -D yuv_disable_asm=1"
-  fi
-fi
-
-if test -n "$MOZ_WEBRTC"; then
-   AC_MSG_RESULT("generating WebRTC Makefiles...")
-
-   if test "${MOZ_WIDGET_TOOLKIT}" = "gonk"; then
-      EXTRA_GYP_DEFINES="${EXTRA_GYP_DEFINES} -D build_with_gonk=1"
-   fi
-
-dnl Any --include files must also appear in -D FORCED_INCLUDE_FILE= entries
-dnl so that regeneration via dependencies works correctly
-   WEBRTC_CONFIG="-D build_with_mozilla=1 -D build_with_chromium=0 --include ${srcdir}/media/webrtc/webrtc_config.gypi -D FORCED_INCLUDE_FILE=${srcdir}/media/webrtc/webrtc_config.gypi"
-
-   if test -n HAVE_CLOCK_MONOTONIC; then
-      WEBRTC_CONFIG="${WEBRTC_CONFIG} -D have_clock_monotonic=1"
-   else
-      WEBRTC_CONFIG="${WEBRTC_CONFIG} -D have_clock_monotonic=0"
-   fi
-
-   if test -n "$MOZ_WEBRTC_HAVE_ETHTOOL_SPEED_HI"; then
-      WEBRTC_CONFIG="${WEBRTC_CONFIG} -D have_ethtool_cmd_speed_hi=1"
-   else
-      WEBRTC_CONFIG="${WEBRTC_CONFIG} -D have_ethtool_cmd_speed_hi=0"
-   fi
-
-   if test -n "$CROSS_COMPILE"; then
-      case "$target" in
-      *-mingw*)
-      	GYP_MOZMAKE_OPTIONS="-G os=win"
-        ;;
-      *-darwin*)
-        GYP_MOZMAKE_OPTIONS="-G os=mac"
-        if test "$MACOS_SDK_DIR"; then
-           GYP_MOZMAKE_OPTIONS="${GYP_MOZMAKE_OPTIONS} -D mac_sdk_path=$MACOS_SDK_DIR"
-        fi
-        ;;
-      *-*linux*)
-        GYP_MOZMAKE_OPTIONS="-G os=linux"
-        ;;
-      *)
-        AC_MSG_ERROR([Don't know what options to give to WebRTC for cross-compilation])
-    	;;
-      esac
-   fi
-
-   GYP_WEBRTC_OPTIONS="--format=mozmake ${GYP_MOZMAKE_OPTIONS} ${WEBRTC_CONFIG} -D target_arch=${WEBRTC_TARGET_ARCH} ${EXTRA_GYP_DEFINES} --depth=${srcdir}/media/webrtc/trunk --toplevel-dir=${srcdir} -G OBJDIR=${_objdir}"
-
-   $PYTHON ${srcdir}/media/webrtc/trunk/build/gyp_chromium \
-     $GYP_WEBRTC_OPTIONS \
-     --generator-output=${_objdir}/media/webrtc/trunk \
-     ${srcdir}/media/webrtc/trunk/peerconnection.gyp
-   if test "$?" != 0; then
-      AC_MSG_ERROR([failed to generate WebRTC Makefiles])
-   fi
-
-   # XXX disable until we land the tranche with signaling
-   if test -n "$MOZ_WEBRTC_SIGNALING"; then
-     AC_MSG_RESULT("generating WebRTC/Signaling Makefiles...")
-     $PYTHON ${srcdir}/media/webrtc/trunk/build/gyp_chromium \
-       $GYP_WEBRTC_OPTIONS \
-       -D build_for_test=0 \
-       --generator-output=${_objdir}/media/webrtc/signaling \
-       ${srcdir}/media/webrtc/signaling/signaling.gyp
-     if test "$?" != 0; then
-        AC_MSG_ERROR([failed to generate WebRTC/Signaling Makefiles])
-     fi
-
-     AC_MSG_RESULT("generating WebRTC/SignalingTest Makefiles...")
-     $PYTHON ${srcdir}/media/webrtc/trunk/build/gyp_chromium --format=mozmake \
-       $GYP_WEBRTC_OPTIONS \
-       -D build_for_test=1 \
-       --generator-output=${_objdir}/media/webrtc/signalingtest \
-       ${srcdir}/media/webrtc/signaling/signaling.gyp
-     if test "$?" != 0; then
-       AC_MSG_ERROR([failed to generate WebRTC/SignalingTest Makefiles])
-     fi
-   fi
-
-   AC_MSG_RESULT("generating gtest Makefiles...")
-   # Ok to pass some extra -D's that are ignored here
-   $PYTHON ${srcdir}/media/webrtc/trunk/build/gyp_chromium \
-     $GYP_WEBRTC_OPTIONS \
-     --generator-output=${_objdir}/media/webrtc/trunk/testing/ \
-     ${srcdir}/media/webrtc/trunk/testing/gtest.gyp
-   if test "$?" != 0; then
-      AC_MSG_ERROR([failed to generate gtest Makefiles])
-   fi
-
-   AC_MSG_RESULT("generating nrappkit Makefiles...")
-   $PYTHON ${srcdir}/media/webrtc/trunk/build/gyp_chromium --format=mozmake \
-     $GYP_WEBRTC_OPTIONS \
-     --generator-output=${_objdir}/media/mtransport/third_party/nrappkit \
-     ${srcdir}/media/mtransport/third_party/nrappkit/nrappkit.gyp
-   if test "$?" != 0; then
-      AC_MSG_ERROR([failed to generate nrappkit Makefiles])
-   fi
-
-   AC_MSG_RESULT("generating nICEr Makefiles...")
-   $PYTHON ${srcdir}/media/webrtc/trunk/build/gyp_chromium --format=mozmake \
-     $GYP_WEBRTC_OPTIONS \
-     --generator-output=${_objdir}/media/mtransport/third_party/nICEr \
-     ${srcdir}/media/mtransport/third_party/nICEr/nicer.gyp
-   if test "$?" != 0; then
-      AC_MSG_ERROR([failed to generate nICEr Makefiles])
-   fi
-fi
-
 # Run jemalloc configure script
 
 if test -z "$MOZ_NATIVE_JEMALLOC" -a "$MOZ_MEMORY" && test -n "$MOZ_JEMALLOC3" -o -n "$MOZ_REPLACE_MALLOC"; then
   ac_configure_args="--build=$build --host=$target --enable-stats --with-jemalloc-prefix=je_"
   if test -n "$MOZ_REPLACE_MALLOC"; then
     # When using replace_malloc, we always want memalign and valloc exported from jemalloc.
     ac_configure_args="$ac_configure_args ac_cv_func_memalign=yes"
     ac_configure_args="$ac_configure_args ac_cv_func_valloc=yes"
--- a/js/src/build/autoconf/arch.m4
+++ b/js/src/build/autoconf/arch.m4
@@ -242,16 +242,17 @@ if test "$CPU_ARCH" = "arm"; then
       fi
   fi
 
 fi # CPU_ARCH = arm
 
 AC_SUBST(HAVE_ARM_SIMD)
 AC_SUBST(HAVE_ARM_NEON)
 AC_SUBST(BUILD_ARM_NEON)
+AC_SUBST(ARM_ARCH)
 
 if test -n "$MOZ_ARCH"; then
   NSPR_CONFIGURE_ARGS="$NSPR_CONFIGURE_ARGS --with-arch=$MOZ_ARCH"
   NSPR_CONFIGURE_ARGS="$NSPR_CONFIGURE_ARGS --with-thumb=$MOZ_THUMB"
   NSPR_CONFIGURE_ARGS="$NSPR_CONFIGURE_ARGS --with-thumb-interwork=$MOZ_THUMB_INTERWORK"
   NSPR_CONFIGURE_ARGS="$NSPR_CONFIGURE_ARGS --with-fpu=$MOZ_FPU"
   NSPR_CONFIGURE_ARGS="$NSPR_CONFIGURE_ARGS --with-float-abi=$MOZ_FLOAT_ABI"
   NSPR_CONFIGURE_ARGS="$NSPR_CONFIGURE_ARGS --with-soft-float=$MOZ_SOFT_FLOAT"
--- a/js/src/config/config.mk
+++ b/js/src/config/config.mk
@@ -582,20 +582,21 @@ HOST_CMMFLAGS += -fobjc-exceptions
 OS_COMPILE_CMFLAGS += -fobjc-exceptions
 OS_COMPILE_CMMFLAGS += -fobjc-exceptions
 ifeq ($(MOZ_WIDGET_TOOLKIT),uikit)
 OS_COMPILE_CMFLAGS += -fobjc-abi-version=2 -fobjc-legacy-dispatch
 OS_COMPILE_CMMFLAGS += -fobjc-abi-version=2 -fobjc-legacy-dispatch
 endif
 endif
 
-COMPILE_CFLAGS	= $(VISIBILITY_FLAGS) $(DEFINES) $(INCLUDES) $(DSO_CFLAGS) $(DSO_PIC_CFLAGS) $(RTL_FLAGS) $(OS_CPPFLAGS) $(OS_COMPILE_CFLAGS) $(CFLAGS)
-COMPILE_CXXFLAGS = $(STL_FLAGS) $(VISIBILITY_FLAGS) $(DEFINES) $(INCLUDES) $(DSO_CFLAGS) $(DSO_PIC_CFLAGS) $(RTL_FLAGS) $(OS_CPPFLAGS) $(OS_COMPILE_CXXFLAGS) $(CXXFLAGS)
-COMPILE_CMFLAGS = $(OS_COMPILE_CMFLAGS)
-COMPILE_CMMFLAGS = $(OS_COMPILE_CMMFLAGS)
+COMPILE_CFLAGS	= $(VISIBILITY_FLAGS) $(DEFINES) $(INCLUDES) $(DSO_CFLAGS) $(DSO_PIC_CFLAGS) $(RTL_FLAGS) $(OS_CPPFLAGS) $(OS_COMPILE_CFLAGS) $(CFLAGS) $(EXTRA_COMPILE_FLAGS)
+COMPILE_CXXFLAGS = $(STL_FLAGS) $(VISIBILITY_FLAGS) $(DEFINES) $(INCLUDES) $(DSO_CFLAGS) $(DSO_PIC_CFLAGS) $(RTL_FLAGS) $(OS_CPPFLAGS) $(OS_COMPILE_CXXFLAGS) $(CXXFLAGS) $(EXTRA_COMPILE_FLAGS)
+COMPILE_CMFLAGS = $(OS_COMPILE_CMFLAGS) $(EXTRA_COMPILE_FLAGS)
+COMPILE_CMMFLAGS = $(OS_COMPILE_CMMFLAGS) $(EXTRA_COMPILE_FLAGS)
+ASFLAGS += $(EXTRA_ASSEMBLER_FLAGS)
 
 ifndef CROSS_COMPILE
 HOST_CFLAGS += $(RTL_FLAGS)
 endif
 
 #
 # Name of the binary code directories
 #
@@ -879,8 +880,26 @@ PLY_INCLUDE = -I$(topsrcdir)/other-licen
 
 export CL_INCLUDES_PREFIX
 
 ifdef MOZ_GTK2_CFLAGS
 MOZ_GTK2_CFLAGS := -I$(topsrcdir)/widget/gtk/compat $(MOZ_GTK2_CFLAGS)
 endif
 
 DEFINES += -DNO_NSPR_10_SUPPORT
+
+ifdef IS_GYP_DIR
+LOCAL_INCLUDES += \
+  -I$(topsrcdir)/ipc/chromium/src \
+  -I$(topsrcdir)/ipc/glue \
+  -I$(DEPTH)/ipc/ipdl/_ipdlheaders \
+  $(NULL)
+
+ifeq (WINNT,$(OS_TARGET))
+# These get set via VC project file settings for normal GYP builds.
+DEFINES += -DUNICODE -D_UNICODE
+LOCAL_INCLUDES += -I'$(MOZ_DIRECTX_SDK_PATH)/include'
+endif
+
+STL_FLAGS=
+# Skip most Mozilla-specific include locations.
+INCLUDES = -I. $(LOCAL_INCLUDES) -I$(DEPTH)/dist/include
+endif
--- a/media/mtransport/third_party/moz.build
+++ b/media/mtransport/third_party/moz.build
@@ -1,7 +1,18 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-PARALLEL_EXTERNAL_MAKE_DIRS += ['nrappkit', 'nICEr']
+include('/build/gyp.mozbuild')
+
+GYP_DIRS += [
+    'nICEr',
+    'nrappkit',
+]
+
+GYP_DIRS['nICEr'].input = 'nICEr/nicer.gyp'
+GYP_DIRS['nICEr'].variables = gyp_vars
+
+GYP_DIRS['nrappkit'].input = 'nrappkit/nrappkit.gyp'
+GYP_DIRS['nrappkit'].variables = gyp_vars
--- a/media/mtransport/third_party/nICEr/nicer.gyp
+++ b/media/mtransport/third_party/nICEr/nicer.gyp
@@ -29,19 +29,16 @@
  	      '../nrappkit/src/port/generic/include',
 
               # INTERNAL
               "./src/crypto",
               "./src/ice",
               "./src/net",
               "./src/stun",
               "./src/util",
-
-	      # Mozilla, hopefully towards the end
-             '$(DEPTH)/dist/include',
           ],
 
           'sources' : [
                 # Crypto
                 "./src/crypto/nr_crypto.c",
                 "./src/crypto/nr_crypto.h",
                 #"./src/crypto/nr_crypto_openssl.c",
                 #"./src/crypto/nr_crypto_openssl.h",
--- a/media/mtransport/third_party/nrappkit/nrappkit.gyp
+++ b/media/mtransport/third_party/nrappkit/nrappkit.gyp
@@ -17,19 +17,16 @@
 	      'src/event',
 	      'src/log',
               'src/port/generic/include',
 	      'src/registry',
 	      'src/share',
 	      'src/stats',
 	      'src/util',
 	      'src/util/libekr',
-
-	      # Mozilla, hopefully towards the end
-             '$(DEPTH)/dist/include',
           ],
 
           'sources' : [
 	      # Shared
 #              './src/share/nr_api.h',
               './src/share/nr_common.h',
 #              './src/share/nr_dynlib.h',
               './src/share/nr_reg_keys.h',
--- a/media/webrtc/moz.build
+++ b/media/webrtc/moz.build
@@ -1,16 +1,33 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-EXTERNAL_MAKE_DIRS += [
-    'trunk',
-    'signaling',
-]
+include('/build/gyp.mozbuild')
+
+GYP_DIRS += ['trunk']
+
+GYP_DIRS['trunk'].input = 'trunk/peerconnection.gyp'
+GYP_DIRS['trunk'].variables = gyp_vars
+
+if CONFIG['MOZ_WEBRTC_SIGNALING']:
+    GYP_DIRS += ['signaling']
+    GYP_DIRS['signaling'].input = 'signaling/signaling.gyp'
+    GYP_DIRS['signaling'].variables = gyp_vars.copy()
+    GYP_DIRS['signaling'].variables.update(
+        build_for_test=0
+    )
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'gonk':
-    EXTERNAL_MAKE_DIRS += [
-        'trunk/testing',
-        'signalingtest',
-    ]
+    GYP_DIRS += ['trunk/testing']
+    GYP_DIRS['trunk/testing'].input = 'trunk/testing/gtest.gyp'
+    GYP_DIRS['trunk/testing'].variables = gyp_vars
+
+    if CONFIG['MOZ_WEBRTC_SIGNALING']:
+        GYP_DIRS += ['signalingtest']
+        GYP_DIRS['signalingtest'].input = 'signaling/signaling.gyp'
+        GYP_DIRS['signalingtest'].variables = gyp_vars.copy()
+        GYP_DIRS['signalingtest'].variables.update(
+            build_for_test=1
+        )
deleted file mode 100644
--- a/media/webrtc/trunk/tools/gyp/pylib/gyp/generator/mozmake.py
+++ /dev/null
@@ -1,485 +0,0 @@
-# Copyright (c) 2012 Mozilla Foundation. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import collections
-import gyp
-import gyp.common
-import sys
-import platform
-import os
-import re
-import shlex
-from mozbuild.util import (
-    FileAvoidWrite,
-    shell_quote,
-)
-
-generator_wants_sorted_dependencies = True
-
-generator_default_variables = {
-}
-for dirname in ['INTERMEDIATE_DIR', 'SHARED_INTERMEDIATE_DIR', 'PRODUCT_DIR',
-                'LIB_DIR', 'SHARED_LIB_DIR']:
-  # Some gyp steps fail if these are empty(!).
-  generator_default_variables[dirname] = 'dir'
-for unused in ['RULE_INPUT_PATH', 'RULE_INPUT_ROOT', 'RULE_INPUT_NAME',
-               'RULE_INPUT_DIRNAME', 'RULE_INPUT_EXT',
-               'EXECUTABLE_PREFIX', 'EXECUTABLE_SUFFIX',
-               'STATIC_LIB_PREFIX', 'STATIC_LIB_SUFFIX',
-               'SHARED_LIB_PREFIX', 'SHARED_LIB_SUFFIX',
-               'LINKER_SUPPORTS_ICF']:
-  generator_default_variables[unused] = ''
-
-COMMON_HEADER = """# This makefile was automatically generated from %(buildfile)s. Please do not edit it directly.
-DEPTH		= %(depth)s
-topsrcdir	= %(topsrcdir)s
-srcdir          = %(srcdir)s
-VPATH           = %(srcdir)s
-
-EXTERNALLY_MANAGED_MAKE_FILE := 1
-
-"""
-
-COMMON_FOOTER = """
-
-include %(common_mk_path)s
-"""
-
-COMMON_MK = """# This file was generated by mozmake.py. Do not edit it directly.
-ifndef COMMON_MK_INCLUDED
-COMMON_MK_INCLUDED := 1
-
-include $(topsrcdir)/config/rules.mk
-
-LOCAL_INCLUDES += \\
-  -I$(topsrcdir)/ipc/chromium/src \\
-  -I$(topsrcdir)/ipc/glue \\
-  -I$(DEPTH)/ipc/ipdl/_ipdlheaders \\
-  $(NULL)
-
-ifdef MOZ_DEBUG
-CFLAGS += $(CPPFLAGS_Debug) $(CFLAGS_Debug)
-CXXFLAGS += $(CPPFLAGS_Debug) $(CXXFLAGS_Debug)
-DEFINES += $(DEFINES_Debug)
-LOCAL_INCLUDES += $(INCLUDES_Debug)
-ASFLAGS += $(ASFLAGS_Debug)
-else # non-MOZ_DEBUG
-CFLAGS += $(CPPFLAGS_Release) $(CFLAGS_Release)
-CXXFLAGS += $(CPPFLAGS_Release) $(CXXFLAGS_Release)
-DEFINES += $(DEFINES_Release)
-LOCAL_INCLUDES += $(INCLUDES_Release)
-ASFLAGS += $(ASFLAGS_Release)
-endif
-
-ifeq (WINNT,$(OS_TARGET))
-# These get set via VC project file settings for normal GYP builds.
-DEFINES += -DUNICODE -D_UNICODE
-LOCAL_INCLUDES += -I'$(MOZ_DIRECTX_SDK_PATH)/include'
-endif
-
-# Don't use STL wrappers when compiling Google code.
-STL_FLAGS =
-
-# Skip most Mozilla-specific include locations.
-INCLUDES = -I. $(LOCAL_INCLUDES) -I$(DEPTH)/dist/include
-
-# Ensure that subdirs for sources get created before compiling
-ifdef OBJS
-SUB_SRCDIRS := $(addsuffix .dirstamp,$(addprefix $(CURDIR)/,$(sort $(dir $(OBJS)))))
-$(OBJS): $(SUB_SRCDIRS)
-$(SUB_SRCDIRS):
-	$(MKDIR) -p $(dir $@)
-	touch $@
-endif
-
-# COPY_SRCS get copied to the current directory to be compiled
-
-define COPY_SRC
-$(notdir $(1)): $(1)
-	$$(INSTALL) $$(IFLAGS1) '$$<' .
-
-endef # COPY_SRC
-ifdef COPY_SRCS
-GARBAGE += $(notdir $(COPY_SRCS))
-$(foreach s,$(COPY_SRCS), $(eval $(call COPY_SRC,$(s))))
-endif
-
-# Rules for regenerating Makefiles from GYP files.
-Makefile: %(input_gypfiles)s %(generator)s
-	$(PYTHON) %(commandline)s
-	@$(TOUCH) $@
-endif
-
-include $(topsrcdir)/config/recurse.mk
-"""
-
-def ensure_directory_exists(path):
-  dir = os.path.dirname(path)
-  if dir and not os.path.exists(dir):
-    os.makedirs(dir)
-
-def GetFlavor(params):
-  """Returns |params.flavor| if it's set, the system's default flavor else."""
-  system = platform.system().lower()
-  flavors = {
-    'microsoft': 'win',
-    'windows'  : 'win',
-    'cygwin'   : 'win',
-    'darwin'   : 'mac',
-    'sunos'    : 'solaris',
-    'dragonfly': 'dragonfly',
-    'freebsd'  : 'freebsd',
-    'netbsd'   : 'netbsd',
-    'openbsd'  : 'openbsd',
-  }
-
-  if 'flavor' in params:
-    return params['flavor']
-  if system in flavors:
-    return flavors[system]
-
-  return 'linux'
-
-
-def CalculateVariables(default_variables, params):
-  generator_flags = params.get('generator_flags', {})
-  default_variables['OS'] = generator_flags.get('os', GetFlavor(params))
-
-
-def CalculateGeneratorInputInfo(params):
-  """Calculate the generator specific info that gets fed to input (called by
-  gyp)."""
-  generator_flags = params.get('generator_flags', {})
-  if generator_flags.get('adjust_static_libraries', False):
-    global generator_wants_static_library_dependencies_adjusted
-    generator_wants_static_library_dependencies_adjusted = True
-
-def WriteMakefile(filename, data, build_file, depth, topsrcdir, srcdir, relative_path, common_mk_path, extra_data=None):
-  if not os.path.isabs(topsrcdir):
-    topsrcdir = depth + "/" + topsrcdir
-  if not os.path.isabs(srcdir):
-    srcdir = depth + "/" + srcdir
-  #TODO: should compare with the existing file and not overwrite it if the
-  # contents are the same!
-  ensure_directory_exists(filename)
-  with FileAvoidWrite(filename) as f:
-    f.write(COMMON_HEADER % {'buildfile': build_file,
-                             'depth': depth,
-                             'topsrcdir': topsrcdir,
-                             'srcdir': srcdir})
-    for k, v in data.iteritems():
-      f.write("%s = %s\n" % (k, " \\\n  ".join([''] + v) if isinstance(v, list) else v))
-    f.write(COMMON_FOOTER % {'common_mk_path': common_mk_path})
-    if extra_data:
-      f.write(extra_data)
-
-def WriteCommonMk(path, build_files, scriptname, commandline):
-  with FileAvoidWrite(path) as f:
-    f.write(COMMON_MK % {'input_gypfiles': ' '.join(build_files),
-                         'generator': scriptname,
-                         'commandline': ' '.join(commandline)})
-
-def striplib(name):
-  "Strip lib prefixes from library names."
-  if name[:3] == 'lib':
-    return name[3:]
-  return name
-
-AS_EXTENSIONS = set([
-  '.s',
-  '.S'
-])
-CPLUSPLUS_EXTENSIONS = set([
-  '.cc',
-  '.cpp',
-  '.cxx'
-])
-COMPILABLE_EXTENSIONS = set([
-  '.c',
-  '.s',
-  '.S',
-  '.m',
-  '.mm'
-])
-COMPILABLE_EXTENSIONS.update(CPLUSPLUS_EXTENSIONS)
-
-def swapslashes(p):
-  "Swap backslashes for forward slashes in a path."
-  return p.replace('\\', '/')
-
-def getdepth(s):
-  """Given a relative path, return a relative path consisting
-  of .. segments that would lead to the parent directory."""
-  return "/".join(".." for x in swapslashes(s).split("/") if x)
-
-def Compilable(filename):
-  return os.path.splitext(filename)[1] in COMPILABLE_EXTENSIONS
-
-class MakefileGenerator(object):
-  def __init__(self, target_dicts, data, options, depth, topsrcdir, relative_topsrcdir, relative_srcdir, output_dir, flavor, common_mk_path):
-    self.target_dicts = target_dicts
-    self.data = data
-    self.options = options
-    self.depth = depth
-    self.relative_srcdir = swapslashes(relative_srcdir)
-    self.topsrcdir = swapslashes(topsrcdir)
-    self.relative_topsrcdir = swapslashes(relative_topsrcdir)
-    self.srcdir = swapslashes(os.path.join(topsrcdir, relative_srcdir))
-    self.output_dir = output_dir
-    self.flavor = flavor
-    self.common_mk_path = common_mk_path
-    # Directories to be built in order.
-    self.dirs = []
-    # Directories that can be built in any order, but before |dirs|.
-    self.parallel_dirs = []
-    # Targets that have been processed.
-    self.visited = set()
-    # Link dependencies.
-    self.target_link_deps = {}
-
-  def CalculateMakefilePath(self, build_file, target_name):
-    """Determine where to write a Makefile for a given gyp file."""
-    rel_path = gyp.common.RelativePath(os.path.dirname(build_file),
-                                       self.srcdir)
-    # Add a subdir using the build_file name and the target_name.
-    rel_path = os.path.join(rel_path,
-                             os.path.splitext(os.path.basename(build_file))[0]
-                             + "_" + target_name)
-    output_file = os.path.join(self.output_dir, rel_path, "Makefile")
-    return swapslashes(rel_path), swapslashes(output_file)
-
-  def ProcessTargets(self, needed_targets):
-    """
-    Put all targets in proper order so that dependencies get built before
-    the targets that need them. Targets that have no dependencies
-    can get built in parallel_dirs. Targets with dependencies must be in
-    dirs, and must also be listed after any of their dependencies.
-    """
-    for qualified_target in needed_targets:
-      if qualified_target in self.visited:
-        continue
-      self.ProcessTarget(qualified_target)
-
-  def ProcessTarget(self, qualified_target):
-    """
-    Write a Makefile.in for |qualified_target| and add it to |dirs| or
-    |parallel_dirs| as appropriate, after processing all of its
-    dependencies.
-    """
-    spec = self.target_dicts[qualified_target]
-    if 'dependencies' in spec and spec['dependencies']:
-      for dep in spec['dependencies']:
-        if dep not in self.visited:
-          self.ProcessTarget(dep)
-      dirs = self.dirs
-    else:
-      # no dependencies
-      dirs = self.parallel_dirs
-    # Now write a Makefile for this target
-    build_file, target, toolset = gyp.common.ParseQualifiedTarget(
-      qualified_target)
-    build_file = os.path.abspath(build_file)
-    rel_path, output_file = self.CalculateMakefilePath(build_file, target)
-    subdepth = self.depth + "/" + getdepth(rel_path)
-    if self.WriteTargetMakefile(output_file, rel_path, qualified_target, spec, build_file, subdepth):
-        # If WriteTargetMakefile returns True, then this is a useful target
-      dirs.append(rel_path)
-    self.visited.add(qualified_target)
-
-  def WriteTargetMakefile(self, output_file, rel_path, qualified_target, spec, build_file, depth):
-    configs = spec['configurations']
-    # Update global list of link dependencies.
-    if spec['type'] in ('static_library', 'shared_library'):
-      self.target_link_deps[qualified_target] = "$(call EXPAND_LIBNAME_PATH,%s,$(DEPTH)/%s/%s)" % (striplib(spec['target_name']), self.relative_srcdir, rel_path)
-
-    data = {}
-    #TODO: handle actions/rules/copies
-    if 'actions' in spec:
-      pass
-    if 'rules' in spec:
-      pass
-    if 'copies' in spec:
-      pass
-    libs = []
-    if 'dependencies' in spec:
-      for dep in spec['dependencies']:
-        if dep in self.target_link_deps:
-          libs.append(self.target_link_deps[dep])
-    if libs:
-      data['EXTRA_LIBS'] = libs
-
-    # Get DEFINES/INCLUDES
-    for configname in sorted(configs.keys()):
-      config = configs[configname]
-      #XXX: this sucks
-      defines = config.get('defines')
-      if defines:
-        data['DEFINES_%s' % configname] = [shell_quote("-D%s" % d) for d in defines]
-      includes = []
-      for i in config.get('include_dirs', []):
-        # Make regular paths into srcdir-relative paths, leave
-        # variable-specified paths alone.
-        if i.startswith("$(") or os.path.isabs(i):
-          if ' ' in i:
-            includes.append('"%s"' % i)
-          else:
-            includes.append(i)
-        else:
-          includes.append("$(srcdir)/" + i)
-      if includes:
-        data['INCLUDES_%s' % configname] = ["-I%s" %i for i in includes]
-      #XXX: handle mac stuff?
-# we want to use our compiler options in general
-#      cflags = config.get('cflags')
-#      if cflags:
-#        data['CPPFLAGS_%s' % configname] = cflags
-#      cflags_c = config.get('cflags_c')
-#      if cflags_c:
-#        data['CFLAGS_%s' % configname] = cflags_c
-#      cflags_cc = config.get('cflags_cc')
-#      if cflags_cc:
-#        data['CXXFLAGS_%s' % configname] = cflags_cc
-# we need to keep pkg-config flags however
-      cflags_mozilla = config.get('cflags_mozilla')
-      if cflags_mozilla:
-        data['CPPFLAGS_%s' % configname] = cflags_mozilla
-      asflags_mozilla = config.get('asflags_mozilla')
-      if asflags_mozilla:
-        data['ASFLAGS_%s' % configname] = asflags_mozilla
-    sources = {
-      'CPPSRCS': {'exts': CPLUSPLUS_EXTENSIONS, 'files': []},
-      'CSRCS': {'exts': ['.c'], 'files': []},
-      'CMSRCS': {'exts': ['.m'], 'files': []},
-      'CMMSRCS': {'exts': ['.mm'], 'files': []},
-      'SSRCS': {'exts': AS_EXTENSIONS, 'files': []},
-      }
-    copy_srcs = []
-    for s in spec.get('sources', []):
-      if not Compilable(s):
-        continue
-
-      # Special-case absolute paths, they'll get copied into the objdir
-      # for compiling.
-      if os.path.isabs(s):
-        # GNU Make falls down pretty badly with spaces in filenames.
-        # Conveniently, using a single-character ? as a wildcard
-        # works fairly well.
-        copy_srcs.append(s.replace(' ', '?'))
-        s = os.path.basename(s)
-
-      ext = os.path.splitext(s)[1]
-      for source_type, d in sources.iteritems():
-        if ext in d['exts']:
-          d['files'].append(s)
-          break
-      
-    for source_type, d in sources.iteritems():
-      if d['files']:
-        data[source_type] = d['files']
-
-    if copy_srcs:
-      data['COPY_SRCS'] = copy_srcs
-
-    if spec['type'] == 'executable':
-      data['PROGRAM'] = spec['target_name']
-    elif spec['type'] == 'static_library':
-      data['LIBRARY_NAME'] = striplib(spec['target_name'])
-      data['FORCE_STATIC_LIB'] = 1
-    elif spec['type'] in ('loadable_module', 'shared_library'):
-      data['LIBRARY_NAME'] = striplib(spec['target_name'])
-      data['FORCE_SHARED_LIB'] = 1
-    else:
-      # Maybe nothing?
-      return False
-    WriteMakefile(output_file, data, build_file, depth, self.topsrcdir,
-                  # we set srcdir up one directory, since the subdir
-                  # doesn't actually exist in the source directory
-                  swapslashes(os.path.normpath(os.path.join(self.topsrcdir, self.relative_srcdir, os.path.split(rel_path)[0]))),
-                  self.relative_srcdir,
-                  self.common_mk_path)
-    return True
-
-def GenerateOutput(target_list, target_dicts, data, params):
-  options = params['options']
-  flavor = GetFlavor(params)
-  generator_flags = params.get('generator_flags', {})
-
-  # Get a few directories into Mozilla-common naming conventions
-  # The root of the source repository.
-  topsrcdir = os.path.abspath(options.toplevel_dir)
-  # The object directory (root of the build).
-  objdir = os.path.abspath(generator_flags['OBJDIR'] if 'OBJDIR' in generator_flags else '.')
-  # A relative path from the objdir to the topsrcdir
-  relative_topsrcdir = gyp.common.RelativePath(topsrcdir, objdir)
-  # The directory containing the gyp file on which gyp was invoked.
-  gyp_file_dir = os.path.abspath(os.path.dirname(params['build_files'][0]) or '.')
-  # The relative path from topsrcdir to gyp_file_dir
-  relative_srcdir = gyp.common.RelativePath(gyp_file_dir, topsrcdir)
-  # The relative path from objdir to gyp_file_dir
-  srcdir = gyp.common.RelativePath(gyp_file_dir, objdir)
-  # The absolute path to the source dir
-  abs_srcdir = topsrcdir + "/" + relative_srcdir
-  # The path to get up to the root of the objdir from the output dir.
-  depth = getdepth(relative_srcdir)
-  # The output directory.
-  output_dir = os.path.abspath(options.generator_output or '.')
-  # The path to the root Makefile
-  makefile_path = os.path.join(output_dir, "Makefile")
-
-  def topsrcdir_path(path):
-    return "$(topsrcdir)/" + swapslashes(gyp.common.RelativePath(path, topsrcdir))
-  def objdir_path(path):
-    return "$(DEPTH)/" + swapslashes(gyp.common.RelativePath(path, objdir))
-
-  # Find the list of targets that derive from the gyp file(s) being built.
-  needed_targets = set()
-  build_files = set()
-  for build_file in params['build_files']:
-    build_file = os.path.normpath(build_file)
-    for target in gyp.common.AllTargets(target_list, target_dicts, build_file):
-      needed_targets.add(target)
-      build_file_, _, _ = gyp.common.ParseQualifiedTarget(target)
-      build_files.add(topsrcdir_path(build_file_))
-
-  common_mk_path = objdir_path(os.path.join(output_dir, "common.mk"))
-
-  generator = MakefileGenerator(target_dicts, data, options, depth, topsrcdir, relative_topsrcdir, relative_srcdir, output_dir, flavor, common_mk_path)
-  generator.ProcessTargets(needed_targets)
-
-  # Write the top-level makefile, which simply calls the other makefiles
-  topdata = {'DIRS': generator.dirs}
-  if generator.parallel_dirs:
-    topdata['PARALLEL_DIRS'] = generator.parallel_dirs
-  WriteMakefile(makefile_path, topdata, params['build_files'][0],
-                depth,
-                swapslashes(topsrcdir),
-                swapslashes(abs_srcdir),
-                swapslashes(relative_srcdir),
-                common_mk_path)
-  scriptname = "$(topsrcdir)/media/webrtc/trunk/tools/gyp/pylib/gyp/generator/mozmake.py"
-  # Reassemble a commandline from parts so that all the paths are correct
-  # NOTE: this MUST match the commandline generated in configure.in!
-  # since we don't see --include statements, duplicate them in FORCE_INCLUDE_FILE lines
-  # Being in a define, they also get used by the common.mk invocation of gyp so they
-  # they don't disappear in the second round of tail-swallowing
-  forced_includes = ""
-  for option in options.defines:
-    if option[:20] == "FORCED_INCLUDE_FILE=":
-      forced_includes += "--include=%s" % option[20:]
-
-  commandline = [topsrcdir_path(sys.argv[0]),
-                 "--format=mozmake",
-                 forced_includes,
-                 "--depth=%s" % topsrcdir_path(options.depth),
-                 "--generator-output=%s" % objdir_path(options.generator_output),
-                 "--toplevel-dir=$(topsrcdir)",
-                 "-G OBJDIR=$(DEPTH)"] + \
-                 ['-G %s' % g for g in options.generator_flags if not g.startswith('OBJDIR=')] + \
-                 ['-D%s' % d for d in options.defines] + \
-                 [topsrcdir_path(b) for b in params['build_files']]
-
-  WriteCommonMk(os.path.join(output_dir, "common.mk"),
-                build_files,
-                scriptname,
-                commandline)
--- a/media/webrtc/trunk/tools/gyp/pylib/gyp/input.py
+++ b/media/webrtc/trunk/tools/gyp/pylib/gyp/input.py
@@ -1419,16 +1419,20 @@ class DependencyGraphNode(object):
   class CircularException(GypError):
     pass
 
   def __init__(self, ref):
     self.ref = ref
     self.dependencies = []
     self.dependents = []
 
+  # This Mozilla change makes DependencyGraphNode more idempotent.
+  def __hash__(self):
+    return hash(self.ref)
+
   def FlattenToList(self):
     # flat_list is the sorted list of dependencies - actually, the list items
     # are the "ref" attributes of DependencyGraphNodes.  Every target will
     # appear in flat_list after all of its dependencies, and before all of its
     # dependents.
     flat_list = []
 
     # in_degree_zeros is the list of DependencyGraphNodes that have no
--- a/media/webrtc/trunk/webrtc/modules/audio_coding/codecs/opus/opus.gypi
+++ b/media/webrtc/trunk/webrtc/modules/audio_coding/codecs/opus/opus.gypi
@@ -10,17 +10,17 @@
   'targets': [
     {
       'target_name': 'webrtc_opus',
       'type': 'static_library',
       'conditions': [
         ['build_with_mozilla==1', {
           # Mozilla provides its own build of the opus library.
           'include_dirs': [
-            '$(DIST)/include/opus',
+            '/media/libopus/include',
            ]
         }, {
           'dependencies': [
             '<(DEPTH)/third_party/opus/opus.gyp:opus'
           ],
         }],
       ],
       'sources': [
--- a/media/webrtc/trunk/webrtc/modules/audio_device/audio_device.gypi
+++ b/media/webrtc/trunk/webrtc/modules/audio_device/audio_device.gypi
@@ -42,19 +42,16 @@
         'audio_device_config.h',
         'dummy/audio_device_dummy.cc',
         'dummy/audio_device_dummy.h',
         'dummy/audio_device_utility_dummy.cc',
         'dummy/audio_device_utility_dummy.h',
       ],
       'conditions': [
         ['build_with_mozilla==1', {
-          'include_dirs': [
-            '$(DIST)/include',
-          ],
           'cflags_mozilla': [
             '$(NSPR_CFLAGS)',
           ],
         }],
         ['OS=="linux" or include_alsa_audio==1 or include_pulse_audio==1', {
           'include_dirs': [
             'linux',
           ],
@@ -71,24 +68,26 @@
         }], # OS==mac
         ['OS=="win"', {
           'include_dirs': [
             'win',
           ],
         }],
         ['OS=="android"', {
           'include_dirs': [
-            '$(topsrcdir)/widget/android',
+            '/widget/android',
             'android',
           ],
         }], # OS==android
         ['moz_widget_toolkit_gonk==1', {
+          'cflags_mozilla': [
+            '-I$(ANDROID_SOURCE)/frameworks/wilhelm/include',
+            '-I$(ANDROID_SOURCE)/system/media/wilhelm/include',
+          ],
           'include_dirs': [
-            '$(ANDROID_SOURCE)/frameworks/wilhelm/include',
-            '$(ANDROID_SOURCE)/system/media/wilhelm/include',
             'android',
           ],
         }], # moz_widget_toolkit_gonk==1
         ['enable_android_opensl==1', {
           'include_dirs': [
 	    'opensl',
           ],
         }], # enable_android_opensl
deleted file mode 100644
--- a/media/webrtc/webrtc_config.gypi
+++ /dev/null
@@ -1,54 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-# definitions to control what gets built in webrtc
-# NOTE!!! if you change something here, due to .gyp files not
-# being reprocessed on .gypi changes, run this before building:
-# "find . -name '*.gyp' | xargs touch"
-{
-  'variables': {
-    'build_with_mozilla': 1,
-    'build_with_chromium': 0,
-    # basic stuff for everything
-    'include_internal_video_render': 0,
-    'clang_use_chrome_plugins': 0,
-    'enable_protobuf': 0,
-    'include_tests': 0,
-    'enable_android_opensl': 1,
-# use_system_lib* still seems to be in use in trunk/build
-    'use_system_libjpeg': 0,
-    'use_system_libvpx': 0,
-    'build_libjpeg': 0,
-    'build_libvpx': 0,
-    # saves 4MB when webrtc_trace is off
-    'enable_lazy_trace_alloc': 1,
-
-    # turn off mandatory use of NEON and instead use NEON detection
-    'arm_neon': 0,
-
-    #if "-D build_with_gonk=1", then set moz_widget_toolkit_gonk to 1
-    'moz_widget_toolkit_gonk': 0,
-    'variables': {
-      'build_with_gonk%': 0,
-    },
-    'conditions': [
-      ['build_with_gonk==1', {
-         'moz_widget_toolkit_gonk': 1,
-      }],
-    ],
-# (for vp8) chromium sets to 0 also
-    'use_temporal_layers': 0,
-# Creates AEC internal sample dump files in current directory
-#    'aec_debug_dump': 1,
-
-    # codec enable/disables:
-    # Note: if you change one here, you must modify layout/media/webrtc/Makefile.in!
-    'include_g711': 1,
-    'include_opus': 1,
-    'include_g722': 0,
-    'include_ilbc': 0,
-    'include_isac': 0,
-    'include_pcm16b': 1,
-  }
-}
--- a/python/mozbuild/mozbuild/backend/recursivemake.py
+++ b/python/mozbuild/mozbuild/backend/recursivemake.py
@@ -88,17 +88,16 @@ class BackendMakeFile(object):
 
         # XPIDLFiles attached to this file.
         self.idls = []
         self.xpt_name = None
 
         self.fh = FileAvoidWrite(self.name, capture_diff=True)
         self.fh.write('# THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT.\n')
         self.fh.write('\n')
-        self.fh.write('MOZBUILD_DERIVED := 1\n')
 
     def write(self, buf):
         self.fh.write(buf)
 
     # For compatibility with makeutil.Makefile
     def add_statement(self, stmt):
         self.write('%s\n' % stmt)
 
--- a/python/mozbuild/mozbuild/frontend/emitter.py
+++ b/python/mozbuild/mozbuild/frontend/emitter.py
@@ -44,16 +44,18 @@ from .data import (
     XPIDLFile,
 )
 
 from .reader import (
     MozbuildSandbox,
     SandboxValidationError,
 )
 
+from .gyp_reader import GypSandbox
+
 
 class TreeMetadataEmitter(LoggingMixin):
     """Converts the executed mozbuild files into data structures.
 
     This is a bridge between reader.py and data.py. It takes what was read by
     reader.BuildReader and converts it into the classes defined in the data
     module.
     """
@@ -86,33 +88,33 @@ class TreeMetadataEmitter(LoggingMixin):
 
         def emit_objs(objs):
             for o in objs:
                 yield o
                 if not o._ack:
                     raise Exception('Unhandled object of type %s' % type(o))
 
         for out in output:
-            if isinstance(out, MozbuildSandbox):
+            if isinstance(out, (MozbuildSandbox, GypSandbox)):
                 # Keep all sandboxes around, we will need them later.
                 sandboxes[out['OBJDIR']] = out
 
                 start = time.time()
                 # We need to expand the generator for the timings to work.
                 objs = list(self.emit_from_sandbox(out))
                 emitter_time += time.time() - start
 
                 for o in emit_objs(objs): yield o
 
                 # Update the stats.
                 file_count += len(out.all_paths)
                 sandbox_execution_time += out.execution_time
 
             else:
-                raise Exception('Unhandled output type: %s' % out)
+                raise Exception('Unhandled output type: %s' % type(out))
 
         start = time.time()
         objs = list(self._emit_libs_derived(sandboxes))
         emitter_time += time.time() - start
 
         for o in emit_objs(objs): yield o
 
         yield ReaderSummary(file_count, sandbox_execution_time, emitter_time)
@@ -204,37 +206,40 @@ class TreeMetadataEmitter(LoggingMixin):
         # desired abstraction of the build definition away from makefiles.
         passthru = VariablePassthru(sandbox)
         varmap = dict(
             # Makefile.in : moz.build
             ANDROID_GENERATED_RESFILES='ANDROID_GENERATED_RESFILES',
             ANDROID_RES_DIRS='ANDROID_RES_DIRS',
             CPP_UNIT_TESTS='CPP_UNIT_TESTS',
             EXPORT_LIBRARY='EXPORT_LIBRARY',
+            EXTRA_ASSEMBLER_FLAGS='EXTRA_ASSEMBLER_FLAGS',
+            EXTRA_COMPILE_FLAGS='EXTRA_COMPILE_FLAGS',
             EXTRA_COMPONENTS='EXTRA_COMPONENTS',
             EXTRA_JS_MODULES='EXTRA_JS_MODULES',
             EXTRA_PP_COMPONENTS='EXTRA_PP_COMPONENTS',
             EXTRA_PP_JS_MODULES='EXTRA_PP_JS_MODULES',
             FAIL_ON_WARNINGS='FAIL_ON_WARNINGS',
             FILES_PER_UNIFIED_FILE='FILES_PER_UNIFIED_FILE',
             FORCE_SHARED_LIB='FORCE_SHARED_LIB',
             FORCE_STATIC_LIB='FORCE_STATIC_LIB',
             GENERATED_FILES='GENERATED_FILES',
             HOST_LIBRARY_NAME='HOST_LIBRARY_NAME',
             IS_COMPONENT='IS_COMPONENT',
+            IS_GYP_DIR='IS_GYP_DIR',
             JS_MODULES_PATH='JS_MODULES_PATH',
             LIBS='LIBS',
             LIBXUL_LIBRARY='LIBXUL_LIBRARY',
             MSVC_ENABLE_PGO='MSVC_ENABLE_PGO',
             NO_DIST_INSTALL='NO_DIST_INSTALL',
             OS_LIBS='OS_LIBS',
             SDK_LIBRARY='SDK_LIBRARY',
         )
         for mak, moz in varmap.items():
-            if sandbox[moz]:
+            if moz in sandbox and sandbox[moz]:
                 passthru.variables[mak] = sandbox[moz]
 
         # NO_VISIBILITY_FLAGS is slightly different
         if sandbox['NO_VISIBILITY_FLAGS']:
             passthru.variables['VISIBILITY_FLAGS'] = ''
 
         varmap = dict(
             SOURCES={
new file mode 100644
--- /dev/null
+++ b/python/mozbuild/mozbuild/frontend/gyp_reader.py
@@ -0,0 +1,190 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.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 gyp
+import sys
+import time
+import os
+import mozpack.path as mozpath
+from mozpack.files import FileFinder
+from .sandbox import (
+    alphabetical_sorted,
+    GlobalNamespace,
+)
+from .sandbox_symbols import VARIABLES
+
+# Define this module as gyp.generator.mozbuild so that gyp can use it
+# as a generator under the name "mozbuild".
+sys.modules['gyp.generator.mozbuild'] = sys.modules[__name__]
+
+# build/gyp_chromium does this:
+#   script_dir = os.path.dirname(os.path.realpath(__file__))
+#   chrome_src = os.path.abspath(os.path.join(script_dir, os.pardir))
+#   sys.path.insert(0, os.path.join(chrome_src, 'tools', 'gyp', 'pylib'))
+# We're not importing gyp_chromium, but we want both script_dir and
+# chrome_src for the default includes, so go backwards from the pylib
+# directory, which is the parent directory of gyp module.
+chrome_src = mozpath.abspath(mozpath.join(mozpath.dirname(gyp.__file__),
+    '../../../..'))
+script_dir = mozpath.join(chrome_src, 'build')
+
+# Default variables gyp uses when evaluating gyp files.
+generator_default_variables = {
+}
+for dirname in ['INTERMEDIATE_DIR', 'SHARED_INTERMEDIATE_DIR', 'PRODUCT_DIR',
+                'LIB_DIR', 'SHARED_LIB_DIR']:
+  # Some gyp steps fail if these are empty(!).
+  generator_default_variables[dirname] = b'dir'
+
+for unused in ['RULE_INPUT_PATH', 'RULE_INPUT_ROOT', 'RULE_INPUT_NAME',
+               'RULE_INPUT_DIRNAME', 'RULE_INPUT_EXT',
+               'EXECUTABLE_PREFIX', 'EXECUTABLE_SUFFIX',
+               'STATIC_LIB_PREFIX', 'STATIC_LIB_SUFFIX',
+               'SHARED_LIB_PREFIX', 'SHARED_LIB_SUFFIX',
+               'LINKER_SUPPORTS_ICF']:
+  generator_default_variables[unused] = b''
+
+
+class GypSandbox(GlobalNamespace):
+    """Class mimicking MozbuildSandbox for processing of the data
+    extracted from Gyp by a mozbuild backend.
+
+    Inherits from GlobalNamespace because it doesn't need the extra
+    functionality from Sandbox.
+    """
+    def __init__(self, main_path, dependencies_paths=[]):
+        self.main_path = main_path
+        self.all_paths = set([main_path]) | set(dependencies_paths)
+        self.execution_time = 0
+        GlobalNamespace.__init__(self, allowed_variables=VARIABLES)
+
+    def get_affected_tiers(self):
+        tiers = (VARIABLES[key][3] for key in self if key in VARIABLES)
+        return set(tier for tier in tiers if tier)
+
+
+def encode(value):
+    if isinstance(value, unicode):
+        return value.encode('utf-8')
+    return value
+
+
+def read_from_gyp(config, path, output, vars):
+    """Read a gyp configuration and emits GypSandboxes for the backend to
+    process.
+
+    config is a ConfigEnvironment, path is the path to a root gyp configuration
+    file, output is the base path under which the objdir for the various gyp
+    dependencies will be, and vars a dict of variables to pass to the gyp
+    processor.
+    """
+
+    time_start = time.time()
+
+    # gyp expects plain str instead of unicode. The frontend code gives us
+    # unicode strings, so convert them.
+    path = encode(path)
+    str_vars = dict((name, encode(value)) for name, value in vars.items())
+
+    params = {
+        b'parallel': False,
+        b'generator_flags': {},
+        b'build_files': [path],
+    }
+
+    # Files that gyp_chromium always includes
+    includes = [encode(mozpath.join(script_dir, 'common.gypi'))]
+    finder = FileFinder(chrome_src, find_executables=False)
+    includes.extend(encode(mozpath.join(chrome_src, name))
+        for name, _ in finder.find('*/supplement.gypi'))
+
+    # Read the given gyp file and its dependencies.
+    generator, flat_list, targets, data = \
+        gyp.Load([path], format=b'mozbuild',
+            default_variables=str_vars,
+            includes=includes,
+            depth=encode(mozpath.dirname(path)),
+            params=params)
+
+    # Process all targets from the given gyp files and its dependencies.
+    # The path given to AllTargets needs to use os.sep, while the frontend code
+    # gives us paths normalized with forward slash separator.
+    for target in gyp.common.AllTargets(flat_list, targets, path.replace(b'/', os.sep)):
+        build_file, target_name, toolset = gyp.common.ParseQualifiedTarget(target)
+        # The list of included files returned by gyp are relative to build_file
+        included_files = [mozpath.abspath(mozpath.join(mozpath.dirname(build_file), f))
+                          for f in data[build_file]['included_files']]
+        # Emit a sandbox for each target.
+        sandbox = GypSandbox(mozpath.abspath(build_file), included_files)
+
+        with sandbox.allow_all_writes() as d:
+            topsrcdir = d['TOPSRCDIR'] = config.topsrcdir
+            d['TOPOBJDIR'] = config.topobjdir
+            relsrcdir = d['RELATIVEDIR'] = mozpath.relpath(mozpath.dirname(build_file), config.topsrcdir)
+            d['SRCDIR'] = mozpath.join(topsrcdir, relsrcdir)
+
+            # Each target is given its own objdir. The base of that objdir
+            # is derived from the relative path from the root gyp file path
+            # to the current build_file, placed under the given output
+            # directory. Since several targets can be in a given build_file,
+            # separate them in subdirectories using the build_file basename
+            # and the target_name.
+            reldir  = mozpath.relpath(mozpath.dirname(build_file),
+                                      mozpath.dirname(path))
+            subdir = '%s_%s' % (
+                mozpath.splitext(mozpath.basename(build_file))[0],
+                target_name,
+            )
+            d['OBJDIR'] = mozpath.join(output, reldir, subdir)
+            d['IS_GYP_DIR'] = True
+
+        spec = targets[target]
+
+        # Derive which gyp configuration to use based on MOZ_DEBUG.
+        c = 'Debug' if config.substs['MOZ_DEBUG'] else 'Release'
+        if c not in spec['configurations']:
+            raise RuntimeError('Missing %s gyp configuration for target %s '
+                               'in %s' % (c, target_name, build_file))
+        target_conf = spec['configurations'][c]
+
+        if spec['type'] == 'none':
+            continue
+        elif spec['type'] == 'static_library':
+            sandbox['FORCE_STATIC_LIB'] = True
+            # Remove leading 'lib' from the target_name if any, and use as
+            # library name.
+            name = spec['target_name']
+            if name.startswith('lib'):
+                name = name[3:]
+            # The sandbox expects an unicode string.
+            sandbox['LIBRARY_NAME'] = name.decode('utf-8')
+            # The sandbox expects alphabetical order when adding sources
+            sources = alphabetical_sorted(spec.get('sources', []))
+            # gyp files contain headers in sources lists.
+            sandbox['SOURCES'] = \
+                [f for f in sources if mozpath.splitext(f)[-1] != '.h']
+
+            for define in target_conf.get('defines', []):
+                if '=' in define:
+                    name, value = define.split('=', 1)
+                    sandbox['DEFINES'][name] = value
+                else:
+                    sandbox['DEFINES'][define] = True
+
+            for include in target_conf.get('include_dirs', []):
+                sandbox['LOCAL_INCLUDES'] += [include]
+
+            with sandbox.allow_all_writes() as d:
+                d['EXTRA_ASSEMBLER_FLAGS'] = target_conf.get('asflags_mozilla', [])
+                d['EXTRA_COMPILE_FLAGS'] = target_conf.get('cflags_mozilla', [])
+        else:
+            # Ignore other types than static_library because we don't have
+            # anything using them, and we're not testing them. They can be
+            # added when that becomes necessary.
+            raise NotImplementedError('Unsupported gyp target type: %s' % spec['type'])
+
+        sandbox.execution_time = time.time() - time_start
+        yield sandbox
+        time_start = time.time()
--- a/python/mozbuild/mozbuild/frontend/reader.py
+++ b/python/mozbuild/mozbuild/frontend/reader.py
@@ -54,17 +54,16 @@ from .sandbox import (
     Sandbox,
 )
 
 from .sandbox_symbols import (
     FUNCTIONS,
     VARIABLES,
 )
 
-
 if sys.version_info.major == 2:
     text_type = unicode
     type_type = types.TypeType
 else:
     text_type = str
     type_type = type
 
 
@@ -729,35 +728,68 @@ class BuildReader(object):
             matches = [v for v in forbidden[var] if sandbox[v]]
             if matches:
                 raise SandboxValidationError('%s is registered as %s in %s/moz.build.\n'
                     'The %s variable%s not allowed in such directories.'
                     % (sandbox['RELATIVEDIR'], var, metadata['parent'],
                        ' and '.join(', '.join(matches).rsplit(', ', 1)),
                        's are' if len(matches) > 1 else ' is'))
 
-        yield sandbox
-
-        # Traverse into referenced files.
-
         # We first collect directories populated in variables.
         dir_vars = ['DIRS', 'PARALLEL_DIRS', 'TOOL_DIRS']
 
         if self.config.substs.get('ENABLE_TESTS', False) == '1':
             dir_vars.extend(['TEST_DIRS', 'TEST_TOOL_DIRS'])
 
+        dirs = [(v, sandbox[v]) for v in dir_vars if v in sandbox]
+
+        curdir = mozpath.dirname(path)
+
+        gyp_sandboxes = []
+        for target_dir in sandbox['GYP_DIRS']:
+            gyp_dir = sandbox['GYP_DIRS'][target_dir]
+            for v in ('input', 'variables'):
+                if not getattr(gyp_dir, v):
+                    raise Exception('Missing value for GYP_DIRS["%s"].%s' %
+                        (target_dir, v))
+
+            # The make backend assumes sandboxes for sub-directories are
+            # emitted after their parent, so accumulate the gyp sandboxes.
+            # We could emit the parent sandbox before processing gyp
+            # configuration, but we need to add the gyp objdirs to that sandbox
+            # first.
+            from .gyp_reader import read_from_gyp
+            gyp_sandboxes.extend(read_from_gyp(self.config,
+                                               mozpath.join(curdir, gyp_dir.input),
+                                               mozpath.join(sandbox['OBJDIR'],
+                                               target_dir),
+                                 gyp_dir.variables))
+
+        # Add the gyp subdirectories to DIRS. We don't care about trying to
+        # place some of them in PARALLEL_DIRS because they're only going to be
+        # relevant for the compile and libs tiers. The compile tier is already
+        # parallelized, and the libs tier is always serialized, and will remain
+        # so until the library linking operations are moved out of it, at which
+        # point PARALLEL_DIRS will be irrelevant anyways.
+        for gyp_sandbox in gyp_sandboxes:
+            sandbox['DIRS'].append(mozpath.relpath(gyp_sandbox['OBJDIR'], sandbox['OBJDIR']))
+
+        yield sandbox
+
+        for gyp_sandbox in gyp_sandboxes:
+            yield gyp_sandbox
+
+        # Traverse into referenced files.
+
         # It's very tempting to use a set here. Unfortunately, the recursive
         # make backend needs order preserved. Once we autogenerate all backend
         # files, we should be able to convert this to a set.
         recurse_info = OrderedDict()
-        for var in dir_vars:
-            if not var in sandbox:
-                continue
-
-            for d in sandbox[var]:
+        for var, var_dirs in dirs:
+            for d in var_dirs:
                 if d in recurse_info:
                     raise SandboxValidationError(
                         'Directory (%s) registered multiple times in %s' % (
                             d, var))
 
                 recurse_info[d] = {'tier': metadata.get('tier', None),
                                    'parent': sandbox['RELATIVEDIR'],
                                    'var': var}
@@ -778,17 +810,16 @@ class BuildReader(object):
                     if d in recurse_info:
                         raise SandboxValidationError(
                             'Tier directory (%s) registered multiple '
                             'times in %s' % (d, tier))
                     recurse_info[d] = {'tier': tier,
                                        'parent': sandbox['RELATIVEDIR'],
                                        'var': 'DIRS'}
 
-        curdir = mozpath.dirname(path)
         for relpath, child_metadata in recurse_info.items():
             child_path = mozpath.join(curdir, relpath, 'moz.build')
 
             # Ensure we don't break out of the topsrcdir. We don't do realpath
             # because it isn't necessary. If there are symlinks in the srcdir,
             # that's not our problem. We're not a hosted application: we don't
             # need to worry about security too much.
             child_path = mozpath.normpath(child_path)
--- a/python/mozbuild/mozbuild/frontend/sandbox_symbols.py
+++ b/python/mozbuild/mozbuild/frontend/sandbox_symbols.py
@@ -568,16 +568,41 @@ VARIABLES = {
 
         The directory is relative to the top of the object directory. The
         default value is dependent on the values of XPI_NAME and DIST_SUBDIR. If
         neither are present, the result is dist/bin. If XPI_NAME is present, the
         result is dist/xpi-stage/$(XPI_NAME). If DIST_SUBDIR is present, then
         the $(DIST_SUBDIR) directory of the otherwise default value is used.
         """, 'libs'),
 
+    'GYP_DIRS': (StrictOrderingOnAppendListWithFlagsFactory({
+            'variables': dict,
+            'input': unicode,
+        }), list,
+        """Defines a list of object directories handled by gyp configurations.
+
+        Elements of this list give the relative object directory. For each
+        element of the list, GYP_DIRS may be accessed as a dictionary
+        (GYP_DIRS[foo]). The object this returns has attributes that need to be
+        set to further specify gyp processing:
+            - input, gives the path to the root gyp configuration file for that
+              object directory.
+            - variables, a dictionary containing variables and values to pass
+              to the gyp processor.
+
+        Typical use looks like:
+            GYP_DIRS += ['foo', 'bar']
+            GYP_DIRS['foo'].input = 'foo/foo.gyp'
+            GYP_DIRS['foo'].variables = {
+                'foo': 'bar',
+                (...)
+            }
+            (...)
+        """, None),
+
     'SPHINX_TREES': (dict, dict,
         """Describes what the Sphinx documentation tree will look like.
 
         Keys are relative directories inside the final Sphinx documentation
         tree to install files into. Values are directories (relative to this
         file) whose content to copy into the Sphinx documentation tree.
         """, None),
 
--- a/python/mozbuild/mozbuild/test/backend/test_recursivemake.py
+++ b/python/mozbuild/mozbuild/test/backend/test_recursivemake.py
@@ -207,17 +207,16 @@ class TestRecursiveMakeBackend(BackendTe
     def test_backend_mk(self):
         """Ensure backend.mk file is written out properly."""
         env = self._consume('stub0', RecursiveMakeBackend)
 
         p = mozpath.join(env.topobjdir, 'backend.mk')
 
         lines = [l.strip() for l in open(p, 'rt').readlines()[2:]]
         self.assertEqual(lines, [
-            'MOZBUILD_DERIVED := 1',
             'DIRS := dir1',
             'PARALLEL_DIRS := dir2',
             'TEST_DIRS := dir3',
         ])
 
     def test_mtime_no_change(self):
         """Ensure mtime is not updated if file content does not change."""
 
@@ -238,17 +237,16 @@ class TestRecursiveMakeBackend(BackendTe
 
     def test_external_make_dirs(self):
         """Ensure we have make recursion into external make directories."""
         env = self._consume('external_make_dirs', RecursiveMakeBackend)
 
         backend_path = mozpath.join(env.topobjdir, 'backend.mk')
         lines = [l.strip() for l in open(backend_path, 'rt').readlines()[2:]]
         self.assertEqual(lines, [
-            'MOZBUILD_DERIVED := 1',
             'DIRS := dir',
             'PARALLEL_DIRS := p_dir',
             'DIRS += external',
             'PARALLEL_DIRS += p_external',
         ])
 
     def test_substitute_config_files(self):
         """Ensure substituted config files are produced."""