Improve Cocoa platform plugin loading.
authorMorten Johan Sorvig <morten.sorvig@digia.com>
Mon, 10 Dec 2012 10:29:54 +0000 (11:29 +0100)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Wed, 12 Dec 2012 00:26:23 +0000 (01:26 +0100)
Loading both the debug and release version of the cocoa
plugins causes the objective-c runtime to print "duplicate
class definitions" warnings.

Fix this by directing the plugin loader to only load
one of the cocoa plugins if both are available. Implement
this as a special case directly in QFactoryLoader.

Define QT_NO_DEBUG_PLUGIN_CHECK to allow mixing
debug and release builds.

Task-number: QTBUG-28155

Change-Id: Ie1927b219cc501a821f91b7e4b56f0589e0acbf5
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
src/corelib/corelib.pro
src/corelib/plugin/qfactoryloader.cpp
src/corelib/plugin/qlibrary.cpp
src/plugins/platforms/cocoa/cocoa.pro

index 1059d0d..f95ee54 100644 (file)
@@ -41,7 +41,6 @@ mac|darwin {
     }
     LIBS_PRIVATE += -framework CoreFoundation
 }
-mac:lib_bundle:DEFINES += QT_NO_DEBUG_PLUGIN_CHECK
 win32:DEFINES-=QT_NO_CAST_TO_ASCII
 DEFINES += $$MODULE_DEFINES
 
index 75652b0..aeb78e8 100644 (file)
@@ -126,9 +126,30 @@ void QFactoryLoader::update()
 
         QStringList plugins = QDir(path).entryList(QDir::Files);
         QLibraryPrivate *library = 0;
+
+#ifdef Q_OS_MAC
+        // Loading both the debug and release version of the cocoa plugins causes the objective-c runtime
+        // to print "duplicate class definitions" warnings. Detect if QFactoryLoader is about to load both,
+        // skip one of them (below).
+        //
+        // ### FIXME find a proper solution
+        //
+        const bool isLoadingDebugAndReleaseCocoa = plugins.contains("libqcocoa_debug.dylib") && plugins.contains("libqcocoa.dylib");
+#endif
         for (int j = 0; j < plugins.count(); ++j) {
             QString fileName = QDir::cleanPath(path + QLatin1Char('/') + plugins.at(j));
 
+#ifdef Q_OS_MAC
+            if (isLoadingDebugAndReleaseCocoa) {
+#ifdef QT_DEBUG
+               if (fileName.contains(QStringLiteral("libqcocoa.dylib")))
+                   continue;    // Skip release plugin in debug mode
+#else
+               if (fileName.contains(QStringLiteral("libqcocoa_debug.dylib")))
+                   continue;    // Skip debug plugin in release mode
+#endif
+            }
+#endif
             if (qt_debug_component()) {
                 qDebug() << "QFactoryLoader::QFactoryLoader() looking at" << fileName;
             }
index 26692ca..8d2e890 100644 (file)
@@ -73,7 +73,7 @@ QT_BEGIN_NAMESPACE
 #  define QLIBRARY_AS_DEBUG true
 #endif
 
-#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
+#if defined(Q_OS_UNIX)
 // We don't use separate debug and release libs on UNIX, so we want
 // to allow loading plugins, regardless of how they were built.
 #  define QT_NO_DEBUG_PLUGIN_CHECK
index 5533650..85e3f00 100644 (file)
@@ -98,13 +98,6 @@ QT += core-private gui-private platformsupport-private
 
 OTHER_FILES += cocoa.json
 
-# Build the release libqcocoa.dylib only, skip the debug version.
-# The Qt plugin loader will dlopen both if found, causing duplicate
-# Objective-c class definitions for the classes defined in the plugin.
-contains(QT_CONFIG,release):CONFIG -= debug
-contains(QT_CONFIG,debug_and_release):CONFIG -= debug_and_release
-contains(QT_CONFIG,build_all):CONFIG -= build_all
-
 # Acccessibility debug support
 # DEFINES += QT_COCOA_ENABLE_ACCESSIBILITY_INSPECTOR
 # include ($$PWD/../../../../util/accessibilityinspector/accessibilityinspector.pri)