From 8a3e8856e5606ec616d4420ff8c4f77969432390 Mon Sep 17 00:00:00 2001 From: Alexander Volkov Date: Sat, 7 Jan 2017 12:23:47 +0300 Subject: [PATCH] qmake: Add test functions for comparing version numbers qmake really lacks version comparing functions: users either use ugly constructions to compare versions by components, such as greaterThan(QT_CLANG_MAJOR_VERSION, 3)|greaterThan(QT_CLANG_MINOR_VERSION, 4): or even incorrectly compare versions as strings: !lessThan(apple_clang_ver, "5.1")|!lessThan(reg_clang_ver, "3.4"): Add test functions versionAtLeast and versionAtMost which use QVersionNumber to compare version numbers by components. Change-Id: I65e6b3c296d0301d544b7e38bf3d44f8d555c7fc Reviewed-by: Oswald Buddenhagen --- qmake/Makefile.unix | 8 ++++-- qmake/Makefile.win32 | 1 + qmake/doc/src/qmake-manual.qdoc | 14 ++++++++++ qmake/library/qmakebuiltins.cpp | 17 ++++++++++++ qmake/qmake.pri | 2 ++ tests/auto/tools/qmakelib/evaltest.cpp | 38 ++++++++++++++++++++++++++ 6 files changed, 78 insertions(+), 2 deletions(-) diff --git a/qmake/Makefile.unix b/qmake/Makefile.unix index 4df0ff281f..768cc0248e 100644 --- a/qmake/Makefile.unix +++ b/qmake/Makefile.unix @@ -30,8 +30,8 @@ QOBJS = \ qarraydata.o qbitarray.o qbytearray.o qbytearraymatcher.o \ qcryptographichash.o qdatetime.o qhash.o qlinkedlist.o qlist.o \ qlocale.o qlocale_tools.o qmap.o qregexp.o qringbuffer.o \ - qstringbuilder.o qstring_compat.o qstring.o qstringlist.o qvsnprintf.o \ - qxmlstream.o qxmlutils.o \ + qstringbuilder.o qstring_compat.o qstring.o qstringlist.o qversionnumber.o \ + qvsnprintf.o qxmlstream.o qxmlutils.o \ $(QTOBJS) $(QTOBJS2) # QTOBJS and QTOBJS2 are populated by Makefile.unix.* as for QTSRC (see below). # Note: qlibraryinfo.o omitted deliberately - see below. @@ -120,6 +120,7 @@ DEPEND_SRC = \ $(SOURCE_PATH)/src/corelib/tools/qstring_compat.cpp \ $(SOURCE_PATH)/src/corelib/tools/qstring.cpp \ $(SOURCE_PATH)/src/corelib/tools/qstringlist.cpp \ + $(SOURCE_PATH)/src/corelib/tools/qversionnumber.cpp \ $(SOURCE_PATH)/src/corelib/tools/qvsnprintf.cpp \ $(SOURCE_PATH)/src/corelib/xml/qxmlstream.cpp \ $(SOURCE_PATH)/src/corelib/xml/qxmlutils.cpp \ @@ -356,6 +357,9 @@ qlocale_unix.o: $(SOURCE_PATH)/src/corelib/tools/qlocale_unix.cpp qlocale_win.o: $(SOURCE_PATH)/src/corelib/tools/qlocale_win.cpp $(CXX) -c -o $@ $(CXXFLAGS) $< +qversionnumber.o: $(SOURCE_PATH)/src/corelib/tools/qversionnumber.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< + qdatastream.o: $(SOURCE_PATH)/src/corelib/io/qdatastream.cpp $(CXX) -c -o $@ $(CXXFLAGS) $< diff --git a/qmake/Makefile.win32 b/qmake/Makefile.win32 index 559870ff0e..4936b3587e 100644 --- a/qmake/Makefile.win32 +++ b/qmake/Makefile.win32 @@ -93,6 +93,7 @@ QTOBJS= \ qlocale.obj \ qlocale_tools.obj \ qlocale_win.obj \ + qversionnumber.obj \ qmalloc.obj \ qmap.obj \ qoperatingsystemversion.obj \ diff --git a/qmake/doc/src/qmake-manual.qdoc b/qmake/doc/src/qmake-manual.qdoc index d8ab7d096d..ceb93fde2d 100644 --- a/qmake/doc/src/qmake-manual.qdoc +++ b/qmake/doc/src/qmake-manual.qdoc @@ -3514,6 +3514,20 @@ \snippet code/doc_src_qmake-manual.pro 169 + \section2 versionAtLeast(variablename, versionNumber) + + Tests that the version number from \c variablename is greater than or equal + to \c versionNumber. The version number is considered to be a sequence of + non-negative decimal numbers delimited by '.'; any non-numerical tail of + the string will be ignored. Comparison is performed segment-wise from left + to right; if one version is a prefix of the other, it is considered smaller. + + \section2 versionAtMost(variablename, versionNumber) + + Tests that the version number from \c variablename is less than or equal to + \c versionNumber. Works as + \l{versionAtLeast(variablename, versionNumber)}{versionAtLeast()}. + \section2 warning(string) Always succeeds, and displays \c string as a warning message to the user. diff --git a/qmake/library/qmakebuiltins.cpp b/qmake/library/qmakebuiltins.cpp index 461f46e705..31b3ae6825 100644 --- a/qmake/library/qmakebuiltins.cpp +++ b/qmake/library/qmakebuiltins.cpp @@ -51,6 +51,7 @@ #ifdef PROEVALUATOR_THREAD_SAFE # include #endif +#include #include @@ -99,6 +100,7 @@ enum ExpandFunc { enum TestFunc { T_INVALID = 0, T_REQUIRES, T_GREATERTHAN, T_LESSTHAN, T_EQUALS, + T_VERSION_AT_LEAST, T_VERSION_AT_MOST, T_EXISTS, T_EXPORT, T_CLEAR, T_UNSET, T_EVAL, T_CONFIG, T_SYSTEM, T_DEFINED, T_DISCARD_FROM, T_CONTAINS, T_INFILE, T_COUNT, T_ISEMPTY, T_PARSE_JSON, T_INCLUDE, T_LOAD, T_DEBUG, T_LOG, T_MESSAGE, T_WARNING, T_ERROR, T_IF, @@ -172,6 +174,8 @@ void QMakeEvaluator::initFunctionStatics() { "lessThan", T_LESSTHAN }, { "equals", T_EQUALS }, { "isEqual", T_EQUALS }, + { "versionAtLeast", T_VERSION_AT_LEAST }, + { "versionAtMost", T_VERSION_AT_MOST }, { "exists", T_EXISTS }, { "export", T_EXPORT }, { "clear", T_CLEAR }, @@ -1557,6 +1561,19 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( } return returnBool(values(map(args.at(0))).join(statics.field_sep) == args.at(1).toQString(m_tmp1)); + case T_VERSION_AT_LEAST: + case T_VERSION_AT_MOST: { + if (args.count() != 2) { + evalError(fL1S("%1(variable, versionNumber) requires two arguments.") + .arg(function.toQString(m_tmp1))); + return ReturnFalse; + } + const QVersionNumber lvn = QVersionNumber::fromString(values(args.at(0).toKey()).join('.')); + const QVersionNumber rvn = QVersionNumber::fromString(args.at(1).toQString()); + if (func_t == T_VERSION_AT_LEAST) + return returnBool(lvn >= rvn); + return returnBool(lvn <= rvn); + } case T_CLEAR: { if (args.count() != 1) { evalError(fL1S("%1(variable) requires one argument.") diff --git a/qmake/qmake.pri b/qmake/qmake.pri index b9ed9ce96a..77c190bb9a 100644 --- a/qmake/qmake.pri +++ b/qmake/qmake.pri @@ -68,6 +68,7 @@ bootstrap { #Qt code qlibraryinfo.cpp \ qsystemerror.cpp \ qvariant.cpp \ + qversionnumber.cpp \ qvsnprintf.cpp \ qxmlstream.cpp \ qxmlutils.cpp \ @@ -119,6 +120,7 @@ bootstrap { #Qt code qtextstream.h \ quuid.h \ qvector.h \ + qversionnumber.h \ qxmlstream.h \ qxmlutils.h \ qjson.h \ diff --git a/tests/auto/tools/qmakelib/evaltest.cpp b/tests/auto/tools/qmakelib/evaltest.cpp index 4e215b8570..10a5d7c0c3 100644 --- a/tests/auto/tools/qmakelib/evaltest.cpp +++ b/tests/auto/tools/qmakelib/evaltest.cpp @@ -2191,6 +2191,44 @@ void tst_qmakelib::addTestFunctions(const QString &qindir) << "" << true; + QTest::newRow("versionAtLeast(): true") + << "VAR = 1.2.3\nversionAtLeast(VAR, 1.2.3): OK = 1" + << "OK = 1" + << "" + << true; + + QTest::newRow("versionAtLeast(): false") + << "VAR = 1.2.2\nversionAtLeast(VAR, 1.2.3): OK = 1" + << "OK = UNDEF" + << "" + << true; + + QTest::newRow("versionAtLeast(): bad number of arguments") + << "versionAtLeast(1): OK = 1\nversionAtLeast(1, 2, 3): OK = 1" + << "OK = UNDEF" + << "##:1: versionAtLeast(variable, versionNumber) requires two arguments.\n" + "##:2: versionAtLeast(variable, versionNumber) requires two arguments." + << true; + + QTest::newRow("versionAtMost(): true") + << "VAR = 1.2.3\nversionAtMost(VAR, 1.2.3): OK = 1" + << "OK = 1" + << "" + << true; + + QTest::newRow("versionAtMost(): false") + << "VAR = 1.2.3\nversionAtMost(VAR, 1.2.2): OK = 1" + << "OK = UNDEF" + << "" + << true; + + QTest::newRow("versionAtMost(): bad number of arguments") + << "versionAtMost(1): OK = 1\nversionAtMost(1, 2, 3): OK = 1" + << "OK = UNDEF" + << "##:1: versionAtMost(variable, versionNumber) requires two arguments.\n" + "##:2: versionAtMost(variable, versionNumber) requires two arguments." + << true; + QTest::newRow("clear(): top-level") << "VAR = there\nclear(VAR): OK = 1" << "OK = 1\nVAR ="