Bug 751541 - Fix for VS11 C++/CX link issues: delay load vccorlib and the winrt standard libraries, and provide a dummy vccorlib on non-win8 platforms so xul lib can load. r=ehsan+khuey, sr=bsmedberg
authorJim Mathies <jmathies@mozilla.com>
Tue, 22 May 2012 16:00:48 -0500
changeset 94617 40ba9d985ba3e7c4363beeac200820823531824d
parent 94616 8344de0f1079e669d55037cf84b0bdb549812a54
child 94618 023f75b6a2ecc02f8a08f48ef9afbfc1bcd72427
push id9705
push userjmathies@mozilla.com
push dateTue, 22 May 2012 21:01:03 +0000
treeherdermozilla-inbound@40ba9d985ba3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersehsan, bsmedberg
bugs751541
milestone15.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 751541 - Fix for VS11 C++/CX link issues: delay load vccorlib and the winrt standard libraries, and provide a dummy vccorlib on non-win8 platforms so xul lib can load. r=ehsan+khuey, sr=bsmedberg
config/autoconf.mk.in
configure.in
toolkit/library/Makefile.in
toolkit/library/nsDllMain.cpp
toolkit/library/winvccorlib/Makefile.in
toolkit/library/winvccorlib/dummyvccorlib.cpp
--- a/config/autoconf.mk.in
+++ b/config/autoconf.mk.in
@@ -519,16 +519,18 @@ MOZ_ENABLE_CAIRO_FT	= @MOZ_ENABLE_CAIRO_
 MOZ_ENABLE_GTK2		= @MOZ_ENABLE_GTK2@
 MOZ_ENABLE_QT		= @MOZ_ENABLE_QT@
 MOZ_ENABLE_XREMOTE	= @MOZ_ENABLE_XREMOTE@
 MOZ_ENABLE_DWRITE_FONT	= @MOZ_ENABLE_DWRITE_FONT@
 MOZ_ENABLE_D2D_SURFACE	= @MOZ_ENABLE_D2D_SURFACE@
 MOZ_ENABLE_D3D9_LAYER	= @MOZ_ENABLE_D3D9_LAYER@
 MOZ_ENABLE_D3D10_LAYER  = @MOZ_ENABLE_D3D10_LAYER@
 MOZ_METRO	= @MOZ_METRO@
+CRTDLLVERSION	= @CRTDLLVERSION@
+CRTEXPDLLVERSION	= @CRTEXPDLLVERSION@
 
 MOZ_GTK2_CFLAGS		= @MOZ_GTK2_CFLAGS@
 MOZ_GTK2_LIBS		= @MOZ_GTK2_LIBS@
 
 MOZ_QT_CFLAGS		= @MOZ_QT_CFLAGS@
 MOZ_QT_LIBS		= @MOZ_QT_LIBS@
 MOZ_ENABLE_QTNETWORK    = @MOZ_ENABLE_QTNETWORK@
 MOZ_ENABLE_QMSYSTEM2    = @MOZ_ENABLE_QMSYSTEM2@
--- a/configure.in
+++ b/configure.in
@@ -613,22 +613,28 @@ MOZ_ARG_ENABLE_BOOL(metro,
     MOZ_METRO=1,
     MOZ_METRO=)
 if test -n "$MOZ_METRO"; then
     AC_DEFINE(MOZ_METRO)
     # Target the Windows 8 Kit
     WINSDK_TARGETVER=602
     # Allow a higher api set
     WINVER=602
+    # toolkit/library/makefile.in needs these, see nsDllMain.
+    CRTDLLVERSION=110
+    CRTEXPDLLVERSION=1-1-0
 else
     # Target the Windows 7 SDK by default
     WINSDK_TARGETVER=601
     WINVER=502
 fi
 
+AC_SUBST(CRTDLLVERSION)
+AC_SUBST(CRTEXPDLLVERSION)
+
 if test -n "$MOZ_METRO"; then
   case "$target" in
   *-mingw*)
     ;;
   *)
     AC_MSG_ERROR([Metro builds only valid on the windows platform.]);
     ;;
   esac
--- a/toolkit/library/Makefile.in
+++ b/toolkit/library/Makefile.in
@@ -12,16 +12,20 @@ include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/rdf/util/src/objs.mk
 include $(topsrcdir)/intl/unicharutil/util/objs.mk
 
 MODULE = libxul
 LIBRARY_NAME = xul
 FORCE_SHARED_LIB = 1
 MOZILLA_INTERNAL_API = 1
 
+ifdef MOZ_METRO
+DIRS += winvccorlib
+endif
+
 ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)
 # This is going to be a framework named "XUL", not an ordinary library named
 # "libxul.dylib"
 LIBRARY_NAME=XUL
 # Setting MAKE_FRAMEWORK makes DLL_PREFIX and DLL_SUFFIX be ignored when
 # setting SHARED_LIBRARY; we need to leave DLL_PREFIX and DLL_SUFFIX
 # as-is so that dependencies of the form -ltracemalloc still work.
 MAKE_FRAMEWORK=1
@@ -539,16 +543,28 @@ EXTRA_DSO_LDOPTS += \
   -DELAYLOAD:psapi.dll \
   -DELAYLOAD:dbghelp.dll \
   -DELAYLOAD:rasapi32.dll \
   -DELAYLOAD:rasdlg.dll \
   -DELAYLOAD:comdlg32.dll \
   -DELAYLOAD:winspool.drv \
   -DELAYLOAD:secur32.dll \
   $(NULL)
+
+# See nsDllMain for an explanation
+ifdef MOZ_METRO
+ifdef MOZ_DEBUG
+EXTRA_DSO_LDOPTS += -DELAYLOAD:VCCORLIB$(CRTDLLVERSION)D.DLL
+else
+EXTRA_DSO_LDOPTS += -DELAYLOAD:VCCORLIB$(CRTDLLVERSION).DLL
+endif
+EXTRA_DSO_LDOPTS += -DELAYLOAD:API-MS-WIN-CORE-WINRT-L$(CRTEXPDLLVERSION).DLL
+EXTRA_DSO_LDOPTS += -DELAYLOAD:API-MS-WIN-CORE-WINRT-STRING-L$(CRTEXPDLLVERSION).DLL
+endif
+
 ifdef ACCESSIBILITY
 EXTRA_DSO_LDOPTS += -DELAYLOAD:oleacc.dll
 endif
 endif
 endif # WINNT
 
 ifdef MOZ_JPROF
 EXTRA_DSO_LDOPTS += -ljprof
--- a/toolkit/library/nsDllMain.cpp
+++ b/toolkit/library/nsDllMain.cpp
@@ -1,14 +1,15 @@
 /* -*- 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 <windows.h>
+#include <delayimp.h>
 #include "nsToolkit.h"
 
 #if defined(__GNUC__)
 // If DllMain gets name mangled, it won't be seen.
 extern "C" {
 #endif
 
 BOOL APIENTRY DllMain(  
@@ -31,11 +32,68 @@ BOOL APIENTRY DllMain(
             nsToolkit::Shutdown();
             break;
 
     }
 
     return TRUE;
 }
 
+#if defined(MOZ_METRO)
+/*
+ * DelayDllLoadHook - the crt calls here anytime a delay load dll is about to
+ * load. There are a number of events, we listen for dliNotePreLoadLibrary.
+ * 
+ * On Win8, we enable Windows Runtime Component Extension support. When enabled
+ * the compiler bakes auto-generated code into our binary, including a c init-
+ * ializer which inits the winrt library through a call into the winrt standard
+ * lib 'vccorlib'. Vccorlib in turn has system dll dependencies which are only
+ * available on Win8 (currently API-MS-WIN-CORE-WINRT and
+ * API-MS-WIN-CORE-WINRT-STRING), which prevent xul.dll from loading on os <=
+ * Win7. To get around this we generate a dummy vccore lib with the three entry
+ * points the initializer needs and load it in place of the real vccorlib. We
+ * also have to add vccorlib and the system dlls to the delay load list.
+ */
+static bool IsWin8OrHigher()
+{
+  static PRInt32 version = 0;
+
+  if (version) {
+    return (version >= 0x602);
+  }
+
+  // Match Win8 or Win8 Server or higher
+  OSVERSIONINFOEX osInfo;
+  osInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+  ::GetVersionEx((OSVERSIONINFO*)&osInfo);
+  version =
+    (osInfo.dwMajorVersion & 0xff) << 8 | (osInfo.dwMinorVersion & 0xff);
+  return (version >= 0x602);
+}
+
+const char* kvccorlib = "vccorlib";
+const char* kwinrtprelim = "api-ms-win-core-winrt";
+
+static bool IsWinRTDLLPresent(PDelayLoadInfo pdli, const char* aLibToken)
+{
+  return (!IsWin8OrHigher() && pdli->szDll &&
+          !strnicmp(pdli->szDll, aLibToken, strlen(aLibToken)));
+}
+
+FARPROC WINAPI DelayDllLoadHook(unsigned dliNotify, PDelayLoadInfo pdli)
+{
+  if (dliNotify == dliNotePreLoadLibrary) {
+    if (IsWinRTDLLPresent(pdli, kvccorlib)) {
+      return (FARPROC)LoadLibraryA("dummyvccorlib.dll");
+    }
+    NS_ASSERTION(!IsWinRTDLLPresent(pdli, kwinrtprelim),
+      "Attempting to load winrt libs in non-metro environment. "
+      "(Winrt variable type placed in global scope?)");
+  }
+  return NULL;
+}
+
+ExternC PfnDliHook __pfnDliNotifyHook2 = DelayDllLoadHook;
+#endif // MOZ_METRO
+
 #if defined(__GNUC__)
 } // extern "C"
 #endif
new file mode 100644
--- /dev/null
+++ b/toolkit/library/winvccorlib/Makefile.in
@@ -0,0 +1,23 @@
+# 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     = ../../..
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+
+LIBRARY_NAME	= dummyvccorlib
+MODULE    = dummyvccorlib
+GRE_MODULE   = 1
+
+include $(DEPTH)/config/autoconf.mk
+
+FORCE_SHARED_LIB=1
+
+CPPSRCS	= \
+	dummyvccorlib.cpp \
+	$(NULL)
+
+include $(topsrcdir)/config/rules.mk
+
new file mode 100644
--- /dev/null
+++ b/toolkit/library/winvccorlib/dummyvccorlib.cpp
@@ -0,0 +1,20 @@
+/* -*- 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 <windows.h>
+
+// A dummy vccorlib.dll for shunting winrt initialization calls when we are not
+// using the winrt library. For a longer explanantion see nsDllMain.cpp.
+
+extern "C" {
+__declspec(dllexport) long __stdcall __InitializeWinRTRuntime(unsigned long data) { return S_OK; }
+}
+
+namespace Platform {
+namespace Details {
+__declspec(dllexport) HRESULT InitializeData(int __threading_model) { return S_OK; }
+__declspec(dllexport) void UninitializeData(int __threading_model) { }
+}
+}