Bug 844288 - Dual link libxul.so and libxul-unit.so and replace enable-gtest by enable-test r=ted,glandium
☠☠ backed out by e4f940af8df8 ☠ ☠
authorBenoit Girard <b56girard@gmail.com>
Mon, 11 Mar 2013 14:47:40 -0400
changeset 144868 816311e43409f6f82c38043fb23a9ed452e8f1a8
parent 144867 c2f79f1f9e6f07d08c23cdf68bd8e56326177712
child 144869 3bead9d0a8a058e8ed1be0f75e9ef5f5f7d36c40
push id2697
push userbbajaj@mozilla.com
push dateMon, 05 Aug 2013 18:49:53 +0000
treeherdermozilla-beta@dfec938c7b63 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersted, glandium
bugs844288
milestone24.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 844288 - Dual link libxul.so and libxul-unit.so and replace enable-gtest by enable-test r=ted,glandium - Remove enable GTest - Add a general target to create gtestxul - Update mach target - Run GTest from make check
configure.in
gfx/2d/Makefile.in
gfx/2d/unittest/GTestMain.cpp
gfx/layers/Makefile.in
gfx/layers/TestTiledLayerBuffer.cpp
gfx/moz.build
gfx/tests/gtest/Makefile.in
gfx/tests/gtest/TestMoz2D.cpp
gfx/tests/gtest/TestTiledLayerBuffer.cpp
gfx/tests/gtest/moz.build
js/src/configure.in
python/mozbuild/mozbuild/mach_commands.py
testing/gtest/Makefile.in
testing/gtest/mozilla/GTestRunner.cpp
testing/gtest/mozilla/GTestRunner.h
toolkit/library/Makefile.in
toolkit/library/winvccorlib/Makefile.in
toolkit/toolkit.mozbuild
toolkit/xre/nsAppRunner.cpp
xpcom/glue/standalone/nsXPCOMGlue.cpp
--- a/configure.in
+++ b/configure.in
@@ -1324,18 +1324,18 @@ dnl ====================================
 dnl GNU specific defaults
 dnl ========================================================
 if test "$GNU_CC"; then
     # Per bug 719659 comment 2, some of the headers on ancient build machines
     # may require gnu89 inline semantics.  But otherwise, we use C99.
     CFLAGS="$CFLAGS -std=gnu99 -fgnu89-inline"
     # FIXME: Let us build with strict aliasing. bug 414641.
     CFLAGS="$CFLAGS -fno-strict-aliasing"
-    MKSHLIB='$(CXX) $(CXXFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -Wl,-h,$@ -o $@'
-    MKCSHLIB='$(CC) $(CFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -Wl,-h,$@ -o $@'
+    MKSHLIB='$(CXX) $(CXXFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -Wl,-h,$(notdir $@) -o $@'
+    MKCSHLIB='$(CC) $(CFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -Wl,-h,$(notdir $@) -o $@'
     DSO_LDOPTS='-shared'
     if test "$GCC_USE_GNU_LD"; then
         # Some tools like ASan use a runtime library that is only
         # linked against executables, so we must allow undefined
         # symbols for shared objects in some cases.
         if test -z "$MOZ_NO_WLZDEFS"; then
             # Don't allow undefined symbols in libraries
             DSO_LDOPTS="$DSO_LDOPTS -Wl,-z,defs"
@@ -1435,18 +1435,18 @@ elif test "$SOLARIS_SUNPRO_CC"; then
     if test "$CPU_ARCH" = "sparc"; then
         # for Sun Studio on Solaris/SPARC
         DSO_PIC_CFLAGS='-xcode=pic32'
     else
         DSO_PIC_CFLAGS='-KPIC'
     fi
     _DEFINES_CFLAGS='$(ACDEFINES) -D_MOZILLA_CONFIG_H_ -DMOZILLA_CLIENT'
 else
-    MKSHLIB='$(LD) $(DSO_LDOPTS) -h $@ -o $@'
-    MKCSHLIB='$(LD) $(DSO_LDOPTS) -h $@ -o $@'
+    MKSHLIB='$(LD) $(DSO_LDOPTS) -h $(notdir $@) -o $@'
+    MKCSHLIB='$(LD) $(DSO_LDOPTS) -h $(notdir $@) -o $@'
 
     DSO_LDOPTS='-shared'
     if test "$GNU_LD"; then
         # Don't allow undefined symbols in libraries
         DSO_LDOPTS="$DSO_LDOPTS -z defs"
     fi
 
     DSO_CFLAGS=''
@@ -2294,18 +2294,18 @@ ia64*-hpux*)
     	DSO_LDOPTS='-shared'
     fi
     # This will fail on a.out systems prior to 1.5.1_ALPHA.
     MKSHLIB_FORCE_ALL='-Wl,--whole-archive'
     MKSHLIB_UNFORCE_ALL='-Wl,--no-whole-archive'
     if test "$LIBRUNPATH"; then
 	DSO_LDOPTS="-Wl,-R$LIBRUNPATH $DSO_LDOPTS"
     fi
-    MKSHLIB='$(CXX) $(CXXFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -Wl,-soname,lib$(LIBRARY_NAME)$(DLL_SUFFIX) -o $@'
-    MKCSHLIB='$(CC) $(CFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -Wl,-soname,lib$(LIBRARY_NAME)$(DLL_SUFFIX) -o $@'
+    MKSHLIB='$(CXX) $(CXXFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -Wl,-soname,$(notdir $@) -o $@'
+    MKCSHLIB='$(CC) $(CFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -Wl,-soname,$(notdir $@)) -o $@'
     ;;
 
 *-openbsd*)
     if test "$SO_VERSION"; then
         DLL_SUFFIX=".so.$SO_VERSION"
     else
         DLL_SUFFIX=".so.1.0"
     fi
@@ -2401,18 +2401,18 @@ ia64*-hpux*)
            _SAVE_LDFLAGS=$LDFLAGS
            LDFLAGS="-M /usr/lib/ld/map.noexstk $LDFLAGS"
            AC_TRY_LINK([#include <stdio.h>],
                        [printf("Hello World\n");],
                        ,
                        [LDFLAGS=$_SAVE_LDFLAGS])
        fi
        MOZ_OPTIMIZE_FLAGS="-xO4"
-       MKSHLIB='$(CXX) $(CXXFLAGS) $(DSO_PIC_FLAGS) $(DSO_LDOPTS) -h $@ -o $@'
-       MKCSHLIB='$(CC) $(CFLAGS) $(DSO_PIC_FLAGS) $(DSO_LDOPTS) -h $@ -o $@'
+       MKSHLIB='$(CXX) $(CXXFLAGS) $(DSO_PIC_FLAGS) $(DSO_LDOPTS) -h $(notdir $@) -o $@'
+       MKCSHLIB='$(CC) $(CFLAGS) $(DSO_PIC_FLAGS) $(DSO_LDOPTS) -h $(notdir $@) -o $@'
        MKSHLIB_FORCE_ALL='-z allextract'
        MKSHLIB_UNFORCE_ALL='-z defaultextract'
        DSO_LDOPTS='-G'
        AR_LIST="$AR t"
        AR_EXTRACT="$AR x"
        AR_DELETE="$AR d"
        AR='$(CXX) -xar'
        AR_FLAGS='-o $@'
@@ -6381,35 +6381,24 @@ AC_SUBST(MOZ_UPDATE_PACKAGING)
 dnl ========================================================
 dnl build the tests by default
 dnl ========================================================
 MOZ_ARG_DISABLE_BOOL(tests,
 [  --disable-tests         Do not build test libraries & programs],
     ENABLE_TESTS=,
     ENABLE_TESTS=1 )
 
-# Currently GTest is linked into libxul. This means it must be off by default.
-# Follow up will be to generate libxul.so and libxul-test.so to let GTest
-# be compiled along with ENABLE_TESTS
-MOZ_ARG_ENABLE_BOOL(gtest,
-[  --enable-gtest
-                          Enable GTest libxul unit test.],
-    MOZ_ENABLE_GTEST=1,
-    MOZ_ENABLE_GTEST= )
-
-if test -n "$MOZ_ENABLE_GTEST"; then
+if test -n "$ENABLE_TESTS"; then
     if test "${OS_TARGET}" = "WINNT" -o "${OS_TARGET}" = "Darwin" -o "${OS_TARGET}" = "Linux" -o "${OS_TARGET}" = "Android"; then
         MOZ_ENABLE_GTEST=1
         GTEST_HAS_RTTI=0
         AC_DEFINE(MOZ_ENABLE_GTEST)
         AC_DEFINE_UNQUOTED(GTEST_HAS_RTTI, 0)
         AC_SUBST(MOZ_ENABLE_GTEST)
         AC_SUBST(GTEST_HAS_RTTI)
-    else
-        AC_MSG_ERROR([Cannot build with --enable-gtest on this platform.])
     fi
     if test "${OS_TARGET}" = "Android"; then
         AC_DEFINE(GTEST_OS_LINUX_ANDROID)
         AC_DEFINE(GTEST_USE_OWN_TR1_TUPLE)
         AC_DEFINE_UNQUOTED(GTEST_HAS_CLONE, 0)
         AC_SUBST(GTEST_OS_LINUX_ANDROID)
         AC_SUBST(GTEST_USE_OWN_TR1_TUPLE)
         AC_SUBST(GTEST_HAS_CLONE)
--- a/gfx/2d/Makefile.in
+++ b/gfx/2d/Makefile.in
@@ -10,24 +10,16 @@ VPATH		=  $(srcdir) $(srcdir)/unittest
 
 include $(DEPTH)/config/autoconf.mk
 
 LIBRARY_NAME	= gfx2d
 MSVC_ENABLE_PGO := 1
 LIBXUL_LIBRARY	= 1
 EXPORT_LIBRARY	= 1
 
-GTEST_CPPSRCS = \
-        GTestMain.cpp \
-        TestBase.cpp \
-        TestPoint.cpp \
-        TestScaling.cpp \
-        TestCairo.cpp \
-        $(NULL)
-
 ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
 CMMSRCS = \
 	   QuartzSupport.mm \
 	   $(NULL)
 endif
 
 DEFINES += -DMOZ_GFX -DUSE_CAIRO -DGFX2D_INTERNAL
 
--- a/gfx/layers/Makefile.in
+++ b/gfx/layers/Makefile.in
@@ -25,20 +25,16 @@ MSVC_ENABLE_PGO := 1
 LIBXUL_LIBRARY = 1
 FORCE_STATIC_LIB = 1
 
 DEFINES += -DIMPL_THEBES
 ifdef MOZ_DEBUG
 DEFINES += -DD3D_DEBUG_INFO
 endif
 
-GTEST_CPPSRCS = \
-        TestTiledLayerBuffer.cpp \
-        $(NULL)
-
 ifdef MOZ_ENABLE_D3D10_LAYER
 DEFINES	+= -DMOZ_ENABLE_D3D10_LAYER
 endif
 
 include $(topsrcdir)/config/rules.mk
 
 include $(topsrcdir)/ipc/chromium/chromium-config.mk
 
--- a/gfx/moz.build
+++ b/gfx/moz.build
@@ -20,12 +20,15 @@ DIRS += [
     'ots/src',
     'thebes',
     'ipc',
 ]
 
 if CONFIG['MOZ_ENABLE_SKIA']:
     DIRS += ['skia']
 
+if CONFIG['ENABLE_TESTS']:
+    DIRS += ['tests/gtest']
+
 TEST_TOOL_DIRS += ['tests']
 
 MODULE = 'gfx'
 
new file mode 100644
--- /dev/null
+++ b/gfx/tests/gtest/Makefile.in
@@ -0,0 +1,43 @@
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+DEPTH          = @DEPTH@
+topsrcdir      = @top_srcdir@
+srcdir         = @srcdir@
+VPATH          = @srcdir@ $(srcdir)/$(DEPTH)/gfx/2d/unittest
+relativesrcdir = @relativesrcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+# Create a GTest library
+MODULE_NAME    = gfxtest
+LIBRARY_NAME   = gfxtest
+LIBXUL_LIBRARY = 1
+IS_COMPONENT   = 1
+EXPORT_LIBRARY = 1
+
+LOCAL_INCLUDES = \
+  -I$(topsrcdir)/gfx/layers \
+  -I$(topsrcdir)/gfx/2d \
+  -I$(topsrcdir)/gfx/2d/unittest \
+  $(NULL)
+
+GTEST_CPPSRCS = \
+  TestTiledLayerBuffer.cpp \
+  $(NULL)
+
+# Because of gkmedia on windows we wont find these
+# symbols in xul.dll.
+ifneq ($(MOZ_WIDGET_TOOLKIT),windows)
+GTEST_CPPSRCS += \
+  TestMoz2D.cpp \
+  TestBase.cpp \
+  TestPoint.cpp \
+  TestScaling.cpp \
+  $(NULL)
+endif
+
+include $(topsrcdir)/config/rules.mk
+
rename from gfx/2d/unittest/GTestMain.cpp
rename to gfx/tests/gtest/TestMoz2D.cpp
rename from gfx/layers/TestTiledLayerBuffer.cpp
rename to gfx/tests/gtest/TestTiledLayerBuffer.cpp
new file mode 100644
--- /dev/null
+++ b/gfx/tests/gtest/moz.build
@@ -0,0 +1,8 @@
+# -*- 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/.
+
+MODULE = 'gfxtest'
+
--- a/js/src/configure.in
+++ b/js/src/configure.in
@@ -1146,18 +1146,18 @@ fi
 
 dnl ========================================================
 dnl GNU specific defaults
 dnl ========================================================
 if test "$GNU_CC"; then
     # Per bug 719659 comment 2, some of the headers on ancient build machines
     # may require gnu89 inline semantics.  But otherwise, we use C99.
     CFLAGS="$CFLAGS -std=gnu99 -fgnu89-inline"
-    MKSHLIB='$(CXX) $(CXXFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -Wl,-h,$@ -o $@'
-    MKCSHLIB='$(CC) $(CFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -Wl,-h,$@ -o $@'
+    MKSHLIB='$(CXX) $(CXXFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -Wl,-h,$(notdir $@) -o $@'
+    MKCSHLIB='$(CC) $(CFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -Wl,-h,$(notdir $@) -o $@'
     DSO_LDOPTS='-shared'
     if test "$GCC_USE_GNU_LD"; then
         # Some tools like ASan use a runtime library that is only
         # linked against executables, so we must allow undefined
         # symbols for shared objects in some cases.
         if test -z "$MOZ_NO_WLZDEFS"; then
             # Don't allow undefined symbols in libraries
             DSO_LDOPTS="$DSO_LDOPTS -Wl,-z,defs"
@@ -1220,18 +1220,18 @@ elif test "$SOLARIS_SUNPRO_CC"; then
     if test "$CPU_ARCH" = "sparc"; then
         # for Sun Studio on Solaris/SPARC
         DSO_PIC_CFLAGS='-xcode=pic32'
     else
         DSO_PIC_CFLAGS='-KPIC'
     fi
     _DEFINES_CFLAGS='$(ACDEFINES) -D_JS_CONFDEFS_H_ -DMOZILLA_CLIENT'
 else
-    MKSHLIB='$(LD) $(DSO_LDOPTS) -h $@ -o $@'
-    MKCSHLIB='$(LD) $(DSO_LDOPTS) -h $@ -o $@'
+    MKSHLIB='$(LD) $(DSO_LDOPTS) -h $(notdir $@) -o $@'
+    MKCSHLIB='$(LD) $(DSO_LDOPTS) -h $(notdir $@) -o $@'
 
     DSO_LDOPTS='-shared'
     if test "$GNU_LD"; then
         # Don't allow undefined symbols in libraries
         DSO_LDOPTS="$DSO_LDOPTS -z defs"
     fi
 
     DSO_CFLAGS=''
@@ -1840,18 +1840,18 @@ ia64*-hpux*)
     	DSO_LDOPTS='-shared'
     fi
     # This will fail on a.out systems prior to 1.5.1_ALPHA.
     MKSHLIB_FORCE_ALL='-Wl,--whole-archive'
     MKSHLIB_UNFORCE_ALL='-Wl,--no-whole-archive'
     if test "$LIBRUNPATH"; then
 	DSO_LDOPTS="-Wl,-R$LIBRUNPATH $DSO_LDOPTS"
     fi
-    MKSHLIB='$(CXX) $(CXXFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -Wl,-soname,lib$(LIBRARY_NAME)$(DLL_SUFFIX) -o $@'
-    MKCSHLIB='$(CC) $(CFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -Wl,-soname,lib$(LIBRARY_NAME)$(DLL_SUFFIX) -o $@'
+    MKSHLIB='$(CXX) $(CXXFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -Wl,-soname,$(notdir $@) -o $@'
+    MKCSHLIB='$(CC) $(CFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -Wl,-soname,$(notdir $@) -o $@'
     ;;
 
 *-openbsd*)
     DLL_SUFFIX=".so.1.0"
     DSO_CFLAGS=''
     DSO_PIC_CFLAGS='-fPIC'
     DSO_LDOPTS='-shared -fPIC'
     if test "$LIBRUNPATH"; then
@@ -1944,18 +1944,18 @@ ia64*-hpux*)
            _SAVE_LDFLAGS=$LDFLAGS
            LDFLAGS="-M /usr/lib/ld/map.noexstk $LDFLAGS"
            AC_TRY_LINK([#include <stdio.h>],
                        [printf("Hello World\n");],
                        ,
                        [LDFLAGS=$_SAVE_LDFLAGS])
        fi
        MOZ_OPTIMIZE_FLAGS="-xO4"
-       MKSHLIB='$(CXX) $(CXXFLAGS) $(DSO_PIC_FLAGS) $(DSO_LDOPTS) -h $@ -o $@'
-       MKCSHLIB='$(CC) $(CFLAGS) $(DSO_PIC_FLAGS) $(DSO_LDOPTS) -h $@ -o $@'
+       MKSHLIB='$(CXX) $(CXXFLAGS) $(DSO_PIC_FLAGS) $(DSO_LDOPTS) -h $(notdir $@) -o $@'
+       MKCSHLIB='$(CC) $(CFLAGS) $(DSO_PIC_FLAGS) $(DSO_LDOPTS) -h $(notdir $@) -o $@'
        MKSHLIB_FORCE_ALL='-z allextract'
        MKSHLIB_UNFORCE_ALL='-z defaultextract'
        DSO_LDOPTS='-G'
        AR_LIST="$AR t"
        AR_EXTRACT="$AR x"
        AR_DELETE="$AR d"
        AR='$(CXX) -xar'
        AR_FLAGS='-o $@'
--- a/python/mozbuild/mozbuild/mach_commands.py
+++ b/python/mozbuild/mozbuild/mach_commands.py
@@ -459,23 +459,29 @@ class GTestCommands(MachCommandBase):
              "optionally followed by a '-' and another ':'-separated pattern list (called the negative patterns).")
     @CommandArgument('--jobs', '-j', default='1', nargs='?', metavar='jobs', type=int,
         help='Run the tests in parallel using multiple processes.')
     @CommandArgument('--tbpl-parser', '-t', action='store_true',
         help='Output test results in a format that can be parsed by TBPL.')
     @CommandArgument('--shuffle', '-s', action='store_true',
         help='Randomize the execution order of tests.')
     def gtest(self, shuffle, jobs, gtest_filter, tbpl_parser):
+
+        # We lazy build gtest because it's slow to link
+        self._run_make(directory="testing/gtest", target='gtest', ensure_exit_code=True)
+
         app_path = self.get_binary_path('app')
 
         # Use GTest environment variable to control test execution
         # For details see:
         # https://code.google.com/p/googletest/wiki/AdvancedGuide#Running_Test_Programs:_Advanced_Options
         gtest_env = {b'GTEST_FILTER': gtest_filter}
 
+        gtest_env[b"MOZ_RUN_GTEST"] = b"True"
+
         if shuffle:
             gtest_env[b"GTEST_SHUFFLE"] = b"True"
 
         if tbpl_parser:
             gtest_env[b"MOZ_TBPL_PARSER"] = b"True"
 
         if jobs == 1:
             return self.run_process([app_path, "-unittest"],
--- a/testing/gtest/Makefile.in
+++ b/testing/gtest/Makefile.in
@@ -31,8 +31,20 @@ LOCAL_INCLUDES += \
   -I$(srcdir)/gtest \
   -I$(srcdir)/gtest/include \
   -I$(srcdir)/gmock \
   -I$(srcdir)/gmock/include \
   $(NULL)
 
 include $(topsrcdir)/config/rules.mk
 
+ifeq (browser,$(MOZ_BUILD_APP))
+# Disable because of metro linking error:
+# LNK1181: cannot open input file 'runtimeobject.lib'
+ifndef MOZ_METRO
+check gtest::
+	$(MAKE) -C $(DEPTH)/toolkit/library gtestxul
+ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
+	$(MAKE) -C $(DEPTH)/browser/app repackage
+endif
+endif
+endif
+
--- a/testing/gtest/mozilla/GTestRunner.cpp
+++ b/testing/gtest/mozilla/GTestRunner.cpp
@@ -1,16 +1,18 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * * This Source Code Form is subject to the terms of the Mozilla Public
  * * License, v. 2.0. If a copy of the MPL was not distributed with this
  * * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+#include "GTestRunner.h"
 #include "gtest/gtest.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/NullPtr.h"
+#include "prenv.h"
 
 using ::testing::EmptyTestEventListener;
 using ::testing::InitGoogleTest;
 using ::testing::Test;
 using ::testing::TestCase;
 using ::testing::TestEventListeners;
 using ::testing::TestInfo;
 using ::testing::TestPartResult;
@@ -60,23 +62,34 @@ static void ReplaceGTestLogger()
   // Code is based on: http://googletest.googlecode.com/svn/trunk/samples/sample9_unittest.cc
   UnitTest& unitTest = *UnitTest::GetInstance();
   TestEventListeners& listeners = unitTest.listeners();
   delete listeners.Release(listeners.default_result_printer());
 
   listeners.Append(new MozillaPrinter);
 }
 
-int RunGTest()
+int RunGTestFunc()
 {
   int c = 0;
   InitGoogleTest(&c, static_cast<char**>(nullptr));
 
   if (getenv("MOZ_TBPL_PARSER")) {
     ReplaceGTestLogger();
   }
 
-  setenv("XPCOM_DEBUG_BREAK", "stack-and-abort", false);
+  PR_SetEnv("XPCOM_DEBUG_BREAK=stack-and-abort");
 
   return RUN_ALL_TESTS();
 }
 
+// We use a static var 'RunGTest' defined in nsAppRunner.cpp.
+// RunGTest is initialized to NULL but if GTest (this file)
+// is linked in then RunGTest will be set here indicating
+// GTest is supported.
+class _InitRunGTest {
+public:
+  _InitRunGTest() {
+    RunGTest = RunGTestFunc;
+  }
+} InitRunGTest;
+
 }
--- a/testing/gtest/mozilla/GTestRunner.h
+++ b/testing/gtest/mozilla/GTestRunner.h
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * * This Source Code Form is subject to the terms of the Mozilla Public
  * * License, v. 2.0. If a copy of the MPL was not distributed with this
  * * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 namespace mozilla {
 
-int RunGTest();
+extern int (*RunGTest)();
 
 }
--- a/toolkit/library/Makefile.in
+++ b/toolkit/library/Makefile.in
@@ -291,20 +291,16 @@ STATIC_LIBS += skia_npapi
 endif
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),gonk)
 COMPONENT_LIBS += widget_gonk
 endif
 
 STATIC_LIBS += thebes gl ycbcr
 
-ifdef MOZ_ENABLE_GTEST
-COMPONENT_LIBS += gtest xpcom_glue_gtest
-endif
-
 ifdef MOZ_ENABLE_PROFILER_SPS
 COMPONENT_LIBS += profiler
 endif
 
 ifeq (windows,$(MOZ_WIDGET_TOOLKIT))
 COMPONENT_LIBS += widget_windows
 ifdef MOZ_METRO
 COMPONENT_LIBS += widget_winrt
@@ -677,12 +673,44 @@ DEFINES += -DENABLE_LAYOUTDEBUG
 endif
 endif
 
 ifeq (WINNT_1,$(OS_TARGET)_$(MOZ_PROFILE_USE))
 # Wrap linker to measure peak virtual memory usage.
 LD := $(PYTHON) $(topsrcdir)/build/link.py $(CURDIR)/linker-vsize $(LD)
 endif
 
+ifndef LINK_GTEST
 libs:: $(FINAL_TARGET)/dependentlibs.list
+else
+libs::
+endif
+
+ifdef MAKE_FRAMEWORK
+EFFECTIVE_LIB_PREFIX=
+else
+EFFECTIVE_LIB_PREFIX=$(LIB_PREFIX)
+endif
+
+$(FINAL_TARGET)/dependentlibs.list.gtest: $(FINAL_TARGET)/dependentlibs.list
+	sed -e "s|$(SHARED_LIBRARY)|gtest/$(SHARED_LIBRARY)|" $< > $@
+
+.PHONY: gtestxul
+
+gtestxul: $(EFFECTIVE_LIB_PREFIX)gtest/$(EFFECTIVE_LIB_PREFIX)$(LIBRARY_NAME)
+
+# Remove this target when actually linking gtest to prevent redefining
+# the implicit rules.mk target
+ifndef LINK_GTEST
+$(EFFECTIVE_LIB_PREFIX)gtest/$(EFFECTIVE_LIB_PREFIX)$(LIBRARY_NAME): $(FINAL_TARGET)/dependentlibs.list.gtest
+	$(MKDIR) -p $(EFFECTIVE_LIB_PREFIX)gtest
+	$(MAKE) libs SHARED_LIBRARY_NAME=gtest/$(EFFECTIVE_LIB_PREFIX)$(LIBRARY_NAME) FINAL_TARGET=$(FINAL_TARGET)/gtest SDK_LIBRARY= IMPORT_LIB_DEST=$(IMPORT_LIB_DEST)/gtest LINK_GTEST=true
+endif
+
+ifdef LINK_GTEST
+COMPONENT_LIBS += \
+  gtest \
+  gfxtest \
+  $(NULL)
+endif
 
 $(FINAL_TARGET)/dependentlibs.list: dependentlibs.py $(SHARED_LIBRARY) $(wildcard $(if $(wildcard $(FINAL_TARGET)/dependentlibs.list),$(addprefix $(FINAL_TARGET)/,$(shell cat $(FINAL_TARGET)/dependentlibs.list))))
 	$(PYTHON) $< $(SHARED_LIBRARY) -L $(FINAL_TARGET) $(if $(TOOLCHAIN_PREFIX),$(addprefix -p ,$(TOOLCHAIN_PREFIX))) > $@
--- a/toolkit/library/winvccorlib/Makefile.in
+++ b/toolkit/library/winvccorlib/Makefile.in
@@ -2,16 +2,22 @@
 # License, v. 2.0. If a copy of the MPL was not distributed with this file,
 # You can obtain one at http://mozilla.org/MPL/2.0/.
 
 DEPTH     = @DEPTH@
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 
+# When we're linking GTest we recurse into this directory but don't need
+# to generate this library
+ifndef LINK_GTEST
+
 LIBRARY_NAME	= dummyvccorlib
 
 include $(DEPTH)/config/autoconf.mk
 
 FORCE_SHARED_LIB=1
 
+endif
+
 include $(topsrcdir)/config/rules.mk
 
--- a/toolkit/toolkit.mozbuild
+++ b/toolkit/toolkit.mozbuild
@@ -123,19 +123,18 @@ if CONFIG['MOZ_OMX_PLUGIN']:
 if not CONFIG['MOZ_NATIVE_PNG']:
     add_tier_dir('platform', 'media/libpng')
 
 add_tier_dir('platform', 'media/kiss_fft')
 
 if CONFIG['ENABLE_TESTS']:
     add_tier_dir('platform', 'testing/specialpowers')
 
-if CONFIG['MOZ_ENABLE_GTEST']:
+if CONFIG['ENABLE_TESTS']:
     add_tier_dir('platform', 'testing/gtest')
-    add_tier_dir('platform', 'xpcom/glue/tests/gtest')
 
 add_tier_dir('platform', [
     'uriloader',
     'caps',
     'parser',
     'gfx',
     'image',
     'dom',
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -191,17 +191,17 @@ using mozilla::scache::StartupCache;
 #ifdef MOZ_CRASHREPORTER
 #include "nsExceptionHandler.h"
 #include "nsICrashReporter.h"
 #define NS_CRASHREPORTER_CONTRACTID "@mozilla.org/toolkit/crash-reporter;1"
 #include "nsIPrefService.h"
 #endif
 
 #include "base/command_line.h"
-#ifdef MOZ_ENABLE_GTEST
+#ifdef MOZ_ENABLE_TESTS
 #include "GTestRunner.h"
 #endif
 
 #ifdef MOZ_WIDGET_ANDROID
 #include "AndroidBridge.h"
 #endif
 
 extern uint32_t gRestartMode;
@@ -237,16 +237,20 @@ static char **gQtOnlyArgv;
 #include <gtk/gtk.h>
 #ifdef MOZ_X11
 #include <gdk/gdkx.h>
 #endif /* MOZ_X11 */
 #include "nsGTKToolkit.h"
 #endif
 #include "BinaryPath.h"
 
+namespace mozilla {
+int (*RunGTest)() = 0;
+}
+
 using mozilla::dom::ContentParent;
 using mozilla::dom::ContentChild;
 
 // Save literal putenv string to environment variable.
 static void
 SaveToEnv(const char *putenv)
 {
   char *expr = strdup(putenv);
@@ -3193,24 +3197,25 @@ XREMain::XRE_mainInit(bool* aExitFlag)
       NS_ENSURE_TRUE(chromeReg, 1);
 
       chromeReg->CheckForNewChrome();
     }
     *aExitFlag = true;
     return 0;
   }
 
-  ar = CheckArg("unittest", true);
-  if (ar == ARG_FOUND) {
-#if MOZ_ENABLE_GTEST
-    int result = mozilla::RunGTest();
-#else
-    int result = 1;
-    printf("TEST-UNEXPECTED-FAIL | Not compiled with GTest enabled\n");
-#endif
+  if (PR_GetEnv("MOZ_RUN_GTEST")) {
+    int result;
+    // RunGTest will only be set if we're in xul-unit
+    if (mozilla::RunGTest) {
+      result = mozilla::RunGTest();
+    } else {
+      result = 1;
+      printf("TEST-UNEXPECTED-FAIL | gtest | Not compiled with enable-tests\n");
+    }
     *aExitFlag = true;
     return result;
   }
 
   return 0;
 }
 
 namespace mozilla {
--- a/xpcom/glue/standalone/nsXPCOMGlue.cpp
+++ b/xpcom/glue/standalone/nsXPCOMGlue.cpp
@@ -411,16 +411,20 @@ XPCOMGlueLoad(const char *xpcomFile)
         strcpy(xpcomDir + len, XPCOM_FILE_PATH_SEPARATOR
                                XPCOM_DEPENDENT_LIBS_LIST);
         cursor = xpcomDir + len + 1;
     } else {
         strcpy(xpcomDir, XPCOM_DEPENDENT_LIBS_LIST);
         cursor = xpcomDir;
     }
 
+    if (getenv("MOZ_RUN_GTEST")) {
+        strcat(xpcomDir, ".gtest");
+    }
+
     ScopedCloseFile flist;
     flist = TS_tfopen(xpcomDir, READ_TEXTMODE);
     if (!flist) {
         return nullptr;
     }
 
     *cursor = '\0';