Allow loading of static plugins if QT_NO_LIBRARY is set.

We keep two symbols from QPluginLoader defined, even if QT_NO_LIBRARY
is set in order to be able to locate static plugins. This doesn't
constitute any loading of shared libraries or plugins from external
files at runtime.

Using these symbols we can enable most of QFactoryLoader even if
QT_NO_LIBRARY is set. Only update(), refreshAll(), library() and
the dtor make no sense then. This way QGenericPlugin also becomes
useful with QT_NO_LIBRARY.

Task-number: QTBUG-3045
Change-Id: Ib7842ce5799e8e2caa46431d95fddd1adda0fc41
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
bb10
Ulf Hermann 2015-06-19 13:29:55 +02:00 committed by Simon Hausmann
parent 1f437e7540
commit 6c76fdc761
10 changed files with 77 additions and 44 deletions

View File

@ -33,7 +33,7 @@
#include "qfactoryloader_p.h"
#ifndef QT_NO_LIBRARY
#ifndef QT_NO_QOBJECT
#include "qfactoryinterface.h"
#include "qmap.h"
#include <qdir.h>
@ -66,6 +66,7 @@ class QFactoryLoaderPrivate : public QObjectPrivate
public:
QFactoryLoaderPrivate(){}
QByteArray iid;
#ifndef QT_NO_LIBRARY
~QFactoryLoaderPrivate();
mutable QMutex mutex;
QList<QLibraryPrivate*> libraryList;
@ -73,8 +74,11 @@ public:
QString suffix;
Qt::CaseSensitivity cs;
QStringList loadedPaths;
#endif
};
#ifndef QT_NO_LIBRARY
Q_GLOBAL_STATIC(QList<QFactoryLoader *>, qt_factory_loaders)
Q_GLOBAL_STATIC_WITH_ARGS(QMutex, qt_factoryloader_mutex, (QMutex::Recursive))
@ -226,6 +230,8 @@ void QFactoryLoader::refreshAll()
}
}
#endif // QT_NO_LIBRARY
QFactoryLoader::QFactoryLoader(const char *iid,
const QString &suffix,
Qt::CaseSensitivity cs)
@ -234,21 +240,28 @@ QFactoryLoader::QFactoryLoader(const char *iid,
moveToThread(QCoreApplicationPrivate::mainThread());
Q_D(QFactoryLoader);
d->iid = iid;
#ifndef QT_NO_LIBRARY
d->cs = cs;
d->suffix = suffix;
QMutexLocker locker(qt_factoryloader_mutex());
update();
qt_factory_loaders()->append(this);
#else
Q_UNUSED(suffix);
Q_UNUSED(cs);
#endif
}
QList<QJsonObject> QFactoryLoader::metaData() const
{
Q_D(const QFactoryLoader);
QList<QJsonObject> metaData;
#ifndef QT_NO_LIBRARY
QMutexLocker locker(&d->mutex);
for (int i = 0; i < d->libraryList.size(); ++i)
metaData.append(d->libraryList.at(i)->metaData);
#endif
foreach (const QStaticPlugin &plugin, QPluginLoader::staticPlugins()) {
const QJsonObject object = plugin.metaData();
@ -265,6 +278,7 @@ QObject *QFactoryLoader::instance(int index) const
if (index < 0)
return 0;
#ifndef QT_NO_LIBRARY
if (index < d->libraryList.size()) {
QLibraryPrivate *library = d->libraryList.at(index);
if (library->instance || library->loadPlugin()) {
@ -280,6 +294,7 @@ QObject *QFactoryLoader::instance(int index) const
return 0;
}
index -= d->libraryList.size();
#endif
QVector<QStaticPlugin> staticPlugins = QPluginLoader::staticPlugins();
for (int i = 0; i < staticPlugins.count(); ++i) {
@ -330,4 +345,4 @@ int QFactoryLoader::indexOf(const QString &needle) const
QT_END_NAMESPACE
#endif // QT_NO_LIBRARY
#endif // QT_NO_QOBJECT

View File

@ -45,17 +45,18 @@
// We mean it.
//
#include "QtCore/qglobal.h"
#ifndef QT_NO_QOBJECT
#include "QtCore/qobject.h"
#include "QtCore/qstringlist.h"
#include "QtCore/qjsonobject.h"
#include "QtCore/qmap.h"
#include "private/qlibrary_p.h"
#ifndef QT_NO_LIBRARY
QT_BEGIN_NAMESPACE
class QFactoryLoaderPrivate;
class Q_CORE_EXPORT QFactoryLoader : public QObject
{
Q_OBJECT
@ -65,21 +66,23 @@ public:
explicit QFactoryLoader(const char *iid,
const QString &suffix = QString(),
Qt::CaseSensitivity = Qt::CaseSensitive);
#ifndef QT_NO_LIBRARY
~QFactoryLoader();
QList<QJsonObject> metaData() const;
QObject *instance(int index) const;
void update();
static void refreshAll();
#if defined(Q_OS_UNIX) && !defined (Q_OS_MAC)
QLibraryPrivate *library(const QString &key) const;
#endif
#endif // Q_OS_UNIX && !Q_OS_MAC
#endif // !QT_NO_LIBRARY
QMultiMap<int, QString> keyMap() const;
int indexOf(const QString &needle) const;
void update();
static void refreshAll();
QList<QJsonObject> metaData() const;
QObject *instance(int index) const;
};
template <class PluginInterface, class FactoryInterface>
@ -112,6 +115,6 @@ PluginInterface *qLoadPlugin1(const QFactoryLoader *loader,
QT_END_NAMESPACE
#endif // QT_NO_LIBRARY
#endif // QT_NO_QOBJECT
#endif // QFACTORYLOADER_P_H

View File

@ -302,7 +302,7 @@ static bool findPatternUnloaded(const QString &library, QLibraryPrivate *lib)
if (pos >= 0) {
if (hasMetaData) {
const char *data = filedata + pos;
QJsonDocument doc = QLibraryPrivate::fromRawMetaData(data);
QJsonDocument doc = qJsonFromRawLibraryMetaData(data);
lib->metaData = doc.object();
if (qt_debug_component())
qWarning("Found metadata in lib %s, metadata=\n%s\n",
@ -677,7 +677,7 @@ static bool qt_get_metadata(QtPluginQueryVerificationDataFunction pfn, QLibraryP
if (!szData)
return false;
QJsonDocument doc = QLibraryPrivate::fromRawMetaData(szData);
QJsonDocument doc = qJsonFromRawLibraryMetaData(szData);
if (doc.isNull())
return false;
priv->metaData = doc.object();

View File

@ -57,9 +57,20 @@
# include "QtCore/qt_windows.h"
#endif
QT_BEGIN_NAMESPACE
// Needed also in case of QT_NO_LIBRARY, for static plugin loading.
inline QJsonDocument qJsonFromRawLibraryMetaData(const char *raw)
{
raw += strlen("QTMETADATA ");
// the size of the embedded JSON object can be found 8 bytes into the data (see qjson_p.h),
// but doesn't include the size of the header (8 bytes)
QByteArray json(raw, qFromLittleEndian<uint>(*(const uint *)(raw + 8)) + 8);
return QJsonDocument::fromBinaryData(json);
}
#ifndef QT_NO_LIBRARY
QT_BEGIN_NAMESPACE
bool qt_debug_component();
@ -104,14 +115,6 @@ public:
void updatePluginState();
bool isPlugin();
static inline QJsonDocument fromRawMetaData(const char *raw) {
raw += strlen("QTMETADATA ");
// the size of the embedded JSON object can be found 8 bytes into the data (see qjson_p.h),
// but doesn't include the size of the header (8 bytes)
QByteArray json(raw, qFromLittleEndian<uint>(*(const uint *)(raw + 8)) + 8);
return QJsonDocument::fromBinaryData(json);
}
private:
explicit QLibraryPrivate(const QString &canonicalFileName, const QString &version, QLibrary::LoadHints loadHints);
~QLibraryPrivate();
@ -132,8 +135,8 @@ private:
friend class QLibraryStore;
};
QT_END_NAMESPACE
#endif // QT_NO_LIBRARY
QT_END_NAMESPACE
#endif // QLIBRARY_P_H

View File

@ -41,10 +41,10 @@
#include "qdebug.h"
#include "qdir.h"
#ifndef QT_NO_LIBRARY
QT_BEGIN_NAMESPACE
#ifndef QT_NO_LIBRARY
/*!
\class QPluginLoader
\inmodule QtCore
@ -382,9 +382,6 @@ QString QPluginLoader::errorString() const
return (!d || d->errorString.isEmpty()) ? tr("Unknown error") : d->errorString;
}
typedef QVector<QStaticPlugin> StaticPluginList;
Q_GLOBAL_STATIC(StaticPluginList, staticPluginList)
/*! \since 4.4
\property QPluginLoader::loadHints
@ -413,6 +410,11 @@ QLibrary::LoadHints QPluginLoader::loadHints() const
return d ? d->loadHints() : QLibrary::LoadHints();
}
#endif // QT_NO_LIBRARY
typedef QVector<QStaticPlugin> StaticPluginList;
Q_GLOBAL_STATIC(StaticPluginList, staticPluginList)
/*!
\relates QPluginLoader
\since 5.0
@ -465,9 +467,8 @@ QVector<QStaticPlugin> QPluginLoader::staticPlugins()
*/
QJsonObject QStaticPlugin::metaData() const
{
return QLibraryPrivate::fromRawMetaData(rawMetaData()).object();
return qJsonFromRawLibraryMetaData(rawMetaData()).object();
}
QT_END_NAMESPACE
#endif // QT_NO_LIBRARY

View File

@ -37,10 +37,10 @@
#include <QtCore/qlibrary.h>
#include <QtCore/qplugin.h>
#ifndef QT_NO_LIBRARY
QT_BEGIN_NAMESPACE
#ifndef QT_NO_LIBRARY
class QLibraryPrivate;
class QJsonObject;
@ -78,8 +78,17 @@ private:
Q_DISABLE_COPY(QPluginLoader)
};
QT_END_NAMESPACE
#else
class Q_CORE_EXPORT QPluginLoader
{
public:
static QObjectList staticInstances();
static QVector<QStaticPlugin> staticPlugins();
};
#endif // QT_NO_LIBRARY
QT_END_NAMESPACE
#endif //QPLUGINLOADER_H

View File

@ -33,8 +33,6 @@
#include "qgenericplugin.h"
#ifndef QT_NO_LIBRARY
QT_BEGIN_NAMESPACE
/*!
@ -90,5 +88,3 @@ QGenericPlugin::~QGenericPlugin()
*/
QT_END_NAMESPACE
#endif // QT_NO_LIBRARY

View File

@ -39,9 +39,6 @@
QT_BEGIN_NAMESPACE
#ifndef QT_NO_LIBRARY
#define QGenericPluginFactoryInterface_iid "org.qt-project.Qt.QGenericPluginFactoryInterface"
class Q_GUI_EXPORT QGenericPlugin : public QObject
@ -54,8 +51,6 @@ public:
virtual QObject* create(const QString& name, const QString &spec) = 0;
};
#endif // QT_NO_LIBRARY
QT_END_NAMESPACE
#endif // QGENERICPLUGIN_H

View File

@ -20,3 +20,8 @@ win32 {
mac: CONFIG -= app_bundle
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
load(qfeatures)
contains(QT_DISABLED_FEATURES, library) {
LIBS += -L ../bin/ -lplugin1 -lplugin2
}

View File

@ -38,6 +38,11 @@
#include "plugin1/plugininterface1.h"
#include "plugin2/plugininterface2.h"
#ifdef QT_NO_LIBRARY
Q_IMPORT_PLUGIN(Plugin1)
Q_IMPORT_PLUGIN(Plugin2)
#endif
class tst_QFactoryLoader : public QObject
{
Q_OBJECT
@ -54,8 +59,9 @@ void tst_QFactoryLoader::initTestCase()
{
const QString binFolder = QFINDTESTDATA(binFolderC);
QVERIFY2(!binFolder.isEmpty(), "Unable to locate 'bin' folder");
#ifndef QT_NO_LIBRARY
QCoreApplication::setLibraryPaths(QStringList(QFileInfo(binFolder).absolutePath()));
#endif
}
void tst_QFactoryLoader::usingTwoFactoriesFromSameDir()