forked from qt-creator/qt-creator
BaseQtVersion: Fix Qt build string parsing
This fixes Qt build string parsing based on feedback from Thiago. Also adds unit test for the code that parses the build string so that we can be more sure that it actually works as expected. Change-Id: I23cff7125be4c7c87d5eba4b1db7cb47c2479b66 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
committed by
Tim Jenssen
parent
3df1d5ef39
commit
68e5691047
@@ -1746,7 +1746,7 @@ static QByteArray scanQtBinaryForBuildString(const FileName &library)
|
|||||||
const size_t oneMiB = 1024 * 1024;
|
const size_t oneMiB = 1024 * 1024;
|
||||||
const size_t keepSpace = 4096;
|
const size_t keepSpace = 4096;
|
||||||
const size_t bufferSize = oneMiB + keepSpace;
|
const size_t bufferSize = oneMiB + keepSpace;
|
||||||
QByteArray buffer(bufferSize, '\0');
|
QByteArray buffer(bufferSize, Qt::Uninitialized);
|
||||||
|
|
||||||
char *const readStart = buffer.data() + keepSpace;
|
char *const readStart = buffer.data() + keepSpace;
|
||||||
auto readStartIt = buffer.begin() + keepSpace;
|
auto readStartIt = buffer.begin() + keepSpace;
|
||||||
@@ -1794,20 +1794,16 @@ static QByteArray scanQtBinaryForBuildString(const FileName &library)
|
|||||||
return buildString;
|
return buildString;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Abi refineAbiFromBuildString(const QByteArray &buildString, const Abi &probableAbi)
|
static QStringList extractFieldsFromBuildString(const QByteArray &buildString)
|
||||||
{
|
{
|
||||||
if (buildString.isEmpty()
|
if (buildString.isEmpty()
|
||||||
|| buildString.count() > 4096)
|
|| buildString.count() > 4096)
|
||||||
return Abi();
|
return QStringList();
|
||||||
|
|
||||||
const QRegularExpression buildStringMatcher("^Qt "
|
const QRegularExpression buildStringMatcher("^Qt "
|
||||||
"([\\d\\.a-zA-Z]*) " // Qt version
|
"([\\d\\.a-zA-Z]*) " // Qt version
|
||||||
"\\("
|
"\\("
|
||||||
"([a-z\\d_]*)-" // CPU
|
"([\\w_-]+) " // Abi information
|
||||||
"(big|little)_endian-"
|
|
||||||
"([a-z]+(?:32|64))" // pointer information
|
|
||||||
"(?:-(qreal|))?" // extra information like -qreal
|
|
||||||
"(?:-([^-]+))? " // ABI information
|
|
||||||
"(shared|static) (?:\\(dynamic\\) )?"
|
"(shared|static) (?:\\(dynamic\\) )?"
|
||||||
"(debug|release)"
|
"(debug|release)"
|
||||||
" build; by "
|
" build; by "
|
||||||
@@ -1815,18 +1811,55 @@ static Abi refineAbiFromBuildString(const QByteArray &buildString, const Abi &pr
|
|||||||
"\\)$");
|
"\\)$");
|
||||||
|
|
||||||
QTC_ASSERT(buildStringMatcher.isValid(), qWarning() << buildStringMatcher.errorString());
|
QTC_ASSERT(buildStringMatcher.isValid(), qWarning() << buildStringMatcher.errorString());
|
||||||
const QRegularExpressionMatch match = buildStringMatcher.match(QString::fromUtf8(buildString));
|
|
||||||
QTC_ASSERT(match.hasMatch(), return Abi());
|
|
||||||
|
|
||||||
// const QString qtVersion = match.captured(1);
|
const QRegularExpressionMatch match = buildStringMatcher.match(QString::fromUtf8(buildString));
|
||||||
// const QString cpu = match.captured(2);
|
if (!match.hasMatch())
|
||||||
// const bool littleEndian = (match.captured(3) == "little");
|
return QStringList();
|
||||||
// const QString pointer = match.captured(4);
|
|
||||||
// const QString extra = match.captured(5);
|
QStringList result;
|
||||||
// const QString abiString = match.captured(6);
|
result.append(match.captured(1)); // qtVersion
|
||||||
// const QString linkage = match.captured(7);
|
|
||||||
// const QString buildType = match.captured(8);
|
// Abi info string:
|
||||||
const QString compiler = match.captured(9);
|
QStringList abiInfo = match.captured(2).split('-', QString::SkipEmptyParts);
|
||||||
|
|
||||||
|
result.append(abiInfo.takeFirst()); // cpu
|
||||||
|
|
||||||
|
const QString endian = abiInfo.takeFirst();
|
||||||
|
QTC_ASSERT(endian.endsWith("_endian"), return QStringList());
|
||||||
|
result.append(endian.left(endian.count() - 7)); // without the "_endian"
|
||||||
|
|
||||||
|
result.append(abiInfo.takeFirst()); // pointer
|
||||||
|
|
||||||
|
if (abiInfo.isEmpty()) {
|
||||||
|
// no extra info whatsoever:
|
||||||
|
result.append(""); // qreal is unset
|
||||||
|
result.append(""); // extra info is unset
|
||||||
|
} else {
|
||||||
|
const QString next = abiInfo.at(0);
|
||||||
|
if (next.startsWith("qreal_")) {
|
||||||
|
abiInfo.takeFirst();
|
||||||
|
result.append(next.mid(6)); // qreal: without the "qreal_" part;
|
||||||
|
} else {
|
||||||
|
result.append(""); // qreal is unset!
|
||||||
|
}
|
||||||
|
|
||||||
|
result.append(abiInfo.join('-')); // extra abi strings
|
||||||
|
}
|
||||||
|
|
||||||
|
result.append(match.captured(3)); // linkage
|
||||||
|
result.append(match.captured(4)); // buildType
|
||||||
|
result.append(match.captured(5)); // compiler
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Abi refineAbiFromBuildString(const QByteArray &buildString, const Abi &probableAbi)
|
||||||
|
{
|
||||||
|
QStringList buildStringData = extractFieldsFromBuildString(buildString);
|
||||||
|
if (buildStringData.count() != 9)
|
||||||
|
return probableAbi;
|
||||||
|
|
||||||
|
const QString compiler = buildStringData.at(8);
|
||||||
|
|
||||||
Abi::Architecture arch = probableAbi.architecture();
|
Abi::Architecture arch = probableAbi.architecture();
|
||||||
Abi::OS os = probableAbi.os();
|
Abi::OS os = probableAbi.os();
|
||||||
@@ -1879,3 +1912,57 @@ QList<Abi> BaseQtVersion::qtAbisFromLibrary(const FileNameList &coreLibraries)
|
|||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(WITH_TESTS)
|
||||||
|
|
||||||
|
#include <QTest>
|
||||||
|
|
||||||
|
#include "qtsupportplugin.h"
|
||||||
|
|
||||||
|
void QtSupportPlugin::testQtBuildStringParsing_data()
|
||||||
|
{
|
||||||
|
QTest::addColumn<QByteArray>("buildString");
|
||||||
|
QTest::addColumn<QString>("expected");
|
||||||
|
|
||||||
|
QTest::newRow("invalid build string")
|
||||||
|
<< QByteArray("Qt with invalid buildstring") << QString();
|
||||||
|
QTest::newRow("empty build string")
|
||||||
|
<< QByteArray("") << QString();
|
||||||
|
QTest::newRow("huge build string")
|
||||||
|
<< QByteArray(8192, 'x') << QString();
|
||||||
|
|
||||||
|
QTest::newRow("valid build string")
|
||||||
|
<< QByteArray("Qt 5.7.1 (x86_64-little_endian-lp64 shared (dynamic) release build; by GCC 6.2.1 20160830)")
|
||||||
|
<< "5.7.1;x86_64;little;lp64;;;shared;release;GCC 6.2.1 20160830";
|
||||||
|
|
||||||
|
QTest::newRow("with qreal")
|
||||||
|
<< QByteArray("Qt 5.7.1 (x86_64-little_endian-lp64-qreal___fp16 shared (dynamic) release build; by GCC 6.2.1 20160830)")
|
||||||
|
<< "5.7.1;x86_64;little;lp64;__fp16;;shared;release;GCC 6.2.1 20160830";
|
||||||
|
QTest::newRow("with qreal and abi")
|
||||||
|
<< QByteArray("Qt 5.7.1 (x86_64-little_endian-lp64-qreal___fp16-eabi shared (dynamic) release build; by GCC 6.2.1 20160830)")
|
||||||
|
<< "5.7.1;x86_64;little;lp64;__fp16;eabi;shared;release;GCC 6.2.1 20160830";
|
||||||
|
QTest::newRow("with qreal, eabi and softfloat")
|
||||||
|
<< QByteArray("Qt 5.7.1 (x86_64-little_endian-lp64-qreal___fp16-eabi-softfloat shared (dynamic) release build; by GCC 6.2.1 20160830)")
|
||||||
|
<< "5.7.1;x86_64;little;lp64;__fp16;eabi-softfloat;shared;release;GCC 6.2.1 20160830";
|
||||||
|
QTest::newRow("with eabi")
|
||||||
|
<< QByteArray("Qt 5.7.1 (x86_64-little_endian-lp64-eabi shared (dynamic) release build; by GCC 6.2.1 20160830)")
|
||||||
|
<< "5.7.1;x86_64;little;lp64;;eabi;shared;release;GCC 6.2.1 20160830";
|
||||||
|
QTest::newRow("with eabi and softfloat")
|
||||||
|
<< QByteArray("Qt 5.7.1 (x86_64-little_endian-lp64-eabi-softfloat shared (dynamic) release build; by GCC 6.2.1 20160830)")
|
||||||
|
<< "5.7.1;x86_64;little;lp64;;eabi-softfloat;shared;release;GCC 6.2.1 20160830";
|
||||||
|
}
|
||||||
|
|
||||||
|
void QtSupportPlugin::testQtBuildStringParsing()
|
||||||
|
{
|
||||||
|
QFETCH(QByteArray, buildString);
|
||||||
|
QFETCH(QString, expected);
|
||||||
|
|
||||||
|
QStringList expectedList;
|
||||||
|
if (!expected.isEmpty())
|
||||||
|
expectedList = expected.split(';');
|
||||||
|
|
||||||
|
QStringList actual = extractFieldsFromBuildString(buildString);
|
||||||
|
QCOMPARE(expectedList, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // WITH_TESTS
|
||||||
|
@@ -53,6 +53,10 @@ private slots:
|
|||||||
|
|
||||||
void testQtProjectImporter_oneProject_data();
|
void testQtProjectImporter_oneProject_data();
|
||||||
void testQtProjectImporter_oneProject();
|
void testQtProjectImporter_oneProject();
|
||||||
|
|
||||||
|
void testQtBuildStringParsing_data();
|
||||||
|
void testQtBuildStringParsing();
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
void testQtProjectImporter_oneProjectExistingKit();
|
void testQtProjectImporter_oneProjectExistingKit();
|
||||||
void testQtProjectImporter_oneProjectNewKitExistingQt();
|
void testQtProjectImporter_oneProjectNewKitExistingQt();
|
||||||
|
Reference in New Issue
Block a user