diff options
Diffstat (limited to 'qmake/library/qmakebuiltins.cpp')
-rw-r--r-- | qmake/library/qmakebuiltins.cpp | 91 |
1 files changed, 48 insertions, 43 deletions
diff --git a/qmake/library/qmakebuiltins.cpp b/qmake/library/qmakebuiltins.cpp index be0d8ea172..a2ebe1e410 100644 --- a/qmake/library/qmakebuiltins.cpp +++ b/qmake/library/qmakebuiltins.cpp @@ -44,6 +44,7 @@ #include "qmakeevaluator_p.h" #include "qmakeglobals.h" #include "qmakeparser.h" +#include "qmakevfs.h" #include "ioutils.h" #include <qbytearray.h> @@ -55,6 +56,9 @@ #include <qset.h> #include <qstringlist.h> #include <qtextstream.h> +#ifdef PROEVALUATOR_THREAD_SAFE +# include <qthreadpool.h> +#endif #ifdef Q_OS_UNIX #include <time.h> @@ -281,46 +285,17 @@ quoteValue(const ProString &val) return ret; } -static bool -doWriteFile(const QString &name, QIODevice::OpenMode mode, const QString &contents, QString *errStr) -{ - QByteArray bytes = contents.toLocal8Bit(); - QFile cfile(name); - if (!(mode & QIODevice::Append) && cfile.open(QIODevice::ReadOnly | QIODevice::Text)) { - if (cfile.readAll() == bytes) - return true; - cfile.close(); - } - if (!cfile.open(mode | QIODevice::WriteOnly | QIODevice::Text)) { - *errStr = cfile.errorString(); - return false; - } - cfile.write(bytes); - cfile.close(); - if (cfile.error() != QFile::NoError) { - *errStr = cfile.errorString(); - return false; - } - return true; -} - QMakeEvaluator::VisitReturn QMakeEvaluator::writeFile(const QString &ctx, const QString &fn, QIODevice::OpenMode mode, const QString &contents) { - QFileInfo qfi(fn); - if (!QDir::current().mkpath(qfi.path())) { - evalError(fL1S("Cannot create %1directory %2.") - .arg(ctx, QDir::toNativeSeparators(qfi.path()))); - return ReturnFalse; - } QString errStr; - if (!doWriteFile(qfi.filePath(), mode, contents, &errStr)) { + if (!m_vfs->writeFile(fn, mode, contents, &errStr)) { evalError(fL1S("Cannot write %1file %2: %3.") - .arg(ctx, QDir::toNativeSeparators(qfi.filePath()), errStr)); + .arg(ctx, QDir::toNativeSeparators(fn), errStr)); return ReturnFalse; } - m_parser->discardFileFromCache(qfi.filePath()); + m_parser->discardFileFromCache(fn); return ReturnTrue; } @@ -1118,11 +1093,11 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( } } return ReturnFalse; -#ifdef PROEVALUATOR_FULL case T_REQUIRES: +#ifdef PROEVALUATOR_FULL checkRequirements(args); - return ReturnFalse; // Another qmake breakage #endif + return ReturnFalse; // Another qmake breakage case T_EVAL: { VisitReturn ret = ReturnFalse; ProFile *pro = m_parser->parsedProBlock(args.join(statics.field_sep), @@ -1389,14 +1364,14 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( } return (func_t == T_ERROR && !m_cumulative) ? ReturnError : ReturnTrue; } -#ifdef PROEVALUATOR_FULL case T_SYSTEM: { - if (m_cumulative) // Anything else would be insanity - return ReturnFalse; if (args.count() != 1) { evalError(fL1S("system(exec) requires one argument.")); return ReturnFalse; } +#ifdef PROEVALUATOR_FULL + if (m_cumulative) // Anything else would be insanity + return ReturnFalse; #ifndef QT_BOOTSTRAPPED QProcess proc; proc.setProcessChannelMode(QProcess::ForwardedChannels); @@ -1407,8 +1382,10 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( + IoUtils::shellQuote(QDir::toNativeSeparators(currentDirectory())) + QLatin1String(" && ") + args.at(0)).toLocal8Bit().constData()) == 0); #endif - } +#else + return ReturnTrue; #endif + } case T_ISEMPTY: { if (args.count() != 1) { evalError(fL1S("isEmpty(var) requires one argument.")); @@ -1423,6 +1400,9 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( } const QString &file = resolvePath(m_option->expandEnvVars(args.at(0).toQString(m_tmp1))); + // Don't use VFS here: + // - it supports neither listing nor even directories + // - it's unlikely that somebody would test for files they created themselves if (IoUtils::exists(file)) return ReturnTrue; int slsh = file.lastIndexOf(QLatin1Char('/')); @@ -1435,17 +1415,18 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( return ReturnFalse; } -#ifdef PROEVALUATOR_FULL case T_MKPATH: { if (args.count() != 1) { evalError(fL1S("mkpath(file) requires one argument.")); return ReturnFalse; } +#ifdef PROEVALUATOR_FULL const QString &fn = resolvePath(args.at(0).toQString(m_tmp1)); if (!QDir::current().mkpath(fn)) { evalError(fL1S("Cannot create directory %1.").arg(QDir::toNativeSeparators(fn))); return ReturnFalse; } +#endif return ReturnTrue; } case T_WRITE_FILE: { @@ -1470,6 +1451,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( evalError(fL1S("touch(file, reffile) requires two arguments.")); return ReturnFalse; } +#ifdef PROEVALUATOR_FULL const QString &tfn = resolvePath(args.at(0).toQString(m_tmp1)); const QString &rfn = resolvePath(args.at(1).toQString(m_tmp2)); #ifdef Q_OS_UNIX @@ -1506,6 +1488,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( SetFileTime(wHand, 0, 0, &ft); CloseHandle(wHand); #endif +#endif return ReturnTrue; } case T_CACHE: { @@ -1558,8 +1541,31 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( ProStringList newval; bool changed = false; for (bool hostBuild = false; ; hostBuild = true) { - if (QMakeBaseEnv *baseEnv = m_option->baseEnvs.value( - QMakeBaseKey(m_buildRoot, hostBuild))) { +#ifdef PROEVALUATOR_THREAD_SAFE + m_option->mutex.lock(); +#endif + QMakeBaseEnv *baseEnv = + m_option->baseEnvs.value(QMakeBaseKey(m_buildRoot, hostBuild)); +#ifdef PROEVALUATOR_THREAD_SAFE + // It's ok to unlock this before locking baseEnv, + // as we have no intention to initialize the env. + m_option->mutex.unlock(); +#endif + do { + if (!baseEnv) + break; +#ifdef PROEVALUATOR_THREAD_SAFE + QMutexLocker locker(&baseEnv->mutex); + if (baseEnv->inProgress && baseEnv->evaluator != this) { + // The env is still in the works, but it may be already past the cache + // loading. So we need to wait for completion and amend it as usual. + QThreadPool::globalInstance()->releaseThread(); + baseEnv->cond.wait(&baseEnv->mutex); + QThreadPool::globalInstance()->reserveThread(); + } + if (!baseEnv->isOk) + break; +#endif QMakeEvaluator *baseEval = baseEnv->evaluator; const ProStringList &oldval = baseEval->values(dstvar); if (mode == CacheSet) { @@ -1590,7 +1596,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( } changed = true; } - } + } while (false); if (hostBuild) break; } @@ -1639,7 +1645,6 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( } return writeFile(fL1S("cache "), fn, QIODevice::Append, varstr); } -#endif default: evalError(fL1S("Function '%1' is not implemented.").arg(function.toQString(m_tmp1))); return ReturnFalse; |