summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/plugin/qlibrary_p.h2
-rw-r--r--src/corelib/plugin/qlibrary_unix.cpp100
-rw-r--r--src/corelib/plugin/qlibrary_win.cpp11
-rw-r--r--src/corelib/plugin/qpluginloader.cpp54
-rw-r--r--tests/auto/corelib/plugin/qpluginloader/almostplugin/almostplugin.pro1
-rw-r--r--tests/auto/corelib/plugin/qpluginloader/theplugin/theplugin.pro5
-rw-r--r--tests/auto/corelib/plugin/qpluginloader/tst/tst.pro1
-rw-r--r--tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp29
8 files changed, 148 insertions, 55 deletions
diff --git a/src/corelib/plugin/qlibrary_p.h b/src/corelib/plugin/qlibrary_p.h
index 337c43acb9..8465d5cf06 100644
--- a/src/corelib/plugin/qlibrary_p.h
+++ b/src/corelib/plugin/qlibrary_p.h
@@ -92,6 +92,8 @@ public:
QFunctionPointer resolve(const char *);
static QLibraryPrivate *findOrCreate(const QString &fileName, const QString &version = QString());
+ static QStringList suffixes_sys(const QString &fullVersion);
+ static QStringList prefixes_sys();
static QVector<QStaticPlugin> staticPlugins();
diff --git a/src/corelib/plugin/qlibrary_unix.cpp b/src/corelib/plugin/qlibrary_unix.cpp
index 2ef6f80466..35d8197306 100644
--- a/src/corelib/plugin/qlibrary_unix.cpp
+++ b/src/corelib/plugin/qlibrary_unix.cpp
@@ -80,6 +80,60 @@ static QString qdlerror()
return err ? QLatin1Char('(') + QString::fromLocal8Bit(err) + QLatin1Char(')'): QString();
}
+QStringList QLibraryPrivate::suffixes_sys(const QString& fullVersion)
+{
+ QStringList suffixes;
+#if defined(Q_OS_HPUX)
+ // according to
+ // http://docs.hp.com/en/B2355-90968/linkerdifferencesiapa.htm
+
+ // In PA-RISC (PA-32 and PA-64) shared libraries are suffixed
+ // with .sl. In IPF (32-bit and 64-bit), the shared libraries
+ // are suffixed with .so. For compatibility, the IPF linker
+ // also supports the .sl suffix.
+
+ // But since we don't know if we are built on HPUX or HPUXi,
+ // we support both .sl (and .<version>) and .so suffixes but
+ // .so is preferred.
+# if defined(__ia64)
+ if (!fullVersion.isEmpty()) {
+ suffixes << QString::fromLatin1(".so.%1").arg(fullVersion);
+ } else {
+ suffixes << QLatin1String(".so");
+ }
+# endif
+ if (!fullVersion.isEmpty()) {
+ suffixes << QString::fromLatin1(".sl.%1").arg(fullVersion);
+ suffixes << QString::fromLatin1(".%1").arg(fullVersion);
+ } else {
+ suffixes << QLatin1String(".sl");
+ }
+#elif defined(Q_OS_AIX)
+ suffixes << ".a";
+
+#else
+ if (!fullVersion.isEmpty()) {
+ suffixes << QString::fromLatin1(".so.%1").arg(fullVersion);
+ } else {
+ suffixes << QLatin1String(".so");
+ }
+#endif
+# ifdef Q_OS_MAC
+ if (!fullVersion.isEmpty()) {
+ suffixes << QString::fromLatin1(".%1.bundle").arg(fullVersion);
+ suffixes << QString::fromLatin1(".%1.dylib").arg(fullVersion);
+ } else {
+ suffixes << QLatin1String(".bundle") << QLatin1String(".dylib");
+ }
+#endif
+ return suffixes;
+}
+
+QStringList QLibraryPrivate::prefixes_sys()
+{
+ return QStringList() << QLatin1String("lib");
+}
+
bool QLibraryPrivate::load_sys()
{
QString attempt;
@@ -96,50 +150,8 @@ bool QLibraryPrivate::load_sys()
QStringList suffixes;
QStringList prefixes;
if (pluginState != IsAPlugin) {
- prefixes << QLatin1String("lib");
-#if defined(Q_OS_HPUX)
- // according to
- // http://docs.hp.com/en/B2355-90968/linkerdifferencesiapa.htm
-
- // In PA-RISC (PA-32 and PA-64) shared libraries are suffixed
- // with .sl. In IPF (32-bit and 64-bit), the shared libraries
- // are suffixed with .so. For compatibility, the IPF linker
- // also supports the .sl suffix.
-
- // But since we don't know if we are built on HPUX or HPUXi,
- // we support both .sl (and .<version>) and .so suffixes but
- // .so is preferred.
-# if defined(__ia64)
- if (!fullVersion.isEmpty()) {
- suffixes << QString::fromLatin1(".so.%1").arg(fullVersion);
- } else {
- suffixes << QLatin1String(".so");
- }
-# endif
- if (!fullVersion.isEmpty()) {
- suffixes << QString::fromLatin1(".sl.%1").arg(fullVersion);
- suffixes << QString::fromLatin1(".%1").arg(fullVersion);
- } else {
- suffixes << QLatin1String(".sl");
- }
-#elif defined(Q_OS_AIX)
- suffixes << ".a";
-
-#else
- if (!fullVersion.isEmpty()) {
- suffixes << QString::fromLatin1(".so.%1").arg(fullVersion);
- } else {
- suffixes << QLatin1String(".so");
- }
-#endif
-# ifdef Q_OS_MAC
- if (!fullVersion.isEmpty()) {
- suffixes << QString::fromLatin1(".%1.bundle").arg(fullVersion);
- suffixes << QString::fromLatin1(".%1.dylib").arg(fullVersion);
- } else {
- suffixes << QLatin1String(".bundle") << QLatin1String(".dylib");
- }
-#endif
+ prefixes = prefixes_sys();
+ suffixes = suffixes_sys(fullVersion);
}
int dlFlags = 0;
#if defined(QT_HPUX_LD)
diff --git a/src/corelib/plugin/qlibrary_win.cpp b/src/corelib/plugin/qlibrary_win.cpp
index 27796aedc1..ef3816a804 100644
--- a/src/corelib/plugin/qlibrary_win.cpp
+++ b/src/corelib/plugin/qlibrary_win.cpp
@@ -57,6 +57,17 @@ QT_BEGIN_NAMESPACE
extern QString qt_error_string(int code);
+QStringList QLibraryPrivate::suffixes_sys(const QString& fullVersion)
+{
+ Q_UNUSED(fullVersion);
+ return QStringList() << ".dll";
+}
+
+QStringList QLibraryPrivate::prefixes_sys()
+{
+ return QStringList();
+}
+
bool QLibraryPrivate::load_sys()
{
//avoid 'Bad Image' message box
diff --git a/src/corelib/plugin/qpluginloader.cpp b/src/corelib/plugin/qpluginloader.cpp
index 31d9fda858..c16a340dbe 100644
--- a/src/corelib/plugin/qpluginloader.cpp
+++ b/src/corelib/plugin/qpluginloader.cpp
@@ -42,6 +42,7 @@
#include "qplatformdefs.h"
#include "qplugin.h"
+#include "qcoreapplication.h"
#include "qpluginloader.h"
#include <qfileinfo.h>
#include "qlibrary_p.h"
@@ -250,14 +251,52 @@ bool QPluginLoader::isLoaded() const
return d && d->pHnd && d->instance;
}
+static QString locatePlugin(const QString& fileName)
+{
+ QStringList prefixes = QLibraryPrivate::prefixes_sys();
+ prefixes.prepend(QString());
+ QStringList suffixes = QLibraryPrivate::suffixes_sys(QString());
+ suffixes.prepend(QString());
+
+ // Split up "subdir/filename"
+ const int slash = fileName.lastIndexOf('/');
+ const QString baseName = fileName.mid(slash + 1);
+ const QString basePath = fileName.left(slash + 1); // keep the '/'
+
+ const bool debug = qt_debug_component();
+
+ QStringList paths = QCoreApplication::libraryPaths();
+ paths.prepend(QStringLiteral("./")); // search in current dir first
+ foreach (const QString &path, paths) {
+ foreach (const QString &prefix, prefixes) {
+ foreach (const QString &suffix, suffixes) {
+ const QString fn = path + QLatin1Char('/') + basePath + prefix + baseName + suffix;
+ if (debug)
+ qDebug() << "Trying..." << fn;
+ if (QFileInfo(fn).isFile())
+ return fn;
+ }
+ }
+ }
+ if (debug)
+ qDebug() << fileName << "not found";
+ return QString();
+}
+
/*!
\property QPluginLoader::fileName
\brief the file name of the plugin
- To be loadable, the file's suffix must be a valid suffix for a
- loadable library in accordance with the platform, e.g. \c .so on
- Unix, \c .dylib on Mac OS X, and \c .dll on Windows. The suffix
- can be verified with QLibrary::isLibrary().
+ We recommend omitting the file's suffix in the file name, since
+ QPluginLoader will automatically look for the file with the appropriate
+ suffix (see QLibrary::isLibrary()).
+
+ When loading the plugin, QPluginLoader searches in the current directory and
+ in all plugin locations specified by QCoreApplication::libraryPaths(),
+ unless the file name has an absolute path. After loading the plugin
+ successfully, fileName() returns the fully-qualified file name of
+ the plugin, including the full path to the plugin if one was given
+ in the constructor or passed to setFileName().
If the file name does not exist, it will not be set. This property
will then contain an empty string.
@@ -277,7 +316,12 @@ void QPluginLoader::setFileName(const QString &fileName)
did_load = false;
}
- QString fn = QFileInfo(fileName).canonicalFilePath();
+ QFileInfo fi(fileName);
+ QString fn;
+ if (fi.isAbsolute())
+ fn = fi.canonicalFilePath();
+ else
+ fn = locatePlugin(fileName);
d = QLibraryPrivate::findOrCreate(fn);
d->loadHints = lh;
diff --git a/tests/auto/corelib/plugin/qpluginloader/almostplugin/almostplugin.pro b/tests/auto/corelib/plugin/qpluginloader/almostplugin/almostplugin.pro
index 0004a8c712..70ab54a964 100644
--- a/tests/auto/corelib/plugin/qpluginloader/almostplugin/almostplugin.pro
+++ b/tests/auto/corelib/plugin/qpluginloader/almostplugin/almostplugin.pro
@@ -4,6 +4,7 @@ HEADERS = almostplugin.h
SOURCES = almostplugin.cpp
TARGET = almostplugin
DESTDIR = ../bin
+QT = core
*-g++*:QMAKE_LFLAGS -= -Wl,--no-undefined
# This is testdata for the tst_qpluginloader test.
diff --git a/tests/auto/corelib/plugin/qpluginloader/theplugin/theplugin.pro b/tests/auto/corelib/plugin/qpluginloader/theplugin/theplugin.pro
index b510f8fb44..2ea9c27cc9 100644
--- a/tests/auto/corelib/plugin/qpluginloader/theplugin/theplugin.pro
+++ b/tests/auto/corelib/plugin/qpluginloader/theplugin/theplugin.pro
@@ -2,8 +2,11 @@ TEMPLATE = lib
CONFIG += plugin
HEADERS = theplugin.h
SOURCES = theplugin.cpp
-TARGET = $$qtLibraryTarget(theplugin)
+# Use a predictable name for the plugin, no debug extension. Just like most apps do.
+#TARGET = $$qtLibraryTarget(theplugin)
+TARGET = theplugin
DESTDIR = ../bin
+QT = core
# This is testdata for the tst_qpluginloader test.
target.path = $$[QT_INSTALL_TESTS]/tst_qpluginloader/bin
diff --git a/tests/auto/corelib/plugin/qpluginloader/tst/tst.pro b/tests/auto/corelib/plugin/qpluginloader/tst/tst.pro
index 48650a5727..a7a9661a54 100644
--- a/tests/auto/corelib/plugin/qpluginloader/tst/tst.pro
+++ b/tests/auto/corelib/plugin/qpluginloader/tst/tst.pro
@@ -4,6 +4,7 @@ TARGET = ../tst_qpluginloader
QT = core testlib
SOURCES = ../tst_qpluginloader.cpp
HEADERS = ../theplugin/plugininterface.h
+CONFIG -= app_bundle
win32 {
CONFIG(debug, debug|release) {
diff --git a/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp b/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp
index 155267f80b..34ec66f63f 100644
--- a/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp
+++ b/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp
@@ -59,7 +59,11 @@
# define bundle_VALID true
# define dylib_VALID true
# define so_VALID true
-# define SUFFIX ".dylib"
+//# ifdef QT_NO_DEBUG
+# define SUFFIX ".dylib"
+//# else
+//# define SUFFIX "_debug.dylib"
+//#endif
# define PREFIX "lib"
#elif defined(Q_OS_HPUX) && !defined(__ia64)
@@ -79,11 +83,11 @@
#elif defined(Q_OS_WIN)
# undef dll_VALID
# define dll_VALID true
-# ifdef QT_NO_DEBUG
+//# ifdef QT_NO_DEBUG
# define SUFFIX ".dll"
-# else
-# define SUFFIX "d.dll"
-# endif
+//# else
+//# define SUFFIX "d.dll"
+//# endif
# define PREFIX ""
#else // all other Unix
@@ -111,6 +115,7 @@ private slots:
#if defined (Q_OS_UNIX)
void loadGarbage();
#endif
+ void relativePath();
void reloadPlugin();
};
@@ -294,6 +299,20 @@ void tst_QPluginLoader::loadGarbage()
}
#endif
+void tst_QPluginLoader::relativePath()
+{
+ // Windows binaries run from release and debug subdirs, so we can't rely on the current dir.
+ const QString binDir = QFINDTESTDATA("bin");
+ QVERIFY(!binDir.isEmpty());
+ QCoreApplication::addLibraryPath(binDir);
+ QPluginLoader loader("theplugin");
+ loader.load(); // not recommended, instance() should do the job.
+ PluginInterface *instance = qobject_cast<PluginInterface*>(loader.instance());
+ QVERIFY(instance);
+ QCOMPARE(instance->pluginName(), QLatin1String("Plugin ok"));
+ QVERIFY(loader.unload());
+}
+
void tst_QPluginLoader::reloadPlugin()
{
QPluginLoader loader;