From 44137dc65ab1121fc360f6f006b7515648f0bae3 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Fri, 9 Mar 2018 14:25:54 +0100 Subject: XCode: Fix the output paths for extra compilers with fileFixify() This ensures that the generated XCode project can correctly find any files that are referenced via a path containing "..". Task-number: QTBUG-35131 Change-Id: I049bc2279b4c515a82acd61142d25b8c240e8f6e Reviewed-by: Oswald Buddenhagen --- qmake/generators/mac/pbuilder_pbx.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'qmake') diff --git a/qmake/generators/mac/pbuilder_pbx.cpp b/qmake/generators/mac/pbuilder_pbx.cpp index db7a1b2714..3b1f904253 100644 --- a/qmake/generators/mac/pbuilder_pbx.cpp +++ b/qmake/generators/mac/pbuilder_pbx.cpp @@ -779,8 +779,9 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) mkt << "\\\n\t"; ++added; const QString file_name = fileFixify(fn, FileFixifyFromOutdir); + const QString tmpOut = fileFixify(tmp_out.first().toQString(), FileFixifyFromOutdir); mkt << ' ' << escapeDependencyPath(Option::fixPathToTargetOS( - replaceExtraCompilerVariables(tmp_out.first().toQString(), file_name, QString(), NoShell))); + replaceExtraCompilerVariables(tmpOut, file_name, QString(), NoShell))); } } } -- cgit v1.2.3 From 58b373c9e3c0a7307e3fbafeb5ad710088b8e685 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Fri, 2 Mar 2018 12:30:44 +0100 Subject: Make sure $$relative_path() uses an absolute path as its first arg Thanks to QTBUG-61373, this qmake function was called with /usr/local/5.10.1 as baseDir, which isn't absolute, leading to an assertion failure. We could raise the error within qmake but it proved easier to simply resolve any non-absolute baseDir using PWD, before trying to use it as an absolute path. Did the same for $$absolute_path(). Documented both. Adjusted the assert that caught this to report any non-absolute path that upsets it. Added simple tests, fixed an existing test. Task-number: QTBUG-66156 Change-Id: Icfef2e2f5b236e071177c9beffa38d71bf404292 Reviewed-by: Oswald Buddenhagen --- qmake/doc/src/qmake-manual.qdoc | 15 +++++++++++---- qmake/library/ioutils.cpp | 2 +- qmake/library/qmakebuiltins.cpp | 8 ++++++-- 3 files changed, 18 insertions(+), 7 deletions(-) (limited to 'qmake') diff --git a/qmake/doc/src/qmake-manual.qdoc b/qmake/doc/src/qmake-manual.qdoc index cc3b73418b..35f24e1793 100644 --- a/qmake/doc/src/qmake-manual.qdoc +++ b/qmake/doc/src/qmake-manual.qdoc @@ -2913,7 +2913,8 @@ Returns the absolute path of \c path. If \c base is not specified, uses the current directory as the base - directory. + directory. If it is a relative path, it is resolved relative to the current + directory before use. For example, the following call returns the string \c {"/home/johndoe/myproject/readme.txt"}: @@ -3152,9 +3153,15 @@ \section2 relative_path(filePath[, base]) - Returns the path to \c filePath relative to \c base. If \c base is not - specified, it is the current project directory. This function is a wrapper - around QDir::relativeFilePath. + Returns the path to \c filePath relative to \c base. + + If \c base is not specified, it is the current project + directory. If it is relative, it is resolved relative to the + current project directory before use. + + If \c filePath is relative, it is first resolved against the base + directory; in that case, this function effectively acts as + $$clean_path(). See also \l{absolute_path(path[, base])}{absolute_path()}, \l{clean_path(path)}{clean_path()}. diff --git a/qmake/library/ioutils.cpp b/qmake/library/ioutils.cpp index afd41912fe..cb4aa5e74d 100644 --- a/qmake/library/ioutils.cpp +++ b/qmake/library/ioutils.cpp @@ -103,7 +103,7 @@ QString IoUtils::resolvePath(const QString &baseDir, const QString &fileName) return QDir::cleanPath(fileName); #ifdef Q_OS_WIN // Add drive to otherwise-absolute path: if (fileName.at(0).unicode() == '/' || fileName.at(0).unicode() == '\\') { - Q_ASSERT(isAbsolutePath(baseDir)); + Q_ASSERT_X(isAbsolutePath(baseDir), "IoUtils::resolvePath", qUtf8Printable(baseDir)); return QDir::cleanPath(baseDir.left(2) + fileName); } #endif // Q_OS_WIN diff --git a/qmake/library/qmakebuiltins.cpp b/qmake/library/qmakebuiltins.cpp index 83c3d1d643..0a83b9b930 100644 --- a/qmake/library/qmakebuiltins.cpp +++ b/qmake/library/qmakebuiltins.cpp @@ -1178,7 +1178,9 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand( evalError(fL1S("absolute_path(path[, base]) requires one or two arguments.")); } else { QString arg = args.at(0).toQString(m_tmp1); - QString baseDir = args.count() > 1 ? args.at(1).toQString(m_tmp2) : currentDirectory(); + QString baseDir = args.count() > 1 + ? IoUtils::resolvePath(currentDirectory(), args.at(1).toQString(m_tmp2)) + : currentDirectory(); QString rstr = arg.isEmpty() ? baseDir : IoUtils::resolvePath(baseDir, arg); ret << (rstr.isSharedWith(m_tmp1) ? args.at(0) @@ -1192,7 +1194,9 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand( evalError(fL1S("relative_path(path[, base]) requires one or two arguments.")); } else { QString arg = args.at(0).toQString(m_tmp1); - QString baseDir = args.count() > 1 ? args.at(1).toQString(m_tmp2) : currentDirectory(); + QString baseDir = args.count() > 1 + ? IoUtils::resolvePath(currentDirectory(), args.at(1).toQString(m_tmp2)) + : currentDirectory(); QString absArg = arg.isEmpty() ? baseDir : IoUtils::resolvePath(baseDir, arg); QString rstr = QDir(baseDir).relativeFilePath(absArg); ret << (rstr.isSharedWith(m_tmp1) ? args.at(0) : ProString(rstr).setSource(args.at(0))); -- cgit v1.2.3 From 38f6b6242edeef56ce68f1357ea9f85a6563f09a Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 1 Mar 2018 16:43:46 +0100 Subject: 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(-) (limited to 'qmake') diff --git a/qmake/library/qmakeevaluator.cpp b/qmake/library/qmakeevaluator.cpp index 6e6c72de59..edd1d5f38f 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)) -- cgit v1.2.3 From fe5f2a235cd51020c04570ec3f37070f6be7a1a3 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 20 Oct 2016 15:02:34 +0200 Subject: 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(-) (limited to 'qmake') diff --git a/qmake/library/qmakeevaluator.cpp b/qmake/library/qmakeevaluator.cpp index edd1d5f38f..3e613038a3 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: -- cgit v1.2.3 From e2de837198884b64345f746ef257e6d83bffa571 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 28 Oct 2016 20:10:40 +0200 Subject: 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 +++++++- 3 files changed, 21 insertions(+), 13 deletions(-) (limited to 'qmake') diff --git a/qmake/library/qmakeparser.cpp b/qmake/library/qmakeparser.cpp index b5d89c1ba6..62e8875c5e 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 5aa9ec9299..7631723b1b 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 8677ba08c1..5e6a2f88e2 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 -- cgit v1.2.3 From 811118f68df4171268f65fa6fc075d6c7633f1e4 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 24 Oct 2016 14:58:11 +0200 Subject: 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(-) (limited to 'qmake') diff --git a/qmake/library/ioutils.cpp b/qmake/library/ioutils.cpp index cb4aa5e74d..4aa3282e3b 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 7631723b1b..c40f49c4ad 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 -- cgit v1.2.3 From e5d909d6d68055c057bbaeadb8f7a4078e6d54e8 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 24 Oct 2016 19:30:24 +0200 Subject: 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 +- 8 files changed, 228 insertions(+), 99 deletions(-) (limited to 'qmake') diff --git a/qmake/library/qmakebuiltins.cpp b/qmake/library/qmakebuiltins.cpp index 0a83b9b930..c1d446263e 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 3e613038a3..7112b57c11 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 7318664d46..1f0255e55a 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 62e8875c5e..37608c7a15 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 a29e9c227d..3ae30dcf74 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 c40f49c4ad..16e21395ba 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 5e6a2f88e2..3b69b60bee 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 e8509ad096..e6bdb04bfb 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; -- cgit v1.2.3 From 85ae0f1f3e369e1d28af7b2ec963f63e177ecd11 Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Wed, 30 Nov 2016 18:26:44 +0100 Subject: 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(-) (limited to 'qmake') diff --git a/qmake/library/qmakevfs.cpp b/qmake/library/qmakevfs.cpp index 16e21395ba..2239a2beec 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 3b69b60bee..1217225471 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) -- cgit v1.2.3 From 13ab4c563dc33abc879d8f2a628b8a525e00e55a Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 24 Jan 2017 13:33:14 +0100 Subject: 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(-) (limited to 'qmake') diff --git a/qmake/library/qmakeglobals.cpp b/qmake/library/qmakeglobals.cpp index d733d479cf..cab04fc239 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 000f685b73..cf71a5afda 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); } -- cgit v1.2.3 From 0158b185091db424516fb4de57b909a6e7e815b2 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 23 Jan 2017 15:58:55 +0100 Subject: 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(-) (limited to 'qmake') diff --git a/qmake/library/qmakeglobals.cpp b/qmake/library/qmakeglobals.cpp index cab04fc239..452b44c045 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 cf71a5afda..6c00b1f3af 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 -- cgit v1.2.3 From 04b93bfb2127a88f35d2b251e900163f982e7cfe Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 6 Mar 2018 19:07:11 +0100 Subject: 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(-) (limited to 'qmake') diff --git a/qmake/library/ioutils.cpp b/qmake/library/ioutils.cpp index 4aa3282e3b..fd84dff59d 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 ad379404f3..32bf675f62 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 }; -- cgit v1.2.3 From 0ee5cbb1a449e05270454dfb6151438b04a5cb84 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Mon, 19 Feb 2018 12:18:57 +0100 Subject: Set WindowsTargetPlatform[Min]Version if WindowsSDKVersion is set This fixes qmake-generated project files for Visual Studio 2017 for setups where the Windows 8.1 SDK is not installed. Task-number: QTBUG-66265 Change-Id: I67712019f7142e40262f171eb23f9f1e6ab3a251 Reviewed-by: Oswald Buddenhagen Reviewed-by: Miguel Costa Reviewed-by: Joerg Bornemann --- qmake/generators/win32/msbuild_objectmodel.cpp | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) (limited to 'qmake') diff --git a/qmake/generators/win32/msbuild_objectmodel.cpp b/qmake/generators/win32/msbuild_objectmodel.cpp index 38bf3a0cbd..9f82ce4f8e 100644 --- a/qmake/generators/win32/msbuild_objectmodel.cpp +++ b/qmake/generators/win32/msbuild_objectmodel.cpp @@ -34,6 +34,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -618,17 +619,30 @@ void VCXProjectWriter::write(XmlOutput &xml, VCProject &tool) << tagValue("RootNamespace", tool.Name) << tagValue("Keyword", tool.Keyword); + QString windowsTargetPlatformVersion; if (isWinRT) { xml << tagValue("MinimumVisualStudioVersion", tool.Version) << tagValue("DefaultLanguage", "en") << tagValue("AppContainerApplication", "true") << tagValue("ApplicationType", "Windows Store") << tagValue("ApplicationTypeRevision", tool.SdkVersion); - if (tool.SdkVersion == "10.0") { - const QString ucrtVersion = qgetenv("UCRTVERSION"); - xml << tagValue("WindowsTargetPlatformVersion", ucrtVersion) - << tagValue("WindowsTargetPlatformMinVersion", ucrtVersion); - } + if (tool.SdkVersion == "10.0") + windowsTargetPlatformVersion = qgetenv("UCRTVERSION"); + } else { + QByteArray winSDKVersionStr = qgetenv("WindowsSDKVersion").trimmed(); + + // This environment variable might end with a backslash due to a VS bug. + if (winSDKVersionStr.endsWith('\\')) + winSDKVersionStr.chop(1); + + QVersionNumber winSDKVersion = QVersionNumber::fromString( + QString::fromLocal8Bit(winSDKVersionStr)); + if (!winSDKVersion.isNull()) + windowsTargetPlatformVersion = winSDKVersionStr; + } + if (!windowsTargetPlatformVersion.isEmpty()) { + xml << tagValue("WindowsTargetPlatformVersion", windowsTargetPlatformVersion) + << tagValue("WindowsTargetPlatformMinVersion", windowsTargetPlatformVersion); } xml << closetag(); -- cgit v1.2.3 From 1a71fe0306d8d8984d62d83e2cd616b9bac7e2fe Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 12 Apr 2018 15:20:15 +0200 Subject: qmake: fix QMAKE_BUNDLE_DATA for (some) generated files the source file must not be written with an absolute path to the makefile, as this won't match the name of the target which generates it, thus leading to an unsatisfied dependency. this is the proper fix for QTBUG-60413 and a bunch of others. amends historical f173e217cd. Change-Id: I28140351c4b4759de35e60daf63bc54b82d104ec Reviewed-by: Alexandru Croitor --- qmake/generators/unix/unixmake2.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'qmake') diff --git a/qmake/generators/unix/unixmake2.cpp b/qmake/generators/unix/unixmake2.cpp index 8ecfa0bf31..5468285c2e 100644 --- a/qmake/generators/unix/unixmake2.cpp +++ b/qmake/generators/unix/unixmake2.cpp @@ -943,7 +943,9 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) QString fn = files.at(file).toQString(); QString src = fileFixify(fn, FileFixifyAbsolute); if (!QFile::exists(src)) - src = fn; + src = fileFixify(fn, FileFixifyFromOutdir); + else + src = fileFixify(fn); QString dst = path + Option::dir_sep + fileInfo(fn).fileName(); bundledFiles << dst; alldeps << dst; -- cgit v1.2.3