@@ -806,6 +806,90 @@ int main( int argc, char *argv[] )
806
806
807
807
QgsApplication myApp ( argc, argv, myUseGuiFlag, configpath );
808
808
809
+ // Redefine QgsApplication::libraryPaths as necessary.
810
+ // IMPORTANT: Do *after* QgsApplication myApp(...), but *before* Qt uses any plugins,
811
+ // e.g. loading splash screen, setting window icon, etc.
812
+ // Always honor QT_PLUGIN_PATH env var or qt.conf, which will
813
+ // be part of libraryPaths just after QgsApplication creation.
814
+ #ifdef Q_OS_WIN
815
+ // For non static builds on win (static builds are not supported)
816
+ // we need to be sure we can find the qt image plugins.
817
+ QCoreApplication::addLibraryPath ( QApplication::applicationDirPath ()
818
+ + QDir::separator () + " qtplugins" );
819
+ #endif
820
+ #ifdef Q_OS_MAC
821
+ // Resulting libraryPaths has critical QGIS plugin paths first, then any Qt plugin paths, then
822
+ // any dev-defined paths (in app's qt.conf) and/or user-defined paths (QT_PLUGIN_PATH env var).
823
+ //
824
+ // NOTE: Minimizes, though does not fully protect against, crashes due to dev/user-defined libs
825
+ // built against a different Qt/QGIS, while still allowing custom C++ plugins to load.
826
+ QStringList libPaths ( QCoreApplication::libraryPaths () );
827
+
828
+ QgsDebugMsgLevel ( QString ( " Initial macOS QCoreApplication::libraryPaths: %1" )
829
+ .arg ( libPaths.join ( " " ) ), 4 );
830
+
831
+ // Strip all critical paths that should always be prepended
832
+ if ( libPaths.removeAll ( QDir::cleanPath ( QgsApplication::pluginPath () ) ) )
833
+ {
834
+ QgsDebugMsgLevel ( QString ( " QgsApplication::pluginPath removed from initial libraryPaths" ), 4 );
835
+ }
836
+ if ( libPaths.removeAll ( QCoreApplication::applicationDirPath () ) )
837
+ {
838
+ QgsDebugMsgLevel ( QString ( " QCoreApplication::applicationDirPath removed from initial libraryPaths" ), 4 );
839
+ }
840
+ // Prepend path, so a standard Qt bundle directory is parsed
841
+ QgsDebugMsgLevel ( QString ( " Prepending QCoreApplication::applicationDirPath to libraryPaths" ), 4 );
842
+ libPaths.prepend ( QCoreApplication::applicationDirPath () );
843
+
844
+ // Check if we are running in a 'release' app bundle, i.e. contains copied-in
845
+ // standard Qt-specific plugin subdirectories (ones never created by QGIS, e.g. 'sqldrivers' is).
846
+ // Note: bundleclicked(...) is inadequate to determine which *type* of bundle was opened, e.g. release or build dir.
847
+ // An app bundled with QGIS_MACAPP_BUNDLE > 0 is considered a release bundle.
848
+ QString relLibPath ( QDir::cleanPath ( QCoreApplication::applicationDirPath ().append ( " /../PlugIns" ) ) );
849
+ // Note: relLibPath becomes the defacto QT_PLUGINS_DIR of a release app bundle
850
+ if ( QFile::exists ( relLibPath + " /imageformats" )
851
+ && QFile::exists ( relLibPath + " /codecs" ) )
852
+ {
853
+ // We are in a release app bundle.
854
+ // Strip QT_PLUGINS_DIR because it will crash a launched release app bundle, since
855
+ // the appropriate Qt frameworks and plugins have been copied into the bundle.
856
+ if ( libPaths.removeAll ( QT_PLUGINS_DIR ) )
857
+ {
858
+ QgsDebugMsgLevel ( QString ( " QT_PLUGINS_DIR removed from initial libraryPaths" ), 4 );
859
+ }
860
+ // Prepend the Plugins path, so copied-in Qt plugin bundle directories are parsed.
861
+ QgsDebugMsgLevel ( QString ( " Prepending <bundle>/Plugins to libraryPaths" ), 4 );
862
+ libPaths.prepend ( relLibPath );
863
+
864
+ // TODO: see if this or another method can be used to avoid QCA's install prefix plugins
865
+ // from being parsed and loaded (causes multi-Qt-loaded errors when bundled Qt should
866
+ // be the only one loaded). QCA core (> v2.1.3) needs an update first.
867
+ // setenv( "QCA_PLUGIN_PATH", relLibPath.toUtf8().constData(), 1 );
868
+ }
869
+ else
870
+ {
871
+ // We are either running from build dir bundle, or launching Mach-O binary directly.
872
+ // Add system Qt plugins, since they are not bundled, and not always referenced by default.
873
+ // An app bundled with QGIS_MACAPP_BUNDLE = 0 will still have Plugins/qgis in it.
874
+ // Note: Don't always prepend.
875
+ // User may have already defined it in QT_PLUGIN_PATH in a specific order.
876
+ if ( !libPaths.contains ( QT_PLUGINS_DIR ) )
877
+ {
878
+ QgsDebugMsgLevel ( QString ( " Prepending QT_PLUGINS_DIR to libraryPaths" ), 4 );
879
+ libPaths.prepend ( QT_PLUGINS_DIR );
880
+ }
881
+ }
882
+
883
+ QgsDebugMsgLevel ( QString ( " Prepending QgsApplication::pluginPath to libraryPaths" ), 4 );
884
+ libPaths.prepend ( QDir::cleanPath ( QgsApplication::pluginPath () ) );
885
+
886
+ // Redefine library search paths.
887
+ QCoreApplication::setLibraryPaths ( libPaths );
888
+
889
+ QgsDebugMsgLevel ( QString ( " Rewritten macOS QCoreApplication::libraryPaths: %1" )
890
+ .arg ( QCoreApplication::libraryPaths ().join ( " " ) ), 4 );
891
+ #endif
892
+
809
893
#ifdef Q_OS_MAC
810
894
// Set 1024x1024 icon for dock, app switcher, etc., rendering
811
895
myApp.setWindowIcon ( QIcon ( QgsApplication::iconsPath () + QLatin1String ( " qgis-icon-macos.png" ) ) );
@@ -1023,36 +1107,6 @@ int main( int argc, char *argv[] )
1023
1107
}
1024
1108
}
1025
1109
1026
- // For non static builds on mac and win (static builds are not supported)
1027
- // we need to be sure we can find the qt image
1028
- // plugins. In mac be sure to look in the
1029
- // application bundle...
1030
- #ifdef Q_OS_WIN
1031
- QCoreApplication::addLibraryPath ( QApplication::applicationDirPath ()
1032
- + QDir::separator () + " qtplugins" );
1033
- #endif
1034
- #ifdef Q_OS_MACX
1035
- // IMPORTANT: do before Qt uses any plugins, e.g. before loading splash screen
1036
- QString myPath ( QCoreApplication::applicationDirPath ().append ( " /../PlugIns" ) );
1037
- // Check if it contains a standard Qt-specific plugin subdirectory
1038
- if ( !QFile::exists ( myPath + " /imageformats" ) )
1039
- {
1040
- // We are either running from build dir bundle, or launching binary directly.
1041
- // Use system Qt plugins, since they are not bundled.
1042
- // An app bundled with QGIS_MACAPP_BUNDLE=0 will still have Plugins/qgis in it
1043
- myPath = QT_PLUGINS_DIR;
1044
- }
1045
-
1046
- // First clear the plugin search paths so we can be sure only plugins we define
1047
- // are being used. Note: this strips QgsApplication::pluginPath()
1048
- QStringList myPathList;
1049
- QCoreApplication::setLibraryPaths ( myPathList );
1050
-
1051
- QgsDebugMsg ( QString ( " Adding Mac QGIS and Qt plugins dirs to search path: %1" ).arg ( myPath ) );
1052
- QCoreApplication::addLibraryPath ( QgsApplication::pluginPath () );
1053
- QCoreApplication::addLibraryPath ( myPath );
1054
- #endif
1055
-
1056
1110
// set authentication database directory
1057
1111
if ( !authdbdirectory.isEmpty () )
1058
1112
{
0 commit comments