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 133378 816311e43409f6f82c38043fb23a9ed452e8f1a8
parent 133377 c2f79f1f9e6f07d08c23cdf68bd8e56326177712
child 133379 3bead9d0a8a058e8ed1be0f75e9ef5f5f7d36c40
push id1682
push userryanvm@gmail.com
push dateThu, 30 May 2013 15:47:22 +0000
treeherderfx-team@b36140a54111 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersted, glandium
bugs844288
milestone24.0a1
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';