Android: activate tst_QPluginLoader

- Use QT_ANDROID_EXTRA_LIBS to correctly deploy libraries on Android.
- Update the test code to use application libraries directory
  on Android.

This allows to enable the test for Android in CMakeLists.txt

Task-number: QTBUG-87438
Pick-to: 6.3 6.2
Change-Id: Ib74da036472320736888052b63a45ca50431de48
Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
This commit is contained in:
Ivan Solovev 2022-03-28 13:28:25 +02:00
parent ed6fe5abc8
commit 7c9b4f86b6
4 changed files with 65 additions and 9 deletions

View File

@ -5,10 +5,7 @@ if(QT_BUILD_SHARED_LIBS)
endif() endif()
add_subdirectory(quuid) add_subdirectory(quuid)
if(QT_FEATURE_library) if(QT_FEATURE_library)
# QTBUG-87438 # special case
if(NOT ANDROID)
add_subdirectory(qpluginloader) add_subdirectory(qpluginloader)
endif()
add_subdirectory(qlibrary) add_subdirectory(qlibrary)
endif() endif()
if(QT_BUILD_SHARED_LIBS AND QT_FEATURE_library) if(QT_BUILD_SHARED_LIBS AND QT_FEATURE_library)

View File

@ -8,7 +8,7 @@ qt_internal_add_cmake_library(staticplugin
STATIC STATIC
SOURCES SOURCES
main.cpp main.cpp
PUBLIC_LIBRARIES LIBRARIES
Qt::Core Qt::Core
MOC_OPTIONS MOC_OPTIONS
"-M" "-M"

View File

@ -14,16 +14,43 @@ qt_internal_add_test(tst_qpluginloader
../fakeplugin.cpp ../fakeplugin.cpp
../theplugin/plugininterface.h ../theplugin/plugininterface.h
../tst_qpluginloader.cpp ../tst_qpluginloader.cpp
PUBLIC_LIBRARIES LIBRARIES
staticplugin staticplugin
TESTDATA ${test_data} TESTDATA ${test_data}
) )
add_dependencies(tst_qpluginloader tst_qpluginloaderlib staticplugin theplugin)
if (UNIX)
if(NOT APPLE)
add_dependencies(tst_qpluginloader theoldplugin)
endif()
if (NOT ANDROID AND NOT APPLE)
add_dependencies(tst_qpluginloader almostplugin)
endif()
endif()
if(ANDROID)
add_compile_definitions(ANDROID_ARCH="${CMAKE_ANDROID_ARCH_ABI}")
set(plugins
theplugin
theoldplugin
tst_qpluginloaderlib
)
set(extra_libs)
foreach(plugin IN LISTS plugins)
list(APPEND extra_libs
"${CMAKE_CURRENT_BINARY_DIR}/../bin/lib${plugin}_${CMAKE_ANDROID_ARCH_ABI}.so")
endforeach()
set_target_properties(tst_qpluginloader PROPERTIES
QT_ANDROID_EXTRA_LIBS "${extra_libs}"
)
endif()
## Scopes: ## Scopes:
##################################################################### #####################################################################
qt_internal_extend_target(tst_qpluginloader CONDITION QT_FEATURE_private_tests qt_internal_extend_target(tst_qpluginloader CONDITION QT_FEATURE_private_tests
PUBLIC_LIBRARIES LIBRARIES
Qt::CorePrivate Qt::CorePrivate
) )

View File

@ -185,12 +185,22 @@ static std::unique_ptr<QTemporaryFile> patchElf(const QString &source, ElfPatche
static QString sys_qualifiedLibraryName(const QString &fileName) static QString sys_qualifiedLibraryName(const QString &fileName)
{ {
#ifdef Q_OS_ANDROID
// On Android all the libraries must be located in the APK's libs subdir
const QStringList paths = QCoreApplication::libraryPaths();
if (!paths.isEmpty()) {
return QLatin1String("%1/%2%3_%4%5").arg(paths.first(), PREFIX, fileName,
ANDROID_ARCH, SUFFIX);
}
return fileName;
#else
QString name = QLatin1String("bin/") + QLatin1String(PREFIX) + fileName + QLatin1String(SUFFIX); QString name = QLatin1String("bin/") + QLatin1String(PREFIX) + fileName + QLatin1String(SUFFIX);
const QString libname = QFINDTESTDATA(name); const QString libname = QFINDTESTDATA(name);
QFileInfo fi(libname); QFileInfo fi(libname);
if (fi.exists()) if (fi.exists())
return fi.canonicalFilePath(); return fi.canonicalFilePath();
return libname; return libname;
#endif
} }
QT_FORWARD_DECLARE_CLASS(QPluginLoader) QT_FORWARD_DECLARE_CLASS(QPluginLoader)
@ -918,11 +928,19 @@ void tst_QPluginLoader::relativePath()
#if !defined(QT_SHARED) #if !defined(QT_SHARED)
QSKIP("This test requires Qt to create shared libraries."); QSKIP("This test requires Qt to create shared libraries.");
#endif #endif
#ifdef Q_OS_ANDROID
// On Android we do not need to explicitly set library paths, as they are
// already set.
// But we need to use ARCH suffix in pulgin name
const QString pluginName("theplugin_" ANDROID_ARCH SUFFIX);
#else
// Windows binaries run from release and debug subdirs, so we can't rely on the current dir. // Windows binaries run from release and debug subdirs, so we can't rely on the current dir.
const QString binDir = QFINDTESTDATA("bin"); const QString binDir = QFINDTESTDATA("bin");
QVERIFY(!binDir.isEmpty()); QVERIFY(!binDir.isEmpty());
QCoreApplication::addLibraryPath(binDir); QCoreApplication::addLibraryPath(binDir);
QPluginLoader loader("theplugin" SUFFIX); const QString pluginName("theplugin" SUFFIX);
#endif
QPluginLoader loader(pluginName);
loader.load(); // not recommended, instance() should do the job. loader.load(); // not recommended, instance() should do the job.
PluginInterface *instance = qobject_cast<PluginInterface*>(loader.instance()); PluginInterface *instance = qobject_cast<PluginInterface*>(loader.instance());
QVERIFY(instance); QVERIFY(instance);
@ -935,13 +953,27 @@ void tst_QPluginLoader::absolutePath()
#if !defined(QT_SHARED) #if !defined(QT_SHARED)
QSKIP("This test requires Qt to create shared libraries."); QSKIP("This test requires Qt to create shared libraries.");
#endif #endif
#ifdef Q_OS_ANDROID
// On Android we need to clear library paths to make sure that the absolute
// path works
const QStringList libraryPaths = QCoreApplication::libraryPaths();
QVERIFY(!libraryPaths.isEmpty());
QCoreApplication::setLibraryPaths(QStringList());
const QString pluginPath(libraryPaths.first() + "/" PREFIX "theplugin_" ANDROID_ARCH SUFFIX);
#else
// Windows binaries run from release and debug subdirs, so we can't rely on the current dir. // Windows binaries run from release and debug subdirs, so we can't rely on the current dir.
const QString binDir = QFINDTESTDATA("bin"); const QString binDir = QFINDTESTDATA("bin");
QVERIFY(!binDir.isEmpty()); QVERIFY(!binDir.isEmpty());
QVERIFY(QDir::isAbsolutePath(binDir)); QVERIFY(QDir::isAbsolutePath(binDir));
QPluginLoader loader(binDir + "/" PREFIX "theplugin" SUFFIX); const QString pluginPath(binDir + "/" PREFIX "theplugin" SUFFIX);
#endif
QPluginLoader loader(pluginPath);
loader.load(); // not recommended, instance() should do the job. loader.load(); // not recommended, instance() should do the job.
PluginInterface *instance = qobject_cast<PluginInterface*>(loader.instance()); PluginInterface *instance = qobject_cast<PluginInterface*>(loader.instance());
#ifdef Q_OS_ANDROID
// Restore library paths
QCoreApplication::setLibraryPaths(libraryPaths);
#endif
QVERIFY(instance); QVERIFY(instance);
QCOMPARE(instance->pluginName(), QLatin1String("Plugin ok")); QCOMPARE(instance->pluginName(), QLatin1String("Plugin ok"));
QVERIFY(loader.unload()); QVERIFY(loader.unload());