Commit ab8fc52d authored by dt's avatar dt

Use exact and aysnc .pro file evaluate

This is a big change touching almost all of our .pro file parsing.
With this patch we only evaluate once exact for all needs and once
greedy for the filelist. That is the qt runconfigurations don't have own
evaluaters but reuse the project wide exact evaluation.

We reevaluate if the user changes the build directory, the qmake
buildconfiguration or the qmake arguments. That is if you open src.pro
(or projects.pro) of qt with a shadow build you still don't get all the
files, but after correcting the build directory, we reevaluate the .pro
files and find all files. So for a suitable definition of fixed, that
bug is now fixed.

We now get the exact defines of all .pro files instead of all defines for all
buildconfigurations. We still don't distinguish in which
.pro file a DEFINE is set. So the code model now knows about all the
defines set for the given configuration but not for which files it is
actually set. Also that includes all DEFINES set in .qmake.cache or the
mkspecs. This means all defines from .pro files should now work.

The intial loading is still synchronous. I haven't looked into it to
deeply, but it seems possible to make it also async.There are probably a
few issues which need to be solved fist.

Also due to the asynchronous nature of the code, the executable is
updated a few seconds after actually changing the build configuration
parent 309163ce
......@@ -61,6 +61,7 @@ Node::Node(NodeType nodeType,
m_folderNode(0),
m_path(filePath)
{
}
NodeType Node::nodeType() const
......
......@@ -116,12 +116,27 @@ ProFileCacheManager *ProFileCacheManager::s_instance = 0;
ProFileCacheManager::ProFileCacheManager(QObject *parent) :
QObject(parent),
m_cache(0)
m_cache(0),
m_refCount(0)
{
s_instance = this;
m_timer.setSingleShot(true);
m_timer.setInterval(5000);
connect(&m_timer, SIGNAL(timeout()), SLOT(clear()));
m_timer.setSingleShot(true);
connect(&m_timer, SIGNAL(timeout()),
this, SLOT(clear()));
}
void ProFileCacheManager::incRefCount()
{
++m_refCount;
m_timer.stop();
}
void ProFileCacheManager::decRefCount()
{
--m_refCount;
if (!m_refCount)
m_timer.start();
}
ProFileCacheManager::~ProFileCacheManager()
......@@ -132,7 +147,6 @@ ProFileCacheManager::~ProFileCacheManager()
ProFileCache *ProFileCacheManager::cache()
{
m_timer.start();
if (!m_cache)
m_cache = new ProFileCache;
return m_cache;
......@@ -140,6 +154,7 @@ ProFileCache *ProFileCacheManager::cache()
void ProFileCacheManager::clear()
{
Q_ASSERT(m_refCount == 0);
// Just deleting the cache will be safe as long as the sequence of
// obtaining a cache pointer and using it is atomic as far as the main
// loop is concerned. Use a shared pointer once this is not true anymore.
......
......@@ -77,13 +77,16 @@ public:
ProFileCache *cache();
void discardFiles(const QString &prefix);
void discardFile(const QString &fileName);
void incRefCount();
void decRefCount();
private:
ProFileCacheManager(QObject *parent);
~ProFileCacheManager();
Q_SLOT void clear();
QTimer m_timer;
ProFileCache *m_cache;
int m_refCount;
QTimer m_timer;
static ProFileCacheManager *s_instance;
......
......@@ -52,7 +52,6 @@ MaemoRunConfiguration::MaemoRunConfiguration(Qt4Target *parent,
const QString &proFilePath)
: RunConfiguration(parent, QLatin1String(MAEMO_RC_ID))
, m_proFilePath(proFilePath)
, m_cachedTargetInformationValid(false)
, m_cachedSimulatorInformationValid(false)
, qemu(0)
{
......@@ -62,9 +61,7 @@ MaemoRunConfiguration::MaemoRunConfiguration(Qt4Target *parent,
MaemoRunConfiguration::MaemoRunConfiguration(Qt4Target *parent,
MaemoRunConfiguration *source)
: RunConfiguration(parent, source)
, m_executable(source->m_executable)
, m_proFilePath(source->m_proFilePath)
, m_cachedTargetInformationValid(false)
, m_simulator(source->m_simulator)
, m_simulatorArgs(source->m_simulatorArgs)
, m_simulatorPath(source->m_simulatorPath)
......@@ -95,8 +92,8 @@ void MaemoRunConfiguration::init()
connect(&MaemoDeviceConfigurations::instance(), SIGNAL(updated()), this,
SLOT(updateDeviceConfigurations()));
connect(qt4Target(), SIGNAL(targetInformationChanged()), this,
SLOT(invalidateCachedTargetInformation()));
connect(qt4Target()->qt4Project(), SIGNAL(proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode*)),
this, SLOT(proFileUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode*)));
connect(qt4Target()->qt4Project(),
SIGNAL(proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode*)),
......@@ -148,7 +145,7 @@ QWidget *MaemoRunConfiguration::configurationWidget()
void MaemoRunConfiguration::proFileUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode *pro)
{
if (m_proFilePath == pro->path())
invalidateCachedTargetInformation();
emit targetInformationChanged();
}
QVariantMap MaemoRunConfiguration::toMap() const
......@@ -329,8 +326,11 @@ const QString MaemoRunConfiguration::dumperLib() const
QString MaemoRunConfiguration::executable() const
{
updateTarget();
return m_executable;
TargetInformation ti = qt4Target()->qt4Project()->rootProjectNode()->targetInformation(m_proFilePath);
if (!ti.valid)
return QString();
return QDir::cleanPath(ti.workingDir + QLatin1Char('/') + ti.target);
}
QString MaemoRunConfiguration::simulatorSshPort() const
......@@ -379,39 +379,6 @@ bool MaemoRunConfiguration::isQemuRunning() const
return (qemu && qemu->state() != QProcess::NotRunning);
}
void MaemoRunConfiguration::invalidateCachedTargetInformation()
{
m_cachedTargetInformationValid = false;
emit targetInformationChanged();
}
void MaemoRunConfiguration::updateTarget() const
{
if (m_cachedTargetInformationValid)
return;
m_executable.clear();
m_cachedTargetInformationValid = true;
Qt4TargetInformation info =
qt4Target()->targetInformation(activeQt4BuildConfiguration(),
m_proFilePath);
if (info.error != Qt4TargetInformation::NoError) {
if (info.error == Qt4TargetInformation::ProParserError) {
Core::ICore::instance()->messageManager()->printToOutputPane(tr(
"Could not parse %1. The Maemo run configuration %2 "
"can not be started.").arg(m_proFilePath).arg(displayName()));
}
emit targetInformationChanged();
return;
}
m_executable
= QDir::cleanPath(info.workingDir % QLatin1Char('/') % info.target);
emit targetInformationChanged();
}
void MaemoRunConfiguration::updateSimulatorInformation() const
{
if (m_cachedSimulatorInformationValid)
......
......@@ -114,14 +114,12 @@ protected:
private slots:
void proFileUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode *pro);
void updateDeviceConfigurations();
void invalidateCachedTargetInformation();
void startStopQemu();
void qemuProcessFinished();
private:
void init();
void updateTarget() const;
void updateSimulatorInformation() const;
const QString cmd(const QString &cmdName) const;
const MaemoToolChain *toolchain() const;
......@@ -133,9 +131,7 @@ private:
QMap<QString, QDateTime> &deployTimes,
const QVariantMap &map);
mutable QString m_executable;
QString m_proFilePath;
mutable bool m_cachedTargetInformationValid;
mutable QString m_simulator;
mutable QString m_simulatorArgs;
......
......@@ -112,7 +112,6 @@ QString pathToId(const QString &path)
S60DeviceRunConfiguration::S60DeviceRunConfiguration(Target *parent, const QString &proFilePath) :
RunConfiguration(parent, QLatin1String(S60_DEVICE_RC_ID)),
m_proFilePath(proFilePath),
m_cachedTargetInformationValid(false),
#ifdef Q_OS_WIN
m_serialPortName(QLatin1String("COM5")),
#else
......@@ -126,7 +125,6 @@ S60DeviceRunConfiguration::S60DeviceRunConfiguration(Target *parent, const QStri
S60DeviceRunConfiguration::S60DeviceRunConfiguration(Target *target, S60DeviceRunConfiguration *source) :
RunConfiguration(target, source),
m_proFilePath(source->m_proFilePath),
m_cachedTargetInformationValid(false),
m_serialPortName(source->m_serialPortName),
m_signingMode(source->m_signingMode),
m_customSignaturePath(source->m_customSignaturePath),
......@@ -135,12 +133,6 @@ S60DeviceRunConfiguration::S60DeviceRunConfiguration(Target *target, S60DeviceRu
ctor();
}
void S60DeviceRunConfiguration::proFileUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode *pro)
{
if (m_proFilePath == pro->path())
invalidateCachedTargetInformation();
}
void S60DeviceRunConfiguration::ctor()
{
if (!m_proFilePath.isEmpty())
......@@ -148,11 +140,17 @@ void S60DeviceRunConfiguration::ctor()
else
setDisplayName(tr("QtS60DeviceRunConfiguration"));
connect(target(), SIGNAL(targetInformationChanged()),
this, SLOT(invalidateCachedTargetInformation()));
connect(qt4Target()->qt4Project(), SIGNAL(proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode*)),
this, SLOT(proFileUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode*)));
connect(qt4Target()->qt4Project(), SIGNAL(targetInformationChanged(Qt4ProjectManager::Internal::Qt4ProFileNode*)),
this, SLOT(proFileUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode*)));
}
void S60DeviceRunConfiguration::proFileUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode *pro)
{
if (m_proFilePath == pro->path())
emit targetInformationChanged();
}
......@@ -246,32 +244,60 @@ void S60DeviceRunConfiguration::setSerialPortName(const QString &name)
QString S60DeviceRunConfiguration::targetName() const
{
const_cast<S60DeviceRunConfiguration *>(this)->updateTarget();
return m_targetName;
TargetInformation ti = qt4Target()->qt4Project()->rootProjectNode()->targetInformation(m_proFilePath);
if (!ti.valid)
return QString();
return ti.target;
}
static inline QString fixBaseNameTarget(const QString &in)
{
if (in == QLatin1String("udeb"))
return QLatin1String("debug");
if (in == QLatin1String("urel"))
return QLatin1String("release");
return in;
}
QString S60DeviceRunConfiguration::basePackageFilePath() const
{
const_cast<S60DeviceRunConfiguration *>(this)->updateTarget();
return m_baseFileName;
TargetInformation ti = qt4Target()->qt4Project()->rootProjectNode()->targetInformation(m_proFilePath);
if (!ti.valid)
return QString();
QString baseFileName = ti.workingDir + QLatin1Char('/') + ti.target;
baseFileName += QLatin1Char('_') + fixBaseNameTarget(symbianPlatform()) + QLatin1Char('_') + symbianTarget();
return baseFileName;
}
QString S60DeviceRunConfiguration::symbianPlatform() const
{
const_cast<S60DeviceRunConfiguration *>(this)->updateTarget();
return m_platform;
Qt4BuildConfiguration *qt4bc = qt4Target()->qt4Project()->activeTarget()->activeBuildConfiguration();
switch (qt4bc->toolChainType()) {
case ToolChain::GCCE:
case ToolChain::GCCE_GNUPOC:
return QLatin1String("gcce");
case ToolChain::RVCT_ARMV5:
return QLatin1String("armv5");
default: // including ToolChain::RVCT_ARMV6_GNUPOC:
return QLatin1String("armv6");
}
}
QString S60DeviceRunConfiguration::symbianTarget() const
{
const_cast<S60DeviceRunConfiguration *>(this)->updateTarget();
return m_target;
Qt4BuildConfiguration *qt4bc = qt4Target()->qt4Project()->activeTarget()->activeBuildConfiguration();
if (qt4bc->qmakeBuildConfiguration() & QtVersion::DebugBuild)
return QString("udeb");
else
return QString("urel");
}
QString S60DeviceRunConfiguration::packageTemplateFileName() const
{
const_cast<S60DeviceRunConfiguration *>(this)->updateTarget();
return m_packageTemplateFileName;
TargetInformation ti = qt4Target()->qt4Project()->rootProjectNode()->targetInformation(m_proFilePath);
if (!ti.valid)
return QString();
return ti.workingDir + QLatin1Char('/') + ti.target + QLatin1String("_template.pkg");
}
S60DeviceRunConfiguration::SigningMode S60DeviceRunConfiguration::signingMode() const
......@@ -373,8 +399,7 @@ QString S60DeviceRunConfiguration::localExecutableFileName() const
QString S60DeviceRunConfiguration::signedPackage() const
{
const_cast<S60DeviceRunConfiguration *>(this)->updateTarget();
return QDir::toNativeSeparators(m_baseFileName + QLatin1String(".sis"));
return QDir::toNativeSeparators(basePackageFilePath() + QLatin1String(".sis"));
}
QStringList S60DeviceRunConfiguration::commandLineArguments() const
......@@ -387,74 +412,6 @@ void S60DeviceRunConfiguration::setCommandLineArguments(const QStringList &args)
m_commandLineArguments = args;
}
// Fix up target specification for "make sis":
// "udeb"-> "debug", "urel" -> "release"
static inline QString fixBaseNameTarget(const QString &in)
{
if (in == QLatin1String("udeb"))
return QLatin1String("debug");
if (in == QLatin1String("urel"))
return QLatin1String("release");
return in;
}
void S60DeviceRunConfiguration::updateTarget()
{
if (m_cachedTargetInformationValid)
return;
Qt4TargetInformation info = qt4Target()->targetInformation(qt4Target()->activeBuildConfiguration(),
m_proFilePath);
if (info.error != Qt4TargetInformation::NoError) {
if (info.error == Qt4TargetInformation::ProParserError) {
Core::ICore::instance()->messageManager()->printToOutputPane(
tr("Could not parse %1. The Qt Symbian Device run configuration %2 can not be started.")
.arg(m_proFilePath).arg(displayName()));
}
m_targetName.clear();
m_baseFileName.clear();
m_packageTemplateFileName.clear();
m_platform.clear();
m_cachedTargetInformationValid = true;
emit targetInformationChanged();
return;
}
m_targetName = info.target;
m_baseFileName = info.workingDir + QLatin1Char('/') + m_targetName;
m_packageTemplateFileName = m_baseFileName + QLatin1String("_template.pkg");
Qt4BuildConfiguration *qt4bc = qt4Target()->activeBuildConfiguration();
switch (qt4bc->toolChainType()) {
case ToolChain::GCCE:
case ToolChain::GCCE_GNUPOC:
m_platform = QLatin1String("gcce");
break;
case ToolChain::RVCT_ARMV5:
case ToolChain::RVCT_ARMV5_GNUPOC:
m_platform = QLatin1String("armv5");
break;
default:
m_platform = QLatin1String("armv6");
break;
}
if (qt4bc->qmakeBuildConfiguration() & QtVersion::DebugBuild)
m_target = QLatin1String("udeb");
else
m_target = QLatin1String("urel");
m_baseFileName += QLatin1Char('_') + fixBaseNameTarget(m_target)
+ QLatin1Char('-') + m_platform;
m_cachedTargetInformationValid = true;
emit targetInformationChanged();
}
void S60DeviceRunConfiguration::invalidateCachedTargetInformation()
{
m_cachedTargetInformationValid = false;
emit targetInformationChanged();
}
// ======== S60DeviceRunConfigurationFactory
S60DeviceRunConfigurationFactory::S60DeviceRunConfigurationFactory(QObject *parent) :
......
......@@ -110,7 +110,6 @@ signals:
void serialPortNameChanged();
private slots:
void invalidateCachedTargetInformation();
void proFileUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode *pro);
protected:
......@@ -119,16 +118,9 @@ protected:
private:
ProjectExplorer::ToolChain::ToolChainType toolChainType(ProjectExplorer::BuildConfiguration *configuration) const;
void updateTarget();
void ctor();
QString m_proFilePath;
QString m_targetName;
QString m_platform;
QString m_target;
QString m_baseFileName;
QString m_packageTemplateFileName;
bool m_cachedTargetInformationValid;
QString m_serialPortName;
SigningMode m_signingMode;
QString m_customSignaturePath;
......
......@@ -76,16 +76,14 @@ QString pathToId(const QString &path)
S60EmulatorRunConfiguration::S60EmulatorRunConfiguration(Target *parent, const QString &proFilePath) :
RunConfiguration(parent, QLatin1String(S60_EMULATOR_RC_ID)),
m_proFilePath(proFilePath),
m_cachedTargetInformationValid(false)
m_proFilePath(proFilePath)
{
ctor();
}
S60EmulatorRunConfiguration::S60EmulatorRunConfiguration(Target *parent, S60EmulatorRunConfiguration *source) :
RunConfiguration(parent, source),
m_proFilePath(source->m_proFilePath),
m_cachedTargetInformationValid(false)
m_proFilePath(source->m_proFilePath)
{
ctor();
}
......@@ -97,11 +95,11 @@ void S60EmulatorRunConfiguration::ctor()
else
setDisplayName(tr("Qt Symbian Emulator RunConfiguration"));
connect(qt4Target(), SIGNAL(targetInformationChanged()),
this, SLOT(invalidateCachedTargetInformation()));
connect(qt4Target()->qt4Project(), SIGNAL(proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode*)),
this, SLOT(proFileUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode*)));
connect(qt4Target()->qt4Project(), SIGNAL(targetInformationChanged(Qt4ProjectManager::Internal::Qt4ProFileNode*)),
this, SLOT(proFileUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode*)));
}
......@@ -112,10 +110,9 @@ S60EmulatorRunConfiguration::~S60EmulatorRunConfiguration()
void S60EmulatorRunConfiguration::proFileUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode *pro)
{
if (m_proFilePath == pro->path())
invalidateCachedTargetInformation();
emit targetInformationChanged();
}
Qt4Target *S60EmulatorRunConfiguration::qt4Target() const
{
return static_cast<Qt4Target *>(target());
......@@ -152,28 +149,6 @@ bool S60EmulatorRunConfiguration::fromMap(const QVariantMap &map)
QString S60EmulatorRunConfiguration::executable() const
{
const_cast<S60EmulatorRunConfiguration *>(this)->updateTarget();
return m_executable;
}
void S60EmulatorRunConfiguration::updateTarget()
{
if (m_cachedTargetInformationValid)
return;
Qt4TargetInformation info = qt4Target()->targetInformation(qt4Target()->activeBuildConfiguration(),
m_proFilePath);
if (info.error != Qt4TargetInformation::NoError) {
if (info.error == Qt4TargetInformation::ProParserError) {
Core::ICore::instance()->messageManager()->printToOutputPane(
tr("Could not parse %1. The Qt for Symbian emulator run configuration %2 can not be started.")
.arg(m_proFilePath).arg(displayName()));
}
m_executable.clear();
m_cachedTargetInformationValid = true;
emit targetInformationChanged();
return;
}
Qt4BuildConfiguration *qt4bc = qt4Target()->activeBuildConfiguration();
QtVersion *qtVersion = qt4bc->qtVersion();
QString baseDir = S60Manager::instance()->deviceForQtVersion(qtVersion).epocRoot;
......@@ -182,18 +157,13 @@ void S60EmulatorRunConfiguration::updateTarget()
qmakeBuildConfig = "udeb";
baseDir += "/epoc32/release/winscw/" + qmakeBuildConfig;
m_executable = QDir::toNativeSeparators(
QDir::cleanPath(baseDir + QLatin1Char('/') + info.target));
m_executable += QLatin1String(".exe");
m_cachedTargetInformationValid = true;
emit targetInformationChanged();
}
TargetInformation ti = qt4Target()->qt4Project()->rootProjectNode()->targetInformation(m_proFilePath);
if (!ti.valid)
return QString();
QString executable = QDir::toNativeSeparators(QDir::cleanPath(baseDir + QLatin1Char('/') + ti.target));
executable += QLatin1String(".exe");
void S60EmulatorRunConfiguration::invalidateCachedTargetInformation()
{
m_cachedTargetInformationValid = false;
emit targetInformationChanged();
return executable;
}
// ======== S60EmulatorRunConfigurationWidget
......
......@@ -75,7 +75,6 @@ signals:
void targetInformationChanged();
private slots:
void invalidateCachedTargetInformation();
void proFileUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode *pro);
protected:
......@@ -87,8 +86,6 @@ private:
void updateTarget();
QString m_proFilePath;
QString m_executable;
bool m_cachedTargetInformationValid;
};
class S60EmulatorRunConfigurationWidget : public QWidget
......
......@@ -277,10 +277,11 @@ void Qt4BuildConfiguration::setShadowBuildAndDirectory(bool shadowBuild, const Q
{
if (m_shadowBuild == shadowBuild && m_buildDirectory == buildDirectory)
return;
m_shadowBuild = shadowBuild;
m_buildDirectory = buildDirectory;
emit buildDirectoryChanged();
emit targetInformationChanged();
emit proFileEvaluateNeeded(this);
}
ProjectExplorer::ToolChain *Qt4BuildConfiguration::toolChain() const
......@@ -340,8 +341,9 @@ void Qt4BuildConfiguration::setQtVersion(QtVersion *version)
return;
m_qtVersionId = version->uniqueId();
emit proFileEvaluateNeeded(this);
emit qtVersionChanged();
emit targetInformationChanged();
emit environmentChanged();
}
......@@ -351,8 +353,9 @@ void Qt4BuildConfiguration::setToolChainType(ProjectExplorer::ToolChain::ToolCha
m_toolChainType == type)
return;
m_toolChainType = type;
emit proFileEvaluateNeeded(this);
emit toolChainTypeChanged();
emit targetInformationChanged();
emit environmentChanged();
}
......@@ -371,8 +374,9 @@ void Qt4BuildConfiguration::setQMakeBuildConfiguration(QtVersion::QmakeBuildConf
if (m_qmakeBuildConfiguration == config)
return;
m_qmakeBuildConfiguration = config;
emit proFileEvaluateNeeded(this);
emit qmakeBuildConfigurationChanged();
emit targetInformationChanged();
}
void Qt4BuildConfiguration::emitQMakeBuildConfigurationChanged()
......
......@@ -84,7 +84,8 @@ public:
QtVersion::QmakeBuildConfigs qmakeBuildConfiguration() const;
void setQMakeBuildConfiguration(QtVersion::QmakeBuildConfigs config);
// used by qmake step to notify that the qmake args have changed