diff --git a/src/shared/proparser/proitems.cpp b/src/shared/proparser/proitems.cpp index be708b0961e..0c0473ddc76 100644 --- a/src/shared/proparser/proitems.cpp +++ b/src/shared/proparser/proitems.cpp @@ -359,7 +359,8 @@ QStringList ProStringList::toQStringList() const ProFile::ProFile(const QString &fileName) : m_refCount(1), m_fileName(fileName), - m_ok(true) + m_ok(true), + m_hostBuild(false) { if (!fileName.startsWith(QLatin1Char('('))) m_directoryName = QFileInfo( // qmake sickness: canonicalize only the directory! diff --git a/src/shared/proparser/proitems.h b/src/shared/proparser/proitems.h index af709094500..b5a84f77e04 100644 --- a/src/shared/proparser/proitems.h +++ b/src/shared/proparser/proitems.h @@ -213,12 +213,16 @@ public: bool isOk() const { return m_ok; } void setOk(bool ok) { m_ok = ok; } + bool isHostBuild() const { return m_hostBuild; } + void setHostBuild(bool host_build) { m_hostBuild = host_build; } + private: ProItemRefCount m_refCount; QString m_proitems; QString m_fileName; QString m_directoryName; bool m_ok; + bool m_hostBuild; }; class ProFunctionDef { diff --git a/src/shared/proparser/qmakeevaluator.cpp b/src/shared/proparser/qmakeevaluator.cpp index 334f504b70c..4fde61fd3b8 100644 --- a/src/shared/proparser/qmakeevaluator.cpp +++ b/src/shared/proparser/qmakeevaluator.cpp @@ -69,6 +69,21 @@ using namespace ProStringConstants; #define fL1S(s) QString::fromLatin1(s) +QMakeBaseKey::QMakeBaseKey(const QString &_root, bool _hostBuild) + : root(_root), hostBuild(_hostBuild) +{ +} + +uint qHash(const QMakeBaseKey &key) +{ + return qHash(key.root) ^ key.hostBuild; +} + +bool operator==(const QMakeBaseKey &one, const QMakeBaseKey &two) +{ + return one.root == two.root && one.hostBuild == two.hostBuild; +} + QMakeBaseEnv::QMakeBaseEnv() : evaluator(0) { @@ -100,6 +115,7 @@ void QMakeEvaluator::initStatics() statics.strDotDot = QLatin1String(".."); statics.strever = QLatin1String("ever"); statics.strforever = QLatin1String("forever"); + statics.strhost_build = QLatin1String("host_build"); statics.strTEMPLATE = ProString("TEMPLATE"); statics.fakeValue = ProStringList(ProString("_FAKE_")); // It has to have a unique begin() value @@ -157,6 +173,7 @@ QMakeEvaluator::QMakeEvaluator(QMakeGlobals *option, #ifdef PROEVALUATOR_CUMULATIVE m_cumulative = false; #endif + m_hostBuild = false; // Evaluator state m_skipLevel = 0; @@ -1030,7 +1047,8 @@ bool QMakeEvaluator::loadSpec() { loadDefaults(); - QString qmakespec = m_option->expandEnvVars(m_option->qmakespec); + QString qmakespec = m_option->expandEnvVars( + m_hostBuild ? m_option->qmakespec : m_option->xqmakespec); { QMakeEvaluator evaluator(m_option, m_parser, m_handler); @@ -1049,14 +1067,18 @@ bool QMakeEvaluator::loadSpec() if (!evaluator.evaluateFileDirect(m_cachefile, QMakeHandler::EvalConfigFile, LoadProOnly)) return false; } - if (qmakespec.isEmpty()) - qmakespec = evaluator.first(ProString("QMAKESPEC")).toQString(); + if (qmakespec.isEmpty()) { + if (!m_hostBuild) + qmakespec = evaluator.first(ProString("XQMAKESPEC")).toQString(); + if (qmakespec.isEmpty()) + qmakespec = evaluator.first(ProString("QMAKESPEC")).toQString(); + } m_qmakepath = evaluator.values(ProString("QMAKEPATH")).toQStringList(); m_qmakefeatures = evaluator.values(ProString("QMAKEFEATURES")).toQStringList(); } if (qmakespec.isEmpty()) - qmakespec = QLatin1String("default"); + qmakespec = m_hostBuild ? QLatin1String("default-host") : QLatin1String("default"); if (IoUtils::isRelativePath(qmakespec)) { foreach (const QString &root, qmakeMkspecPaths()) { QString mkspec = root + QLatin1Char('/') + qmakespec; @@ -1140,10 +1162,12 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProFile( if (!prepareProject(pro->directoryName())) return ReturnFalse; + m_hostBuild = pro->isHostBuild(); + #ifdef PROEVALUATOR_THREAD_SAFE m_option->mutex.lock(); #endif - QMakeBaseEnv **baseEnvPtr = &m_option->baseEnvs[QMakeBaseKey(m_buildRoot)]; + QMakeBaseEnv **baseEnvPtr = &m_option->baseEnvs[QMakeBaseKey(m_buildRoot, m_hostBuild)]; if (!*baseEnvPtr) *baseEnvPtr = new QMakeBaseEnv; QMakeBaseEnv *baseEnv = *baseEnvPtr; @@ -1173,6 +1197,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProFile( baseEval->m_cachefile = m_cachefile; baseEval->m_sourceRoot = m_sourceRoot; baseEval->m_buildRoot = m_buildRoot; + baseEval->m_hostBuild = m_hostBuild; bool ok = baseEval->loadSpec(); #ifdef PROEVALUATOR_THREAD_SAFE @@ -1637,6 +1662,9 @@ bool QMakeEvaluator::isActiveConfig(const QString &config, bool regex) if (config == statics.strfalse) return false; + if (config == statics.strhost_build) + return m_hostBuild; + if (regex && (config.contains(QLatin1Char('*')) || config.contains(QLatin1Char('?')))) { QString cfg = config; cfg.detach(); // Keep m_tmp out of QRegExp's cache diff --git a/src/shared/proparser/qmakeevaluator.h b/src/shared/proparser/qmakeevaluator.h index 69b85b38a3d..149ce806222 100644 --- a/src/shared/proparser/qmakeevaluator.h +++ b/src/shared/proparser/qmakeevaluator.h @@ -208,6 +208,7 @@ public: QString m_outputDir; int m_listCount; + bool m_hostBuild; QString m_qmakespec; QString m_qmakespecFull; QString m_qmakespecName; diff --git a/src/shared/proparser/qmakeevaluator_p.h b/src/shared/proparser/qmakeevaluator_p.h index e054f1fb02e..ea958ace4c6 100644 --- a/src/shared/proparser/qmakeevaluator_p.h +++ b/src/shared/proparser/qmakeevaluator_p.h @@ -49,6 +49,7 @@ struct QMakeStatics { QString strDotDot; QString strever; QString strforever; + QString strhost_build; ProString strTEMPLATE; QHash expands; QHash functions; diff --git a/src/shared/proparser/qmakeglobals.h b/src/shared/proparser/qmakeglobals.h index 9df259d6063..8ca220aac4e 100644 --- a/src/shared/proparser/qmakeglobals.h +++ b/src/shared/proparser/qmakeglobals.h @@ -48,7 +48,17 @@ QT_BEGIN_NAMESPACE class QMakeEvaluator; -typedef QString QMakeBaseKey; +class QMakeBaseKey +{ +public: + QMakeBaseKey(const QString &_root, bool _hostBuild); + + QString root; + bool hostBuild; +}; + +uint qHash(const QMakeBaseKey &key); +bool operator==(const QMakeBaseKey &one, const QMakeBaseKey &two); class QMakeBaseEnv { @@ -77,6 +87,7 @@ public: QString dir_sep; QString dirlist_sep; QString qmakespec; + QString xqmakespec; QString cachefile; #ifndef QT_BOOTSTRAPPED QProcessEnvironment environment; diff --git a/src/shared/proparser/qmakeparser.cpp b/src/shared/proparser/qmakeparser.cpp index 800969a53ee..49873b10198 100644 --- a/src/shared/proparser/qmakeparser.cpp +++ b/src/shared/proparser/qmakeparser.cpp @@ -96,6 +96,8 @@ static struct { QString strfor; QString strdefineTest; QString strdefineReplace; + QString stroption; + QString strhost_build; QString strLINE; QString strFILE; QString strLITERAL_HASH; @@ -114,6 +116,8 @@ void QMakeParser::initialize() statics.strfor = QLatin1String("for"); statics.strdefineTest = QLatin1String("defineTest"); statics.strdefineReplace = QLatin1String("defineReplace"); + statics.stroption = QLatin1String("option"); + statics.strhost_build = QLatin1String("host_build"); statics.strLINE = QLatin1String("_LINE_"); statics.strFILE = QLatin1String("_FILE_"); statics.strLITERAL_HASH = QLatin1String("LITERAL_HASH"); @@ -1037,6 +1041,26 @@ void QMakeParser::finalizeCall(ushort *&tokPtr, ushort *uc, ushort *ptr, int arg } parseError(fL1S("%1(function) requires one literal argument.").arg(*defName)); return; + } else if (m_tmp == statics.stroption) { + if (m_state != StNew || m_blockstack.top().braceLevel || m_blockstack.size() > 1 + || m_invert || m_operator != NoOperator) { + parseError(fL1S("option() must appear outside any control structures.")); + return; + } + if (*uce == (TokLiteral|TokNewStr)) { + uint nlen = uce[1]; + if (uce[nlen + 2] == TokFuncTerminator) { + m_tmp.setRawData((QChar *)uce + 2, nlen); + if (m_tmp == statics.strhost_build) { + m_proFile->setHostBuild(true); + } else { + parseError(fL1S("Unknown option() %1.").arg(m_tmp)); + } + return; + } + } + parseError(fL1S("option() requires one literal argument.")); + return; } } }