qmakeglobals.cpp 12.09 KiB
/****************************************************************************
**
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the Qt Linguist of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
** $QT_END_LICENSE$
****************************************************************************/
#include "qmakeglobals.h"
#include "qmakeevaluator.h"
#include "ioutils.h"
#include <qbytearray.h>
#include <qdatetime.h>
#include <qdebug.h>
#include <qdir.h>
#include <qfile.h>
#include <qfileinfo.h>
#include <qlist.h>
#include <qregexp.h>
#include <qset.h>
#include <qstack.h>
#include <qstring.h>
#include <qstringlist.h>
#include <qtextstream.h>
#ifdef PROEVALUATOR_THREAD_SAFE
# include <qthreadpool.h>
#endif
#ifdef Q_OS_UNIX
#include <unistd.h>
#include <sys/utsname.h>
#else
#include <windows.h>
#endif
#include <stdio.h>
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
#include <stdlib.h> #ifdef Q_OS_WIN32 #define QT_POPEN _popen #define QT_PCLOSE _pclose #else #define QT_POPEN popen #define QT_PCLOSE pclose #endif QT_BEGIN_NAMESPACE #define fL1S(s) QString::fromLatin1(s) namespace { // MSVC doesn't seem to know the semantics of "static" ... static struct { QRegExp reg_variableName; } statics; } static void initStatics() { if (!statics.reg_variableName.isEmpty()) return; statics.reg_variableName.setPattern(QLatin1String("\\$\\(.*\\)")); statics.reg_variableName.setMinimal(true); } QMakeGlobals::QMakeGlobals() { initStatics(); do_cache = true; #ifdef PROEVALUATOR_DEBUG debugLevel = 0; #endif #ifdef Q_OS_WIN dirlist_sep = QLatin1Char(';'); dir_sep = QLatin1Char('\\'); #else dirlist_sep = QLatin1Char(':'); dir_sep = QLatin1Char('/'); #endif qmakespec = getEnv(QLatin1String("QMAKESPEC")); } QMakeGlobals::~QMakeGlobals() { qDeleteAll(baseEnvs); } QString QMakeGlobals::cleanSpec(QMakeCmdLineParserState &state, const QString &spec) { QString ret = QDir::cleanPath(spec); if (ret.contains(QLatin1Char('/'))) { QString absRet = QDir(state.pwd).absoluteFilePath(ret); if (QFile::exists(absRet)) ret = QDir::cleanPath(absRet); } return ret; } QMakeGlobals::ArgumentReturn QMakeGlobals::addCommandLineArguments( QMakeCmdLineParserState &state, QStringList &args, int *pos) { enum { ArgNone, ArgConfig, ArgSpec, ArgXSpec, ArgTmpl, ArgTmplPfx, ArgCache } argState = ArgNone;
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
for (; *pos < args.count(); (*pos)++) { QString arg = args.at(*pos); switch (argState) { case ArgConfig: if (state.after) state.postconfigs << arg; else state.preconfigs << arg; break; case ArgSpec: qmakespec = args[*pos] = cleanSpec(state, arg); break; case ArgXSpec: xqmakespec = args[*pos] = cleanSpec(state, arg); break; case ArgTmpl: user_template = arg; break; case ArgTmplPfx: user_template_prefix = arg; break; case ArgCache: cachefile = args[*pos] = QDir::cleanPath(QDir(state.pwd).absoluteFilePath(arg)); break; default: if (arg.startsWith(QLatin1Char('-'))) { if (arg == QLatin1String("-after")) { state.after = true; } else if (arg == QLatin1String("-config")) { argState = ArgConfig; } else if (arg == QLatin1String("-nocache")) { do_cache = false; } else if (arg == QLatin1String("-cache")) { argState = ArgCache; } else if (arg == QLatin1String("-platform") || arg == QLatin1String("-spec")) { argState = ArgSpec; } else if (arg == QLatin1String("-xplatform") || arg == QLatin1String("-xspec")) { argState = ArgXSpec; } else if (arg == QLatin1String("-template") || arg == QLatin1String("-t")) { argState = ArgTmpl; } else if (arg == QLatin1String("-template_prefix") || arg == QLatin1String("-tp")) { argState = ArgTmplPfx; } else if (arg == QLatin1String("-win32")) { dir_sep = QLatin1Char('\\'); } else if (arg == QLatin1String("-unix")) { dir_sep = QLatin1Char('/'); } else { return ArgumentUnknown; } } else if (arg.contains(QLatin1Char('='))) { if (state.after) state.postcmds << arg; else state.precmds << arg; } else { return ArgumentUnknown; } continue; } argState = ArgNone; } if (argState != ArgNone) return ArgumentMalformed; return ArgumentsOk; } void QMakeGlobals::commitCommandLineArguments(QMakeCmdLineParserState &state) { if (!state.preconfigs.isEmpty()) state.precmds << (fL1S("CONFIG += ") + state.preconfigs.join(fL1S(" ")));
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
precmds = state.precmds.join(fL1S("\n")); if (!state.postconfigs.isEmpty()) state.postcmds << (fL1S("CONFIG += ") + state.postconfigs.join(fL1S(" "))); postcmds = state.postcmds.join(fL1S("\n")); if (xqmakespec.isEmpty()) xqmakespec = qmakespec; } void QMakeGlobals::useEnvironment() { if (xqmakespec.isEmpty()) xqmakespec = getEnv(QLatin1String("XQMAKESPEC")); if (qmakespec.isEmpty()) { qmakespec = getEnv(QLatin1String("QMAKESPEC")); if (xqmakespec.isEmpty()) xqmakespec = qmakespec; } } void QMakeGlobals::setCommandLineArguments(const QString &pwd, const QStringList &_args) { QStringList args = _args; QMakeCmdLineParserState state(pwd); for (int pos = 0; pos < args.size(); pos++) addCommandLineArguments(state, args, &pos); commitCommandLineArguments(state); useEnvironment(); } void QMakeGlobals::setDirectories(const QString &input_dir, const QString &output_dir) { if (input_dir != output_dir && !output_dir.isEmpty()) { QString srcpath = input_dir; if (!srcpath.endsWith(QLatin1Char('/'))) srcpath += QLatin1Char('/'); QString dstpath = output_dir; if (!dstpath.endsWith(QLatin1Char('/'))) dstpath += QLatin1Char('/'); int srcLen = srcpath.length(); int dstLen = dstpath.length(); int lastSl = -1; while (++lastSl, srcpath.at(--srcLen) == dstpath.at(--dstLen)) if (srcpath.at(srcLen) == QLatin1Char('/')) lastSl = 0; source_root = srcpath.left(srcLen + lastSl); build_root = dstpath.left(dstLen + lastSl); } } QString QMakeGlobals::shadowedPath(const QString &fileName) const { if (source_root.isEmpty()) return fileName; if (fileName.startsWith(source_root) && (fileName.length() == source_root.length() || fileName.at(source_root.length()) == QLatin1Char('/'))) { return build_root + fileName.mid(source_root.length()); } return QString(); } QString QMakeGlobals::getEnv(const QString &var) const { #ifdef PROEVALUATOR_SETENV return environment.value(var); #else return QString::fromLocal8Bit(qgetenv(var.toLocal8Bit().constData())); #endif
281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
} QStringList QMakeGlobals::getPathListEnv(const QString &var) const { QStringList ret; QString val = getEnv(var); if (!val.isEmpty()) { QDir bdir; QStringList vals = val.split(dirlist_sep); ret.reserve(vals.length()); foreach (const QString &it, vals) ret << QDir::cleanPath(bdir.absoluteFilePath(it)); } return ret; } QString QMakeGlobals::expandEnvVars(const QString &str) const { QString string = str; int rep; QRegExp reg_variableName = statics.reg_variableName; // Copy for thread safety while ((rep = reg_variableName.indexIn(string)) != -1) string.replace(rep, reg_variableName.matchedLength(), getEnv(string.mid(rep + 2, reg_variableName.matchedLength() - 3))); return string; } #ifndef QT_BUILD_QMAKE #ifdef PROEVALUATOR_INIT_PROPS bool QMakeGlobals::initProperties() { QByteArray data; #ifndef QT_BOOTSTRAPPED QProcess proc; proc.start(qmake_abslocation, QStringList() << QLatin1String("-query")); if (!proc.waitForFinished()) return false; data = proc.readAll(); #else if (FILE *proc = QT_POPEN(QString(IoUtils::shellQuote(qmake_abslocation) + QLatin1String(" -query")) .toLocal8Bit(), "r")) { char buff[1024]; while (!feof(proc)) data.append(buff, int(fread(buff, 1, 1023, proc))); QT_PCLOSE(proc); } #endif foreach (QByteArray line, data.split('\n')) if (!line.startsWith("QMAKE_")) { int off = line.indexOf(':'); if (off < 0) // huh? continue; if (line.endsWith('\r')) line.chop(1); QString name = QString::fromLatin1(line.left(off)); ProString value = ProString(QDir::fromNativeSeparators( QString::fromLocal8Bit(line.mid(off + 1)))); properties.insert(ProKey(name), value); if (name.startsWith(QLatin1String("QT_")) && !name.contains(QLatin1Char('/'))) { if (name.startsWith(QLatin1String("QT_INSTALL_"))) { properties.insert(ProKey(name + QLatin1String("/raw")), value); properties.insert(ProKey(name + QLatin1String("/get")), value); if (name == QLatin1String("QT_INSTALL_PREFIX") || name == QLatin1String("QT_INSTALL_DATA") || name == QLatin1String("QT_INSTALL_BINS")) { name.replace(3, 7, QLatin1String("HOST")); properties.insert(ProKey(name), value); properties.insert(ProKey(name + QLatin1String("/get")), value); } } else if (name.startsWith(QLatin1String("QT_HOST_"))) {
351352353354355356357358359360361362363364365366367368369
properties.insert(ProKey(name + QLatin1String("/get")), value); } } } properties.insert(ProKey("QMAKE_VERSION"), ProString("2.01a")); return true; } #else void QMakeGlobals::setProperties(const QHash<QString, QString> &props) { QHash<QString, QString>::ConstIterator it = props.constBegin(), eit = props.constEnd(); for (; it != eit; ++it) properties.insert(ProKey(it.key()), ProString(it.value())); } #endif #endif // QT_BUILD_QMAKE QT_END_NAMESPACE