port qmake to qt creator's qmake language evaluator
this is a monster commit which does the following things: - import the evaluator as-is from qt creator into qmake/library/ - integrate it into qmake's makefiles - overwrite proitems.h with actual special types - remove the parts of Option which are redundant with QMakeGlobals - make QMakeProperty a singleton owned by Option::globals. the dynamic handling so far made no sense. - make QMakeProject a subclass of QMakeEvaluator, with relatively few extensions the changes to existing qmake code outside project.* and option.* are minor. implementing the changes gradually would mean changing a lot of code which will be just replaced in the next commit, so i'm not wasting my time on it. Change-Id: I9746650423b8c5b3fbd8c3979a73228982a46195 Reviewed-by: Qt Doc Bot <qt_docbot@qt-project.org> Reviewed-by: Joerg Bornemann <joerg.bornemann@nokia.com>
This commit is contained in:
parent
ed7594db5d
commit
0e78e50802
@ -11,8 +11,10 @@ QMKLIBSRC = $(QMKSRC)/library
|
||||
QMKGENSRC = $(QMKSRC)/generators
|
||||
|
||||
#qmake code
|
||||
OBJS=project.o property.o main.o makefile.o unixmake2.o unixmake.o \
|
||||
mingw_make.o option.o winmakefile.o projectgenerator.o \
|
||||
OBJS=project.o option.o property.o main.o ioutils.o proitems.o \
|
||||
qmakeglobals.o qmakeparser.o qmakeevaluator.o qmakebuiltins.o \
|
||||
makefile.o unixmake2.o unixmake.o \
|
||||
mingw_make.o winmakefile.o projectgenerator.o \
|
||||
meta.o makefiledeps.o metamakefile.o xmloutput.o pbuilder_pbx.o \
|
||||
msvc_vcproj.o msvc_vcxproj.o msvc_nmake.o msvc_objectmodel.o msbuild_objectmodel.o \
|
||||
gbuild.o cesdkhandler.o
|
||||
@ -36,6 +38,8 @@ QOBJS=qtextcodec.o qutfcodec.o qstring.o qstringbuilder.o qtextstream.o qiodevic
|
||||
DEPEND_SRC = \
|
||||
$(QMKSRC)/main.cpp $(QMKSRC)/project.cpp $(QMKSRC)/option.cpp $(QMKSRC)/property.cpp \
|
||||
$(QMKSRC)/meta.cpp \
|
||||
$(QMKLIBSRC)/ioutils.cpp $(QMKLIBSRC)/proitems.cpp $(QMKLIBSRC)/qmakeglobals.cpp \
|
||||
$(QMKLIBSRC)/qmakeparser.cpp $(QMKLIBSRC)/qmakeevaluator.cpp $(QMKLIBSRC)/qmakebuiltins.cpp \
|
||||
$(QMKGENSRC)/makefiledeps.cpp $(QMKGENSRC)/metamakefile.cpp \
|
||||
$(QMKGENSRC)/projectgenerator.cpp $(QMKGENSRC)/makefile.cpp \
|
||||
$(QMKGENSRC)/unix/unixmake.cpp $(QMKGENSRC)/unix/unixmake2.cpp \
|
||||
@ -90,7 +94,7 @@ CPPFLAGS = -g $(OPENSOURCE_CXXFLAGS) \
|
||||
-I$(BUILD_PATH)/src/corelib/global -DHAVE_QCONFIG_CPP \
|
||||
-I$(QMAKESPEC) \
|
||||
-I$(SOURCE_PATH)/tools/shared \
|
||||
-DQT_BUILD_QMAKE -DQT_BOOTSTRAPPED \
|
||||
-DQT_BUILD_QMAKE -DQT_BOOTSTRAPPED -DPROEVALUATOR_FULL -DPROEVALUATOR_DEBUG \
|
||||
-DQT_NO_TEXTCODEC -DQT_NO_UNICODETABLES -DQT_NO_COMPONENT -DQT_NO_COMPRESS \
|
||||
-DQT_NO_THREAD -DQT_NO_QOBJECT -DQT_NO_GEOM_VARIANT -DQT_NO_DATASTREAM
|
||||
|
||||
@ -112,6 +116,24 @@ depend:
|
||||
makedepend -D__MAKEDEPEND__ $(CPPFLAGS) $(DEPEND_SRC)
|
||||
|
||||
|
||||
ioutils.o: $(QMKLIBSRC)/ioutils.cpp
|
||||
$(CXX) -c -o $@ $(CXXFLAGS) $<
|
||||
|
||||
proitems.o: $(QMKLIBSRC)/proitems.cpp
|
||||
$(CXX) -c -o $@ $(CXXFLAGS) $<
|
||||
|
||||
qmakeglobals.o: $(QMKLIBSRC)/qmakeglobals.cpp
|
||||
$(CXX) -c -o $@ $(CXXFLAGS) $<
|
||||
|
||||
qmakeparser.o: $(QMKLIBSRC)/qmakeparser.cpp
|
||||
$(CXX) -c -o $@ $(CXXFLAGS) $<
|
||||
|
||||
qmakeevaluator.o: $(QMKLIBSRC)/qmakeevaluator.cpp
|
||||
$(CXX) -c -o $@ $(CXXFLAGS) $<
|
||||
|
||||
qmakebuiltins.o: $(QMKLIBSRC)/qmakebuiltins.cpp
|
||||
$(CXX) -c -o $@ $(CXXFLAGS) $<
|
||||
|
||||
project.o: $(QMKSRC)/project.cpp
|
||||
$(CXX) -c -o $@ $(CXXFLAGS) $<
|
||||
|
||||
|
@ -38,7 +38,7 @@ CFLAGS_BARE = -c -Fo./ \
|
||||
-I$(BUILD_PATH)\src\corelib\global -DHAVE_QCONFIG_CPP \
|
||||
-I$(SOURCE_PATH)\mkspecs\$(QMAKESPEC) \
|
||||
-I$(SOURCE_PATH)\tools\shared \
|
||||
-DQT_BUILD_QMAKE -DQT_BOOTSTRAPPED \
|
||||
-DQT_BUILD_QMAKE -DQT_BOOTSTRAPPED -DPROEVALUATOR_FULL -DPROEVALUATOR_DEBUG \
|
||||
-DQT_NO_TEXTCODEC -DQT_NO_UNICODETABLES -DQT_NO_COMPONENT -DQT_NO_COMPRESS \
|
||||
-DQT_NO_THREAD -DQT_NO_QOBJECT -DQT_NO_GEOM_VARIANT -DQT_NO_DATASTREAM \
|
||||
-DUNICODE
|
||||
@ -57,7 +57,9 @@ ADDCLEAN = vc60.pdb vc70.pdb qmake.pdb qmake.ilk
|
||||
!ENDIF
|
||||
|
||||
#qmake code
|
||||
OBJS = project.obj main.obj makefile.obj unixmake.obj unixmake2.obj mingw_make.obj \
|
||||
OBJS = project.obj main.obj ioutils.obj proitems.obj \
|
||||
qmakeglobals.obj qmakeparser.obj qmakeevaluator.obj qmakebuiltins.obj \
|
||||
makefile.obj unixmake.obj unixmake2.obj mingw_make.obj \
|
||||
option.obj winmakefile.obj projectgenerator.obj property.obj meta.obj \
|
||||
makefiledeps.obj metamakefile.obj xmloutput.obj pbuilder_pbx.obj \
|
||||
msvc_nmake.obj msvc_vcproj.obj msvc_vcxproj.obj \
|
||||
@ -164,6 +166,9 @@ $(QTOBJS): qmake_pch.obj
|
||||
qmake_pch.obj:
|
||||
$(CXX) $(CXXFLAGS_BARE) -c -Yc -Fpqmake_pch.pch -TP $(QMKSRC)\qmake_pch.h
|
||||
|
||||
{$(SOURCE_PATH)\qmake\library}.cpp{}.obj::
|
||||
$(CXX) $(CXXFLAGS) $<
|
||||
|
||||
{$(SOURCE_PATH)\qmake\generators\mac}.cpp{}.obj::
|
||||
$(CXX) $(CXXFLAGS) $<
|
||||
|
||||
|
@ -49,7 +49,7 @@ CFLAGS = -c -o$@ -O \
|
||||
-I$(BUILD_PATH)/src/corelib/global -DHAVE_QCONFIG_CPP \
|
||||
-I$(SOURCE_PATH)/mkspecs/win32-g++ \
|
||||
-I$(SOURCE_PATH)/tools/shared \
|
||||
-DQT_BUILD_QMAKE -DQT_BOOTSTRAPPED \
|
||||
-DQT_BUILD_QMAKE -DQT_BOOTSTRAPPED -DPROEVALUATOR_FULL -DPROEVALUATOR_DEBUG \
|
||||
-DQT_NO_TEXTCODEC -DQT_NO_UNICODETABLES -DQT_NO_COMPONENT -DQT_NO_COMPRESS \
|
||||
-DQT_NO_THREAD -DQT_NO_QOBJECT -DQT_NO_GEOM_VARIANT -DQT_NO_DATASTREAM \
|
||||
-DUNICODE
|
||||
@ -61,7 +61,9 @@ ADDCLEAN =
|
||||
|
||||
|
||||
#qmake code
|
||||
OBJS = project.o main.o makefile.o unixmake.o unixmake2.o mingw_make.o \
|
||||
OBJS = project.o main.o ioutils.o proitems.o \
|
||||
qmakeglobals.o qmakeparser.o qmakeevaluator.o qmakebuiltins.o \
|
||||
makefile.o unixmake.o unixmake2.o mingw_make.o \
|
||||
option.o winmakefile.o projectgenerator.o property.o meta.o \
|
||||
makefiledeps.o metamakefile.o xmloutput.o pbuilder_pbx.o \
|
||||
msvc_nmake.o msvc_vcproj.o msvc_vcxproj.o \
|
||||
@ -149,7 +151,7 @@ distclean:: clean
|
||||
$(CXX) $(CXXFLAGS) $<
|
||||
|
||||
QTVPATH = $(TOOLSRC)/shared/windows:$(CORESRC)/global:$(CORESRC)/kernel:$(CORESRC)/tools:$(CORESRC)/codecs:$(CORESRC)/io:$(CORESRC)/xml:$(CORESRC)/plugin:$(BUILD_PATH)/src/corelib/global
|
||||
VPATH = $(QMKSRC):$(QMKSRC)/generators:$(QMKSRC)/generators/unix:$(QMKSRC)/generators/mac:$(QMKSRC)/generators/win32:$(QMKSRC)/generators/integrity:$(QTVPATH)
|
||||
VPATH = $(QMKSRC):$(QMKLIBSRC):$(QMKSRC)/generators:$(QMKSRC)/generators/unix:$(QMKSRC)/generators/mac:$(QMKSRC)/generators/win32:$(QMKSRC)/generators/integrity:$(QTVPATH)
|
||||
|
||||
project.o: $(QMKSRC)/project.h $(QMKSRC)/option.h
|
||||
meta.o: $(QMKSRC)/project.h $(QMKSRC)/option.h
|
||||
|
@ -194,7 +194,7 @@ MakefileGenerator::initOutPaths()
|
||||
ProValueMap &v = project->variables();
|
||||
//for shadow builds
|
||||
if(!v.contains("QMAKE_ABSOLUTE_SOURCE_PATH")) {
|
||||
if (Option::mkfile::do_cache && !project->cacheFile().isEmpty() &&
|
||||
if (Option::globals->do_cache && !project->cacheFile().isEmpty() &&
|
||||
v.contains("QMAKE_ABSOLUTE_SOURCE_ROOT")) {
|
||||
QString root = v["QMAKE_ABSOLUTE_SOURCE_ROOT"].first().toQString();
|
||||
root = QDir::fromNativeSeparators(root);
|
||||
@ -884,7 +884,7 @@ MakefileGenerator::init()
|
||||
|
||||
// escape qmake command
|
||||
project->values("QMAKE_QMAKE") =
|
||||
ProStringList(escapeFilePath(Option::fixPathToTargetOS(Option::qmake_abslocation, false)));
|
||||
ProStringList(escapeFilePath(Option::fixPathToTargetOS(Option::globals->qmake_abslocation, false)));
|
||||
}
|
||||
|
||||
bool
|
||||
@ -2682,7 +2682,7 @@ MakefileGenerator::writeMakeQmake(QTextStream &t, bool noDummyQmakeAll)
|
||||
if(!ofile.isEmpty() && !project->isActiveConfig("no_autoqmake")) {
|
||||
t << escapeFilePath(ofile) << ": "
|
||||
<< escapeDependencyPath(fileFixify(project->projectFile())) << " ";
|
||||
if (Option::mkfile::do_cache) {
|
||||
if (Option::globals->do_cache) {
|
||||
if (!project->confFile().isEmpty())
|
||||
t << escapeDependencyPath(fileFixify(project->confFile())) << " ";
|
||||
if (!project->cacheFile().isEmpty())
|
||||
|
@ -235,7 +235,7 @@ MakefileGenerator
|
||||
basevars["BUILD_NAME"] = (buildname.isEmpty() ? ProStringList(build) : buildname);
|
||||
|
||||
//create project
|
||||
QMakeProject *build_proj = new QMakeProject(project->properties());
|
||||
QMakeProject *build_proj = new QMakeProject;
|
||||
build_proj->setExtraVars(basevars);
|
||||
build_proj->setExtraConfigs(basecfgs);
|
||||
|
||||
@ -317,7 +317,7 @@ SubdirsMetaMakefileGenerator::init()
|
||||
}
|
||||
|
||||
//handle sub project
|
||||
QMakeProject *sub_proj = new QMakeProject(project->properties());
|
||||
QMakeProject *sub_proj = new QMakeProject;
|
||||
for (int ind = 0; ind < sub->indent; ++ind)
|
||||
printf(" ");
|
||||
sub->input_dir = subdir.absolutePath();
|
||||
|
@ -76,14 +76,17 @@ ProjectGenerator::init()
|
||||
init_flag = true;
|
||||
verifyCompilers();
|
||||
|
||||
project->read(QMakeProject::ReadFeatures);
|
||||
project->loadSpec();
|
||||
project->evaluateFeatureFile("default_pre.prf");
|
||||
project->evaluateFeatureFile("default_post.prf");
|
||||
project->evaluateConfigFeatures();
|
||||
project->values("CONFIG").clear();
|
||||
Option::postProcessProject(project);
|
||||
|
||||
ProValueMap &v = project->variables();
|
||||
QString templ = Option::user_template.isEmpty() ? QString("app") : Option::user_template;
|
||||
if(!Option::user_template_prefix.isEmpty())
|
||||
templ.prepend(Option::user_template_prefix);
|
||||
QString templ = Option::globals->user_template.isEmpty() ? QString("app") : Option::globals->user_template;
|
||||
if (!Option::globals->user_template_prefix.isEmpty())
|
||||
templ.prepend(Option::globals->user_template_prefix);
|
||||
v["TEMPLATE_ASSIGN"] += templ;
|
||||
|
||||
//the scary stuff
|
||||
@ -344,9 +347,8 @@ ProjectGenerator::writeMakefile(QTextStream &t)
|
||||
t << "######################################################################" << endl;
|
||||
t << "# Automatically generated by qmake (" << qmake_version() << ") " << QDateTime::currentDateTime().toString() << endl;
|
||||
t << "######################################################################" << endl << endl;
|
||||
int i;
|
||||
for(i = 0; i < Option::before_user_vars.size(); ++i)
|
||||
t << Option::before_user_vars[i] << endl;
|
||||
if (!Option::globals->precmds.isEmpty())
|
||||
t << Option::globals->precmds << endl;
|
||||
t << getWritableVar("TEMPLATE_ASSIGN", false);
|
||||
if(project->first("TEMPLATE_ASSIGN") == "subdirs") {
|
||||
t << endl << "# Directories" << "\n"
|
||||
@ -373,8 +375,8 @@ ProjectGenerator::writeMakefile(QTextStream &t)
|
||||
<< getWritableVar("RESOURCES")
|
||||
<< getWritableVar("TRANSLATIONS");
|
||||
}
|
||||
for(i = 0; i < Option::after_user_vars.size(); ++i)
|
||||
t << Option::after_user_vars[i] << endl;
|
||||
if (!Option::globals->postcmds.isEmpty())
|
||||
t << Option::globals->postcmds << endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -442,8 +442,8 @@ void VcprojGenerator::writeSubDirs(QTextStream &t)
|
||||
// Make sure that all temp projects are configured
|
||||
// for release so that the depends are created
|
||||
// without the debug <lib>dxxx.lib name mangling
|
||||
QStringList old_after_vars = Option::after_user_vars;
|
||||
Option::after_user_vars.append("CONFIG+=release");
|
||||
QString old_after_vars = Option::globals->postcmds;
|
||||
Option::globals->postcmds.append("\nCONFIG+=release");
|
||||
|
||||
QStringList subdirs = collectSubDirs(project);
|
||||
for(int i = 0; i < subdirs.size(); ++i) {
|
||||
@ -627,7 +627,7 @@ nextfile:
|
||||
t << _slnProjDepBeg;
|
||||
|
||||
// Restore previous after_user_var options
|
||||
Option::after_user_vars = old_after_vars;
|
||||
Option::globals->postcmds = old_after_vars;
|
||||
|
||||
// Figure out dependencies
|
||||
for(QList<VcsolutionDepend*>::Iterator it = solution_cleanup.begin(); it != solution_cleanup.end(); ++it) {
|
||||
|
168
qmake/library/ioutils.cpp
Normal file
168
qmake/library/ioutils.cpp
Normal file
@ -0,0 +1,168 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/
|
||||
**
|
||||
** This file is part of the qmake application of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** GNU Lesser General Public License Usage
|
||||
** 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, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia 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.
|
||||
**
|
||||
** Other Usage
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "ioutils.h"
|
||||
|
||||
#include <qdir.h>
|
||||
#include <qfile.h>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
# include <windows.h>
|
||||
#else
|
||||
# include <sys/types.h>
|
||||
# include <sys/stat.h>
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
using namespace QMakeInternal;
|
||||
|
||||
IoUtils::FileType IoUtils::fileType(const QString &fileName)
|
||||
{
|
||||
Q_ASSERT(fileName.isEmpty() || isAbsolutePath(fileName));
|
||||
#ifdef Q_OS_WIN
|
||||
DWORD attr = GetFileAttributesW((WCHAR*)fileName.utf16());
|
||||
if (attr == INVALID_FILE_ATTRIBUTES)
|
||||
return FileNotFound;
|
||||
return (attr & FILE_ATTRIBUTE_DIRECTORY) ? FileIsDir : FileIsRegular;
|
||||
#else
|
||||
struct ::stat st;
|
||||
if (::stat(fileName.toLocal8Bit().constData(), &st))
|
||||
return FileNotFound;
|
||||
return S_ISDIR(st.st_mode) ? FileIsDir : FileIsRegular;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool IoUtils::isRelativePath(const QString &path)
|
||||
{
|
||||
if (path.startsWith(QLatin1Char('/')))
|
||||
return false;
|
||||
#ifdef Q_OS_WIN
|
||||
if (path.startsWith(QLatin1Char('\\')))
|
||||
return false;
|
||||
// Unlike QFileInfo, this won't accept a relative path with a drive letter.
|
||||
// Such paths result in a royal mess anyway ...
|
||||
if (path.length() >= 3 && path.at(1) == QLatin1Char(':') && path.at(0).isLetter()
|
||||
&& (path.at(2) == QLatin1Char('/') || path.at(2) == QLatin1Char('\\')))
|
||||
return false;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
QStringRef IoUtils::fileName(const QString &fileName)
|
||||
{
|
||||
return fileName.midRef(fileName.lastIndexOf(QLatin1Char('/')) + 1);
|
||||
}
|
||||
|
||||
QString IoUtils::resolvePath(const QString &baseDir, const QString &fileName)
|
||||
{
|
||||
if (fileName.isEmpty())
|
||||
return QString();
|
||||
if (isAbsolutePath(fileName))
|
||||
return QDir::cleanPath(fileName);
|
||||
return QDir::cleanPath(baseDir + QLatin1Char('/') + fileName);
|
||||
}
|
||||
|
||||
inline static
|
||||
bool hasSpecialChars(const QString &arg, const uchar (&iqm)[16])
|
||||
{
|
||||
for (int x = arg.length() - 1; x >= 0; --x) {
|
||||
ushort c = arg.unicode()[x].unicode();
|
||||
if ((c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7))))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
QString IoUtils::shellQuoteUnix(const QString &arg)
|
||||
{
|
||||
// Chars that should be quoted (TM). This includes:
|
||||
static const uchar iqm[] = {
|
||||
0xff, 0xff, 0xff, 0xff, 0xdf, 0x07, 0x00, 0xd8,
|
||||
0x00, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0x78
|
||||
}; // 0-32 \'"$`<>|;&(){}*?#!~[]
|
||||
|
||||
if (!arg.length())
|
||||
return QString::fromLatin1("\"\"");
|
||||
|
||||
QString ret(arg);
|
||||
if (hasSpecialChars(ret, iqm)) {
|
||||
ret.replace(QLatin1Char('\''), QLatin1String("'\\''"));
|
||||
ret.prepend(QLatin1Char('\''));
|
||||
ret.append(QLatin1Char('\''));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
QString IoUtils::shellQuoteWin(const QString &arg)
|
||||
{
|
||||
// Chars that should be quoted (TM). This includes:
|
||||
// - control chars & space
|
||||
// - the shell meta chars "&()<>^|
|
||||
// - the potential separators ,;=
|
||||
static const uchar iqm[] = {
|
||||
0xff, 0xff, 0xff, 0xff, 0x45, 0x13, 0x00, 0x78,
|
||||
0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10
|
||||
};
|
||||
|
||||
if (!arg.length())
|
||||
return QString::fromLatin1("\"\"");
|
||||
|
||||
QString ret(arg);
|
||||
if (hasSpecialChars(ret, iqm)) {
|
||||
// Quotes are escaped and their preceding backslashes are doubled.
|
||||
// It's impossible to escape anything inside a quoted string on cmd
|
||||
// level, so the outer quoting must be "suspended".
|
||||
ret.replace(QRegExp(QLatin1String("(\\\\*)\"")), QLatin1String("\"\\1\\1\\^\"\""));
|
||||
// The argument must not end with a \ since this would be interpreted
|
||||
// as escaping the quote -- rather put the \ behind the quote: e.g.
|
||||
// rather use "foo"\ than "foo\"
|
||||
int i = ret.length();
|
||||
while (i > 0 && ret.at(i - 1) == QLatin1Char('\\'))
|
||||
--i;
|
||||
ret.insert(i, QLatin1Char('"'));
|
||||
ret.prepend(QLatin1Char('"'));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
83
qmake/library/ioutils.h
Normal file
83
qmake/library/ioutils.h
Normal file
@ -0,0 +1,83 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/
|
||||
**
|
||||
** This file is part of the qmake application of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** GNU Lesser General Public License Usage
|
||||
** 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, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia 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.
|
||||
**
|
||||
** Other Usage
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef IOUTILS_H
|
||||
#define IOUTILS_H
|
||||
|
||||
#include <qstring.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
namespace QMakeInternal {
|
||||
|
||||
/*!
|
||||
This class provides replacement functionality for QFileInfo, QFile & QDir,
|
||||
as these are abysmally slow.
|
||||
*/
|
||||
class IoUtils {
|
||||
public:
|
||||
enum FileType {
|
||||
FileNotFound = 0,
|
||||
FileIsRegular = 1,
|
||||
FileIsDir = 2
|
||||
};
|
||||
|
||||
static FileType fileType(const QString &fileName);
|
||||
static bool exists(const QString &fileName) { return fileType(fileName) != FileNotFound; }
|
||||
static bool isRelativePath(const QString &fileName);
|
||||
static bool isAbsolutePath(const QString &fileName) { return !isRelativePath(fileName); }
|
||||
static QStringRef fileName(const QString &fileName); // Requires normalized path
|
||||
static QString resolvePath(const QString &baseDir, const QString &fileName);
|
||||
static QString shellQuoteUnix(const QString &arg);
|
||||
static QString shellQuoteWin(const QString &arg);
|
||||
static QString shellQuote(const QString &arg)
|
||||
#ifdef Q_OS_UNIX
|
||||
{ return shellQuoteUnix(arg); }
|
||||
#else
|
||||
{ return shellQuoteWin(arg); }
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace ProFileEvaluatorInternal
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // IOUTILS_H
|
452
qmake/library/proitems.cpp
Normal file
452
qmake/library/proitems.cpp
Normal file
@ -0,0 +1,452 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/
|
||||
**
|
||||
** This file is part of the qmake application of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** GNU Lesser General Public License Usage
|
||||
** 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, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia 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.
|
||||
**
|
||||
** Other Usage
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "proitems.h"
|
||||
|
||||
#include <qfileinfo.h>
|
||||
#include <qset.h>
|
||||
#include <qstringlist.h>
|
||||
#include <qtextstream.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
// from qhash.cpp
|
||||
uint ProString::hash(const QChar *p, int n)
|
||||
{
|
||||
uint h = 0;
|
||||
|
||||
while (n--) {
|
||||
h = (h << 4) + (*p++).unicode();
|
||||
h ^= (h & 0xf0000000) >> 23;
|
||||
h &= 0x0fffffff;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
ProString::ProString() :
|
||||
m_offset(0), m_length(0), m_file(0), m_hash(0x80000000)
|
||||
{
|
||||
}
|
||||
|
||||
ProString::ProString(const ProString &other) :
|
||||
m_string(other.m_string), m_offset(other.m_offset), m_length(other.m_length), m_file(other.m_file), m_hash(other.m_hash)
|
||||
{
|
||||
}
|
||||
|
||||
ProString::ProString(const ProString &other, OmitPreHashing) :
|
||||
m_string(other.m_string), m_offset(other.m_offset), m_length(other.m_length), m_file(other.m_file), m_hash(0x80000000)
|
||||
{
|
||||
}
|
||||
|
||||
ProString::ProString(const QString &str, DoPreHashing) :
|
||||
m_string(str), m_offset(0), m_length(str.length()), m_file(0)
|
||||
{
|
||||
updatedHash();
|
||||
}
|
||||
|
||||
ProString::ProString(const QString &str) :
|
||||
m_string(str), m_offset(0), m_length(str.length()), m_file(0), m_hash(0x80000000)
|
||||
{
|
||||
}
|
||||
|
||||
ProString::ProString(const char *str, DoPreHashing) :
|
||||
m_string(QString::fromLatin1(str)), m_offset(0), m_length(qstrlen(str)), m_file(0)
|
||||
{
|
||||
updatedHash();
|
||||
}
|
||||
|
||||
ProString::ProString(const char *str) :
|
||||
m_string(QString::fromLatin1(str)), m_offset(0), m_length(qstrlen(str)), m_file(0), m_hash(0x80000000)
|
||||
{
|
||||
}
|
||||
|
||||
ProString::ProString(const QString &str, int offset, int length, DoPreHashing) :
|
||||
m_string(str), m_offset(offset), m_length(length), m_file(0)
|
||||
{
|
||||
updatedHash();
|
||||
}
|
||||
|
||||
ProString::ProString(const QString &str, int offset, int length, uint hash) :
|
||||
m_string(str), m_offset(offset), m_length(length), m_file(0), m_hash(hash)
|
||||
{
|
||||
}
|
||||
|
||||
ProString::ProString(const QString &str, int offset, int length) :
|
||||
m_string(str), m_offset(offset), m_length(length), m_file(0), m_hash(0x80000000)
|
||||
{
|
||||
}
|
||||
|
||||
void ProString::setValue(const QString &str)
|
||||
{
|
||||
m_string = str, m_offset = 0, m_length = str.length(), m_hash = 0x80000000;
|
||||
}
|
||||
|
||||
uint ProString::updatedHash() const
|
||||
{
|
||||
return (m_hash = hash(m_string.constData() + m_offset, m_length));
|
||||
}
|
||||
|
||||
uint qHash(const ProString &str)
|
||||
{
|
||||
if (!(str.m_hash & 0x80000000))
|
||||
return str.m_hash;
|
||||
return str.updatedHash();
|
||||
}
|
||||
|
||||
ProKey::ProKey(const QString &str) :
|
||||
ProString(str, DoHash)
|
||||
{
|
||||
}
|
||||
|
||||
ProKey::ProKey(const char *str) :
|
||||
ProString(str, DoHash)
|
||||
{
|
||||
}
|
||||
|
||||
ProKey::ProKey(const QString &str, int off, int len) :
|
||||
ProString(str, off, len, DoHash)
|
||||
{
|
||||
}
|
||||
|
||||
ProKey::ProKey(const QString &str, int off, int len, uint hash) :
|
||||
ProString(str, off, len, hash)
|
||||
{
|
||||
}
|
||||
|
||||
void ProKey::setValue(const QString &str)
|
||||
{
|
||||
m_string = str, m_offset = 0, m_length = str.length();
|
||||
updatedHash();
|
||||
}
|
||||
|
||||
QString ProString::toQString() const
|
||||
{
|
||||
return m_string.mid(m_offset, m_length);
|
||||
}
|
||||
|
||||
QString &ProString::toQString(QString &tmp) const
|
||||
{
|
||||
return tmp.setRawData(m_string.constData() + m_offset, m_length);
|
||||
}
|
||||
|
||||
QChar *ProString::prepareExtend(int extraLen, int thisTarget, int extraTarget)
|
||||
{
|
||||
if (m_string.isDetached() && m_length + extraLen <= m_string.capacity()) {
|
||||
m_string.reserve(0); // Prevent the resize() below from reallocating
|
||||
QChar *ptr = (QChar *)m_string.constData();
|
||||
if (m_offset != thisTarget)
|
||||
memmove(ptr + thisTarget, ptr + m_offset, m_length * 2);
|
||||
ptr += extraTarget;
|
||||
m_offset = 0;
|
||||
m_length += extraLen;
|
||||
m_string.resize(m_length);
|
||||
m_hash = 0x80000000;
|
||||
return ptr;
|
||||
} else {
|
||||
QString neu(m_length + extraLen, Qt::Uninitialized);
|
||||
QChar *ptr = (QChar *)neu.constData();
|
||||
memcpy(ptr + thisTarget, m_string.constData() + m_offset, m_length * 2);
|
||||
ptr += extraTarget;
|
||||
*this = ProString(neu);
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
|
||||
ProString &ProString::prepend(const ProString &other)
|
||||
{
|
||||
if (other.m_length) {
|
||||
if (!m_length) {
|
||||
*this = other;
|
||||
} else {
|
||||
QChar *ptr = prepareExtend(other.m_length, other.m_length, 0);
|
||||
memcpy(ptr, other.constData(), other.m_length * 2);
|
||||
if (!m_file)
|
||||
m_file = other.m_file;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ProString &ProString::append(const QLatin1String other)
|
||||
{
|
||||
const char *latin1 = other.latin1();
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
|
||||
int size = other.size();
|
||||
#else
|
||||
int size = strlen(latin1);
|
||||
#endif
|
||||
if (size) {
|
||||
QChar *ptr = prepareExtend(size, 0, m_length);
|
||||
for (int i = 0; i < size; i++)
|
||||
*ptr++ = QLatin1Char(latin1[i]);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ProString &ProString::append(QChar other)
|
||||
{
|
||||
QChar *ptr = prepareExtend(1, 0, m_length);
|
||||
*ptr = other;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// If pending != 0, prefix with space if appending to non-empty non-pending
|
||||
ProString &ProString::append(const ProString &other, bool *pending)
|
||||
{
|
||||
if (other.m_length) {
|
||||
if (!m_length) {
|
||||
*this = other;
|
||||
} else {
|
||||
QChar *ptr;
|
||||
if (pending && !*pending) {
|
||||
ptr = prepareExtend(1 + other.m_length, 0, m_length);
|
||||
*ptr++ = 32;
|
||||
} else {
|
||||
ptr = prepareExtend(other.m_length, 0, m_length);
|
||||
}
|
||||
memcpy(ptr, other.m_string.constData() + other.m_offset, other.m_length * 2);
|
||||
if (other.m_file)
|
||||
m_file = other.m_file;
|
||||
}
|
||||
if (pending)
|
||||
*pending = true;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ProString &ProString::append(const ProStringList &other, bool *pending, bool skipEmpty1st)
|
||||
{
|
||||
if (const int sz = other.size()) {
|
||||
int startIdx = 0;
|
||||
if (pending && !*pending && skipEmpty1st && other.at(0).isEmpty()) {
|
||||
if (sz == 1)
|
||||
return *this;
|
||||
startIdx = 1;
|
||||
}
|
||||
if (!m_length && sz == startIdx + 1) {
|
||||
*this = other.at(startIdx);
|
||||
} else {
|
||||
int totalLength = sz - startIdx;
|
||||
for (int i = startIdx; i < sz; ++i)
|
||||
totalLength += other.at(i).size();
|
||||
bool putSpace = false;
|
||||
if (pending && !*pending && m_length)
|
||||
putSpace = true;
|
||||
else
|
||||
totalLength--;
|
||||
|
||||
QChar *ptr = prepareExtend(totalLength, 0, m_length);
|
||||
for (int i = startIdx; i < sz; ++i) {
|
||||
if (putSpace)
|
||||
*ptr++ = 32;
|
||||
else
|
||||
putSpace = true;
|
||||
const ProString &str = other.at(i);
|
||||
memcpy(ptr, str.m_string.constData() + str.m_offset, str.m_length * 2);
|
||||
ptr += str.m_length;
|
||||
}
|
||||
if (other.last().m_file)
|
||||
m_file = other.last().m_file;
|
||||
}
|
||||
if (pending)
|
||||
*pending = true;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
QString operator+(const ProString &one, const ProString &two)
|
||||
{
|
||||
if (two.m_length) {
|
||||
if (!one.m_length) {
|
||||
return two.toQString();
|
||||
} else {
|
||||
QString neu(one.m_length + two.m_length, Qt::Uninitialized);
|
||||
ushort *ptr = (ushort *)neu.constData();
|
||||
memcpy(ptr, one.m_string.constData() + one.m_offset, one.m_length * 2);
|
||||
memcpy(ptr + one.m_length, two.m_string.constData() + two.m_offset, two.m_length * 2);
|
||||
return neu;
|
||||
}
|
||||
}
|
||||
return one.toQString();
|
||||
}
|
||||
|
||||
|
||||
ProString ProString::mid(int off, int len) const
|
||||
{
|
||||
ProString ret(*this, NoHash);
|
||||
if (off > m_length)
|
||||
off = m_length;
|
||||
ret.m_offset += off;
|
||||
ret.m_length -= off;
|
||||
if ((uint)ret.m_length > (uint)len) // Unsigned comparison to interpret < 0 as infinite
|
||||
ret.m_length = len;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ProString ProString::trimmed() const
|
||||
{
|
||||
ProString ret(*this, NoHash);
|
||||
int cur = m_offset;
|
||||
int end = cur + m_length;
|
||||
const QChar *data = m_string.constData();
|
||||
for (; cur < end; cur++)
|
||||
if (!data[cur].isSpace()) {
|
||||
// No underrun check - we know there is at least one non-whitespace
|
||||
while (data[end - 1].isSpace())
|
||||
end--;
|
||||
break;
|
||||
}
|
||||
ret.m_offset = cur;
|
||||
ret.m_length = end - cur;
|
||||
return ret;
|
||||
}
|
||||
|
||||
QTextStream &operator<<(QTextStream &t, const ProString &str)
|
||||
{
|
||||
t << str.toQString(); // XXX optimize ... somehow
|
||||
return t;
|
||||
}
|
||||
|
||||
QString ProStringList::join(const QString &sep) const
|
||||
{
|
||||
int totalLength = 0;
|
||||
const int sz = size();
|
||||
|
||||
for (int i = 0; i < sz; ++i)
|
||||
totalLength += at(i).size();
|
||||
|
||||
if (sz)
|
||||
totalLength += sep.size() * (sz - 1);
|
||||
|
||||
QString res(totalLength, Qt::Uninitialized);
|
||||
QChar *ptr = (QChar *)res.constData();
|
||||
for (int i = 0; i < sz; ++i) {
|
||||
if (i) {
|
||||
memcpy(ptr, sep.constData(), sep.size() * 2);
|
||||
ptr += sep.size();
|
||||
}
|
||||
memcpy(ptr, at(i).constData(), at(i).size() * 2);
|
||||
ptr += at(i).size();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void ProStringList::removeAll(const ProString &str)
|
||||
{
|
||||
for (int i = size(); --i >= 0; )
|
||||
if (at(i) == str)
|
||||
remove(i);
|
||||
}
|
||||
|
||||
void ProStringList::removeAll(const char *str)
|
||||
{
|
||||
for (int i = size(); --i >= 0; )
|
||||
if (at(i) == str)
|
||||
remove(i);
|
||||
}
|
||||
|
||||
void ProStringList::removeDuplicates()
|
||||
{
|
||||
int n = size();
|
||||
int j = 0;
|
||||
QSet<ProString> seen;
|
||||
seen.reserve(n);
|
||||
for (int i = 0; i < n; ++i) {
|
||||
const ProString &s = at(i);
|
||||
if (seen.contains(s))
|
||||
continue;
|
||||
seen.insert(s);
|
||||
if (j != i)
|
||||
(*this)[j] = s;
|
||||
++j;
|
||||
}
|
||||
if (n != j)
|
||||
erase(begin() + j, end());
|
||||
}
|
||||
|
||||
ProStringList::ProStringList(const QStringList &list)
|
||||
{
|
||||
reserve(list.size());
|
||||
foreach (const QString &str, list)
|
||||
*this << ProString(str);
|
||||
}
|
||||
|
||||
QStringList ProStringList::toQStringList() const
|
||||
{
|
||||
QStringList ret;
|
||||
ret.reserve(size());
|
||||
foreach (const ProString &str, *this)
|
||||
ret << str.toQString();
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ProStringList::contains(const ProString &str, Qt::CaseSensitivity cs) const
|
||||
{
|
||||
for (int i = 0; i < size(); i++)
|
||||
if (!at(i).compare(str, cs))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ProStringList::contains(const char *str, Qt::CaseSensitivity cs) const
|
||||
{
|
||||
for (int i = 0; i < size(); i++)
|
||||
if (!at(i).compare(str, cs))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
ProFile::ProFile(const QString &fileName)
|
||||
: m_refCount(1),
|
||||
m_fileName(fileName),
|
||||
m_ok(true),
|
||||
m_hostBuild(false)
|
||||
{
|
||||
if (!fileName.startsWith(QLatin1Char('(')))
|
||||
m_directoryName = QFileInfo( // qmake sickness: canonicalize only the directory!
|
||||
fileName.left(fileName.lastIndexOf(QLatin1Char('/')))).canonicalFilePath();
|
||||
}
|
||||
|
||||
ProFile::~ProFile()
|
||||
{
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
@ -44,14 +44,29 @@
|
||||
|
||||
#include "qmake_global.h"
|
||||
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QHash>
|
||||
#include <QTextStream>
|
||||
#include <qstring.h>
|
||||
#include <qvector.h>
|
||||
#include <qhash.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
#if 0
|
||||
class QTextStream;
|
||||
|
||||
#ifdef PROPARSER_THREAD_SAFE
|
||||
typedef QAtomicInt ProItemRefCount;
|
||||
#else
|
||||
class ProItemRefCount {
|
||||
public:
|
||||
ProItemRefCount(int cnt = 0) : m_cnt(cnt) {}
|
||||
bool ref() { return ++m_cnt != 0; }
|
||||
bool deref() { return --m_cnt != 0; }
|
||||
ProItemRefCount &operator=(int value) { m_cnt = value; return *this; }
|
||||
private:
|
||||
int m_cnt;
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef QT_BUILD_QMAKE
|
||||
# define PROITEM_EXPLICIT explicit
|
||||
#else
|
||||
# define PROITEM_EXPLICIT
|
||||
@ -59,27 +74,36 @@ QT_BEGIN_NAMESPACE
|
||||
|
||||
class ProKey;
|
||||
class ProStringList;
|
||||
class ProFile;
|
||||
|
||||
class ProString {
|
||||
public:
|
||||
ProString() {}
|
||||
ProString(const ProString &other) : m_string(other.m_string) {}
|
||||
PROITEM_EXPLICIT ProString(const QString &str) : m_string(str) {}
|
||||
PROITEM_EXPLICIT ProString(const char *str) : m_string(QLatin1String(str)) {}
|
||||
void clear() { m_string.clear(); }
|
||||
ProString();
|
||||
ProString(const ProString &other);
|
||||
PROITEM_EXPLICIT ProString(const QString &str);
|
||||
PROITEM_EXPLICIT ProString(const char *str);
|
||||
ProString(const QString &str, int offset, int length);
|
||||
void setValue(const QString &str);
|
||||
void clear() { m_string.clear(); m_length = 0; }
|
||||
ProString &setSource(const ProString &other) { m_file = other.m_file; return *this; }
|
||||
ProString &setSource(const ProFile *pro) { m_file = pro; return *this; }
|
||||
const ProFile *sourceFile() const { return m_file; }
|
||||
|
||||
ProString &prepend(const ProString &other) { m_string.prepend(other.m_string); return *this; }
|
||||
ProString &append(const ProString &other) { m_string.append(other.m_string); return *this; }
|
||||
ProString &append(const QString &other) { m_string.append(other); return *this; }
|
||||
ProString &append(const char *other) { m_string.append(QLatin1String(other)); return *this; }
|
||||
ProString &append(QChar other) { m_string.append(other); return *this; }
|
||||
ProString &prepend(const ProString &other);
|
||||
ProString &append(const ProString &other, bool *pending = 0);
|
||||
ProString &append(const QString &other) { return append(ProString(other)); }
|
||||
ProString &append(const QLatin1String other);
|
||||
ProString &append(const char *other) { return append(QLatin1String(other)); }
|
||||
ProString &append(QChar other);
|
||||
ProString &append(const ProStringList &other, bool *pending = 0, bool skipEmpty1st = false);
|
||||
ProString &operator+=(const ProString &other) { return append(other); }
|
||||
ProString &operator+=(const QString &other) { return append(other); }
|
||||
ProString &operator+=(const QLatin1String other) { return append(other); }
|
||||
ProString &operator+=(const char *other) { return append(other); }
|
||||
ProString &operator+=(QChar other) { return append(other); }
|
||||
|
||||
void chop(int n) { m_string.chop(n); }
|
||||
void chopFront(int n) { m_string.remove(0, n); }
|
||||
void chop(int n) { Q_ASSERT(n <= m_length); m_length -= n; }
|
||||
void chopFront(int n) { Q_ASSERT(n <= m_length); m_offset += n; m_length -= n; }
|
||||
|
||||
bool operator==(const ProString &other) const { return toQStringRef() == other.toQStringRef(); }
|
||||
bool operator==(const QString &other) const { return toQStringRef() == other; }
|
||||
@ -90,15 +114,15 @@ public:
|
||||
bool operator!=(QLatin1String other) const { return !(*this == other); }
|
||||
bool operator!=(const char *other) const { return !(*this == other); }
|
||||
bool isNull() const { return m_string.isNull(); }
|
||||
bool isEmpty() const { return m_string.isEmpty(); }
|
||||
int length() const { return m_string.size(); }
|
||||
int size() const { return m_string.size(); }
|
||||
QChar at(int i) const { return m_string.at(i); }
|
||||
const QChar *constData() const { return m_string.constData(); }
|
||||
ProString mid(int off, int len = -1) const { return m_string.mid(off, len); }
|
||||
bool isEmpty() const { return !m_length; }
|
||||
int length() const { return m_length; }
|
||||
int size() const { return m_length; }
|
||||
QChar at(int i) const { Q_ASSERT((uint)i < (uint)m_length); return constData()[i]; }
|
||||
const QChar *constData() const { return m_string.constData() + m_offset; }
|
||||
ProString mid(int off, int len = -1) const;
|
||||
ProString left(int len) const { return mid(0, len); }
|
||||
ProString right(int len) const { return mid(qMax(0, size() - len)); }
|
||||
ProString trimmed() const { return m_string.trimmed(); }
|
||||
ProString trimmed() const;
|
||||
int compare(const ProString &sub, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return toQStringRef().compare(sub.toQStringRef(), cs); }
|
||||
int compare(const QString &sub, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return toQStringRef().compare(sub, cs); }
|
||||
int compare(const char *sub, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return toQStringRef().compare(QLatin1String(sub), cs); }
|
||||
@ -122,12 +146,15 @@ public:
|
||||
int toInt(bool *ok = 0) const { return toQString().toInt(ok); } // XXX optimize
|
||||
short toShort(bool *ok = 0) const { return toQString().toShort(ok); } // XXX optimize
|
||||
|
||||
ALWAYS_INLINE QStringRef toQStringRef() const { return QStringRef(&m_string, 0, m_string.length()); }
|
||||
static uint hash(const QChar *p, int n);
|
||||
|
||||
ALWAYS_INLINE QStringRef toQStringRef() const { return QStringRef(&m_string, m_offset, m_length); }
|
||||
|
||||
ALWAYS_INLINE ProKey &toKey() { return *(ProKey *)this; }
|
||||
ALWAYS_INLINE const ProKey &toKey() const { return *(const ProKey *)this; }
|
||||
|
||||
QString toQString() const { return m_string; }
|
||||
QString toQString() const;
|
||||
QString &toQString(QString &tmp) const;
|
||||
|
||||
QByteArray toLatin1() const { return toQStringRef().toLatin1(); }
|
||||
|
||||
@ -135,10 +162,23 @@ private:
|
||||
ProString(const ProKey &other);
|
||||
ProString &operator=(const ProKey &other);
|
||||
|
||||
enum OmitPreHashing { NoHash };
|
||||
ProString(const ProString &other, OmitPreHashing);
|
||||
|
||||
enum DoPreHashing { DoHash };
|
||||
ALWAYS_INLINE ProString(const QString &str, DoPreHashing);
|
||||
ALWAYS_INLINE ProString(const char *str, DoPreHashing);
|
||||
ALWAYS_INLINE ProString(const QString &str, int offset, int length, DoPreHashing);
|
||||
ALWAYS_INLINE ProString(const QString &str, int offset, int length, uint hash);
|
||||
|
||||
QString m_string;
|
||||
friend uint qHash(const ProKey &str, uint seed);
|
||||
int m_offset, m_length;
|
||||
const ProFile *m_file;
|
||||
mutable uint m_hash;
|
||||
QChar *prepareExtend(int extraLen, int thisTarget, int extraTarget);
|
||||
uint updatedHash() const;
|
||||
friend uint qHash(const ProString &str);
|
||||
friend QString operator+(const ProString &one, const ProString &two);
|
||||
friend QString &operator+=(QString &that, const ProString &other);
|
||||
friend class ProKey;
|
||||
};
|
||||
Q_DECLARE_TYPEINFO(ProString, Q_MOVABLE_TYPE);
|
||||
@ -146,8 +186,11 @@ Q_DECLARE_TYPEINFO(ProString, Q_MOVABLE_TYPE);
|
||||
class ProKey : public ProString {
|
||||
public:
|
||||
ALWAYS_INLINE ProKey() : ProString() {}
|
||||
explicit ProKey(const QString &str) : ProString(str) {}
|
||||
PROITEM_EXPLICIT ProKey(const char *str) : ProString(str) {}
|
||||
explicit ProKey(const QString &str);
|
||||
PROITEM_EXPLICIT ProKey(const char *str);
|
||||
ProKey(const QString &str, int off, int len);
|
||||
ProKey(const QString &str, int off, int len, uint hash);
|
||||
void setValue(const QString &str);
|
||||
|
||||
#ifdef Q_CC_MSVC
|
||||
// Workaround strange MSVC behaviour when exporting classes with ProKey members.
|
||||
@ -167,10 +210,8 @@ private:
|
||||
};
|
||||
Q_DECLARE_TYPEINFO(ProKey, Q_MOVABLE_TYPE);
|
||||
|
||||
inline uint qHash(const ProKey &key, uint seed = 0)
|
||||
{ return qHash(key.m_string, seed); }
|
||||
inline QString operator+(const ProString &one, const ProString &two)
|
||||
{ return one.m_string + two.m_string; }
|
||||
uint qHash(const ProString &str);
|
||||
QString operator+(const ProString &one, const ProString &two);
|
||||
inline QString operator+(const ProString &one, const QString &two)
|
||||
{ return one + ProString(two); }
|
||||
inline QString operator+(const QString &one, const ProString &two)
|
||||
@ -189,29 +230,31 @@ inline bool operator==(const QString &that, const ProString &other)
|
||||
inline bool operator!=(const QString &that, const ProString &other)
|
||||
{ return !(other == that); }
|
||||
|
||||
inline QTextStream &operator<<(QTextStream &t, const ProString &str)
|
||||
{ t << str.toQString(); return t; }
|
||||
QTextStream &operator<<(QTextStream &t, const ProString &str);
|
||||
|
||||
class ProStringList : public QList<ProString> {
|
||||
class ProStringList : public QVector<ProString> {
|
||||
public:
|
||||
ProStringList() {}
|
||||
ProStringList(const ProString &str) { *this << str; }
|
||||
explicit ProStringList(const QStringList &list) : QList<ProString>(*(const ProStringList *)&list) {}
|
||||
QStringList toQStringList() const { return *(const QStringList *)this; }
|
||||
explicit ProStringList(const QStringList &list);
|
||||
QStringList toQStringList() const;
|
||||
|
||||
ProStringList &operator<<(const ProString &str)
|
||||
{ QList<ProString>::operator<<(str); return *this; }
|
||||
{ QVector<ProString>::operator<<(str); return *this; }
|
||||
|
||||
QString join(const QString &sep) const { return toQStringList().join(sep); }
|
||||
int length() const { return size(); }
|
||||
|
||||
void remove(int idx) { removeAt(idx); }
|
||||
QString join(const QString &sep) const;
|
||||
|
||||
bool contains(const ProString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
|
||||
{ return contains(str.toQString(), cs); }
|
||||
void removeAll(const ProString &str);
|
||||
void removeAll(const char *str);
|
||||
void removeAt(int idx) { remove(idx); }
|
||||
void removeDuplicates();
|
||||
|
||||
bool contains(const ProString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
|
||||
bool contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
|
||||
{ return (*(const QStringList *)this).contains(str, cs); }
|
||||
bool contains(const char *str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
|
||||
{ return (*(const QStringList *)this).contains(str, cs); }
|
||||
{ return contains(ProString(str), cs); }
|
||||
bool contains(const char *str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
|
||||
};
|
||||
Q_DECLARE_TYPEINFO(ProStringList, Q_MOVABLE_TYPE);
|
||||
|
||||
@ -220,6 +263,131 @@ inline ProStringList operator+(const ProStringList &one, const ProStringList &tw
|
||||
|
||||
typedef QHash<ProKey, ProStringList> ProValueMap;
|
||||
|
||||
// These token definitions affect both ProFileEvaluator and ProWriter
|
||||
enum ProToken {
|
||||
TokTerminator = 0, // end of stream (possibly not included in length; must be zero)
|
||||
TokLine, // line marker:
|
||||
// - line (1)
|
||||
TokAssign, // variable =
|
||||
TokAppend, // variable +=
|
||||
TokAppendUnique, // variable *=
|
||||
TokRemove, // variable -=
|
||||
TokReplace, // variable ~=
|
||||
// previous literal/expansion is a variable manipulation
|
||||
// - value expression + TokValueTerminator
|
||||
TokValueTerminator, // assignment value terminator
|
||||
TokLiteral, // literal string (fully dequoted)
|
||||
// - length (1)
|
||||
// - string data (length; unterminated)
|
||||
TokHashLiteral, // literal string with hash (fully dequoted)
|
||||
// - hash (2)
|
||||
// - length (1)
|
||||
// - string data (length; unterminated)
|
||||
TokVariable, // qmake variable expansion
|
||||
// - hash (2)
|
||||
// - name length (1)
|
||||
// - name (name length; unterminated)
|
||||
TokProperty, // qmake property expansion
|
||||
// - hash (2)
|
||||
// - name length (1)
|
||||
// - name (name length; unterminated)
|
||||
TokEnvVar, // environment variable expansion
|
||||
// - name length (1)
|
||||
// - name (name length; unterminated)
|
||||
TokFuncName, // replace function expansion
|
||||
// - hash (2)
|
||||
// - name length (1)
|
||||
// - name (name length; unterminated)
|
||||
// - ((nested expansion + TokArgSeparator)* + nested expansion)?
|
||||
// - TokFuncTerminator
|
||||
TokArgSeparator, // function argument separator
|
||||
TokFuncTerminator, // function argument list terminator
|
||||
TokCondition, // previous literal/expansion is a conditional
|
||||
TokTestCall, // previous literal/expansion is a test function call
|
||||
// - ((nested expansion + TokArgSeparator)* + nested expansion)?
|
||||
// - TokFuncTerminator
|
||||
TokNot, // '!' operator
|
||||
TokAnd, // ':' operator
|
||||
TokOr, // '|' operator
|
||||
TokBranch, // branch point:
|
||||
// - then block length (2)
|
||||
// - then block + TokTerminator (then block length)
|
||||
// - else block length (2)
|
||||
// - else block + TokTerminator (else block length)
|
||||
TokForLoop, // for loop:
|
||||
// - variable name: hash (2), length (1), chars (length)
|
||||
// - expression: length (2), bytes + TokValueTerminator (length)
|
||||
// - body length (2)
|
||||
// - body + TokTerminator (body length)
|
||||
TokTestDef, // test function definition:
|
||||
TokReplaceDef, // replace function definition:
|
||||
// - function name: hash (2), length (1), chars (length)
|
||||
// - body length (2)
|
||||
// - body + TokTerminator (body length)
|
||||
TokMask = 0xff,
|
||||
TokQuoted = 0x100, // The expression is quoted => join expanded stringlist
|
||||
TokNewStr = 0x200 // Next stringlist element
|
||||
};
|
||||
|
||||
class QMAKE_EXPORT ProFile
|
||||
{
|
||||
public:
|
||||
explicit ProFile(const QString &fileName);
|
||||
~ProFile();
|
||||
|
||||
QString fileName() const { return m_fileName; }
|
||||
QString directoryName() const { return m_directoryName; }
|
||||
const QString &items() const { return m_proitems; }
|
||||
QString *itemsRef() { return &m_proitems; }
|
||||
const ushort *tokPtr() const { return (const ushort *)m_proitems.constData(); }
|
||||
|
||||
void ref() { m_refCount.ref(); }
|
||||
void deref() { if (!m_refCount.deref()) delete this; }
|
||||
|
||||
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 {
|
||||
public:
|
||||
ProFunctionDef(ProFile *pro, int offset) : m_pro(pro), m_offset(offset) { m_pro->ref(); }
|
||||
ProFunctionDef(const ProFunctionDef &o) : m_pro(o.m_pro), m_offset(o.m_offset) { m_pro->ref(); }
|
||||
~ProFunctionDef() { m_pro->deref(); }
|
||||
ProFunctionDef &operator=(const ProFunctionDef &o)
|
||||
{
|
||||
if (this != &o) {
|
||||
m_pro->deref();
|
||||
m_pro = o.m_pro;
|
||||
m_pro->ref();
|
||||
m_offset = o.m_offset;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
ProFile *pro() const { return m_pro; }
|
||||
const ushort *tokPtr() const { return m_pro->tokPtr() + m_offset; }
|
||||
private:
|
||||
ProFile *m_pro;
|
||||
int m_offset;
|
||||
};
|
||||
|
||||
Q_DECLARE_TYPEINFO(ProFunctionDef, Q_MOVABLE_TYPE);
|
||||
|
||||
struct ProFunctionDefs {
|
||||
QHash<ProKey, ProFunctionDef> testFunctions;
|
||||
QHash<ProKey, ProFunctionDef> replaceFunctions;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // PROITEMS_H
|
||||
|
1684
qmake/library/qmakebuiltins.cpp
Normal file
1684
qmake/library/qmakebuiltins.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1981
qmake/library/qmakeevaluator.cpp
Normal file
1981
qmake/library/qmakeevaluator.cpp
Normal file
File diff suppressed because it is too large
Load Diff
309
qmake/library/qmakeevaluator.h
Normal file
309
qmake/library/qmakeevaluator.h
Normal file
@ -0,0 +1,309 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/
|
||||
**
|
||||
** This file is part of the qmake application of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** GNU Lesser General Public License Usage
|
||||
** 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, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia 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.
|
||||
**
|
||||
** Other Usage
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QMAKEEVALUATOR_H
|
||||
#define QMAKEEVALUATOR_H
|
||||
|
||||
#if defined(PROEVALUATOR_FULL) && defined(PROEVALUATOR_THREAD_SAFE)
|
||||
# error PROEVALUATOR_FULL is incompatible with PROEVALUATOR_THREAD_SAFE due to cache() implementation
|
||||
#endif
|
||||
|
||||
#include "qmakeparser.h"
|
||||
#include "ioutils.h"
|
||||
|
||||
#include <qlist.h>
|
||||
#include <qlinkedlist.h>
|
||||
#include <qset.h>
|
||||
#include <qstack.h>
|
||||
#include <qstring.h>
|
||||
#include <qstringlist.h>
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
# include <qprocess.h>
|
||||
#endif
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QMakeGlobals;
|
||||
|
||||
class QMAKE_EXPORT QMakeHandler : public QMakeParserHandler
|
||||
{
|
||||
public:
|
||||
enum {
|
||||
SourceEvaluator = 0x10,
|
||||
|
||||
EvalWarnLanguage = SourceEvaluator | WarningMessage | WarnLanguage,
|
||||
EvalWarnDeprecated = SourceEvaluator | WarningMessage | WarnDeprecated,
|
||||
|
||||
EvalError = ErrorMessage | SourceEvaluator
|
||||
};
|
||||
|
||||
// error(), warning() and message() from .pro file
|
||||
virtual void fileMessage(const QString &msg) = 0;
|
||||
|
||||
enum EvalFileType { EvalProjectFile, EvalIncludeFile, EvalConfigFile, EvalFeatureFile, EvalAuxFile };
|
||||
virtual void aboutToEval(ProFile *parent, ProFile *proFile, EvalFileType type) = 0;
|
||||
virtual void doneWithEval(ProFile *parent) = 0;
|
||||
};
|
||||
|
||||
// We use a QLinkedList based stack instead of a QVector based one (QStack), so that
|
||||
// the addresses of value maps stay constant. The qmake generators rely on that.
|
||||
class QMAKE_EXPORT ProValueMapStack : public QLinkedList<ProValueMap>
|
||||
{
|
||||
public:
|
||||
inline void push(const ProValueMap &t) { append(t); }
|
||||
inline ProValueMap pop() { return takeLast(); }
|
||||
ProValueMap &top() { return last(); }
|
||||
const ProValueMap &top() const { return last(); }
|
||||
};
|
||||
|
||||
class QMAKE_EXPORT QMakeEvaluator
|
||||
{
|
||||
public:
|
||||
enum LoadFlag {
|
||||
LoadProOnly = 0,
|
||||
LoadPreFiles = 1,
|
||||
LoadPostFiles = 2,
|
||||
LoadAll = LoadPreFiles|LoadPostFiles,
|
||||
LoadSilent = 0x10
|
||||
};
|
||||
Q_DECLARE_FLAGS(LoadFlags, LoadFlag)
|
||||
|
||||
static void initStatics();
|
||||
static void initFunctionStatics();
|
||||
QMakeEvaluator(QMakeGlobals *option, QMakeParser *parser,
|
||||
QMakeHandler *handler);
|
||||
~QMakeEvaluator();
|
||||
|
||||
#ifdef QT_BUILD_QMAKE
|
||||
void setExtraVars(const ProValueMap &extraVars) { m_extraVars = extraVars; }
|
||||
void setExtraConfigs(const ProStringList &extraConfigs) { m_extraConfigs = extraConfigs; }
|
||||
#endif
|
||||
void setOutputDir(const QString &outputDir) { m_outputDir = outputDir; }
|
||||
|
||||
ProStringList values(const ProKey &variableName) const;
|
||||
ProStringList &valuesRef(const ProKey &variableName);
|
||||
ProString first(const ProKey &variableName) const;
|
||||
ProString propertyValue(const ProKey &val) const;
|
||||
|
||||
ProString dirSep() const { return m_dirSep; }
|
||||
bool isHostBuild() const { return m_hostBuild; }
|
||||
|
||||
enum VisitReturn {
|
||||
ReturnFalse,
|
||||
ReturnTrue,
|
||||
ReturnError,
|
||||
ReturnBreak,
|
||||
ReturnNext,
|
||||
ReturnReturn
|
||||
};
|
||||
|
||||
static ALWAYS_INLINE VisitReturn returnBool(bool b)
|
||||
{ return b ? ReturnTrue : ReturnFalse; }
|
||||
|
||||
static ALWAYS_INLINE uint getBlockLen(const ushort *&tokPtr);
|
||||
ProString getStr(const ushort *&tokPtr);
|
||||
ProKey getHashStr(const ushort *&tokPtr);
|
||||
void evaluateExpression(const ushort *&tokPtr, ProStringList *ret, bool joined);
|
||||
static ALWAYS_INLINE void skipStr(const ushort *&tokPtr);
|
||||
static ALWAYS_INLINE void skipHashStr(const ushort *&tokPtr);
|
||||
void skipExpression(const ushort *&tokPtr);
|
||||
|
||||
void loadDefaults();
|
||||
bool prepareProject(const QString &inDir);
|
||||
bool loadSpecInternal();
|
||||
bool loadSpec();
|
||||
void initFrom(const QMakeEvaluator &other);
|
||||
void setupProject();
|
||||
void evaluateCommand(const QString &cmds, const QString &where);
|
||||
VisitReturn visitProFile(ProFile *pro, QMakeHandler::EvalFileType type,
|
||||
LoadFlags flags);
|
||||
VisitReturn visitProBlock(ProFile *pro, const ushort *tokPtr);
|
||||
VisitReturn visitProBlock(const ushort *tokPtr);
|
||||
VisitReturn visitProLoop(const ProKey &variable, const ushort *exprPtr,
|
||||
const ushort *tokPtr);
|
||||
void visitProFunctionDef(ushort tok, const ProKey &name, const ushort *tokPtr);
|
||||
void visitProVariable(ushort tok, const ProStringList &curr, const ushort *&tokPtr);
|
||||
|
||||
ALWAYS_INLINE const ProKey &map(const ProString &var) { return map(var.toKey()); }
|
||||
const ProKey &map(const ProKey &var);
|
||||
ProValueMap *findValues(const ProKey &variableName, ProValueMap::Iterator *it);
|
||||
|
||||
void setTemplate();
|
||||
|
||||
ProStringList split_value_list(const QString &vals, const ProFile *source = 0);
|
||||
ProStringList expandVariableReferences(const ProString &value, int *pos = 0, bool joined = false);
|
||||
ProStringList expandVariableReferences(const ushort *&tokPtr, int sizeHint = 0, bool joined = false);
|
||||
|
||||
QString currentFileName() const;
|
||||
QString currentDirectory() const;
|
||||
ProFile *currentProFile() const;
|
||||
QString resolvePath(const QString &fileName) const
|
||||
{ return QMakeInternal::IoUtils::resolvePath(currentDirectory(), fileName); }
|
||||
|
||||
bool evaluateFile(const QString &fileName, QMakeHandler::EvalFileType type,
|
||||
LoadFlags flags);
|
||||
bool evaluateFileChecked(const QString &fileName, QMakeHandler::EvalFileType type,
|
||||
LoadFlags flags);
|
||||
bool evaluateFeatureFile(const QString &fileName, bool silent = false);
|
||||
bool evaluateFileInto(const QString &fileName,
|
||||
ProValueMap *values, // output-only
|
||||
LoadFlags flags);
|
||||
void evaluateConfigFeatures();
|
||||
void message(int type, const QString &msg) const;
|
||||
void evalError(const QString &msg) const
|
||||
{ message(QMakeHandler::EvalError, msg); }
|
||||
void languageWarning(const QString &msg) const
|
||||
{ message(QMakeHandler::EvalWarnLanguage, msg); }
|
||||
void deprecationWarning(const QString &msg) const
|
||||
{ message(QMakeHandler::EvalWarnDeprecated, msg); }
|
||||
|
||||
QList<ProStringList> prepareFunctionArgs(const ushort *&tokPtr);
|
||||
ProStringList evaluateFunction(const ProFunctionDef &func,
|
||||
const QList<ProStringList> &argumentsList, bool *ok);
|
||||
VisitReturn evaluateBoolFunction(const ProFunctionDef &func,
|
||||
const QList<ProStringList> &argumentsList,
|
||||
const ProString &function);
|
||||
|
||||
ProStringList evaluateExpandFunction(const ProKey &function, const ushort *&tokPtr);
|
||||
VisitReturn evaluateConditionalFunction(const ProKey &function, const ushort *&tokPtr);
|
||||
|
||||
ProStringList evaluateBuiltinExpand(const ProKey &function, const ProStringList &args);
|
||||
VisitReturn evaluateBuiltinConditional(const ProKey &function, const ProStringList &args);
|
||||
|
||||
bool evaluateConditional(const QString &cond, const QString &where, int line = -1);
|
||||
#ifdef PROEVALUATOR_FULL
|
||||
void checkRequirements(const ProStringList &deps);
|
||||
#endif
|
||||
|
||||
void updateMkspecPaths();
|
||||
void updateFeaturePaths();
|
||||
|
||||
bool isActiveConfig(const QString &config, bool regex = false);
|
||||
|
||||
void populateDeps(
|
||||
const ProStringList &deps, const ProString &prefix,
|
||||
QHash<ProKey, QSet<ProKey> > &dependencies,
|
||||
ProValueMap &dependees, ProStringList &rootSet) const;
|
||||
|
||||
VisitReturn writeFile(const QString &ctx, const QString &fn, QIODevice::OpenMode mode,
|
||||
const QString &contents);
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
void runProcess(QProcess *proc, const QString &command) const;
|
||||
#endif
|
||||
QByteArray getCommandOutput(const QString &args) const;
|
||||
|
||||
static void removeEach(ProStringList *varlist, const ProStringList &value);
|
||||
|
||||
QMakeEvaluator *m_caller;
|
||||
int m_loopLevel; // To report unexpected break() and next()s
|
||||
#ifdef PROEVALUATOR_CUMULATIVE
|
||||
bool m_cumulative;
|
||||
int m_skipLevel;
|
||||
#else
|
||||
enum { m_cumulative = 0 };
|
||||
enum { m_skipLevel = 0 };
|
||||
#endif
|
||||
|
||||
#ifdef PROEVALUATOR_DEBUG
|
||||
void debugMsgInternal(int level, const char *fmt, ...) const;
|
||||
void traceMsgInternal(const char *fmt, ...) const;
|
||||
static QString formatValue(const ProString &val, bool forceQuote = false);
|
||||
static QString formatValueList(const ProStringList &vals, bool commas = false);
|
||||
static QString formatValueListList(const QList<ProStringList> &vals);
|
||||
|
||||
const int m_debugLevel;
|
||||
#else
|
||||
ALWAYS_INLINE void debugMsgInternal(int, const char *, ...) const {}
|
||||
ALWAYS_INLINE void traceMsgInternal(const char *, ...) const {}
|
||||
|
||||
enum { m_debugLevel = 0 };
|
||||
#endif
|
||||
|
||||
struct Location {
|
||||
Location() : pro(0), line(0) {}
|
||||
Location(ProFile *_pro, ushort _line) : pro(_pro), line(_line) {}
|
||||
void clear() { pro = 0; line = 0; }
|
||||
ProFile *pro;
|
||||
ushort line;
|
||||
};
|
||||
|
||||
Location m_current; // Currently evaluated location
|
||||
QStack<Location> m_locationStack; // All execution location changes
|
||||
QStack<ProFile *> m_profileStack; // Includes only
|
||||
|
||||
#ifdef QT_BUILD_QMAKE
|
||||
ProValueMap m_extraVars;
|
||||
ProStringList m_extraConfigs;
|
||||
#endif
|
||||
QString m_outputDir;
|
||||
|
||||
int m_listCount;
|
||||
bool m_valuemapInited;
|
||||
bool m_hostBuild;
|
||||
QString m_qmakespec;
|
||||
QString m_qmakespecFull;
|
||||
QString m_qmakespecName;
|
||||
QString m_superfile;
|
||||
QString m_conffile;
|
||||
QString m_cachefile;
|
||||
QString m_sourceRoot;
|
||||
QString m_buildRoot;
|
||||
QStringList m_qmakepath;
|
||||
QStringList m_qmakefeatures;
|
||||
QStringList m_mkspecPaths;
|
||||
QStringList m_featureRoots;
|
||||
ProString m_dirSep;
|
||||
ProFunctionDefs m_functionDefs;
|
||||
ProStringList m_returnValue;
|
||||
ProValueMapStack m_valuemapStack; // VariableName must be us-ascii, the content however can be non-us-ascii.
|
||||
QString m_tmp1, m_tmp2, m_tmp3, m_tmp[2]; // Temporaries for efficient toQString
|
||||
mutable QString m_mtmp;
|
||||
|
||||
QMakeGlobals *m_option;
|
||||
QMakeParser *m_parser;
|
||||
QMakeHandler *m_handler;
|
||||
};
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(QMakeEvaluator::LoadFlags)
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QMAKEEVALUATOR_H
|
107
qmake/library/qmakeevaluator_p.h
Normal file
107
qmake/library/qmakeevaluator_p.h
Normal file
@ -0,0 +1,107 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/
|
||||
**
|
||||
** This file is part of the qmake application of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** GNU Lesser General Public License Usage
|
||||
** 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, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia 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.
|
||||
**
|
||||
** Other Usage
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QMAKEEVALUATOR_P_H
|
||||
#define QMAKEEVALUATOR_P_H
|
||||
|
||||
#include "proitems.h"
|
||||
|
||||
#include <qregexp.h>
|
||||
|
||||
#define debugMsg if (!m_debugLevel) {} else debugMsgInternal
|
||||
#define traceMsg if (!m_debugLevel) {} else traceMsgInternal
|
||||
#ifdef PROEVALUATOR_DEBUG
|
||||
# define dbgBool(b) (b ? "true" : "false")
|
||||
# define dbgReturn(r) \
|
||||
(r == ReturnError ? "error" : \
|
||||
r == ReturnBreak ? "break" : \
|
||||
r == ReturnNext ? "next" : \
|
||||
r == ReturnReturn ? "return" : \
|
||||
"<invalid>")
|
||||
# define dbgKey(s) qPrintable(s.toString().toQString())
|
||||
# define dbgStr(s) qPrintable(formatValue(s, true))
|
||||
# define dbgStrList(s) qPrintable(formatValueList(s))
|
||||
# define dbgSepStrList(s) qPrintable(formatValueList(s, true))
|
||||
# define dbgStrListList(s) qPrintable(formatValueListList(s))
|
||||
# define dbgQStr(s) dbgStr(ProString(s))
|
||||
#else
|
||||
# define dbgBool(b) 0
|
||||
# define dbgReturn(r) 0
|
||||
# define dbgKey(s) 0
|
||||
# define dbgStr(s) 0
|
||||
# define dbgStrList(s) 0
|
||||
# define dbgSepStrList(s) 0
|
||||
# define dbgStrListList(s) 0
|
||||
# define dbgQStr(s) 0
|
||||
#endif
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
namespace QMakeInternal {
|
||||
|
||||
struct QMakeStatics {
|
||||
QString field_sep;
|
||||
QString strtrue;
|
||||
QString strfalse;
|
||||
ProKey strCONFIG;
|
||||
ProKey strARGS;
|
||||
QString strDot;
|
||||
QString strDotDot;
|
||||
QString strever;
|
||||
QString strforever;
|
||||
QString strhost_build;
|
||||
ProKey strTEMPLATE;
|
||||
#ifdef PROEVALUATOR_FULL
|
||||
ProKey strREQUIRES;
|
||||
#endif
|
||||
QHash<ProKey, int> expands;
|
||||
QHash<ProKey, int> functions;
|
||||
QHash<ProKey, ProKey> varMap;
|
||||
ProStringList fakeValue;
|
||||
};
|
||||
|
||||
extern QMakeStatics statics;
|
||||
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QMAKEEVALUATOR_P_H
|
368
qmake/library/qmakeglobals.cpp
Normal file
368
qmake/library/qmakeglobals.cpp
Normal file
@ -0,0 +1,368 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/
|
||||
**
|
||||
** This file is part of the qmake application of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** GNU Lesser General Public License Usage
|
||||
** 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, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia 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.
|
||||
**
|
||||
** Other Usage
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
** $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>
|
||||
#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;
|
||||
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(" ")));
|
||||
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
|
||||
}
|
||||
|
||||
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_"))) {
|
||||
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
|
173
qmake/library/qmakeglobals.h
Normal file
173
qmake/library/qmakeglobals.h
Normal file
@ -0,0 +1,173 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/
|
||||
**
|
||||
** This file is part of the qmake application of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** GNU Lesser General Public License Usage
|
||||
** 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, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia 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.
|
||||
**
|
||||
** Other Usage
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QMAKEGLOBALS_H
|
||||
#define QMAKEGLOBALS_H
|
||||
|
||||
#include "qmake_global.h"
|
||||
#include "proitems.h"
|
||||
|
||||
#ifdef QT_BUILD_QMAKE
|
||||
# include <property.h>
|
||||
#endif
|
||||
|
||||
#include <qhash.h>
|
||||
#include <qstringlist.h>
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
# include <qprocess.h>
|
||||
#endif
|
||||
#ifdef PROEVALUATOR_THREAD_SAFE
|
||||
# include <qmutex.h>
|
||||
# include <qwaitcondition.h>
|
||||
#endif
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QMakeEvaluator;
|
||||
|
||||
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
|
||||
{
|
||||
public:
|
||||
QMakeBaseEnv();
|
||||
~QMakeBaseEnv();
|
||||
|
||||
#ifdef PROEVALUATOR_THREAD_SAFE
|
||||
QMutex mutex;
|
||||
QWaitCondition cond;
|
||||
bool inProgress;
|
||||
// The coupling of this flag to thread safety exists because for other
|
||||
// use cases failure is immediately fatal anyway.
|
||||
bool isOk;
|
||||
#endif
|
||||
QMakeEvaluator *evaluator;
|
||||
};
|
||||
|
||||
class QMAKE_EXPORT QMakeCmdLineParserState
|
||||
{
|
||||
public:
|
||||
QMakeCmdLineParserState(const QString &_pwd) : pwd(_pwd), after(false) {}
|
||||
QString pwd;
|
||||
QStringList precmds, preconfigs, postcmds, postconfigs;
|
||||
bool after;
|
||||
};
|
||||
|
||||
class QMAKE_EXPORT QMakeGlobals
|
||||
{
|
||||
public:
|
||||
QMakeGlobals();
|
||||
~QMakeGlobals();
|
||||
|
||||
bool do_cache;
|
||||
QString dir_sep;
|
||||
QString dirlist_sep;
|
||||
QString cachefile;
|
||||
#ifdef PROEVALUATOR_SETENV
|
||||
QProcessEnvironment environment;
|
||||
#endif
|
||||
QString qmake_abslocation;
|
||||
|
||||
QString qmakespec, xqmakespec;
|
||||
QString user_template, user_template_prefix;
|
||||
QString precmds, postcmds;
|
||||
|
||||
#ifdef PROEVALUATOR_DEBUG
|
||||
int debugLevel;
|
||||
#endif
|
||||
|
||||
enum ArgumentReturn { ArgumentUnknown, ArgumentMalformed, ArgumentsOk };
|
||||
ArgumentReturn addCommandLineArguments(QMakeCmdLineParserState &state,
|
||||
QStringList &args, int *pos);
|
||||
void commitCommandLineArguments(QMakeCmdLineParserState &state);
|
||||
void setCommandLineArguments(const QString &pwd, const QStringList &args);
|
||||
void useEnvironment();
|
||||
void setDirectories(const QString &input_dir, const QString &output_dir);
|
||||
#ifdef QT_BUILD_QMAKE
|
||||
void setQMakeProperty(QMakeProperty *prop) { property = prop; }
|
||||
ProString propertyValue(const ProKey &name) const { return property->value(name); }
|
||||
#else
|
||||
# ifdef PROEVALUATOR_INIT_PROPS
|
||||
bool initProperties();
|
||||
# else
|
||||
void setProperties(const QHash<QString, QString> &props);
|
||||
# endif
|
||||
ProString propertyValue(const ProKey &name) const { return properties.value(name); }
|
||||
#endif
|
||||
|
||||
QString expandEnvVars(const QString &str) const;
|
||||
QString shadowedPath(const QString &fileName) const;
|
||||
|
||||
private:
|
||||
QString getEnv(const QString &) const;
|
||||
QStringList getPathListEnv(const QString &var) const;
|
||||
|
||||
QString cleanSpec(QMakeCmdLineParserState &state, const QString &spec);
|
||||
|
||||
QString source_root, build_root;
|
||||
|
||||
#ifdef QT_BUILD_QMAKE
|
||||
QMakeProperty *property;
|
||||
#else
|
||||
QHash<ProKey, ProString> properties;
|
||||
#endif
|
||||
|
||||
#ifdef PROEVALUATOR_THREAD_SAFE
|
||||
QMutex mutex;
|
||||
#endif
|
||||
QHash<QMakeBaseKey, QMakeBaseEnv *> baseEnvs;
|
||||
|
||||
friend class QMakeEvaluator;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QMAKEGLOBALS_H
|
1185
qmake/library/qmakeparser.cpp
Normal file
1185
qmake/library/qmakeparser.cpp
Normal file
File diff suppressed because it is too large
Load Diff
214
qmake/library/qmakeparser.h
Normal file
214
qmake/library/qmakeparser.h
Normal file
@ -0,0 +1,214 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/
|
||||
**
|
||||
** This file is part of the qmake application of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** GNU Lesser General Public License Usage
|
||||
** 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, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia 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.
|
||||
**
|
||||
** Other Usage
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QMAKEPARSER_H
|
||||
#define QMAKEPARSER_H
|
||||
|
||||
#include "qmake_global.h"
|
||||
#include "proitems.h"
|
||||
|
||||
#include <qhash.h>
|
||||
#include <qstack.h>
|
||||
#ifdef PROPARSER_THREAD_SAFE
|
||||
# include <qmutex.h>
|
||||
# include <qwaitcondition.h>
|
||||
#endif
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QMAKE_EXPORT QMakeParserHandler
|
||||
{
|
||||
public:
|
||||
enum {
|
||||
CategoryMask = 0xf00,
|
||||
WarningMessage = 0x000,
|
||||
ErrorMessage = 0x100,
|
||||
|
||||
SourceMask = 0xf0,
|
||||
SourceParser = 0,
|
||||
|
||||
CodeMask = 0xf,
|
||||
WarnLanguage = 0,
|
||||
WarnDeprecated,
|
||||
|
||||
ParserWarnLanguage = SourceParser | WarningMessage | WarnLanguage,
|
||||
ParserWarnDeprecated = SourceParser | WarningMessage | WarnDeprecated,
|
||||
|
||||
ParserIoError = ErrorMessage | SourceParser,
|
||||
ParserError
|
||||
};
|
||||
virtual void message(int type, const QString &msg,
|
||||
const QString &fileName = QString(), int lineNo = 0) = 0;
|
||||
};
|
||||
|
||||
class ProFileCache;
|
||||
|
||||
class QMAKE_EXPORT QMakeParser
|
||||
{
|
||||
public:
|
||||
// Call this from a concurrency-free context
|
||||
static void initialize();
|
||||
|
||||
QMakeParser(ProFileCache *cache, QMakeParserHandler *handler);
|
||||
|
||||
enum SubGrammar { FullGrammar, TestGrammar, ValueGrammar };
|
||||
// fileName is expected to be absolute and cleanPath()ed.
|
||||
ProFile *parsedProFile(const QString &fileName, bool cache = false);
|
||||
ProFile *parsedProBlock(const QString &contents, const QString &name, int line = 0,
|
||||
SubGrammar grammar = FullGrammar);
|
||||
|
||||
private:
|
||||
struct BlockScope {
|
||||
BlockScope() : start(0), braceLevel(0), special(false), inBranch(false) {}
|
||||
BlockScope(const BlockScope &other) { *this = other; }
|
||||
ushort *start; // Where this block started; store length here
|
||||
int braceLevel; // Nesting of braces in scope
|
||||
bool special; // Single-line conditionals inside loops, etc. cannot have else branches
|
||||
bool inBranch; // The 'else' branch of the previous TokBranch is still open
|
||||
};
|
||||
|
||||
enum ScopeState {
|
||||
StNew, // Fresh scope
|
||||
StCtrl, // Control statement (for or else) met on current line
|
||||
StCond // Conditionals met on current line
|
||||
};
|
||||
|
||||
enum Context { CtxTest, CtxValue, CtxPureValue, CtxArgs };
|
||||
struct ParseCtx {
|
||||
int parens; // Nesting of non-functional parentheses
|
||||
int argc; // Number of arguments in current function call
|
||||
int wordCount; // Number of words in current expression
|
||||
Context context;
|
||||
ushort quote; // Enclosing quote type
|
||||
ushort terminator; // '}' if replace function call is braced, ':' if test function
|
||||
};
|
||||
|
||||
bool read(ProFile *pro);
|
||||
bool read(ProFile *pro, const QString &content, int line, SubGrammar grammar);
|
||||
|
||||
ALWAYS_INLINE void putTok(ushort *&tokPtr, ushort tok);
|
||||
ALWAYS_INLINE void putBlockLen(ushort *&tokPtr, uint len);
|
||||
ALWAYS_INLINE void putBlock(ushort *&tokPtr, const ushort *buf, uint len);
|
||||
void putHashStr(ushort *&pTokPtr, const ushort *buf, uint len);
|
||||
void finalizeHashStr(ushort *buf, uint len);
|
||||
void putLineMarker(ushort *&tokPtr);
|
||||
ALWAYS_INLINE bool resolveVariable(ushort *xprPtr, int tlen, int needSep, ushort **ptr,
|
||||
ushort **buf, QString *xprBuff,
|
||||
ushort **tokPtr, QString *tokBuff,
|
||||
const ushort *cur, const QString &in);
|
||||
void finalizeCond(ushort *&tokPtr, ushort *uc, ushort *ptr, int wordCount);
|
||||
void finalizeCall(ushort *&tokPtr, ushort *uc, ushort *ptr, int argc);
|
||||
void finalizeTest(ushort *&tokPtr);
|
||||
void bogusTest(ushort *&tokPtr);
|
||||
void enterScope(ushort *&tokPtr, bool special, ScopeState state);
|
||||
void leaveScope(ushort *&tokPtr);
|
||||
void flushCond(ushort *&tokPtr);
|
||||
void flushScopes(ushort *&tokPtr);
|
||||
|
||||
void message(int type, const QString &msg) const;
|
||||
void parseError(const QString &msg) const
|
||||
{ message(QMakeParserHandler::ParserError, msg); }
|
||||
void languageWarning(const QString &msg) const
|
||||
{ message(QMakeParserHandler::ParserWarnLanguage, msg); }
|
||||
void deprecationWarning(const QString &msg) const
|
||||
{ message(QMakeParserHandler::ParserWarnDeprecated, msg); }
|
||||
|
||||
// Current location
|
||||
ProFile *m_proFile;
|
||||
int m_lineNo;
|
||||
|
||||
QStack<BlockScope> m_blockstack;
|
||||
ScopeState m_state;
|
||||
int m_markLine; // Put marker for this line
|
||||
bool m_inError; // Current line had a parsing error; suppress followup error messages
|
||||
bool m_canElse; // Conditionals met on previous line, but no scope was opened
|
||||
bool m_invert; // Pending conditional is negated
|
||||
enum { NoOperator, AndOperator, OrOperator } m_operator; // Pending conditional is ORed/ANDed
|
||||
|
||||
QString m_tmp; // Temporary for efficient toQString
|
||||
|
||||
ProFileCache *m_cache;
|
||||
QMakeParserHandler *m_handler;
|
||||
|
||||
// This doesn't help gcc 3.3 ...
|
||||
template<typename T> friend class QTypeInfo;
|
||||
|
||||
friend class ProFileCache;
|
||||
};
|
||||
|
||||
class QMAKE_EXPORT ProFileCache
|
||||
{
|
||||
public:
|
||||
ProFileCache() {}
|
||||
~ProFileCache();
|
||||
|
||||
void discardFile(const QString &fileName);
|
||||
void discardFiles(const QString &prefix);
|
||||
|
||||
private:
|
||||
struct Entry {
|
||||
ProFile *pro;
|
||||
#ifdef PROPARSER_THREAD_SAFE
|
||||
struct Locker {
|
||||
Locker() : waiters(0), done(false) {}
|
||||
QWaitCondition cond;
|
||||
int waiters;
|
||||
bool done;
|
||||
};
|
||||
Locker *locker;
|
||||
#endif
|
||||
};
|
||||
|
||||
QHash<QString, Entry> parsed_files;
|
||||
#ifdef PROPARSER_THREAD_SAFE
|
||||
QMutex mutex;
|
||||
#endif
|
||||
|
||||
friend class QMakeParser;
|
||||
};
|
||||
|
||||
#if !defined(__GNUC__) || __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 3)
|
||||
Q_DECLARE_TYPEINFO(QMakeParser::BlockScope, Q_MOVABLE_TYPE);
|
||||
Q_DECLARE_TYPEINFO(QMakeParser::Context, Q_PRIMITIVE_TYPE);
|
||||
#endif
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // PROFILEPARSER_H
|
@ -85,6 +85,9 @@ int runQMake(int argc, char **argv)
|
||||
// This is particularly important for things like QtCreator and scripted builds.
|
||||
setvbuf(stdout, (char *)NULL, _IONBF, 0);
|
||||
|
||||
QMakeGlobals globals;
|
||||
Option::globals = &globals;
|
||||
|
||||
// parse command line
|
||||
int ret = Option::init(argc, argv);
|
||||
if(ret != Option::QMAKE_CMDLINE_SUCCESS) {
|
||||
@ -125,8 +128,14 @@ int runQMake(int argc, char **argv)
|
||||
Option::qmake_mode == Option::QMAKE_SET_PROPERTY ||
|
||||
Option::qmake_mode == Option::QMAKE_UNSET_PROPERTY)
|
||||
return prop.exec() ? 0 : 101;
|
||||
globals.setQMakeProperty(&prop);
|
||||
|
||||
QMakeProject project(&prop);
|
||||
ProFileCache proFileCache;
|
||||
Option::proFileCache = &proFileCache;
|
||||
QMakeParser parser(&proFileCache, &Option::evalHandler);
|
||||
Option::parser = &parser;
|
||||
|
||||
QMakeProject project;
|
||||
int exit_val = 0;
|
||||
QStringList files;
|
||||
if(Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT)
|
||||
|
@ -76,7 +76,7 @@ QMakeMetaInfo::readLib(QString lib)
|
||||
meta_type = "libtool";
|
||||
} else if(meta_file.endsWith(Option::prl_ext)) {
|
||||
QMakeProject proj;
|
||||
if(!proj.read(Option::normalizePath(meta_file), QMakeProject::ReadProFile))
|
||||
if (!proj.read(Option::normalizePath(meta_file), QMakeEvaluator::LoadProOnly))
|
||||
return false;
|
||||
meta_type = "qmake";
|
||||
vars = proj.variables();
|
||||
@ -136,7 +136,7 @@ QMakeMetaInfo::readLibtoolFile(const QString &f)
|
||||
/* I can just run the .la through the .pro parser since they are compatible.. */
|
||||
QMakeProject proj;
|
||||
QString nf = Option::normalizePath(f);
|
||||
if(!proj.read(nf, QMakeProject::ReadProFile))
|
||||
if (!proj.read(nf, QMakeEvaluator::LoadProOnly))
|
||||
return false;
|
||||
QString dirf = nf.section(QLatin1Char('/'), 0, -2);
|
||||
if(dirf == nf)
|
||||
|
295
qmake/option.cpp
295
qmake/option.cpp
@ -51,6 +51,11 @@
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
EvalHandler Option::evalHandler;
|
||||
QMakeGlobals *Option::globals;
|
||||
ProFileCache *Option::proFileCache;
|
||||
QMakeParser *Option::parser;
|
||||
|
||||
//convenience
|
||||
const char *Option::application_argv0 = 0;
|
||||
QString Option::prf_ext;
|
||||
@ -67,7 +72,6 @@ QString Option::lex_ext;
|
||||
QString Option::yacc_ext;
|
||||
QString Option::pro_ext;
|
||||
QString Option::dir_sep;
|
||||
QString Option::dirlist_sep;
|
||||
QString Option::h_moc_mod;
|
||||
QString Option::yacc_mod;
|
||||
QString Option::lex_mod;
|
||||
@ -78,17 +82,12 @@ char Option::field_sep;
|
||||
Option::QMAKE_MODE Option::qmake_mode = Option::QMAKE_GENERATE_NOTHING;
|
||||
|
||||
//all modes
|
||||
QString Option::qmake_abslocation;
|
||||
QStringList Option::qmake_args;
|
||||
int Option::warn_level = WarnLogic | WarnDeprecated;
|
||||
int Option::debug_level = 0;
|
||||
QFile Option::output;
|
||||
QString Option::output_dir;
|
||||
bool Option::recursive = false;
|
||||
QStringList Option::before_user_vars;
|
||||
QStringList Option::after_user_vars;
|
||||
QString Option::user_template;
|
||||
QString Option::user_template_prefix;
|
||||
|
||||
//QMAKE_*_PROPERTY stuff
|
||||
QStringList Option::prop::properties;
|
||||
@ -98,18 +97,12 @@ bool Option::projfile::do_pwd = true;
|
||||
QStringList Option::projfile::project_dirs;
|
||||
|
||||
//QMAKE_GENERATE_MAKEFILE stuff
|
||||
QString Option::mkfile::qmakespec;
|
||||
QString Option::mkfile::xqmakespec;
|
||||
int Option::mkfile::cachefile_depth = -1;
|
||||
bool Option::mkfile::do_deps = true;
|
||||
bool Option::mkfile::do_mocs = true;
|
||||
bool Option::mkfile::do_dep_heuristics = true;
|
||||
bool Option::mkfile::do_preprocess = false;
|
||||
bool Option::mkfile::do_stub_makefile = false;
|
||||
bool Option::mkfile::do_cache = true;
|
||||
QString Option::mkfile::source_root;
|
||||
QString Option::mkfile::build_root;
|
||||
QString Option::mkfile::cachefile;
|
||||
QStringList Option::mkfile::project_files;
|
||||
|
||||
static Option::QMAKE_MODE default_mode(QString progname)
|
||||
@ -138,17 +131,6 @@ static QString detectProjectFile(const QString &path)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static QString cleanSpec(const QString &spec)
|
||||
{
|
||||
QString ret = QDir::cleanPath(spec);
|
||||
if (ret.contains('/')) {
|
||||
const QFileInfo specDirInfo(ret);
|
||||
if (specDirInfo.exists() && specDirInfo.isDir())
|
||||
ret = QDir::cleanPath(specDirInfo.absoluteFilePath());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
QString project_builtin_regx();
|
||||
bool usage(const char *a0)
|
||||
{
|
||||
@ -213,102 +195,87 @@ bool usage(const char *a0)
|
||||
int
|
||||
Option::parseCommandLine(QStringList &args)
|
||||
{
|
||||
QStringList user_configs;
|
||||
|
||||
bool before = true;
|
||||
args << QString(); // Avoid bounds checking for options which take an argument
|
||||
for (int x = 0; x < args.size() - 1; ) {
|
||||
QString arg = args.at(x);
|
||||
if (arg.size() > 1 && arg.startsWith('-')) { /* options */
|
||||
QString opt = arg.mid(1);
|
||||
if(opt == "o" || opt == "output") {
|
||||
Option::output.setFileName(args.at(x + 1));
|
||||
args.erase(args.begin() + x, args.begin() + x + 2);
|
||||
continue;
|
||||
} else if(opt == "after") {
|
||||
before = false;
|
||||
} else if(opt == "t" || opt == "template") {
|
||||
Option::user_template = args.at(++x);
|
||||
} else if(opt == "tp" || opt == "template_prefix") {
|
||||
Option::user_template_prefix = args.at(++x);
|
||||
} else if(opt == "unix") {
|
||||
Option::dir_sep = "/";
|
||||
} else if(opt == "win32") {
|
||||
Option::dir_sep = "\\";
|
||||
} else if(opt == "d") {
|
||||
Option::debug_level++;
|
||||
} else if(opt == "version" || opt == "v" || opt == "-version") {
|
||||
fprintf(stdout,
|
||||
"QMake version %s\n"
|
||||
"Using Qt version %s in %s\n",
|
||||
qmake_version(), QT_VERSION_STR,
|
||||
QLibraryInfo::location(QLibraryInfo::LibrariesPath).toLatin1().constData());
|
||||
QMakeCmdLineParserState state(QDir::currentPath());
|
||||
enum { ArgNone, ArgOutput } argState = ArgNone;
|
||||
int x = 0;
|
||||
while (x < args.count()) {
|
||||
switch (argState) {
|
||||
case ArgOutput:
|
||||
Option::output.setFileName(args.at(x--));
|
||||
args.erase(args.begin() + x, args.begin() + x + 2);
|
||||
argState = ArgNone;
|
||||
continue;
|
||||
default:
|
||||
QMakeGlobals::ArgumentReturn cmdRet = globals->addCommandLineArguments(state, args, &x);
|
||||
if (cmdRet == QMakeGlobals::ArgumentsOk)
|
||||
break;
|
||||
if (cmdRet == QMakeGlobals::ArgumentMalformed) {
|
||||
fprintf(stderr, "***Option %s requires a parameter\n", qPrintable(args.at(x - 1)));
|
||||
return Option::QMAKE_CMDLINE_SHOW_USAGE | Option::QMAKE_CMDLINE_ERROR;
|
||||
}
|
||||
Q_ASSERT(cmdRet == QMakeGlobals::ArgumentUnknown);
|
||||
QString arg = args.at(x);
|
||||
if (arg.startsWith(QLatin1Char('-'))) {
|
||||
if (arg == "-d") {
|
||||
Option::debug_level++;
|
||||
} else if (arg == "-v" || arg == "-version" || arg == "--version") {
|
||||
fprintf(stdout,
|
||||
"QMake version %s\n"
|
||||
"Using Qt version %s in %s\n",
|
||||
qmake_version(), QT_VERSION_STR,
|
||||
QLibraryInfo::location(QLibraryInfo::LibrariesPath).toLatin1().constData());
|
||||
#ifdef QMAKE_OPENSOURCE_VERSION
|
||||
fprintf(stdout, "QMake is Open Source software from Nokia Corporation and/or its subsidiary(-ies).\n");
|
||||
fprintf(stdout, "QMake is Open Source software from Nokia Corporation and/or its subsidiary(-ies).\n");
|
||||
#endif
|
||||
return Option::QMAKE_CMDLINE_BAIL;
|
||||
} else if(opt == "h" || opt == "help") {
|
||||
return Option::QMAKE_CMDLINE_SHOW_USAGE;
|
||||
} else if(opt == "Wall") {
|
||||
Option::warn_level |= WarnAll;
|
||||
} else if(opt == "Wparser") {
|
||||
Option::warn_level |= WarnParser;
|
||||
} else if(opt == "Wlogic") {
|
||||
Option::warn_level |= WarnLogic;
|
||||
} else if(opt == "Wdeprecated") {
|
||||
Option::warn_level |= WarnDeprecated;
|
||||
} else if(opt == "Wnone") {
|
||||
Option::warn_level = WarnNone;
|
||||
} else if(opt == "r" || opt == "recursive") {
|
||||
Option::recursive = true;
|
||||
args.removeAt(x);
|
||||
continue;
|
||||
} else if(opt == "nr" || opt == "norecursive") {
|
||||
Option::recursive = false;
|
||||
args.removeAt(x);
|
||||
continue;
|
||||
} else if(opt == "config") {
|
||||
user_configs += args.at(++x);
|
||||
} else {
|
||||
if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE ||
|
||||
Option::qmake_mode == Option::QMAKE_GENERATE_PRL) {
|
||||
if(opt == "nodepend" || opt == "nodepends") {
|
||||
Option::mkfile::do_deps = false;
|
||||
} else if(opt == "nomoc") {
|
||||
Option::mkfile::do_mocs = false;
|
||||
} else if(opt == "nocache") {
|
||||
Option::mkfile::do_cache = false;
|
||||
} else if(opt == "createstub") {
|
||||
Option::mkfile::do_stub_makefile = true;
|
||||
} else if(opt == "nodependheuristics") {
|
||||
Option::mkfile::do_dep_heuristics = false;
|
||||
} else if(opt == "E") {
|
||||
Option::mkfile::do_preprocess = true;
|
||||
} else if(opt == "cache") {
|
||||
Option::mkfile::cachefile = args.at(++x);
|
||||
} else if(opt == "platform" || opt == "spec") {
|
||||
Option::mkfile::qmakespec = args[x] = cleanSpec(args.at(++x));
|
||||
} else if (opt == "xplatform" || opt == "xspec") {
|
||||
Option::mkfile::xqmakespec = args[x] = cleanSpec(args.at(x));
|
||||
} else {
|
||||
fprintf(stderr, "***Unknown option -%s\n", opt.toLatin1().constData());
|
||||
return Option::QMAKE_CMDLINE_SHOW_USAGE | Option::QMAKE_CMDLINE_ERROR;
|
||||
}
|
||||
} else if(Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT) {
|
||||
if(opt == "nopwd") {
|
||||
Option::projfile::do_pwd = false;
|
||||
} else {
|
||||
fprintf(stderr, "***Unknown option -%s\n", opt.toLatin1().constData());
|
||||
return Option::QMAKE_CMDLINE_SHOW_USAGE | Option::QMAKE_CMDLINE_ERROR;
|
||||
return Option::QMAKE_CMDLINE_BAIL;
|
||||
} else if (arg == "-h" || arg == "-help" || arg == "--help") {
|
||||
return Option::QMAKE_CMDLINE_SHOW_USAGE;
|
||||
} else if (arg == "-Wall") {
|
||||
Option::warn_level |= WarnAll;
|
||||
} else if (arg == "-Wparser") {
|
||||
Option::warn_level |= WarnParser;
|
||||
} else if (arg == "-Wlogic") {
|
||||
Option::warn_level |= WarnLogic;
|
||||
} else if (arg == "-Wdeprecated") {
|
||||
Option::warn_level |= WarnDeprecated;
|
||||
} else if (arg == "-Wnone") {
|
||||
Option::warn_level = WarnNone;
|
||||
} else if (arg == "-r" || arg == "-recursive") {
|
||||
Option::recursive = true;
|
||||
args.removeAt(x);
|
||||
continue;
|
||||
} else if (arg == "-nr" || arg == "-norecursive") {
|
||||
Option::recursive = false;
|
||||
args.removeAt(x);
|
||||
continue;
|
||||
} else if (arg == "-o" || arg == "-output") {
|
||||
argState = ArgOutput;
|
||||
} else {
|
||||
if (Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE ||
|
||||
Option::qmake_mode == Option::QMAKE_GENERATE_PRL) {
|
||||
if (arg == "-nodepend" || arg == "-nodepends") {
|
||||
Option::mkfile::do_deps = false;
|
||||
} else if (arg == "-nomoc") {
|
||||
Option::mkfile::do_mocs = false;
|
||||
} else if (arg == "-createstub") {
|
||||
Option::mkfile::do_stub_makefile = true;
|
||||
} else if (arg == "-nodependheuristics") {
|
||||
Option::mkfile::do_dep_heuristics = false;
|
||||
} else if (arg == "-E") {
|
||||
Option::mkfile::do_preprocess = true;
|
||||
} else {
|
||||
fprintf(stderr, "***Unknown option %s\n", arg.toLatin1().constData());
|
||||
return Option::QMAKE_CMDLINE_SHOW_USAGE | Option::QMAKE_CMDLINE_ERROR;
|
||||
}
|
||||
} else if (Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT) {
|
||||
if (arg == "-nopwd") {
|
||||
Option::projfile::do_pwd = false;
|
||||
} else {
|
||||
fprintf(stderr, "***Unknown option %s\n", arg.toLatin1().constData());
|
||||
return Option::QMAKE_CMDLINE_SHOW_USAGE | Option::QMAKE_CMDLINE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(arg.indexOf('=') != -1) {
|
||||
if(before)
|
||||
Option::before_user_vars.append(arg);
|
||||
else
|
||||
Option::after_user_vars.append(arg);
|
||||
} else {
|
||||
bool handled = true;
|
||||
if(Option::qmake_mode == Option::QMAKE_QUERY_PROPERTY ||
|
||||
@ -342,14 +309,12 @@ Option::parseCommandLine(QStringList &args)
|
||||
}
|
||||
x++;
|
||||
}
|
||||
|
||||
if (!user_configs.isEmpty())
|
||||
Option::before_user_vars += "CONFIG += " + user_configs.join(" ");
|
||||
|
||||
if (Option::mkfile::xqmakespec.isEmpty())
|
||||
Option::mkfile::xqmakespec = Option::mkfile::qmakespec;
|
||||
|
||||
args.takeLast();
|
||||
if (argState != ArgNone) {
|
||||
fprintf(stderr, "***Option %s requires a parameter\n", qPrintable(args.at(x - 1)));
|
||||
return Option::QMAKE_CMDLINE_SHOW_USAGE | Option::QMAKE_CMDLINE_ERROR;
|
||||
}
|
||||
globals->commitCommandLineArguments(state);
|
||||
globals->debugLevel = Option::debug_level;
|
||||
return Option::QMAKE_CMDLINE_SUCCESS;
|
||||
}
|
||||
|
||||
@ -359,13 +324,6 @@ Option::init(int argc, char **argv)
|
||||
Option::application_argv0 = 0;
|
||||
Option::prf_ext = ".prf";
|
||||
Option::pro_ext = ".pro";
|
||||
#ifdef Q_OS_WIN
|
||||
Option::dir_sep = "\\";
|
||||
Option::dirlist_sep = ";";
|
||||
#else
|
||||
Option::dir_sep = "/";
|
||||
Option::dirlist_sep = ":";
|
||||
#endif
|
||||
Option::field_sep = ' ';
|
||||
|
||||
if(argc && argv) {
|
||||
@ -374,13 +332,13 @@ Option::init(int argc, char **argv)
|
||||
if(Option::qmake_mode == Option::QMAKE_GENERATE_NOTHING)
|
||||
Option::qmake_mode = default_mode(argv0);
|
||||
if(!argv0.isEmpty() && !QFileInfo(argv0).isRelative()) {
|
||||
Option::qmake_abslocation = argv0;
|
||||
globals->qmake_abslocation = argv0;
|
||||
} else if (argv0.contains(QLatin1Char('/'))
|
||||
#ifdef Q_OS_WIN
|
||||
|| argv0.contains(QLatin1Char('\\'))
|
||||
#endif
|
||||
) { //relative PWD
|
||||
Option::qmake_abslocation = QDir::current().absoluteFilePath(argv0);
|
||||
globals->qmake_abslocation = QDir::current().absoluteFilePath(argv0);
|
||||
} else { //in the PATH
|
||||
QByteArray pEnv = qgetenv("PATH");
|
||||
QDir currentDir = QDir::current();
|
||||
@ -397,16 +355,16 @@ Option::init(int argc, char **argv)
|
||||
candidate += ".exe";
|
||||
#endif
|
||||
if (QFile::exists(candidate)) {
|
||||
Option::qmake_abslocation = candidate;
|
||||
globals->qmake_abslocation = candidate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!Option::qmake_abslocation.isNull())
|
||||
Option::qmake_abslocation = QDir::cleanPath(Option::qmake_abslocation);
|
||||
if (!globals->qmake_abslocation.isNull())
|
||||
globals->qmake_abslocation = QDir::cleanPath(globals->qmake_abslocation);
|
||||
else // This is rather unlikely to ever happen on a modern system ...
|
||||
Option::qmake_abslocation = QLibraryInfo::rawLocation(QLibraryInfo::HostBinariesPath,
|
||||
QLibraryInfo::EffectivePaths) +
|
||||
globals->qmake_abslocation = QLibraryInfo::rawLocation(QLibraryInfo::HostBinariesPath,
|
||||
QLibraryInfo::EffectivePaths) +
|
||||
#ifdef Q_OS_WIN
|
||||
"/qmake.exe";
|
||||
#else
|
||||
@ -485,13 +443,7 @@ Option::init(int argc, char **argv)
|
||||
//last chance for defaults
|
||||
if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE ||
|
||||
Option::qmake_mode == Option::QMAKE_GENERATE_PRL) {
|
||||
if (Option::mkfile::xqmakespec.isEmpty())
|
||||
Option::mkfile::xqmakespec = QString::fromLocal8Bit(qgetenv("XQMAKESPEC").constData());
|
||||
if (Option::mkfile::qmakespec.isEmpty()) {
|
||||
Option::mkfile::qmakespec = QString::fromLocal8Bit(qgetenv("QMAKESPEC").constData());
|
||||
if (Option::mkfile::xqmakespec.isEmpty())
|
||||
Option::mkfile::xqmakespec = Option::mkfile::qmakespec;
|
||||
}
|
||||
globals->useEnvironment();
|
||||
|
||||
//try REALLY hard to do it for them, lazy..
|
||||
if(Option::mkfile::project_files.isEmpty()) {
|
||||
@ -513,23 +465,7 @@ Option::init(int argc, char **argv)
|
||||
void Option::prepareProject(const QString &pfile)
|
||||
{
|
||||
QString srcpath = QDir::cleanPath(QFileInfo(pfile).absolutePath());
|
||||
if (srcpath != output_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;
|
||||
mkfile::source_root = srcpath.left(srcLen + lastSl);
|
||||
mkfile::build_root = dstpath.left(dstLen + lastSl);
|
||||
} else {
|
||||
mkfile::source_root.clear();
|
||||
}
|
||||
globals->setDirectories(srcpath, output_dir);
|
||||
}
|
||||
|
||||
bool Option::postProcessProject(QMakeProject *project)
|
||||
@ -550,6 +486,8 @@ bool Option::postProcessProject(QMakeProject *project)
|
||||
Option::lex_mod = project->first("QMAKE_MOD_LEX").toQString();
|
||||
Option::yacc_mod = project->first("QMAKE_MOD_YACC").toQString();
|
||||
|
||||
Option::dir_sep = project->dirSep().toQString();
|
||||
|
||||
if (Option::output_dir.startsWith(project->buildRoot()))
|
||||
Option::mkfile::cachefile_depth =
|
||||
Option::output_dir.mid(project->buildRoot().length()).count('/');
|
||||
@ -665,6 +603,37 @@ void warn_msg(QMakeWarn type, const char *fmt, ...)
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
void EvalHandler::message(int type, const QString &msg, const QString &fileName, int lineNo)
|
||||
{
|
||||
QString pfx;
|
||||
if ((type & QMakeHandler::CategoryMask) == QMakeHandler::WarningMessage) {
|
||||
int code = (type & QMakeHandler::CodeMask);
|
||||
if ((code == QMakeHandler::WarnLanguage && !(Option::warn_level & WarnParser))
|
||||
|| (code == QMakeHandler::WarnDeprecated && !(Option::warn_level & WarnDeprecated)))
|
||||
return;
|
||||
pfx = QString::fromLatin1("WARNING: ");
|
||||
}
|
||||
if (lineNo > 0)
|
||||
fprintf(stderr, "%s%s:%d: %s\n", qPrintable(pfx), qPrintable(fileName), lineNo, qPrintable(msg));
|
||||
else if (lineNo)
|
||||
fprintf(stderr, "%s%s: %s\n", qPrintable(pfx), qPrintable(fileName), qPrintable(msg));
|
||||
else
|
||||
fprintf(stderr, "%s%s\n", qPrintable(pfx), qPrintable(msg));
|
||||
}
|
||||
|
||||
void EvalHandler::fileMessage(const QString &msg)
|
||||
{
|
||||
fprintf(stderr, "%s\n", qPrintable(msg));
|
||||
}
|
||||
|
||||
void EvalHandler::aboutToEval(ProFile *, ProFile *, EvalFileType)
|
||||
{
|
||||
}
|
||||
|
||||
void EvalHandler::doneWithEval(ProFile *)
|
||||
{
|
||||
}
|
||||
|
||||
class QMakeCacheClearItem {
|
||||
private:
|
||||
qmakeCacheClearFunc func;
|
||||
@ -693,8 +662,8 @@ qmakeAddCacheClear(qmakeCacheClearFunc func, void **data)
|
||||
|
||||
QString qmake_libraryInfoFile()
|
||||
{
|
||||
if(!Option::qmake_abslocation.isEmpty())
|
||||
return QDir(QFileInfo(Option::qmake_abslocation).absolutePath()).filePath("qt.conf");
|
||||
if (!Option::globals->qmake_abslocation.isEmpty())
|
||||
return QDir(QFileInfo(Option::globals->qmake_abslocation).absolutePath()).filePath("qt.conf");
|
||||
return QString();
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,10 @@
|
||||
#ifndef OPTION_H
|
||||
#define OPTION_H
|
||||
|
||||
#include "project.h"
|
||||
#include <qmakeglobals.h>
|
||||
#include <qmakeparser.h>
|
||||
#include <qmakeevaluator.h>
|
||||
|
||||
#include <qstring.h>
|
||||
#include <qstringlist.h>
|
||||
#include <qfile.h>
|
||||
@ -69,8 +72,26 @@ enum QMakeWarn {
|
||||
};
|
||||
void warn_msg(QMakeWarn t, const char *fmt, ...);
|
||||
|
||||
class QMakeProject;
|
||||
|
||||
class EvalHandler : public QMakeHandler {
|
||||
public:
|
||||
void message(int type, const QString &msg, const QString &fileName, int lineNo);
|
||||
|
||||
void fileMessage(const QString &msg);
|
||||
|
||||
void aboutToEval(ProFile *, ProFile *, EvalFileType);
|
||||
void doneWithEval(ProFile *);
|
||||
};
|
||||
|
||||
struct Option
|
||||
{
|
||||
static EvalHandler evalHandler;
|
||||
|
||||
static QMakeGlobals *globals;
|
||||
static ProFileCache *proFileCache;
|
||||
static QMakeParser *parser;
|
||||
|
||||
//simply global convenience
|
||||
static QString libtool_ext;
|
||||
static QString pkgcfg_ext;
|
||||
@ -88,7 +109,6 @@ struct Option
|
||||
static QString lex_mod;
|
||||
static QString yacc_mod;
|
||||
static QString dir_sep;
|
||||
static QString dirlist_sep;
|
||||
static QString pro_ext;
|
||||
static QString res_ext;
|
||||
static char field_sep;
|
||||
@ -160,15 +180,12 @@ struct Option
|
||||
static QMAKE_MODE qmake_mode;
|
||||
|
||||
//all modes
|
||||
static QString qmake_abslocation;
|
||||
static QStringList qmake_args;
|
||||
static QFile output;
|
||||
static QString output_dir;
|
||||
static int debug_level;
|
||||
static int warn_level;
|
||||
static bool recursive;
|
||||
static QStringList before_user_vars, after_user_vars;
|
||||
static QString user_template, user_template_prefix;
|
||||
|
||||
//QMAKE_*_PROPERTY options
|
||||
struct prop {
|
||||
@ -183,17 +200,11 @@ struct Option
|
||||
|
||||
//QMAKE_GENERATE_MAKEFILE options
|
||||
struct mkfile {
|
||||
static QString qmakespec;
|
||||
static QString xqmakespec;
|
||||
static bool do_cache;
|
||||
static bool do_deps;
|
||||
static bool do_mocs;
|
||||
static bool do_dep_heuristics;
|
||||
static bool do_preprocess;
|
||||
static bool do_stub_makefile;
|
||||
static QString source_root;
|
||||
static QString build_root;
|
||||
static QString cachefile;
|
||||
static int cachefile_depth;
|
||||
static QStringList project_files;
|
||||
};
|
||||
@ -203,7 +214,7 @@ private:
|
||||
};
|
||||
|
||||
inline QString fixEnvVariables(const QString &x) { return Option::fixString(x, Option::FixEnvVars); }
|
||||
inline QStringList splitPathList(const QString &paths) { return paths.isEmpty() ? QStringList() : paths.split(Option::dirlist_sep); }
|
||||
inline QStringList splitPathList(const QString &paths) { return paths.isEmpty() ? QStringList() : paths.split(Option::globals->dirlist_sep); }
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
|
3758
qmake/project.cpp
3758
qmake/project.cpp
File diff suppressed because it is too large
Load Diff
171
qmake/project.h
171
qmake/project.h
@ -42,165 +42,54 @@
|
||||
#ifndef PROJECT_H
|
||||
#define PROJECT_H
|
||||
|
||||
#include <proitems.h>
|
||||
|
||||
#include <qstringlist.h>
|
||||
#include <qtextstream.h>
|
||||
#include <qstring.h>
|
||||
#include <qstack.h>
|
||||
#include <qhash.h>
|
||||
#include <qmetatype.h>
|
||||
#include <qmakeevaluator.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QMakeProperty;
|
||||
|
||||
struct ParsableBlock;
|
||||
struct IteratorBlock;
|
||||
struct FunctionBlock;
|
||||
|
||||
class QMakeProject
|
||||
class QMakeProject : private QMakeEvaluator
|
||||
{
|
||||
struct ScopeBlock
|
||||
{
|
||||
enum TestStatus { TestNone, TestFound, TestSeek };
|
||||
ScopeBlock() : iterate(0), ignore(false), else_status(TestNone) { }
|
||||
ScopeBlock(bool i) : iterate(0), ignore(i), else_status(TestNone) { }
|
||||
~ScopeBlock();
|
||||
IteratorBlock *iterate;
|
||||
uint ignore : 1, else_status : 2;
|
||||
};
|
||||
friend struct ParsableBlock;
|
||||
friend struct IteratorBlock;
|
||||
friend struct FunctionBlock;
|
||||
|
||||
QStack<ScopeBlock> scope_blocks;
|
||||
QStack<FunctionBlock *> function_blocks;
|
||||
IteratorBlock *iterator;
|
||||
FunctionBlock *function;
|
||||
QHash<QString, FunctionBlock*> testFunctions, replaceFunctions;
|
||||
|
||||
bool host_build;
|
||||
bool need_restart;
|
||||
bool own_prop;
|
||||
bool backslashWarned;
|
||||
QString project_build_root;
|
||||
QString conffile;
|
||||
QString superfile;
|
||||
QString cachefile;
|
||||
QString real_spec, short_spec;
|
||||
QString pfile;
|
||||
QMakeProperty *prop;
|
||||
void reset();
|
||||
ProStringList extra_configs;
|
||||
ProValueMap extra_vars;
|
||||
QHash<QString, QStringList> vars, init_vars, base_vars;
|
||||
bool parse(const QString &text, QHash<QString, QStringList> &place, int line_count=1);
|
||||
|
||||
enum IncludeStatus {
|
||||
IncludeSuccess,
|
||||
IncludeFeatureAlreadyLoaded,
|
||||
IncludeFailure,
|
||||
IncludeNoExist,
|
||||
IncludeParseFailure
|
||||
};
|
||||
enum IncludeFlags {
|
||||
IncludeFlagNone = 0x00,
|
||||
IncludeFlagFeature = 0x01,
|
||||
IncludeFlagNewParser = 0x02,
|
||||
IncludeFlagNewProject = 0x04
|
||||
};
|
||||
IncludeStatus doProjectInclude(QString file, uchar flags, QHash<QString, QStringList> &place);
|
||||
|
||||
bool doProjectCheckReqs(const QStringList &deps, QHash<QString, QStringList> &place);
|
||||
bool doVariableReplace(QString &str, QHash<QString, QStringList> &place);
|
||||
QStringList doVariableReplaceExpand(const QString &str, QHash<QString, QStringList> &place, bool *ok=0);
|
||||
void init(QMakeProperty *);
|
||||
void cleanup();
|
||||
void loadDefaults();
|
||||
void setupProject();
|
||||
QStringList &values(const QString &v, QHash<QString, QStringList> &place);
|
||||
QStringList magicValues(const QString &v, const QHash<QString, QStringList> &place) const;
|
||||
QStringList qmakeFeaturePaths();
|
||||
QString m_projectFile;
|
||||
|
||||
public:
|
||||
QMakeProject(QMakeProperty *p = 0) { init(p); }
|
||||
QMakeProject(QMakeProject *p, const QHash<QString, QStringList> *nvars=0);
|
||||
~QMakeProject();
|
||||
QMakeProject();
|
||||
QMakeProject(QMakeProject *p);
|
||||
|
||||
void setExtraVars(const ProValueMap &_vars) { extra_vars = _vars; }
|
||||
void setExtraConfigs(const ProStringList &_cfgs) { extra_configs = _cfgs; }
|
||||
bool read(const QString &project, LoadFlags what = LoadAll);
|
||||
|
||||
enum { ReadProFile=0x01, ReadSetup=0x02, ReadFeatures=0x04, ReadAll=0xFF };
|
||||
inline bool parse(const QString &text) { return parse(text, vars); }
|
||||
bool read(const QString &project, uchar cmd=ReadAll);
|
||||
bool read(uchar cmd=ReadAll);
|
||||
QString projectFile() const { return m_projectFile; }
|
||||
QString buildRoot() const { return m_buildRoot; }
|
||||
QString confFile() const { return m_conffile; }
|
||||
QString cacheFile() const { return m_cachefile; }
|
||||
QString specDir() const { return m_qmakespecFull; }
|
||||
|
||||
QStringList userExpandFunctions() { return replaceFunctions.keys(); }
|
||||
QStringList userTestFunctions() { return testFunctions.keys(); }
|
||||
|
||||
QString projectFile();
|
||||
QString buildRoot() const { return project_build_root; }
|
||||
QString confFile() const { return conffile; }
|
||||
QString cacheFile() const { return cachefile; }
|
||||
QString specDir() const { return real_spec; }
|
||||
inline QMakeProperty *properties() { return prop; }
|
||||
|
||||
bool doProjectTest(QString str, QHash<QString, QStringList> &place);
|
||||
bool doProjectTest(QString func, const QString ¶ms,
|
||||
QHash<QString, QStringList> &place);
|
||||
bool doProjectTest(QString func, QStringList args,
|
||||
QHash<QString, QStringList> &place);
|
||||
bool doProjectTest(QString func, QList<QStringList> args,
|
||||
QHash<QString, QStringList> &place);
|
||||
QStringList doProjectExpand(QString func, const QString ¶ms,
|
||||
QHash<QString, QStringList> &place);
|
||||
QStringList doProjectExpand(QString func, QStringList args,
|
||||
QHash<QString, QStringList> &place);
|
||||
QStringList doProjectExpand(QString func, QList<QStringList> args,
|
||||
QHash<QString, QStringList> &place);
|
||||
|
||||
QStringList expand(const QString &v);
|
||||
QString expand(const QString &v, const QString &file, int line);
|
||||
ProString expand(const QString &v, const QString &file, int line);
|
||||
QStringList expand(const ProKey &func, const QList<ProStringList> &args);
|
||||
bool test(const QString &v);
|
||||
bool test(const QString &v)
|
||||
{ m_current.clear(); return evaluateConditional(v, QStringLiteral("(generator)")); }
|
||||
bool test(const ProKey &func, const QList<ProStringList> &args);
|
||||
bool isActiveConfig(const QString &x, bool regex=false,
|
||||
QHash<QString, QStringList> *place=NULL);
|
||||
|
||||
bool isSet(const ProKey &v) const { return (*(const ProValueMap *)&vars).contains(v); }
|
||||
bool isSet(const ProKey &v) const { return m_valuemapStack.first().contains(v); }
|
||||
bool isEmpty(const ProKey &v) const;
|
||||
ProStringList values(const ProKey &v) const { return (*(const ProValueMap *)&vars)[v]; }
|
||||
ProStringList &values(const ProKey &v) { return (*(ProValueMap *)&vars)[v]; }
|
||||
ProString first(const ProKey &v) const;
|
||||
ProStringList &values(const ProKey &v) { return valuesRef(v); }
|
||||
int intValue(const ProKey &v, int defaultValue = 0) const;
|
||||
const ProValueMap &variables() const { return *(const ProValueMap *)&vars; }
|
||||
ProValueMap &variables() { return *(ProValueMap *)&vars; }
|
||||
const ProValueMap &variables() const { return m_valuemapStack.first(); }
|
||||
ProValueMap &variables() { return m_valuemapStack.first(); }
|
||||
|
||||
void dump() const;
|
||||
|
||||
bool isHostBuild() const { return host_build; }
|
||||
|
||||
protected:
|
||||
friend class MakefileGenerator;
|
||||
bool read(const QString &file, QHash<QString, QStringList> &place);
|
||||
bool read(QTextStream &file, QHash<QString, QStringList> &place);
|
||||
|
||||
using QMakeEvaluator::LoadFlags;
|
||||
using QMakeEvaluator::setExtraVars;
|
||||
using QMakeEvaluator::setExtraConfigs;
|
||||
using QMakeEvaluator::loadSpec;
|
||||
using QMakeEvaluator::evaluateFeatureFile;
|
||||
using QMakeEvaluator::evaluateConfigFeatures;
|
||||
using QMakeEvaluator::evaluateExpression;
|
||||
using QMakeEvaluator::values;
|
||||
using QMakeEvaluator::first;
|
||||
using QMakeEvaluator::isActiveConfig;
|
||||
using QMakeEvaluator::isHostBuild;
|
||||
using QMakeEvaluator::dirSep;
|
||||
};
|
||||
Q_DECLARE_METATYPE(QMakeProject*)
|
||||
|
||||
inline QString QMakeProject::projectFile()
|
||||
{
|
||||
return pfile;
|
||||
}
|
||||
|
||||
inline ProString QMakeProject::first(const ProKey &v) const
|
||||
{
|
||||
const ProStringList &vals = values(v);
|
||||
if(vals.isEmpty())
|
||||
return ProString("");
|
||||
return vals.first();
|
||||
}
|
||||
|
||||
inline int QMakeProject::intValue(const ProKey &v, int defaultValue) const
|
||||
{
|
||||
|
@ -5,7 +5,10 @@ DEFINES += QT_NO_TEXTCODEC QT_NO_LIBRARY QT_NO_COMPRESS QT_NO_UNICODETABLES \
|
||||
QT_NO_GEOM_VARIANT QT_NO_DATASTREAM
|
||||
|
||||
#qmake code
|
||||
SOURCES += project.cpp property.cpp main.cpp generators/makefile.cpp \
|
||||
SOURCES += project.cpp property.cpp main.cpp \
|
||||
library/ioutils.cpp library/proitems.cpp library/qmakeglobals.cpp \
|
||||
library/qmakeparser.cpp library/qmakeevaluator.cpp library/qmakebuiltins.cpp \
|
||||
generators/makefile.cpp \
|
||||
generators/unix/unixmake2.cpp generators/unix/unixmake.cpp meta.cpp \
|
||||
option.cpp generators/win32/winmakefile.cpp generators/win32/mingw_make.cpp \
|
||||
generators/makefiledeps.cpp generators/metamakefile.cpp generators/mac/pbuilder_pbx.cpp \
|
||||
@ -18,7 +21,8 @@ SOURCES += project.cpp property.cpp main.cpp generators/makefile.cpp \
|
||||
generators/win32/cesdkhandler.cpp
|
||||
|
||||
HEADERS += project.h property.h \
|
||||
library/qmake_global.h library/proitems.h \
|
||||
library/qmake_global.h library/ioutils.h library/proitems.h library/qmakeglobals.h \
|
||||
library/qmakeparser.h library/qmakeevaluator.h library/qmakeevaluator_p.h \
|
||||
generators/makefile.h \
|
||||
generators/unix/unixmake.h meta.h option.h cachekeys.h \
|
||||
generators/win32/winmakefile.h generators/win32/mingw_make.h generators/projectgenerator.h \
|
||||
|
@ -6,7 +6,8 @@
|
||||
option(host_build)
|
||||
CONFIG += console bootstrap
|
||||
CONFIG -= qt shared app_bundle uic
|
||||
DEFINES += QT_BUILD_QMAKE QT_BOOTSTRAPPED
|
||||
DEFINES += QT_BUILD_QMAKE QT_BOOTSTRAPPED \
|
||||
PROEVALUATOR_FULL PROEVALUATOR_DEBUG
|
||||
DESTDIR = ../bin/
|
||||
|
||||
OBJECTS_DIR = .
|
||||
|
@ -484,7 +484,7 @@ void tst_qmake::bundle_spaces()
|
||||
void tst_qmake::includefunction()
|
||||
{
|
||||
QString workDir = base_path + "/testdata/include_function";
|
||||
QString warningMsg("Unable to find file for inclusion");
|
||||
QRegExp warningMsg("Include file .* not found");
|
||||
QVERIFY(test_compiler.qmake( workDir, "include_existing_file"));
|
||||
QVERIFY(!test_compiler.commandOutput().contains(warningMsg));
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user