QFactoryLoader: Prioritize plugin that matches Qt's build config
In debug-and-release builds (on Windows or Apple operating systems), we will scan for plugin libraries and find both debug and release versions of these libraries. However, we do not end up loading both, thanks to additional logic. On Windows we rely on logic in QLibraryPrivate::updatePluginState() that uses the IsDebug metadata of the plugin, skipping any mismatch. On Apple operating systems, there is logic in QFactoryLoaderPrivate's updateSinglePath that ties to match the `_debug` suffix of the plugin with the Qt build config. As the string matching logic for Apple platforms is fragile we want to remove it, but we can't re-use the logic for Windows, to ensure we only load a single copy of a plugin, as the Windows logic prevents _any_ mismatch between plugin config and Qt config, even for non- debug-and-release builds (due to the Windows runtime being incompatible between debug and release). To solve this we add logic to QFactoryLoader to prioritize plugins based on the Qt build config, similar to how we prioritize plugins based on their Qt version if we find two or more plugins claiming the same plugin key. Change-Id: I772ba8ae79627e39418ba80107e3729bba8f9ac8 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> (cherry picked from commit 90773b501795a088762dd540c442a7cd251a5d8e) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
1c66b77f52
commit
67b3c40ae2
@ -363,20 +363,28 @@ inline void QFactoryLoaderPrivate::updateSinglePath(const QString &path)
|
||||
|
||||
int keyUsageCount = 0;
|
||||
for (const QString &key : std::as_const(keys)) {
|
||||
// first come first serve, unless the first
|
||||
// library was built with a future Qt version,
|
||||
// whereas the new one has a Qt version that fits
|
||||
// better
|
||||
constexpr int QtVersionNoPatch = QT_VERSION_CHECK(QT_VERSION_MAJOR, QT_VERSION_MINOR, 0);
|
||||
QLibraryPrivate *&keyMapEntry = keyMap[key];
|
||||
int prev_qt_version = 0;
|
||||
if (keyMapEntry)
|
||||
prev_qt_version = int(keyMapEntry->metaData.value(QtPluginMetaDataKeys::QtVersion).toInteger());
|
||||
int qt_version = int(library->metaData.value(QtPluginMetaDataKeys::QtVersion).toInteger());
|
||||
if (!keyMapEntry || (prev_qt_version > QtVersionNoPatch && qt_version <= QtVersionNoPatch)) {
|
||||
keyMapEntry = library.get(); // we WILL .release()
|
||||
++keyUsageCount;
|
||||
if (QLibraryPrivate *existingLibrary = keyMapEntry) {
|
||||
static constexpr bool QtBuildIsDebug = QT_CONFIG(debug);
|
||||
bool existingIsDebug = existingLibrary->metaData.value(QtPluginMetaDataKeys::IsDebug).toBool();
|
||||
bool thisIsDebug = library->metaData.value(QtPluginMetaDataKeys::IsDebug).toBool();
|
||||
bool configsAreDifferent = thisIsDebug != existingIsDebug;
|
||||
bool thisConfigDoesNotMatchQt = thisIsDebug != QtBuildIsDebug;
|
||||
if (configsAreDifferent && thisConfigDoesNotMatchQt)
|
||||
continue; // Existing library matches Qt's build config
|
||||
|
||||
// If the existing library was built with a future Qt version,
|
||||
// whereas the one we're considering has a Qt version that fits
|
||||
// better, we prioritize the better match.
|
||||
static constexpr qint64 QtVersionNoPatch = QT_VERSION_CHECK(QT_VERSION_MAJOR, QT_VERSION_MINOR, 0);
|
||||
int existingVersion = existingLibrary->metaData.value(QtPluginMetaDataKeys::QtVersion).toInteger();
|
||||
int thisVersion = library->metaData.value(QtPluginMetaDataKeys::QtVersion).toInteger();
|
||||
if (!(existingVersion > QtVersionNoPatch && thisVersion <= QtVersionNoPatch))
|
||||
continue; // Existing version is a better match
|
||||
}
|
||||
|
||||
keyMapEntry = library.get();
|
||||
++keyUsageCount;
|
||||
}
|
||||
if (keyUsageCount || keys.isEmpty()) {
|
||||
library->setLoadHints(QLibrary::PreventUnloadHint); // once loaded, don't unload
|
||||
|
Loading…
x
Reference in New Issue
Block a user