From 2e496e93225503c8af068e53294c5eb13aa3bfd7 Mon Sep 17 00:00:00 2001 From: Mauro Persano Date: Thu, 29 Mar 2018 10:37:25 -0300 Subject: [PATCH 01/17] Windows: handle multiple transient children when closing windows On Windows, we must update the transient children of a window that's about to be destroyed or its transient children will be destroyed as well. This is already being done in the case of a single transient child, but there are still problems when there are more than one. Change-Id: Ib0de6767bf43dca508ecdb87cbdfedb59e9146e8 Reviewed-by: Friedemann Kleint --- .../platforms/windows/qwindowswindow.cpp | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 9fff4b5e429..9872b6b4e00 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -1161,23 +1161,19 @@ void QWindowsWindow::fireExpose(const QRegion ®ion, bool force) QWindowSystemInterface::handleExposeEvent(window(), region); } -static inline QWindow *findTransientChild(const QWindow *parent) -{ - foreach (QWindow *w, QGuiApplication::topLevelWindows()) - if (w->transientParent() == parent) - return w; - return 0; -} - void QWindowsWindow::destroyWindow() { qCDebug(lcQpaWindows) << __FUNCTION__ << this << window() << m_data.hwnd; if (m_data.hwnd) { // Stop event dispatching before Window is destroyed. setFlag(WithinDestroy); // Clear any transient child relationships as Windows will otherwise destroy them (QTBUG-35499, QTBUG-36666) - if (QWindow *transientChild = findTransientChild(window())) - if (QWindowsWindow *tw = QWindowsWindow::windowsWindowOf(transientChild)) - tw->updateTransientParent(); + const auto tlw = QGuiApplication::topLevelWindows(); + for (QWindow *w : tlw) { + if (w->transientParent() == window()) { + if (QWindowsWindow *tw = QWindowsWindow::windowsWindowOf(w)) + tw->updateTransientParent(); + } + } QWindowsContext *context = QWindowsContext::instance(); if (context->windowUnderMouse() == window()) context->clearWindowUnderMouse(); From 72f8f994b26fe51bf4828e17096b7ec0abe1f0d3 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 22 Mar 2018 23:06:56 +0800 Subject: [PATCH 02/17] QSemaphore: attempt to fix again the 64-bit Linux semaphore MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This time, the issue was that we could race a wait and a wake. A multi- token waiter would not notice that the number of tokens changed because it only performed a fetch-and-OR, then waited on the high part which did not change. That means the futex_wait() would succeed, when we wanted it to have failed. So we have to bring back a portion of what commit 081c001deb75fa38385d3ff8cbbdb4f788529133 removed: we need to keep both the token count and the waiter count in the high word. Task-number: QTBUG-67214 Change-Id: I04a43ee94975482f9e32fffd151e467a9e0030b3 Reviewed-by: Mårten Nordheim Reviewed-by: Thiago Macieira --- src/corelib/thread/qsemaphore.cpp | 33 +++++++++++++++++++------------ 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/src/corelib/thread/qsemaphore.cpp b/src/corelib/thread/qsemaphore.cpp index c2e4d7d9d14..c440d6db39f 100644 --- a/src/corelib/thread/qsemaphore.cpp +++ b/src/corelib/thread/qsemaphore.cpp @@ -120,12 +120,12 @@ using namespace QtFutex; If the system has the ability to wake up a precise number of threads, has Linux's FUTEX_WAKE_OP functionality, and is 64-bit, instead of using a - single bit indicating a contended semaphore, we'll store the total number - of waiters in the high word. Additionally, all multi-token waiters will be - waiting on that high word. So when releasing n tokens on those systems, we - tell the kernel to wake up n single-token threads and all of the - multi-token ones. Which threads get woken up is unspecified, but it's - likely single-token threads will get woken up first. + single bit indicating a contended semaphore, we'll store the number of + tokens *plus* total number of waiters in the high word. Additionally, all + multi-token waiters will be waiting on that high word. So when releasing n + tokens on those systems, we tell the kernel to wake up n single-token + threads and all of the multi-token ones. Which threads get woken up is + unspecified, but it's likely single-token threads will get woken up first. */ #if defined(FUTEX_OP) && QT_POINTER_SIZE > 4 @@ -231,10 +231,14 @@ template bool futexSemaphoreTryAcquire(QBasicAtomicInteger= n) { // try to acquire - quintptr newValue = curValue - n; + quintptr newValue = curValue - nn; if (u.testAndSetOrdered(curValue, newValue, curValue)) return true; // succeeded! } @@ -242,7 +246,6 @@ template bool futexSemaphoreTryAcquire(QBasicAtomicInteger bool futexSemaphoreTryAcquire(QBasicAtomicInteger> 32) == 0x7fffffff) + return false; // overflow! curValue += oneWaiter; - // Also adjust valueToSubtract to subtract oneWaiter when we succeed in - // acquiring. - valueToSubtract += oneWaiter; + // Also adjust nn to subtract oneWaiter when we succeed in acquiring. + nn += oneWaiter; } - if (futexSemaphoreTryAcquire_loop(u, curValue, valueToSubtract, timeout)) + if (futexSemaphoreTryAcquire_loop(u, curValue, nn, timeout)) return true; if (futexHasWaiterCount) { @@ -345,7 +349,10 @@ void QSemaphore::release(int n) Q_ASSERT_X(n >= 0, "QSemaphore::release", "parameter 'n' must be non-negative"); if (futexAvailable()) { - quintptr prevValue = u.fetchAndAddRelease(n); + quintptr nn = unsigned(n); + if (futexHasWaiterCount) + nn |= quint64(nn) << 32; // token count replicated in high word + quintptr prevValue = u.fetchAndAddRelease(nn); if (futexNeedsWake(prevValue)) { #ifdef FUTEX_OP if (!futexHasWaiterCount) { From 38f6b6242edeef56ce68f1357ea9f85a6563f09a Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 1 Mar 2018 16:43:46 +0100 Subject: [PATCH 03/17] qmake: prevent .prf files from postponing work to build passes just a sync-up from lupdate; no effect on qmake itself. alternative source: qt-creator/7e86b98836342035684cc1c1aa49292224faed07. Change-Id: I5e10b44637d527799f55c578a99076eb4750f131 (cherry picked from qttools/8e7e60dbdea04c943bc6d50290db12d3fefd39f2) Reviewed-by: Joerg Bornemann --- qmake/library/qmakeevaluator.cpp | 39 ++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/qmake/library/qmakeevaluator.cpp b/qmake/library/qmakeevaluator.cpp index 6e6c72de59a..edd1d5f38f4 100644 --- a/qmake/library/qmakeevaluator.cpp +++ b/qmake/library/qmakeevaluator.cpp @@ -1980,23 +1980,34 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateFeatureFile( // needs to be determined. Failed lookups are represented via non-null empty strings. QString *fnp = &m_featureRoots->cache[qMakePair(fn, currFn)]; if (fnp->isNull()) { - int start_root = 0; - const QStringList &paths = m_featureRoots->paths; - if (!currFn.isEmpty()) { - QStringRef currPath = IoUtils::pathName(currFn); - for (int root = 0; root < paths.size(); ++root) - if (currPath == paths.at(root)) { - start_root = root + 1; - break; - } - } - for (int root = start_root; root < paths.size(); ++root) { - QString fname = paths.at(root) + fn; - if (IoUtils::exists(fname)) { - fn = fname; +#ifdef QMAKE_OVERRIDE_PRFS + { + QString ovrfn(QLatin1String(":/qmake/override_features/") + fn); + if (QFileInfo::exists(ovrfn)) { + fn = ovrfn; goto cool; } } +#endif + { + int start_root = 0; + const QStringList &paths = m_featureRoots->paths; + if (!currFn.isEmpty()) { + QStringRef currPath = IoUtils::pathName(currFn); + for (int root = 0; root < paths.size(); ++root) + if (currPath == paths.at(root)) { + start_root = root + 1; + break; + } + } + for (int root = start_root; root < paths.size(); ++root) { + QString fname = paths.at(root) + fn; + if (IoUtils::exists(fname)) { + fn = fname; + goto cool; + } + } + } #ifdef QMAKE_BUILTIN_PRFS fn.prepend(QLatin1String(":/qmake/features/")); if (QFileInfo::exists(fn)) From fe5f2a235cd51020c04570ec3f37070f6be7a1a3 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 20 Oct 2016 15:02:34 +0200 Subject: [PATCH 04/17] qmake: make message about not found mkspec less confusing Change-Id: I9cfa2c9476d3d7fdb68b0a23e175eea4b3b11ad9 Reviewed-by: Tobias Hunger (cherry picked from qtcreator/c0ddf0a34407f9d3ad9f575176550ba33d536d12) Reviewed-by: Joerg Bornemann --- qmake/library/qmakeevaluator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qmake/library/qmakeevaluator.cpp b/qmake/library/qmakeevaluator.cpp index edd1d5f38f4..3e613038a3c 100644 --- a/qmake/library/qmakeevaluator.cpp +++ b/qmake/library/qmakeevaluator.cpp @@ -1259,7 +1259,7 @@ bool QMakeEvaluator::loadSpec() goto cool; } } - evalError(fL1S("Could not find qmake configuration file %1.").arg(qmakespec)); + evalError(fL1S("Could not find qmake spec '%1'.").arg(qmakespec)); return false; } cool: From e2de837198884b64345f746ef257e6d83bffa571 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 28 Oct 2016 20:10:40 +0200 Subject: [PATCH 05/17] qmake: let QMakeVfs::readFile() report ENOFILE explicitly when the QFile object is already constructed, querying whether the file exists is actually cheap, so do it right away instead of later on demand. that makes the calling code a bit cleaner. fwiw, that we need to explicitly query the file's existence at all is a result of QFile's completely useless error "codes" (which merely say which function failed, as if the caller would not know). Change-Id: Ifec39d05b1713d8128046f679287e510f10e45dc Reviewed-by: Tobias Hunger (cherry picked from qtcreator/5ba32e3484ead2e35cc7732dcd59a97e7459dbfd) Reviewed-by: Joerg Bornemann --- qmake/library/qmakeparser.cpp | 5 +++-- qmake/library/qmakevfs.cpp | 21 +++++++++++---------- qmake/library/qmakevfs.h | 8 +++++++- tests/auto/tools/qmakelib/evaltest.cpp | 4 ---- 4 files changed, 21 insertions(+), 17 deletions(-) diff --git a/qmake/library/qmakeparser.cpp b/qmake/library/qmakeparser.cpp index b5d89c1ba68..62e8875c5ec 100644 --- a/qmake/library/qmakeparser.cpp +++ b/qmake/library/qmakeparser.cpp @@ -254,8 +254,9 @@ bool QMakeParser::read(ProFile *pro, ParseFlags flags) { QString content; QString errStr; - if (!m_vfs->readFile(pro->fileName(), &content, &errStr)) { - if (m_handler && ((flags & ParseReportMissing) || m_vfs->exists(pro->fileName()))) + QMakeVfs::ReadResult result = m_vfs->readFile(pro->fileName(), &content, &errStr); + if (result != QMakeVfs::ReadOk) { + if (m_handler && ((flags & ParseReportMissing) || result != QMakeVfs::ReadNotFound)) m_handler->message(QMakeParserHandler::ParserIoError, fL1S("Cannot read %1: %2").arg(pro->fileName(), errStr)); return false; diff --git a/qmake/library/qmakevfs.cpp b/qmake/library/qmakevfs.cpp index 5aa9ec9299f..7631723b1b4 100644 --- a/qmake/library/qmakevfs.cpp +++ b/qmake/library/qmakevfs.cpp @@ -100,7 +100,7 @@ bool QMakeVfs::writeFile(const QString &fn, QIODevice::OpenMode mode, bool exe, #endif } -bool QMakeVfs::readFile(const QString &fn, QString *contents, QString *errStr) +QMakeVfs::ReadResult QMakeVfs::readFile(const QString &fn, QString *contents, QString *errStr) { #ifndef PROEVALUATOR_FULL # ifdef PROEVALUATOR_THREAD_SAFE @@ -110,25 +110,26 @@ bool QMakeVfs::readFile(const QString &fn, QString *contents, QString *errStr) if (it != m_files.constEnd()) { if (it->constData() == m_magicMissing.constData()) { *errStr = fL1S("No such file or directory"); - return false; + return ReadNotFound; } if (it->constData() != m_magicExisting.constData()) { *contents = *it; - return true; + return ReadOk; } } #endif QFile file(fn); if (!file.open(QIODevice::ReadOnly)) { + if (!file.exists()) { #ifndef PROEVALUATOR_FULL - if (!IoUtils::exists(fn)) { m_files[fn] = m_magicMissing; - *errStr = fL1S("No such file or directory"); - } else #endif - *errStr = file.errorString(); - return false; + *errStr = fL1S("No such file or directory"); + return ReadNotFound; + } + *errStr = file.errorString(); + return ReadOtherError; } #ifndef PROEVALUATOR_FULL m_files[fn] = m_magicExisting; @@ -138,10 +139,10 @@ bool QMakeVfs::readFile(const QString &fn, QString *contents, QString *errStr) if (bcont.startsWith("\xef\xbb\xbf")) { // UTF-8 BOM will cause subtle errors *errStr = fL1S("Unexpected UTF-8 BOM"); - return false; + return ReadOtherError; } *contents = QString::fromLocal8Bit(bcont); - return true; + return ReadOk; } bool QMakeVfs::exists(const QString &fn) diff --git a/qmake/library/qmakevfs.h b/qmake/library/qmakevfs.h index 8677ba08c12..5e6a2f88e25 100644 --- a/qmake/library/qmakevfs.h +++ b/qmake/library/qmakevfs.h @@ -45,10 +45,16 @@ QT_BEGIN_NAMESPACE class QMAKE_EXPORT QMakeVfs { public: + enum ReadResult { + ReadOk, + ReadNotFound, + ReadOtherError + }; + QMakeVfs(); bool writeFile(const QString &fn, QIODevice::OpenMode mode, bool exe, const QString &contents, QString *errStr); - bool readFile(const QString &fn, QString *contents, QString *errStr); + ReadResult readFile(const QString &fn, QString *contents, QString *errStr); bool exists(const QString &fn); #ifndef PROEVALUATOR_FULL diff --git a/tests/auto/tools/qmakelib/evaltest.cpp b/tests/auto/tools/qmakelib/evaltest.cpp index abb7a1a9645..3fdd30b6857 100644 --- a/tests/auto/tools/qmakelib/evaltest.cpp +++ b/tests/auto/tools/qmakelib/evaltest.cpp @@ -2375,11 +2375,7 @@ void tst_qmakelib::addTestFunctions(const QString &qindir) QTest::newRow("include(): fail") << "include(include/nope.pri): OK = 1" << "OK = UNDEF" -#ifdef Q_OS_WIN - << "Cannot read " + m_indir + "/include/nope.pri: The system cannot find the file specified." -#else << "Cannot read " + m_indir + "/include/nope.pri: No such file or directory" -#endif << true; QTest::newRow("include(): silent fail") From 811118f68df4171268f65fa6fc075d6c7633f1e4 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 24 Oct 2016 14:58:11 +0200 Subject: [PATCH 06/17] qmake: make IoUtils::fileType() return more expressive result it now does not see anything except regular files and directories any more. that's not expected to be a problem, given the function's scope. Change-Id: I53063ad8cacb3afe5cc1baf6d6d5feba3465e74f Reviewed-by: Tobias Hunger (cherry picked from qtcreator/cf82f210804151452fce3cddb3cb2793dab976eb) Reviewed-by: Joerg Bornemann --- qmake/library/ioutils.cpp | 2 +- qmake/library/qmakevfs.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/qmake/library/ioutils.cpp b/qmake/library/ioutils.cpp index cb4aa5e74d9..4aa3282e3b4 100644 --- a/qmake/library/ioutils.cpp +++ b/qmake/library/ioutils.cpp @@ -60,7 +60,7 @@ IoUtils::FileType IoUtils::fileType(const QString &fileName) struct ::stat st; if (::stat(fileName.toLocal8Bit().constData(), &st)) return FileNotFound; - return S_ISDIR(st.st_mode) ? FileIsDir : FileIsRegular; + return S_ISDIR(st.st_mode) ? FileIsDir : S_ISREG(st.st_mode) ? FileIsRegular : FileNotFound; #endif } diff --git a/qmake/library/qmakevfs.cpp b/qmake/library/qmakevfs.cpp index 7631723b1b4..c40f49c4ad9 100644 --- a/qmake/library/qmakevfs.cpp +++ b/qmake/library/qmakevfs.cpp @@ -155,7 +155,7 @@ bool QMakeVfs::exists(const QString &fn) if (it != m_files.constEnd()) return it->constData() != m_magicMissing.constData(); #endif - bool ex = IoUtils::exists(fn); + bool ex = IoUtils::fileType(fn) == IoUtils::FileIsRegular; #ifndef PROEVALUATOR_FULL m_files[fn] = ex ? m_magicExisting : m_magicMissing; #endif From e5d909d6d68055c057bbaeadb8f7a4078e6d54e8 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 24 Oct 2016 19:30:24 +0200 Subject: [PATCH 07/17] qmake: make VFS aware of exact vs. cumulative evaluation sync-up with qt-creator; no effect on qmake. comment on cherry-pick: this is actually a lot more than a cherry-pick, because the dual VFS needs to deal with the file ids which were concurrently introduced on the qmake side. Change-Id: I2c1eb16c97526fa275a1c6a2eae9266d385859ac (cherry picked from qtcreator/424639ecac9d2e404d2bfaff7f46b45ed98664b8) (cherry picked from qtcreator/a8010b0fff47d903d4a1f80e3adb1a2ef41beb33) Reviewed-by: Joerg Bornemann --- qmake/library/qmakebuiltins.cpp | 25 +++--- qmake/library/qmakeevaluator.cpp | 16 ++-- qmake/library/qmakeevaluator.h | 3 +- qmake/library/qmakeparser.cpp | 79 ++++++++--------- qmake/library/qmakeparser.h | 29 +++---- qmake/library/qmakevfs.cpp | 105 +++++++++++++++++++---- qmake/library/qmakevfs.h | 68 ++++++++++++--- qmake/project.cpp | 2 +- tests/auto/tools/qmakelib/evaltest.cpp | 4 +- tests/auto/tools/qmakelib/parsertest.cpp | 2 +- 10 files changed, 231 insertions(+), 102 deletions(-) diff --git a/qmake/library/qmakebuiltins.cpp b/qmake/library/qmakebuiltins.cpp index 0a83b9b930c..c1d446263eb 100644 --- a/qmake/library/qmakebuiltins.cpp +++ b/qmake/library/qmakebuiltins.cpp @@ -443,15 +443,18 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::parseJsonInto(const QByteArray &json QMakeEvaluator::VisitReturn QMakeEvaluator::writeFile(const QString &ctx, const QString &fn, QIODevice::OpenMode mode, - bool exe, const QString &contents) + QMakeVfs::VfsFlags flags, const QString &contents) { + int oldId = m_vfs->idForFileName(fn, flags | QMakeVfs::VfsAccessedOnly); + int id = m_vfs->idForFileName(fn, flags | QMakeVfs::VfsCreate); QString errStr; - if (!m_vfs->writeFile(fn, mode, exe, contents, &errStr)) { + if (!m_vfs->writeFile(id, mode, flags, contents, &errStr)) { evalError(fL1S("Cannot write %1file %2: %3") .arg(ctx, QDir::toNativeSeparators(fn), errStr)); return ReturnFalse; } - m_parser->discardFileFromCache(fn); + if (oldId) + m_parser->discardFileFromCache(oldId); return ReturnTrue; } @@ -1343,7 +1346,8 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( return ReturnFalse; } QString fn = resolvePath(args.at(0).toQString(m_tmp1)); - int pro = m_parser->idForFileName(fn); + QMakeVfs::VfsFlags flags = (m_cumulative ? QMakeVfs::VfsCumulative : QMakeVfs::VfsExact); + int pro = m_vfs->idForFileName(fn, flags | QMakeVfs::VfsAccessedOnly); if (!pro) return ReturnFalse; ProValueMap &vmap = m_valuemapStack.first(); @@ -1416,7 +1420,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( VisitReturn ret = ReturnFalse; QString contents = args.join(statics.field_sep); ProFile *pro = m_parser->parsedProBlock(QStringRef(&contents), - m_current.pro->fileName(), m_current.line); + 0, m_current.pro->fileName(), m_current.line); if (m_cumulative || pro->isOk()) { m_locationStack.push(m_current); visitProBlock(pro, pro->tokPtr()); @@ -1784,7 +1788,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( return ReturnFalse; } QIODevice::OpenMode mode = QIODevice::Truncate; - bool exe = false; + QMakeVfs::VfsFlags flags = (m_cumulative ? QMakeVfs::VfsCumulative : QMakeVfs::VfsExact); QString contents; if (args.count() >= 2) { const ProStringList &vals = values(args.at(1).toKey()); @@ -1796,7 +1800,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( if (opt == QLatin1String("append")) { mode = QIODevice::Append; } else if (opt == QLatin1String("exe")) { - exe = true; + flags |= QMakeVfs::VfsExecutable; } else { evalError(fL1S("write_file(): invalid flag %1.").arg(opt.toQString(m_tmp3))); return ReturnFalse; @@ -1806,7 +1810,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( } QString path = resolvePath(args.at(0).toQString(m_tmp1)); path.detach(); // make sure to not leak m_tmp1 into the map of written files. - return writeFile(QString(), path, mode, exe, contents); + return writeFile(QString(), path, mode, flags, contents); } case T_TOUCH: { if (args.count() != 2) { @@ -1960,6 +1964,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( varstr += QLatin1Char('\n'); } QString fn; + QMakeVfs::VfsFlags flags = (m_cumulative ? QMakeVfs::VfsCumulative : QMakeVfs::VfsExact); if (target == TargetSuper) { if (m_superfile.isEmpty()) { m_superfile = QDir::cleanPath(m_outputDir + QLatin1String("/.qmake.super")); @@ -1983,12 +1988,12 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( fn = m_stashfile; if (fn.isEmpty()) fn = QDir::cleanPath(m_outputDir + QLatin1String("/.qmake.stash")); - if (!m_vfs->exists(fn)) { + if (!m_vfs->exists(fn, flags)) { printf("Info: creating stash file %s\n", qPrintable(QDir::toNativeSeparators(fn))); valuesRef(ProKey("_QMAKE_STASH_")) << ProString(fn); } } - return writeFile(fL1S("cache "), fn, QIODevice::Append, false, varstr); + return writeFile(fL1S("cache "), fn, QIODevice::Append, flags, varstr); } case T_RELOAD_PROPERTIES: #ifdef QT_BUILD_QMAKE diff --git a/qmake/library/qmakeevaluator.cpp b/qmake/library/qmakeevaluator.cpp index 3e613038a3c..7112b57c112 100644 --- a/qmake/library/qmakeevaluator.cpp +++ b/qmake/library/qmakeevaluator.cpp @@ -1104,6 +1104,7 @@ void QMakeEvaluator::loadDefaults() bool QMakeEvaluator::prepareProject(const QString &inDir) { + QMakeVfs::VfsFlags flags = (m_cumulative ? QMakeVfs::VfsCumulative : QMakeVfs::VfsExact); QString superdir; if (m_option->do_cache) { QString conffile; @@ -1114,7 +1115,7 @@ bool QMakeEvaluator::prepareProject(const QString &inDir) superdir = m_outputDir; forever { QString superfile = superdir + QLatin1String("/.qmake.super"); - if (m_vfs->exists(superfile)) { + if (m_vfs->exists(superfile, flags)) { m_superfile = QDir::cleanPath(superfile); break; } @@ -1129,10 +1130,10 @@ bool QMakeEvaluator::prepareProject(const QString &inDir) QString dir = m_outputDir; forever { conffile = sdir + QLatin1String("/.qmake.conf"); - if (!m_vfs->exists(conffile)) + if (!m_vfs->exists(conffile, flags)) conffile.clear(); cachefile = dir + QLatin1String("/.qmake.cache"); - if (!m_vfs->exists(cachefile)) + if (!m_vfs->exists(cachefile, flags)) cachefile.clear(); if (!conffile.isEmpty() || !cachefile.isEmpty()) { if (dir != sdir) @@ -1160,7 +1161,7 @@ bool QMakeEvaluator::prepareProject(const QString &inDir) QString dir = m_outputDir; forever { QString stashfile = dir + QLatin1String("/.qmake.stash"); - if (dir == (!superdir.isEmpty() ? superdir : m_buildRoot) || m_vfs->exists(stashfile)) { + if (dir == (!superdir.isEmpty() ? superdir : m_buildRoot) || m_vfs->exists(stashfile, flags)) { m_stashfile = QDir::cleanPath(stashfile); break; } @@ -1285,7 +1286,8 @@ bool QMakeEvaluator::loadSpec() m_cachefile, QMakeHandler::EvalConfigFile, LoadProOnly) != ReturnTrue) return false; } - if (!m_stashfile.isEmpty() && m_vfs->exists(m_stashfile)) { + QMakeVfs::VfsFlags flags = (m_cumulative ? QMakeVfs::VfsCumulative : QMakeVfs::VfsExact); + if (!m_stashfile.isEmpty() && m_vfs->exists(m_stashfile, flags)) { valuesRef(ProKey("_QMAKE_STASH_")) << ProString(m_stashfile); if (evaluateFile( m_stashfile, QMakeHandler::EvalConfigFile, LoadProOnly) != ReturnTrue) @@ -1308,7 +1310,7 @@ void QMakeEvaluator::setupProject() void QMakeEvaluator::evaluateCommand(const QString &cmds, const QString &where) { if (!cmds.isEmpty()) { - ProFile *pro = m_parser->parsedProBlock(QStringRef(&cmds), where, -1); + ProFile *pro = m_parser->parsedProBlock(QStringRef(&cmds), 0, where, -1); if (pro->isOk()) { m_locationStack.push(m_current); visitProBlock(pro, pro->tokPtr()); @@ -1812,7 +1814,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateConditional( const QStringRef &cond, const QString &where, int line) { VisitReturn ret = ReturnFalse; - ProFile *pro = m_parser->parsedProBlock(cond, where, line, QMakeParser::TestGrammar); + ProFile *pro = m_parser->parsedProBlock(cond, 0, where, line, QMakeParser::TestGrammar); if (pro->isOk()) { m_locationStack.push(m_current); ret = visitProBlock(pro, pro->tokPtr()); diff --git a/qmake/library/qmakeevaluator.h b/qmake/library/qmakeevaluator.h index 7318664d464..1f0255e55aa 100644 --- a/qmake/library/qmakeevaluator.h +++ b/qmake/library/qmakeevaluator.h @@ -34,6 +34,7 @@ #endif #include "qmakeparser.h" +#include "qmakevfs.h" #include "ioutils.h" #include @@ -237,7 +238,7 @@ public: VisitReturn parseJsonInto(const QByteArray &json, const QString &into, ProValueMap *value); VisitReturn writeFile(const QString &ctx, const QString &fn, QIODevice::OpenMode mode, - bool exe, const QString &contents); + QMakeVfs::VfsFlags flags, const QString &contents); #if QT_CONFIG(process) void runProcess(QProcess *proc, const QString &command) const; #endif diff --git a/qmake/library/qmakeparser.cpp b/qmake/library/qmakeparser.cpp index 62e8875c5ec..37608c7a154 100644 --- a/qmake/library/qmakeparser.cpp +++ b/qmake/library/qmakeparser.cpp @@ -52,12 +52,22 @@ ProFileCache::~ProFileCache() ent.pro->deref(); } -void ProFileCache::discardFile(const QString &fileName) +void ProFileCache::discardFile(const QString &fileName, QMakeVfs *vfs) +{ + int eid = vfs->idForFileName(fileName, QMakeVfs::VfsExact | QMakeVfs::VfsAccessedOnly); + if (eid) + discardFile(eid); + int cid = vfs->idForFileName(fileName, QMakeVfs::VfsCumulative | QMakeVfs::VfsAccessedOnly); + if (cid && cid != eid) + discardFile(cid); +} + +void ProFileCache::discardFile(int id) { #ifdef PROPARSER_THREAD_SAFE QMutexLocker lck(&mutex); #endif - QHash::Iterator it = parsed_files.find(fileName); + auto it = parsed_files.find(id); if (it != parsed_files.end()) { #ifdef PROPARSER_THREAD_SAFE if (it->locker) { @@ -77,16 +87,16 @@ void ProFileCache::discardFile(const QString &fileName) } } -void ProFileCache::discardFiles(const QString &prefix) +void ProFileCache::discardFiles(const QString &prefix, QMakeVfs *vfs) { #ifdef PROPARSER_THREAD_SAFE QMutexLocker lck(&mutex); #endif - QHash::Iterator - it = parsed_files.begin(), - end = parsed_files.end(); - while (it != end) - if (it.key().startsWith(prefix)) { + auto it = parsed_files.begin(), end = parsed_files.end(); + while (it != end) { + // Note: this is empty for virtual files from other VFSes. + QString fn = vfs->fileNameForId(it.key()); + if (fn.startsWith(prefix)) { #ifdef PROPARSER_THREAD_SAFE if (it->locker) { if (!it->locker->done) { @@ -105,6 +115,7 @@ void ProFileCache::discardFiles(const QString &prefix) } else { ++it; } + } } ////////// Parser /////////// @@ -167,12 +178,15 @@ QMakeParser::QMakeParser(ProFileCache *cache, QMakeVfs *vfs, QMakeParserHandler ProFile *QMakeParser::parsedProFile(const QString &fileName, ParseFlags flags) { ProFile *pro; + QMakeVfs::VfsFlags vfsFlags = ((flags & ParseCumulative) ? QMakeVfs::VfsCumulative + : QMakeVfs::VfsExact); + int id = m_vfs->idForFileName(fileName, vfsFlags); if ((flags & ParseUseCache) && m_cache) { ProFileCache::Entry *ent; #ifdef PROPARSER_THREAD_SAFE QMutexLocker locker(&m_cache->mutex); #endif - QHash::Iterator it = m_cache->parsed_files.find(fileName); + auto it = m_cache->parsed_files.find(id); if (it != m_cache->parsed_files.end()) { ent = &*it; #ifdef PROPARSER_THREAD_SAFE @@ -190,18 +204,18 @@ ProFile *QMakeParser::parsedProFile(const QString &fileName, ParseFlags flags) if ((pro = ent->pro)) pro->ref(); } else { - ent = &m_cache->parsed_files[fileName]; + ent = &m_cache->parsed_files[id]; #ifdef PROPARSER_THREAD_SAFE ent->locker = new ProFileCache::Entry::Locker; locker.unlock(); #endif - pro = new ProFile(idForFileName(fileName), fileName); - if (!read(pro, flags)) { - delete pro; - pro = 0; - } else { + QString contents; + if (readFile(id, flags, &contents)) { + pro = parsedProBlock(QStringRef(&contents), id, fileName, 1, FullGrammar); pro->itemsRef()->squeeze(); pro->ref(); + } else { + pro = 0; } ent->pro = pro; #ifdef PROPARSER_THREAD_SAFE @@ -216,52 +230,39 @@ ProFile *QMakeParser::parsedProFile(const QString &fileName, ParseFlags flags) #endif } } else { - pro = new ProFile(idForFileName(fileName), fileName); - if (!read(pro, flags)) { - delete pro; + QString contents; + if (readFile(id, flags, &contents)) + pro = parsedProBlock(QStringRef(&contents), id, fileName, 1, FullGrammar); + else pro = 0; - } } return pro; } ProFile *QMakeParser::parsedProBlock( - const QStringRef &contents, const QString &name, int line, SubGrammar grammar) + const QStringRef &contents, int id, const QString &name, int line, SubGrammar grammar) { - ProFile *pro = new ProFile(0, name); + ProFile *pro = new ProFile(id, name); read(pro, contents, line, grammar); return pro; } -int QMakeParser::idForFileName(const QString &fileName) -{ -#ifdef PROPARSER_THREAD_SAFE - QMutexLocker lck(&fileIdMutex); -#endif - int &place = fileIdMap[fileName]; - if (!place) - place = ++fileIdCounter; - return place; -} - -void QMakeParser::discardFileFromCache(const QString &fileName) +void QMakeParser::discardFileFromCache(int id) { if (m_cache) - m_cache->discardFile(fileName); + m_cache->discardFile(id); } -bool QMakeParser::read(ProFile *pro, ParseFlags flags) +bool QMakeParser::readFile(int id, ParseFlags flags, QString *contents) { - QString content; QString errStr; - QMakeVfs::ReadResult result = m_vfs->readFile(pro->fileName(), &content, &errStr); + QMakeVfs::ReadResult result = m_vfs->readFile(id, contents, &errStr); if (result != QMakeVfs::ReadOk) { if (m_handler && ((flags & ParseReportMissing) || result != QMakeVfs::ReadNotFound)) m_handler->message(QMakeParserHandler::ParserIoError, - fL1S("Cannot read %1: %2").arg(pro->fileName(), errStr)); + fL1S("Cannot read %1: %2").arg(m_vfs->fileNameForId(id), errStr)); return false; } - read(pro, QStringRef(&content), 1, FullGrammar); return true; } diff --git a/qmake/library/qmakeparser.h b/qmake/library/qmakeparser.h index a29e9c227d6..3ae30dcf749 100644 --- a/qmake/library/qmakeparser.h +++ b/qmake/library/qmakeparser.h @@ -30,6 +30,7 @@ #define QMAKEPARSER_H #include "qmake_global.h" +#include "qmakevfs.h" #include "proitems.h" #include @@ -78,7 +79,12 @@ public: enum ParseFlag { ParseDefault = 0, ParseUseCache = 1, - ParseReportMissing = 4 + ParseReportMissing = 4, +#ifdef PROEVALUATOR_DUAL_VFS + ParseCumulative = 8 +#else + ParseCumulative = 0 +#endif }; Q_DECLARE_FLAGS(ParseFlags, ParseFlag) @@ -87,12 +93,10 @@ public: enum SubGrammar { FullGrammar, TestGrammar, ValueGrammar }; // fileName is expected to be absolute and cleanPath()ed. ProFile *parsedProFile(const QString &fileName, ParseFlags flags = ParseDefault); - ProFile *parsedProBlock(const QStringRef &contents, const QString &name, int line = 0, + ProFile *parsedProBlock(const QStringRef &contents, int id, const QString &name, int line = 0, SubGrammar grammar = FullGrammar); - int idForFileName(const QString &fileName); - - void discardFileFromCache(const QString &fileName); + void discardFileFromCache(int id); #ifdef PROPARSER_DEBUG static QString formatProBlock(const QString &block); @@ -131,7 +135,7 @@ private: ushort terminator; // '}' if replace function call is braced, ':' if test function }; - bool read(ProFile *pro, ParseFlags flags); + bool readFile(int id, QMakeParser::ParseFlags flags, QString *contents); void read(ProFile *pro, const QStringRef &content, int line, SubGrammar grammar); ALWAYS_INLINE void putTok(ushort *&tokPtr, ushort tok); @@ -182,12 +186,6 @@ private: QString m_tmp; // Temporary for efficient toQString - QHash fileIdMap; -#ifdef PROEVALUATOR_THREAD_SAFE - QMutex fileIdMutex; -#endif - int fileIdCounter = 0; - ProFileCache *m_cache; QMakeParserHandler *m_handler; QMakeVfs *m_vfs; @@ -206,8 +204,9 @@ public: ProFileCache() {} ~ProFileCache(); - void discardFile(const QString &fileName); - void discardFiles(const QString &prefix); + void discardFile(int id); + void discardFile(const QString &fileName, QMakeVfs *vfs); + void discardFiles(const QString &prefix, QMakeVfs *vfs); private: struct Entry { @@ -223,7 +222,7 @@ private: #endif }; - QHash parsed_files; + QHash parsed_files; #ifdef PROPARSER_THREAD_SAFE QMutex mutex; #endif diff --git a/qmake/library/qmakevfs.cpp b/qmake/library/qmakevfs.cpp index c40f49c4ad9..16e21395baf 100644 --- a/qmake/library/qmakevfs.cpp +++ b/qmake/library/qmakevfs.cpp @@ -47,32 +47,102 @@ QMakeVfs::QMakeVfs() { } -bool QMakeVfs::writeFile(const QString &fn, QIODevice::OpenMode mode, bool exe, +#ifdef PROPARSER_THREAD_SAFE +QMutex QMakeVfs::s_mutex; +#endif +QAtomicInt QMakeVfs::s_fileIdCounter; +QHash QMakeVfs::s_fileIdMap; +QHash QMakeVfs::s_idFileMap; + +int QMakeVfs::idForFileName(const QString &fn, VfsFlags flags) +{ +#ifdef PROEVALUATOR_DUAL_VFS + { +# ifdef PROPARSER_THREAD_SAFE + QMutexLocker locker(&m_vmutex); +# endif + int idx = (flags & VfsCumulative) ? 1 : 0; + if (flags & VfsCreate) { + int &id = m_virtualFileIdMap[idx][fn]; + if (!id) { + id = ++s_fileIdCounter; + m_virtualIdFileMap[id] = fn; + } + return id; + } + int id = m_virtualFileIdMap[idx].value(fn); + if (id || (flags & VfsCreatedOnly)) + return id; + } +#endif + if (!(flags & VfsAccessedOnly)) { +#ifdef PROPARSER_THREAD_SAFE + QMutexLocker locker(&s_mutex); +#endif + int &id = s_fileIdMap[fn]; + if (!id) { + id = ++s_fileIdCounter; + s_idFileMap[id] = fn; + } + return id; + } + return s_fileIdMap.value(fn); +} + +QString QMakeVfs::fileNameForId(int id) +{ +#ifdef PROEVALUATOR_DUAL_VFS + { +# ifdef PROPARSER_THREAD_SAFE + QMutexLocker locker(&m_vmutex); +# endif + const QString &fn = m_virtualIdFileMap.value(id); + if (!fn.isEmpty()) + return fn; + } +#endif +#ifdef PROPARSER_THREAD_SAFE + QMutexLocker locker(&s_mutex); +#endif + return s_idFileMap.value(id); +} + +void QMakeVfs::clearIds() +{ +#ifdef PROEVALUATOR_THREAD_SAFE + QMutexLocker locker(&s_mutex); +#endif + s_fileIdCounter = 0; + s_fileIdMap.clear(); + s_idFileMap.clear(); +} + +bool QMakeVfs::writeFile(int id, QIODevice::OpenMode mode, VfsFlags flags, const QString &contents, QString *errStr) { #ifndef PROEVALUATOR_FULL # ifdef PROEVALUATOR_THREAD_SAFE QMutexLocker locker(&m_mutex); # endif - QString *cont = &m_files[fn]; + QString *cont = &m_files[id]; + Q_UNUSED(flags) if (mode & QIODevice::Append) *cont += contents; else *cont = contents; Q_UNUSED(errStr) - Q_UNUSED(exe) return true; #else - QFileInfo qfi(fn); + QFileInfo qfi(fileNameForId(id)); if (!QDir::current().mkpath(qfi.path())) { *errStr = fL1S("Cannot create parent directory"); return false; } QByteArray bytes = contents.toLocal8Bit(); - QFile cfile(fn); + QFile cfile(qfi.filePath()); if (!(mode & QIODevice::Append) && cfile.open(QIODevice::ReadOnly | QIODevice::Text)) { if (cfile.readAll() == bytes) { - if (exe) { + if (flags & VfsExecutable) { cfile.setPermissions(cfile.permissions() | QFile::ExeUser | QFile::ExeGroup | QFile::ExeOther); } else { @@ -93,20 +163,20 @@ bool QMakeVfs::writeFile(const QString &fn, QIODevice::OpenMode mode, bool exe, *errStr = cfile.errorString(); return false; } - if (exe) + if (flags & VfsExecutable) cfile.setPermissions(cfile.permissions() | QFile::ExeUser | QFile::ExeGroup | QFile::ExeOther); return true; #endif } -QMakeVfs::ReadResult QMakeVfs::readFile(const QString &fn, QString *contents, QString *errStr) +QMakeVfs::ReadResult QMakeVfs::readFile(int id, QString *contents, QString *errStr) { #ifndef PROEVALUATOR_FULL # ifdef PROEVALUATOR_THREAD_SAFE QMutexLocker locker(&m_mutex); # endif - QHash::ConstIterator it = m_files.constFind(fn); + auto it = m_files.constFind(id); if (it != m_files.constEnd()) { if (it->constData() == m_magicMissing.constData()) { *errStr = fL1S("No such file or directory"); @@ -119,11 +189,11 @@ QMakeVfs::ReadResult QMakeVfs::readFile(const QString &fn, QString *contents, QS } #endif - QFile file(fn); + QFile file(fileNameForId(id)); if (!file.open(QIODevice::ReadOnly)) { if (!file.exists()) { #ifndef PROEVALUATOR_FULL - m_files[fn] = m_magicMissing; + m_files[id] = m_magicMissing; #endif *errStr = fL1S("No such file or directory"); return ReadNotFound; @@ -132,7 +202,7 @@ QMakeVfs::ReadResult QMakeVfs::readFile(const QString &fn, QString *contents, QS return ReadOtherError; } #ifndef PROEVALUATOR_FULL - m_files[fn] = m_magicExisting; + m_files[id] = m_magicExisting; #endif QByteArray bcont = file.readAll(); @@ -145,19 +215,22 @@ QMakeVfs::ReadResult QMakeVfs::readFile(const QString &fn, QString *contents, QS return ReadOk; } -bool QMakeVfs::exists(const QString &fn) +bool QMakeVfs::exists(const QString &fn, VfsFlags flags) { #ifndef PROEVALUATOR_FULL # ifdef PROEVALUATOR_THREAD_SAFE QMutexLocker locker(&m_mutex); # endif - QHash::ConstIterator it = m_files.constFind(fn); + int id = idForFileName(fn, flags); + auto it = m_files.constFind(id); if (it != m_files.constEnd()) return it->constData() != m_magicMissing.constData(); +#else + Q_UNUSED(flags) #endif bool ex = IoUtils::fileType(fn) == IoUtils::FileIsRegular; #ifndef PROEVALUATOR_FULL - m_files[fn] = ex ? m_magicExisting : m_magicMissing; + m_files[id] = ex ? m_magicExisting : m_magicMissing; #endif return ex; } @@ -169,7 +242,7 @@ void QMakeVfs::invalidateCache() # ifdef PROEVALUATOR_THREAD_SAFE QMutexLocker locker(&m_mutex); # endif - QHash::Iterator it = m_files.begin(), eit = m_files.end(); + auto it = m_files.begin(), eit = m_files.end(); while (it != eit) { if (it->constData() == m_magicMissing.constData() ||it->constData() == m_magicExisting.constData()) diff --git a/qmake/library/qmakevfs.h b/qmake/library/qmakevfs.h index 5e6a2f88e25..3b69b60bee3 100644 --- a/qmake/library/qmakevfs.h +++ b/qmake/library/qmakevfs.h @@ -31,12 +31,16 @@ #include "qmake_global.h" -# include -#ifndef PROEVALUATOR_FULL -# include -# include -# ifdef PROEVALUATOR_THREAD_SAFE -# include +#include +#include +#include +#ifdef PROEVALUATOR_THREAD_SAFE +# include +#endif + +#ifdef PROEVALUATOR_DUAL_VFS +# ifndef PROEVALUATOR_CUMULATIVE +# error PROEVALUATOR_DUAL_VFS requires PROEVALUATOR_CUMULATIVE # endif #endif @@ -51,11 +55,30 @@ public: ReadOtherError }; + enum VfsFlag { + VfsExecutable = 1, + VfsExact = 0, +#ifdef PROEVALUATOR_DUAL_VFS + VfsCumulative = 2, + VfsCreate = 4, + VfsCreatedOnly = 8, +#else + VfsCumulative = 0, + VfsCreate = 0, + VfsCreatedOnly = 0, +#endif + VfsAccessedOnly = 16 + }; + Q_DECLARE_FLAGS(VfsFlags, VfsFlag) + QMakeVfs(); - bool writeFile(const QString &fn, QIODevice::OpenMode mode, bool exe, const QString &contents, QString *errStr); - ReadResult readFile(const QString &fn, QString *contents, QString *errStr); - bool exists(const QString &fn); + int idForFileName(const QString &fn, VfsFlags flags); + QString fileNameForId(int id); + static void clearIds(); + bool writeFile(int id, QIODevice::OpenMode mode, VfsFlags flags, const QString &contents, QString *errStr); + ReadResult readFile(int id, QString *contents, QString *errStr); + bool exists(const QString &fn, QMakeVfs::VfsFlags flags); #ifndef PROEVALUATOR_FULL void invalidateCache(); @@ -63,16 +86,41 @@ public: #endif private: +#ifdef PROEVALUATOR_THREAD_SAFE + static QMutex s_mutex; +#endif + static QAtomicInt s_fileIdCounter; + // Qt Creator's ProFile cache is a singleton to maximize its cross-project + // effectiveness (shared prf files from QtVersions). + // For this to actually work, real files need a global mapping. + // This is fine, because the namespace of real files is indeed global. + static QHash s_fileIdMap; + static QHash s_idFileMap; +#ifdef PROEVALUATOR_DUAL_VFS +# ifdef PROEVALUATOR_THREAD_SAFE + // The simple way to avoid recursing m_mutex. + QMutex m_vmutex; +# endif + // Virtual files are bound to the project context they were created in, + // so their ids need to be local as well. + // We violate that rule in lupdate (which has a non-dual VFS), but that + // does not matter, because it has only one project context anyway. + QHash m_virtualFileIdMap[2]; // Exact and cumulative + QHash m_virtualIdFileMap; // Only one map, as ids are unique across realms. +#endif + #ifndef PROEVALUATOR_FULL # ifdef PROEVALUATOR_THREAD_SAFE QMutex m_mutex; # endif - QHash m_files; + QHash m_files; QString m_magicMissing; QString m_magicExisting; #endif }; +Q_DECLARE_OPERATORS_FOR_FLAGS(QMakeVfs::VfsFlags) + QT_END_NAMESPACE #endif // QMAKEVFS_H diff --git a/qmake/project.cpp b/qmake/project.cpp index e8509ad0961..e6bdb04bfbe 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -123,7 +123,7 @@ QStringList QMakeProject::expand(const ProKey &func, const QList ProString QMakeProject::expand(const QString &expr, const QString &where, int line) { ProString ret; - ProFile *pro = m_parser->parsedProBlock(QStringRef(&expr), where, line, + ProFile *pro = m_parser->parsedProBlock(QStringRef(&expr), 0, where, line, QMakeParser::ValueGrammar); if (pro->isOk()) { m_current.pro = pro; diff --git a/tests/auto/tools/qmakelib/evaltest.cpp b/tests/auto/tools/qmakelib/evaltest.cpp index 3fdd30b6857..aeedf4ae322 100644 --- a/tests/auto/tools/qmakelib/evaltest.cpp +++ b/tests/auto/tools/qmakelib/evaltest.cpp @@ -2869,12 +2869,12 @@ void tst_qmakelib::proEval() globals.environment = m_env; globals.setProperties(m_prop); globals.setDirectories(m_indir, m_outdir); - ProFile *outPro = parser.parsedProBlock(QStringRef(&out), "out", 1, QMakeParser::FullGrammar); + ProFile *outPro = parser.parsedProBlock(QStringRef(&out), 0, "out", 1, QMakeParser::FullGrammar); if (!outPro->isOk()) { qWarning("Expected output is malformed"); verified = false; } - ProFile *pro = parser.parsedProBlock(QStringRef(&in), infile, 1, QMakeParser::FullGrammar); + ProFile *pro = parser.parsedProBlock(QStringRef(&in), 0, infile, 1, QMakeParser::FullGrammar); QMakeEvaluator visitor(&globals, &parser, &vfs, &handler); visitor.setOutputDir(m_outdir); #ifdef Q_OS_WIN diff --git a/tests/auto/tools/qmakelib/parsertest.cpp b/tests/auto/tools/qmakelib/parsertest.cpp index 70f1be5fc3b..f736bf38bfa 100644 --- a/tests/auto/tools/qmakelib/parsertest.cpp +++ b/tests/auto/tools/qmakelib/parsertest.cpp @@ -2031,7 +2031,7 @@ void tst_qmakelib::proParser() handler.setExpectedMessages(msgs.split('\n', QString::SkipEmptyParts)); QMakeVfs vfs; QMakeParser parser(0, &vfs, &handler); - ProFile *pro = parser.parsedProBlock(QStringRef(&in), "in", 1, QMakeParser::FullGrammar); + ProFile *pro = parser.parsedProBlock(QStringRef(&in), 0, "in", 1, QMakeParser::FullGrammar); if (handler.printedMessages()) { qWarning("Got unexpected message(s)"); verified = false; From 85ae0f1f3e369e1d28af7b2ec963f63e177ecd11 Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Wed, 30 Nov 2016 18:26:44 +0100 Subject: [PATCH 08/17] qmake: add text codec support to VFS sync-up with qt-creator; no effect on qmake. Change-Id: I34b42bd19e0de973deb2291e91f306d1ca7c630e (cherry picked from qtcreator/15148d8e4454ff3277131ea52a4204c5fa0b7ab0) Reviewed-by: Joerg Bornemann --- qmake/library/qmakevfs.cpp | 20 +++++++++++++++++++- qmake/library/qmakevfs.h | 11 +++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/qmake/library/qmakevfs.cpp b/qmake/library/qmakevfs.cpp index 16e21395baf..2239a2beec6 100644 --- a/qmake/library/qmakevfs.cpp +++ b/qmake/library/qmakevfs.cpp @@ -35,6 +35,10 @@ using namespace QMakeInternal; #include #include +#ifndef QT_NO_TEXTCODEC +#include +#endif + #define fL1S(s) QString::fromLatin1(s) QT_BEGIN_NAMESPACE @@ -45,6 +49,9 @@ QMakeVfs::QMakeVfs() , m_magicExisting(fL1S("existing")) #endif { +#ifndef QT_NO_TEXTCODEC + m_textCodec = 0; +#endif } #ifdef PROPARSER_THREAD_SAFE @@ -211,7 +218,11 @@ QMakeVfs::ReadResult QMakeVfs::readFile(int id, QString *contents, QString *errS *errStr = fL1S("Unexpected UTF-8 BOM"); return ReadOtherError; } - *contents = QString::fromLocal8Bit(bcont); + *contents = +#ifndef QT_NO_TEXTCODEC + m_textCodec ? m_textCodec->toUnicode(bcont) : +#endif + QString::fromLocal8Bit(bcont); return ReadOk; } @@ -262,4 +273,11 @@ void QMakeVfs::invalidateContents() } #endif +#ifndef QT_NO_TEXTCODEC +void QMakeVfs::setTextCodec(const QTextCodec *textCodec) +{ + m_textCodec = textCodec; +} +#endif + QT_END_NAMESPACE diff --git a/qmake/library/qmakevfs.h b/qmake/library/qmakevfs.h index 3b69b60bee3..12172254714 100644 --- a/qmake/library/qmakevfs.h +++ b/qmake/library/qmakevfs.h @@ -38,6 +38,10 @@ # include #endif +#ifndef QT_NO_TEXTCODEC +QT_FORWARD_DECLARE_CLASS(QTextCodec) +#endif + #ifdef PROEVALUATOR_DUAL_VFS # ifndef PROEVALUATOR_CUMULATIVE # error PROEVALUATOR_DUAL_VFS requires PROEVALUATOR_CUMULATIVE @@ -85,6 +89,10 @@ public: void invalidateContents(); #endif +#ifndef QT_NO_TEXTCODEC + void setTextCodec(const QTextCodec *textCodec); +#endif + private: #ifdef PROEVALUATOR_THREAD_SAFE static QMutex s_mutex; @@ -117,6 +125,9 @@ private: QString m_magicMissing; QString m_magicExisting; #endif +#ifndef QT_NO_TEXTCODEC + const QTextCodec *m_textCodec; +#endif }; Q_DECLARE_OPERATORS_FOR_FLAGS(QMakeVfs::VfsFlags) From 13ab4c563dc33abc879d8f2a628b8a525e00e55a Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 24 Jan 2017 13:33:14 +0100 Subject: [PATCH 09/17] qmake: remove unnecessary QMakeGlobals::setProperties() overload sync-up with qt-creator; no effect on qmake. Change-Id: I926bc97fe6fa510ac5a8fe77b64014333a69bd04 (cherry picked from qtcreator/8a69c254757eab7852443b5e4bd5eafb68908d3d) Reviewed-by: Joerg Bornemann --- qmake/library/qmakeglobals.cpp | 7 ------- qmake/library/qmakeglobals.h | 1 - 2 files changed, 8 deletions(-) diff --git a/qmake/library/qmakeglobals.cpp b/qmake/library/qmakeglobals.cpp index d733d479cf0..cab04fc239f 100644 --- a/qmake/library/qmakeglobals.cpp +++ b/qmake/library/qmakeglobals.cpp @@ -370,13 +370,6 @@ bool QMakeGlobals::initProperties() } return true; } -#else -void QMakeGlobals::setProperties(const QHash &props) -{ - QHash::ConstIterator it = props.constBegin(), eit = props.constEnd(); - for (; it != eit; ++it) - properties.insert(ProKey(it.key()), ProString(it.value())); -} #endif #endif // QT_BUILD_QMAKE diff --git a/qmake/library/qmakeglobals.h b/qmake/library/qmakeglobals.h index 000f685b731..cf71a5afda9 100644 --- a/qmake/library/qmakeglobals.h +++ b/qmake/library/qmakeglobals.h @@ -134,7 +134,6 @@ public: # ifdef PROEVALUATOR_INIT_PROPS bool initProperties(); # else - void setProperties(const QHash &props); void setProperties(const QHash &props) { properties = props; } # endif ProString propertyValue(const ProKey &name) const { return properties.value(name); } From 0158b185091db424516fb4de57b909a6e7e815b2 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 23 Jan 2017 15:58:55 +0100 Subject: [PATCH 10/17] qmake: updates to the parsing code of external properties sync-up with qt-creator; no effect on qmake. Change-Id: I7555de5c72a9250b31e20fc60e39680d19882fcb (cherry picked from qtcreator/2cb7c81e620d224d386860a637dc889acb15435e) (cherry picked from qtcreator/89868ee2b9093ecf40602ae302b991d6a60014b0) (cherry picked from qtcreator/03e699ce2985eedcd33d247aa47d04b14bc4bc04) (cherry picked from qtcreator/61419e7bf0f3bff6dcf63876b05b72c56e60c2a8) (cherry picked from qtcreator/19eaf87ef95a510351557119a955223a4aeea7b3) (cherry picked from qtcreator/3080bda0661989e88dfa62101b4c3f5d5e6754a1) (cherry picked from qtcreator/99714239b616e628ff4e0afe3db7eb7511ccf569) Reviewed-by: Joerg Bornemann --- qmake/library/qmakeglobals.cpp | 57 ++++++++++++++++++++++------------ qmake/library/qmakeglobals.h | 1 + 2 files changed, 38 insertions(+), 20 deletions(-) diff --git a/qmake/library/qmakeglobals.cpp b/qmake/library/qmakeglobals.cpp index cab04fc239f..452b44c0455 100644 --- a/qmake/library/qmakeglobals.cpp +++ b/qmake/library/qmakeglobals.cpp @@ -327,6 +327,13 @@ bool QMakeGlobals::initProperties() QT_PCLOSE(proc); } #endif + parseProperties(data, properties); + return true; +} +#endif + +void QMakeGlobals::parseProperties(const QByteArray &data, QHash &properties) +{ const auto lines = data.split('\n'); for (QByteArray line : lines) { int off = line.indexOf(':'); @@ -337,40 +344,50 @@ bool QMakeGlobals::initProperties() QString name = QString::fromLatin1(line.left(off)); ProString value = ProString(QDir::fromNativeSeparators( QString::fromLocal8Bit(line.mid(off + 1)))); + if (value.isNull()) + value = ProString(""); // Make sure it is not null, to discern from missing keys properties.insert(ProKey(name), value); if (name.startsWith(QLatin1String("QT_"))) { - bool plain = !name.contains(QLatin1Char('/')); - if (!plain) { - if (!name.endsWith(QLatin1String("/get"))) + enum { PropPut, PropRaw, PropGet } variant; + if (name.contains(QLatin1Char('/'))) { + if (name.endsWith(QLatin1String("/raw"))) + variant = PropRaw; + else if (name.endsWith(QLatin1String("/get"))) + variant = PropGet; + else // Nothing falls back on /src or /dev. continue; name.chop(4); + } else { + variant = PropPut; } if (name.startsWith(QLatin1String("QT_INSTALL_"))) { - if (plain) { - properties.insert(ProKey(name + QLatin1String("/raw")), value); - properties.insert(ProKey(name + QLatin1String("/get")), value); - } - properties.insert(ProKey(name + QLatin1String("/src")), value); - if (name == QLatin1String("QT_INSTALL_PREFIX") - || name == QLatin1String("QT_INSTALL_DATA") - || name == QLatin1String("QT_INSTALL_BINS")) { - name.replace(3, 7, QLatin1String("HOST")); - if (plain) { - properties.insert(ProKey(name), value); - properties.insert(ProKey(name + QLatin1String("/get")), value); + if (variant < PropRaw) { + if (name == QLatin1String("QT_INSTALL_PREFIX") + || name == QLatin1String("QT_INSTALL_DATA") + || name == QLatin1String("QT_INSTALL_LIBS") + || name == QLatin1String("QT_INSTALL_BINS")) { + // Qt4 fallback + QString hname = name; + hname.replace(3, 7, QLatin1String("HOST")); + properties.insert(ProKey(hname), value); + properties.insert(ProKey(hname + QLatin1String("/get")), value); + properties.insert(ProKey(hname + QLatin1String("/src")), value); } - properties.insert(ProKey(name + QLatin1String("/src")), value); + properties.insert(ProKey(name + QLatin1String("/raw")), value); } - } else if (name.startsWith(QLatin1String("QT_HOST_"))) { - if (plain) + if (variant <= PropRaw) + properties.insert(ProKey(name + QLatin1String("/dev")), value); + } else if (!name.startsWith(QLatin1String("QT_HOST_"))) { + continue; + } + if (variant != PropRaw) { + if (variant < PropGet) properties.insert(ProKey(name + QLatin1String("/get")), value); properties.insert(ProKey(name + QLatin1String("/src")), value); } } } - return true; } -#endif #endif // QT_BUILD_QMAKE QT_END_NAMESPACE diff --git a/qmake/library/qmakeglobals.h b/qmake/library/qmakeglobals.h index cf71a5afda9..6c00b1f3af8 100644 --- a/qmake/library/qmakeglobals.h +++ b/qmake/library/qmakeglobals.h @@ -131,6 +131,7 @@ public: void reloadProperties() { property->reload(); } ProString propertyValue(const ProKey &name) const { return property->value(name); } #else + static void parseProperties(const QByteArray &data, QHash &props); # ifdef PROEVALUATOR_INIT_PROPS bool initProperties(); # else From 04b93bfb2127a88f35d2b251e900163f982e7cfe Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 6 Mar 2018 19:07:11 +0100 Subject: [PATCH 11/17] qmake: minor fixups to ioutils for building in qt creator context Change-Id: If82a5387a03f400cde04d582dd7e8567a2b661a0 Reviewed-by: Joerg Bornemann --- qmake/library/ioutils.cpp | 5 +++-- qmake/library/ioutils.h | 8 +++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/qmake/library/ioutils.cpp b/qmake/library/ioutils.cpp index 4aa3282e3b4..fd84dff59d6 100644 --- a/qmake/library/ioutils.cpp +++ b/qmake/library/ioutils.cpp @@ -258,9 +258,8 @@ bool IoUtils::touchFile(const QString &targetFileName, const QString &referenceF # endif return true; } -#endif -#ifdef Q_OS_UNIX +#if defined(QT_BUILD_QMAKE) && defined(Q_OS_UNIX) bool IoUtils::readLinkTarget(const QString &symlinkPath, QString *target) { const QByteArray localSymlinkPath = QFile::encodeName(symlinkPath); @@ -295,4 +294,6 @@ bool IoUtils::readLinkTarget(const QString &symlinkPath, QString *target) } #endif +#endif // PROEVALUATOR_FULL + QT_END_NAMESPACE diff --git a/qmake/library/ioutils.h b/qmake/library/ioutils.h index ad379404f30..32bf675f623 100644 --- a/qmake/library/ioutils.h +++ b/qmake/library/ioutils.h @@ -29,6 +29,8 @@ #ifndef IOUTILS_H #define IOUTILS_H +#include "qmake_global.h" + #include QT_BEGIN_NAMESPACE @@ -39,7 +41,7 @@ namespace QMakeInternal { This class provides replacement functionality for QFileInfo, QFile & QDir, as these are abysmally slow. */ -class IoUtils { +class QMAKE_EXPORT IoUtils { public: enum FileType { FileNotFound = 0, @@ -64,9 +66,9 @@ public: #endif #if defined(PROEVALUATOR_FULL) static bool touchFile(const QString &targetFileName, const QString &referenceFileName, QString *errorString); -#endif -#ifdef Q_OS_UNIX +# if defined(QT_BUILD_QMAKE) && defined(Q_OS_UNIX) static bool readLinkTarget(const QString &symlinkPath, QString *target); +# endif #endif }; From 1d537071dea5668df991b0ccb82f14a5880b62c9 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 21 Mar 2018 17:51:54 +0100 Subject: [PATCH 12/17] rcc: prune dead wildcard matching code clearly, rcc was meant to support wildcard patterns in entries. however, since its inception, this code was broken: the exists() check was done first, so the decomposition into path and wildcard would never happen. as actually supporting wildcards woulds just complicate matters, simply remove that dead code. on the way, re-arrange the code in a way that is advantageous for subsequent changes, and insert a case that catches non-regular file nodes (this would have previously run into the wildcard code). Change-Id: Iac1a168b844ef5b176f6cc45d6a779fde0bec6f7 Reviewed-by: hjk --- src/tools/rcc/rcc.cpp | 61 ++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 32 deletions(-) diff --git a/src/tools/rcc/rcc.cpp b/src/tools/rcc/rcc.cpp index 92d3c5c171a..4c7d095ca37 100644 --- a/src/tools/rcc/rcc.cpp +++ b/src/tools/rcc/rcc.cpp @@ -504,38 +504,8 @@ bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice, if (QDir::isRelativePath(absFileName)) absFileName.prepend(currentPath); QFileInfo file(absFileName); - if (!file.exists()) { - m_failedResources.push_back(absFileName); - const QString msg = QString::fromLatin1("RCC: Error in '%1': Cannot find file '%2'\n") - .arg(fname, fileName); - m_errorDevice->write(msg.toUtf8()); - if (ignoreErrors) - continue; - else - return false; - } else if (file.isFile()) { - const bool arc = - addFile(alias, - RCCFileInfo(alias.section(slash, -1), - file, - language, - country, - RCCFileInfo::NoFlags, - compressLevel, - compressThreshold) - ); - if (!arc) - m_failedResources.push_back(absFileName); - } else { - QDir dir; - if (file.isDir()) { - dir.setPath(file.filePath()); - } else { - dir.setPath(file.path()); - dir.setNameFilters(QStringList(file.fileName())); - if (alias.endsWith(file.fileName())) - alias = alias.left(alias.length()-file.fileName().length()); - } + if (file.isDir()) { + QDir dir(file.filePath()); if (!alias.endsWith(slash)) alias += slash; QDirIterator it(dir, QDirIterator::FollowSymlinks|QDirIterator::Subdirectories); @@ -557,6 +527,33 @@ bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice, m_failedResources.push_back(child.fileName()); } } + } else if (file.isFile()) { + const bool arc = + addFile(alias, + RCCFileInfo(alias.section(slash, -1), + file, + language, + country, + RCCFileInfo::NoFlags, + compressLevel, + compressThreshold) + ); + if (!arc) + m_failedResources.push_back(absFileName); + } else if (file.exists()) { + m_failedResources.push_back(absFileName); + const QString msg = QString::fromLatin1("RCC: Error in '%1': Entry '%2' is neither a file nor a directory\n") + .arg(fname, fileName); + m_errorDevice->write(msg.toUtf8()); + return false; + } else { + m_failedResources.push_back(absFileName); + const QString msg = QString::fromLatin1("RCC: Error in '%1': Cannot find file '%2'\n") + .arg(fname, fileName); + m_errorDevice->write(msg.toUtf8()); + if (ignoreErrors) + continue; + return false; } } break; From 1c4cae62771eb53987cc0684dcb662732a8509a9 Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Fri, 10 Nov 2017 21:36:27 +0100 Subject: [PATCH 13/17] Improve the Frozen Column example This patch updates the frozen column example to use QTextStream which offers a more convenient way to read text files and also takes care of converting the 8-bit data stored on disk into a 16-bit Unicode QString. Change-Id: Ifd03903ac14b48b026d8770cda726f8ed2756ab4 Reviewed-by: Sze Howe Koh --- examples/widgets/itemviews/frozencolumn/main.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/examples/widgets/itemviews/frozencolumn/main.cpp b/examples/widgets/itemviews/frozencolumn/main.cpp index 5a4d3e0f42e..6f2b4a8d71e 100644 --- a/examples/widgets/itemviews/frozencolumn/main.cpp +++ b/examples/widgets/itemviews/frozencolumn/main.cpp @@ -51,6 +51,7 @@ #include #include #include +#include #include "freezetablewidget.h" @@ -63,14 +64,16 @@ int main(int argc, char* argv[]) QFile file(":/grades.txt"); if (file.open(QFile::ReadOnly)) { - QString line = file.readLine(200); + QTextStream stream(&file); + + QString line = stream.readLine(); QStringList list = line.simplified().split(','); model->setHorizontalHeaderLabels(list); int row = 0; QStandardItem *newItem = 0; - while (file.canReadLine()) { - line = file.readLine(200); + while (!stream.atEnd()) { + line = stream.readLine(); if (!line.startsWith('#') && line.contains(',')) { list = line.simplified().split(','); for (int col = 0; col < list.length(); ++col){ From 62da8e34800afb658a19037fa37715c869311fae Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Fri, 10 Nov 2017 22:23:53 +0100 Subject: [PATCH 14/17] doc: Improve QByteArray::fromRawData snippet The current snippet uses integer literals that will trigger the Wnarrowing warning with recent version of gcc. This patch replaces them with character literals to fix this warning. Change-Id: Iffad495f24cc9d4c1674a7fe3f6b45c46a625ff8 Reviewed-by: Sze Howe Koh --- .../doc/snippets/code/src_corelib_tools_qbytearray.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp index a17e541df36..d163129d54e 100644 --- a/src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp @@ -395,10 +395,10 @@ QByteArray ba = QByteArray::number(12.3456, 'E', 3); //! [43] static const char mydata[] = { - 0x00, 0x00, 0x03, 0x84, 0x78, 0x9c, 0x3b, 0x76, - 0xec, 0x18, 0xc3, 0x31, 0x0a, 0xf1, 0xcc, 0x99, + '\x00', '\x00', '\x03', '\x84', '\x78', '\x9c', '\x3b', '\x76', + '\xec', '\x18', '\xc3', '\x31', '\x0a', '\xf1', '\xcc', '\x99', ... - 0x6d, 0x5b + '\x6d', '\x5b' }; QByteArray data = QByteArray::fromRawData(mydata, sizeof(mydata)); From f3a461c4a2ca41669e1cccec0b528c0b1482b0ad Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 7 Dec 2017 16:31:43 +0100 Subject: [PATCH 15/17] Stabilize tst_QGraphicsProxyWidget::tooltip_basic() Use QTRY_VERIFY instead of hard-coded wait for the tooltip to appear. Also use QTRY_VERIFY to verify that no top level widgets are left over to account for tooltips and effect windows. Change-Id: Ia9835fdc480c6abb034f6fc4ad3d6b32751ee536 Reviewed-by: Sami Nurmenniemi Reviewed-by: Kari Oikarinen --- .../tst_qgraphicsproxywidget.cpp | 31 +++++++++++-------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp index 8287b9ebdd5..4cd2fef2dc4 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp @@ -281,7 +281,7 @@ void tst_QGraphicsProxyWidget::initTestCase() // This will be called after every test function. void tst_QGraphicsProxyWidget::cleanup() { - QVERIFY(QApplication::topLevelWidgets().isEmpty()); + QTRY_VERIFY(QApplication::topLevelWidgets().isEmpty()); } void tst_QGraphicsProxyWidget::qgraphicsproxywidget_data() @@ -2575,6 +2575,22 @@ void tst_QGraphicsProxyWidget::changingCursor_basic() } #endif +static bool findViewAndTipLabel(const QWidget *view) +{ + bool foundView = false; + bool foundTipLabel = false; + const QWidgetList &topLevels = QApplication::topLevelWidgets(); + for (const QWidget *widget : topLevels) { + if (widget == view) + foundView = true; + if (widget->inherits("QTipLabel")) + foundTipLabel = true; + if (foundView && foundTipLabel) + return true; + } + return false; +} + void tst_QGraphicsProxyWidget::tooltip_basic() { QString toolTip = "Qt rocks!"; @@ -2627,18 +2643,7 @@ void tst_QGraphicsProxyWidget::tooltip_basic() QHelpEvent helpEvent(QEvent::ToolTip, view.mapFromScene(proxy->boundingRect().center()), view.viewport()->mapToGlobal(view.mapFromScene(proxy->boundingRect().center()))); QApplication::sendEvent(view.viewport(), &helpEvent); - QTest::qWait(350); - - bool foundView = false; - bool foundTipLabel = false; - foreach (QWidget *widget, QApplication::topLevelWidgets()) { - if (widget == &view) - foundView = true; - if (widget->inherits("QTipLabel")) - foundTipLabel = true; - } - QVERIFY(foundView); - QVERIFY(foundTipLabel); + QTRY_VERIFY(findViewAndTipLabel(&view)); } } From 84c71207ae4a393237e209e2e754786959ba653d Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 27 Mar 2018 13:33:16 +0200 Subject: [PATCH 16/17] Fix debug_and_release builds with CONFIG += qtquickcompiler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For correct debug/ and release/ suffix substitution and thus avoid concurrent access to generated files, we have to declare the output directory variable used by qtquickcompiler.prf in qtdeclarative here and enable it for substitution. Change-Id: Id8483daffdf1b9990396c55f7bc0d08a2f65cafd Task-number: QTBUG-66675 Reviewed-by: Tor Arne Vestbø Reviewed-by: Oswald Buddenhagen --- mkspecs/features/exclusive_builds.prf | 4 ++-- mkspecs/features/qt_build_config.prf | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/mkspecs/features/exclusive_builds.prf b/mkspecs/features/exclusive_builds.prf index b477cff1623..2d7f0e1ab61 100644 --- a/mkspecs/features/exclusive_builds.prf +++ b/mkspecs/features/exclusive_builds.prf @@ -38,5 +38,5 @@ defineTest(addExclusiveBuilds) { } # Default directories to process -QMAKE_DIR_REPLACE = OBJECTS_DIR MOC_DIR RCC_DIR PRECOMPILED_DIR QGLTF_DIR DESTDIR TRACEGEN_DIR -QMAKE_DIR_REPLACE_SANE += QGLTF_DIR TRACEGEN_DIR +QMAKE_DIR_REPLACE = OBJECTS_DIR MOC_DIR RCC_DIR PRECOMPILED_DIR QGLTF_DIR DESTDIR TRACEGEN_DIR QMLCACHE_DIR +QMAKE_DIR_REPLACE_SANE += QGLTF_DIR TRACEGEN_DIR QMLCACHE_DIR diff --git a/mkspecs/features/qt_build_config.prf b/mkspecs/features/qt_build_config.prf index a2fa1be4811..021036e4f93 100644 --- a/mkspecs/features/qt_build_config.prf +++ b/mkspecs/features/qt_build_config.prf @@ -26,6 +26,7 @@ MOC_DIR = .moc RCC_DIR = .rcc UI_DIR = .uic TRACEGEN_DIR = .tracegen +QMLCACHE_DIR = .qmlcache intel_icl { # ICL 14.0 has a bug that makes it not find #includes in dirs starting with . MOC_DIR = tmp/moc From dbdd5f0ffbce52c8b789ed09f1aa3f1da6c02e23 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Fri, 30 Mar 2018 11:58:16 -0700 Subject: [PATCH 17/17] QCoreTextFontEngine: Fix build with Xcode 9.3 Apple LLVM version 9.1.0 (clang-902.0.39.1) Error message: .../qfontengine_coretext.mm:827:20: error: qualified reference to 'QFixed' is a constructor name rather than a type in this context return QFixed::QFixed(int(CTFontGetUnitsPerEm(ctfont))); Change-Id: Iebe26b3b087a16b10664208fc8851cbddb47f043 Reviewed-by: Konstantin Ritt --- src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm index 25ff69d877d..98b753eff96 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm @@ -824,7 +824,7 @@ void QCoreTextFontEngine::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, gl QFixed QCoreTextFontEngine::emSquareSize() const { - return QFixed::QFixed(int(CTFontGetUnitsPerEm(ctfont))); + return QFixed(int(CTFontGetUnitsPerEm(ctfont))); } QFontEngine *QCoreTextFontEngine::cloneWithSize(qreal pixelSize) const