QLibrary/Unix: update the x86-64-v3 prefix path in our search
glibc introduced the glibc-hwcaps/XXXX path in glibc 2.33 (2020) and removed the old, legacy "haswell/" prefix in glibc 2.37 (2022). This means anyone deploying HW-capable libraries must be deploying symlinks, so we are not losing functionality. Because it says "glibc-hwcaps", I am now making this dependent on glibc for libraries. Added unit testing for this feature. Tested on Linux, FreeBSD, macOS, and Windows (the QLibrary test SKIPs everywhere except Linux). We do create a "libtheplugin.dylib.avx2" on macOS with this change, but won't attempt to load it (Darwin has fat binaries so lipo(1)ing the files together would be the right thing to do). Pick-to: 6.8 Change-Id: Ic0adfa808d28487a8303fffd17d9e78ec87bbd9a Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
parent
01d4be4a83
commit
a1db295912
@ -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
|
||||
|
@ -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)
|
||||
|
38
tests/auto/corelib/plugin/qlibrary/archlib/CMakeLists.txt
Normal file
38
tests/auto/corelib/plugin/qlibrary/archlib/CMakeLists.txt
Normal file
@ -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()
|
13
tests/auto/corelib/plugin/qlibrary/archlib/mylib.c
Normal file
13
tests/auto/corelib/plugin/qlibrary/archlib/mylib.c
Normal file
@ -0,0 +1,13 @@
|
||||
// Copyright (C) 2024 Intel Corporation.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
|
||||
|
||||
#include <qglobal.h>
|
||||
|
||||
Q_DECL_EXPORT const char *archname()
|
||||
{
|
||||
#ifdef ARCH
|
||||
return ARCH;
|
||||
#else
|
||||
return "";
|
||||
#endif
|
||||
}
|
@ -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<QString>("lib");
|
||||
QTest::addColumn<int>("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)
|
||||
|
@ -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()
|
||||
|
@ -8,6 +8,7 @@
|
||||
struct PluginInterface {
|
||||
virtual ~PluginInterface() {}
|
||||
virtual QString pluginName() const = 0;
|
||||
virtual const char *architectureName() const { return ""; };
|
||||
};
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
@ -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 <QtCore/QString>
|
||||
#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()
|
||||
{
|
||||
|
@ -15,6 +15,7 @@ class ThePlugin : public QObject, public PluginInterface
|
||||
|
||||
public:
|
||||
virtual QString pluginName() const override;
|
||||
const char *architectureName() const override;
|
||||
};
|
||||
|
||||
#endif // THEPLUGIN_H
|
||||
|
@ -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<PluginInterface*>(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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user