@@ -867,6 +867,90 @@ int main( int argc, char *argv[] )
867
867
}
868
868
}
869
869
870
+ // Redefine QgsApplication::libraryPaths as necessary.
871
+ // IMPORTANT: Do *after* QgsApplication myApp(...), but *before* Qt uses any plugins,
872
+ // e.g. loading splash screen, setting window icon, etc.
873
+ // Always honor QT_PLUGIN_PATH env var or qt.conf, which will
874
+ // be part of libraryPaths just after QgsApplication creation.
875
+ #ifdef Q_OS_WIN
876
+ // For non static builds on win (static builds are not supported)
877
+ // we need to be sure we can find the qt image plugins.
878
+ QCoreApplication::addLibraryPath ( QApplication::applicationDirPath ()
879
+ + QDir::separator () + " qtplugins" );
880
+ #endif
881
+ #ifdef Q_OS_MAC
882
+ // Resulting libraryPaths has critical QGIS plugin paths first, then any Qt plugin paths, then
883
+ // any dev-defined paths (in app's qt.conf) and/or user-defined paths (QT_PLUGIN_PATH env var).
884
+ //
885
+ // NOTE: Minimizes, though does not fully protect against, crashes due to dev/user-defined libs
886
+ // built against a different Qt/QGIS, while still allowing custom C++ plugins to load.
887
+ QStringList libPaths ( QCoreApplication::libraryPaths () );
888
+
889
+ QgsDebugMsgLevel ( QStringLiteral ( " Initial macOS QCoreApplication::libraryPaths: %1" )
890
+ .arg ( libPaths.join ( " " ) ), 4 );
891
+
892
+ // Strip all critical paths that should always be prepended
893
+ if ( libPaths.removeAll ( QDir::cleanPath ( QgsApplication::pluginPath () ) ) )
894
+ {
895
+ QgsDebugMsgLevel ( QStringLiteral ( " QgsApplication::pluginPath removed from initial libraryPaths" ), 4 );
896
+ }
897
+ if ( libPaths.removeAll ( QCoreApplication::applicationDirPath () ) )
898
+ {
899
+ QgsDebugMsgLevel ( QStringLiteral ( " QCoreApplication::applicationDirPath removed from initial libraryPaths" ), 4 );
900
+ }
901
+ // Prepend path, so a standard Qt bundle directory is parsed
902
+ QgsDebugMsgLevel ( QStringLiteral ( " Prepending QCoreApplication::applicationDirPath to libraryPaths" ), 4 );
903
+ libPaths.prepend ( QCoreApplication::applicationDirPath () );
904
+
905
+ // Check if we are running in a 'release' app bundle, i.e. contains copied-in
906
+ // standard Qt-specific plugin subdirectories (ones never created by QGIS, e.g. 'sqldrivers' is).
907
+ // Note: bundleclicked(...) is inadequate to determine which *type* of bundle was opened, e.g. release or build dir.
908
+ // An app bundled with QGIS_MACAPP_BUNDLE > 0 is considered a release bundle.
909
+ QString relLibPath ( QDir::cleanPath ( QCoreApplication::applicationDirPath ().append ( " /../PlugIns" ) ) );
910
+ // Note: relLibPath becomes the defacto QT_PLUGINS_DIR of a release app bundle
911
+ if ( QFile::exists ( relLibPath + QStringLiteral ( " /imageformats" ) )
912
+ && QFile::exists ( relLibPath + QStringLiteral ( " /codecs" ) ) )
913
+ {
914
+ // We are in a release app bundle.
915
+ // Strip QT_PLUGINS_DIR because it will crash a launched release app bundle, since
916
+ // the appropriate Qt frameworks and plugins have been copied into the bundle.
917
+ if ( libPaths.removeAll ( QT_PLUGINS_DIR ) )
918
+ {
919
+ QgsDebugMsgLevel ( QStringLiteral ( " QT_PLUGINS_DIR removed from initial libraryPaths" ), 4 );
920
+ }
921
+ // Prepend the Plugins path, so copied-in Qt plugin bundle directories are parsed.
922
+ QgsDebugMsgLevel ( QStringLiteral ( " Prepending <bundle>/Plugins to libraryPaths" ), 4 );
923
+ libPaths.prepend ( relLibPath );
924
+
925
+ // TODO: see if this or another method can be used to avoid QCA's install prefix plugins
926
+ // from being parsed and loaded (causes multi-Qt-loaded errors when bundled Qt should
927
+ // be the only one loaded). QCA core (> v2.1.3) needs an update first.
928
+ // setenv( "QCA_PLUGIN_PATH", relLibPath.toUtf8().constData(), 1 );
929
+ }
930
+ else
931
+ {
932
+ // We are either running from build dir bundle, or launching Mach-O binary directly.
933
+ // Add system Qt plugins, since they are not bundled, and not always referenced by default.
934
+ // An app bundled with QGIS_MACAPP_BUNDLE = 0 will still have Plugins/qgis in it.
935
+ // Note: Don't always prepend.
936
+ // User may have already defined it in QT_PLUGIN_PATH in a specific order.
937
+ if ( !libPaths.contains ( QT_PLUGINS_DIR ) )
938
+ {
939
+ QgsDebugMsgLevel ( QStringLiteral ( " Prepending QT_PLUGINS_DIR to libraryPaths" ), 4 );
940
+ libPaths.prepend ( QT_PLUGINS_DIR );
941
+ }
942
+ }
943
+
944
+ QgsDebugMsgLevel ( QStringLiteral ( " Prepending QgsApplication::pluginPath to libraryPaths" ), 4 );
945
+ libPaths.prepend ( QDir::cleanPath ( QgsApplication::pluginPath () ) );
946
+
947
+ // Redefine library search paths.
948
+ QCoreApplication::setLibraryPaths ( libPaths );
949
+
950
+ QgsDebugMsgLevel ( QStringLiteral ( " Rewritten macOS QCoreApplication::libraryPaths: %1" )
951
+ .arg ( QCoreApplication::libraryPaths ().join ( " " ) ), 4 );
952
+ #endif
953
+
870
954
#ifdef Q_OS_MAC
871
955
// Set hidpi icons; use SVG icons, as PNGs will be relatively too small
872
956
QCoreApplication::setAttribute ( Qt::AA_UseHighDpiPixmaps );
@@ -1100,36 +1184,6 @@ int main( int argc, char *argv[] )
1100
1184
}
1101
1185
}
1102
1186
1103
- // For non static builds on mac and win (static builds are not supported)
1104
- // we need to be sure we can find the qt image
1105
- // plugins. In mac be sure to look in the
1106
- // application bundle...
1107
- #ifdef Q_OS_WIN
1108
- QCoreApplication::addLibraryPath ( QApplication::applicationDirPath ()
1109
- + QDir::separator () + " qtplugins" );
1110
- #endif
1111
- #ifdef Q_OS_MACX
1112
- // IMPORTANT: do before Qt uses any plugins, e.g. before loading splash screen
1113
- QString myPath ( QCoreApplication::applicationDirPath ().append ( " /../PlugIns" ) );
1114
- // Check if it contains a standard Qt-specific plugin subdirectory
1115
- if ( !QFile::exists ( myPath + " /imageformats" ) )
1116
- {
1117
- // We are either running from build dir bundle, or launching binary directly.
1118
- // Use system Qt plugins, since they are not bundled.
1119
- // An app bundled with QGIS_MACAPP_BUNDLE=0 will still have Plugins/qgis in it
1120
- myPath = QT_PLUGINS_DIR;
1121
- }
1122
-
1123
- // First clear the plugin search paths so we can be sure only plugins we define
1124
- // are being used. Note: this strips QgsApplication::pluginPath()
1125
- QStringList myPathList;
1126
- QCoreApplication::setLibraryPaths ( myPathList );
1127
-
1128
- QgsDebugMsg ( QString ( " Adding Mac QGIS and Qt plugins dirs to search path: %1" ).arg ( myPath ) );
1129
- QCoreApplication::addLibraryPath ( QgsApplication::pluginPath () );
1130
- QCoreApplication::addLibraryPath ( myPath );
1131
- #endif
1132
-
1133
1187
// set authentication database directory
1134
1188
if ( !authdbdirectory.isEmpty () )
1135
1189
{
0 commit comments