diff --git a/src/corelib/plugin/qlibrary_unix.cpp b/src/corelib/plugin/qlibrary_unix.cpp index 479c08f2afe..d05a5fa0ac8 100644 --- a/src/corelib/plugin/qlibrary_unix.cpp +++ b/src/corelib/plugin/qlibrary_unix.cpp @@ -169,8 +169,10 @@ bool QLibraryPrivate::load_sys() // add ".avx2" to each suffix in the list transform(suffixes, [](QString *s) { s->append(".avx2"_L1); }); } else { - // prepend "haswell/" to each prefix in the list - transform(prefixes, [](QString *s) { s->prepend("haswell/"_L1); }); +# ifdef __GLIBC__ + // prepend "glibc-hwcaps/x86-64-v3/" to each prefix in the list + transform(prefixes, [](QString *s) { s->prepend("glibc-hwcaps/x86-64-v3/"_L1); }); +# endif } } #endif diff --git a/tests/auto/corelib/plugin/qlibrary/CMakeLists.txt b/tests/auto/corelib/plugin/qlibrary/CMakeLists.txt index b8f4af5aa84..4ee7e6b06ef 100644 --- a/tests/auto/corelib/plugin/qlibrary/CMakeLists.txt +++ b/tests/auto/corelib/plugin/qlibrary/CMakeLists.txt @@ -7,6 +7,7 @@ if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() +add_subdirectory(archlib) add_subdirectory(lib) add_subdirectory(lib2) add_subdirectory(tst) diff --git a/tests/auto/corelib/plugin/qlibrary/archlib/CMakeLists.txt b/tests/auto/corelib/plugin/qlibrary/archlib/CMakeLists.txt new file mode 100644 index 00000000000..329e8d7202d --- /dev/null +++ b/tests/auto/corelib/plugin/qlibrary/archlib/CMakeLists.txt @@ -0,0 +1,38 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# Copyright (C) 2024 Intel Corporation. +# SPDX-License-Identifier: BSD-3-Clause + +if (UNIX) + qt_internal_add_cmake_library(tst_qlibrary_myarchlib + SHARED + OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../" + SOURCES + mylib.c + LIBRARIES + Qt::Core + ) + + set_target_properties(tst_qlibrary_myarchlib PROPERTIES + OUTPUT_NAME myarchlib + VERSION 1.0.0 + SOVERSION 1 + ) + + if ("${TEST_architecture_arch}" STREQUAL "x86_64") + qt_internal_add_cmake_library(tst_qlibrary_myarchlib_x86-64-v3 + DEFINES + ARCH="x86-64-v3" + SHARED + OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../glibc-hwcaps/x86-64-v3" + SOURCES + mylib.c + LIBRARIES + Qt::Core + ) + set_target_properties(tst_qlibrary_myarchlib_x86-64-v3 PROPERTIES + OUTPUT_NAME myarchlib + VERSION 1.0.0 + SOVERSION 1 + ) + endif() +endif() diff --git a/tests/auto/corelib/plugin/qlibrary/archlib/mylib.c b/tests/auto/corelib/plugin/qlibrary/archlib/mylib.c new file mode 100644 index 00000000000..5d9fe081cbb --- /dev/null +++ b/tests/auto/corelib/plugin/qlibrary/archlib/mylib.c @@ -0,0 +1,13 @@ +// Copyright (C) 2024 Intel Corporation. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include + +Q_DECL_EXPORT const char *archname() +{ +#ifdef ARCH + return ARCH; +#else + return ""; +#endif +} diff --git a/tests/auto/corelib/plugin/qlibrary/tst_qlibrary.cpp b/tests/auto/corelib/plugin/qlibrary/tst_qlibrary.cpp index 72957374fab..5ae49ff1707 100644 --- a/tests/auto/corelib/plugin/qlibrary/tst_qlibrary.cpp +++ b/tests/auto/corelib/plugin/qlibrary/tst_qlibrary.cpp @@ -63,6 +63,8 @@ # define PREFIX "lib" #endif +using namespace Qt::StringLiterals; + QT_FORWARD_DECLARE_CLASS(QLibrary) class tst_QLibrary : public QObject { @@ -97,6 +99,8 @@ private slots: void version_data(); void version(); void loadTwoVersions(); + void archSpecificVersion_data(); + void archSpecificVersion(); void setFileNameAndVersionTwice(); void setFileNameAndVersionAfterFailedLoad_data() { version_data(); } void setFileNameAndVersionAfterFailedLoad(); @@ -229,6 +233,42 @@ void tst_QLibrary::loadTwoVersions() lib1.unload(); } +void tst_QLibrary::archSpecificVersion_data() +{ +#if !defined(__GLIBC__) || !defined(Q_PROCESSOR_X86_64) + QSKIP("Test not applicable on this platform"); +#endif + + QTest::addColumn("lib"); + QTest::addColumn("version"); + + for (const char *prefix : { "", PREFIX }) { + QString libname = prefix + u"myarchlib"_s; + QTest::addRow("%s v1", qPrintable(libname)) << libname << 1; + QTest::addRow("%s.so.1", qPrintable(libname)) << (libname + SUFFIX + ".1") << -1; + } +} + +void tst_QLibrary::archSpecificVersion() +{ + QFETCH(QString, lib); + QFETCH(int, version); + QString expectedArch; + +#if defined(__GLIBC__) && defined(Q_PROCESSOR_X86_64) + if (__builtin_cpu_supports("avx2") && __builtin_cpu_supports("fma")) + expectedArch = "x86-64-v3"; +#endif + + QString appDir = directory; + QLibrary library(appDir + QLatin1Char('/') + lib, version); + QVERIFY2(library.load(), qPrintable(library.errorString())); + + auto archfunction = (const char *(*)())library.resolve("archname"); + QVERIFY(archfunction); + QCOMPARE(archfunction(), expectedArch); +} + void tst_QLibrary::setFileNameAndVersionTwice() { #if defined(Q_OS_ANDROID) || defined(Q_OS_WIN) diff --git a/tests/auto/corelib/plugin/qpluginloader/theplugin/CMakeLists.txt b/tests/auto/corelib/plugin/qpluginloader/theplugin/CMakeLists.txt index dfce9d6a524..8151f80db36 100644 --- a/tests/auto/corelib/plugin/qpluginloader/theplugin/CMakeLists.txt +++ b/tests/auto/corelib/plugin/qpluginloader/theplugin/CMakeLists.txt @@ -30,3 +30,21 @@ if (UNIX AND NOT APPLE) target_compile_options(theoldplugin PRIVATE -O0 -g3) endif() +if (UNIX AND "${TEST_architecture_arch}" STREQUAL "x86_64") + qt_internal_add_cmake_library(theplugin_x86-64-v3 + DEFINES + ARCH="x86-64-v3" + MODULE + INSTALL_DIRECTORY "${INSTALL_TESTSDIR}/tst_qpluginloader/bin" + OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../bin" + SOURCES + theplugin.cpp theplugin.h + LIBRARIES + Qt::Core + ) + qt_autogen_tools_initial_setup(theplugin_x86-64-v3) + set_target_properties(theplugin_x86-64-v3 PROPERTIES + OUTPUT_NAME theplugin + SUFFIX "${CMAKE_SHARED_LIBRARY_SUFFIX}.avx2" + ) +endif() diff --git a/tests/auto/corelib/plugin/qpluginloader/theplugin/plugininterface.h b/tests/auto/corelib/plugin/qpluginloader/theplugin/plugininterface.h index 3fd6c384a4f..a7682fef508 100644 --- a/tests/auto/corelib/plugin/qpluginloader/theplugin/plugininterface.h +++ b/tests/auto/corelib/plugin/qpluginloader/theplugin/plugininterface.h @@ -8,6 +8,7 @@ struct PluginInterface { virtual ~PluginInterface() {} virtual QString pluginName() const = 0; + virtual const char *architectureName() const { return ""; }; }; QT_BEGIN_NAMESPACE diff --git a/tests/auto/corelib/plugin/qpluginloader/theplugin/theplugin.cpp b/tests/auto/corelib/plugin/qpluginloader/theplugin/theplugin.cpp index bfa45c7c484..69cc37dad83 100644 --- a/tests/auto/corelib/plugin/qpluginloader/theplugin/theplugin.cpp +++ b/tests/auto/corelib/plugin/qpluginloader/theplugin/theplugin.cpp @@ -1,4 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. +// Copyright (C) 2024 Intel Corporation. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include #include "theplugin.h" @@ -9,6 +10,15 @@ QString ThePlugin::pluginName() const return QLatin1String("Plugin ok"); } +const char *ThePlugin::architectureName() const +{ +#ifdef ARCH + return ARCH; +#else + return ""; +#endif +} + static int pluginVariable = 0xc0ffee; extern "C" Q_DECL_EXPORT int *pointerAddress() { diff --git a/tests/auto/corelib/plugin/qpluginloader/theplugin/theplugin.h b/tests/auto/corelib/plugin/qpluginloader/theplugin/theplugin.h index a6b7e4a0839..9c8d5177af2 100644 --- a/tests/auto/corelib/plugin/qpluginloader/theplugin/theplugin.h +++ b/tests/auto/corelib/plugin/qpluginloader/theplugin/theplugin.h @@ -15,6 +15,7 @@ class ThePlugin : public QObject, public PluginInterface public: virtual QString pluginName() const override; + const char *architectureName() const override; }; #endif // THEPLUGIN_H diff --git a/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp b/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp index 4ff93f9de49..46ec5f693d9 100644 --- a/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp +++ b/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp @@ -201,6 +201,7 @@ private slots: void loadCorruptElfOldPlugin(); # endif #endif + void archSpecificVersion(); void loadMachO_data(); void loadMachO(); void relativePath(); @@ -850,6 +851,26 @@ void tst_QPluginLoader::loadCorruptElfOldPlugin() # endif // Qt 7 #endif // Q_OF_ELF +void tst_QPluginLoader::archSpecificVersion() +{ +#if !defined(QT_SHARED) + QSKIP("This test requires Qt to create shared libraries."); +#endif + QPluginLoader loader(sys_qualifiedLibraryName("theplugin")); + QVERIFY2(loader.load(), qPrintable(loader.errorString())); + + QString expectedArch; +#if defined(Q_PROCESSOR_X86_64) && defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN) + if (__builtin_cpu_supports("avx2") && __builtin_cpu_supports("fma")) + expectedArch = "x86-64-v3"; +#endif + + PluginInterface* theplugin = qobject_cast(loader.instance()); + QVERIFY(theplugin); + QCOMPARE(theplugin->architectureName(), expectedArch); + QVERIFY(loader.unload()); +} + void tst_QPluginLoader::loadMachO_data() { #if defined(QT_BUILD_INTERNAL) && defined(Q_OF_MACH_O)