forked from qt-creator/qt-creator
Fix importing creating additional kits on OS X
Extract the whole makefile parsing code into a separate class, to make the code more manageable. Also fix some bugs on importing additional flags like qt quick compiler or separate debug info. Task-number: QTCREATORBUG-13947 Change-Id: Id04bff191c188f95230274d990b1676e9b2f419d Reviewed-by: Eike Ziller <eike.ziller@theqtcompany.com> Reviewed-by: Daniel Teske <daniel.teske@theqtcompany.com>
This commit is contained in:
394
src/plugins/qmakeprojectmanager/makefileparse.cpp
Normal file
394
src/plugins/qmakeprojectmanager/makefileparse.cpp
Normal file
@@ -0,0 +1,394 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2015 The Qt Company Ltd.
|
||||
** Contact: http://www.qt.io/licensing
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms and
|
||||
** conditions see http://www.qt.io/terms-conditions. For further information
|
||||
** use the contact form at http://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 or version 3 as published by the Free
|
||||
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
||||
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
||||
** following information to ensure the GNU Lesser General Public License
|
||||
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, The Qt Company gives you certain additional
|
||||
** rights. These rights are described in The Qt Company LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "makefileparse.h"
|
||||
|
||||
#include <qtsupport/qtversionmanager.h>
|
||||
#include <qtsupport/baseqtversion.h>
|
||||
#include <utils/qtcprocess.h>
|
||||
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QFileInfo>
|
||||
#include <QTextStream>
|
||||
#include <QLoggingCategory>
|
||||
|
||||
using namespace QmakeProjectManager;
|
||||
using namespace Internal;
|
||||
|
||||
using Utils::FileName;
|
||||
using Utils::QtcProcess;
|
||||
using QtSupport::QtVersionManager;
|
||||
using QtSupport::BaseQtVersion;
|
||||
|
||||
static QString findQMakeLine(const QString &makefile, const QString &key)
|
||||
{
|
||||
QFile fi(makefile);
|
||||
if (fi.exists() && fi.open(QFile::ReadOnly)) {
|
||||
QTextStream ts(&fi);
|
||||
while (!ts.atEnd()) {
|
||||
const QString line = ts.readLine();
|
||||
if (line.startsWith(key))
|
||||
return line;
|
||||
}
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
/// This function trims the "#Command /path/to/qmake" from the line
|
||||
static QString trimLine(const QString &line)
|
||||
{
|
||||
|
||||
// Actually the first space after #Command: /path/to/qmake
|
||||
const int firstSpace = line.indexOf(QLatin1Char(' '), 11);
|
||||
return line.mid(firstSpace).trimmed();
|
||||
}
|
||||
|
||||
void MakeFileParse::parseArgs(const QString &args, QList<QMakeAssignment> *assignments, QList<QMakeAssignment> *afterAssignments)
|
||||
{
|
||||
QRegExp regExp(QLatin1String("([^\\s\\+-]*)\\s*(\\+=|=|-=|~=)(.*)"));
|
||||
bool after = false;
|
||||
bool ignoreNext = false;
|
||||
m_unparsedArguments = args;
|
||||
QtcProcess::ArgIterator ait(&m_unparsedArguments);
|
||||
while (ait.next()) {
|
||||
if (ignoreNext) {
|
||||
// Ignoring
|
||||
ignoreNext = false;
|
||||
ait.deleteArg();
|
||||
} else if (ait.value() == QLatin1String("-after")) {
|
||||
after = true;
|
||||
ait.deleteArg();
|
||||
} else if (ait.value().contains(QLatin1Char('='))) {
|
||||
if (regExp.exactMatch(ait.value())) {
|
||||
QMakeAssignment qa;
|
||||
qa.variable = regExp.cap(1);
|
||||
qa.op = regExp.cap(2);
|
||||
qa.value = regExp.cap(3).trimmed();
|
||||
if (after)
|
||||
afterAssignments->append(qa);
|
||||
else
|
||||
assignments->append(qa);
|
||||
} else {
|
||||
qDebug()<<"regexp did not match";
|
||||
}
|
||||
ait.deleteArg();
|
||||
} else if (ait.value() == QLatin1String("-o")) {
|
||||
ignoreNext = true;
|
||||
ait.deleteArg();
|
||||
#if defined(Q_OS_WIN32)
|
||||
} else if (ait.value() == QLatin1String("-win32")) {
|
||||
#elif defined(Q_OS_MAC)
|
||||
} else if (ait.value() == QLatin1String("-macx")) {
|
||||
#elif defined(Q_OS_QNX6)
|
||||
} else if (ait.value() == QLatin1String("-qnx6")) {
|
||||
#else
|
||||
} else if (ait.value() == QLatin1String("-unix")) {
|
||||
#endif
|
||||
ait.deleteArg();
|
||||
}
|
||||
}
|
||||
ait.deleteArg(); // The .pro file is always the last arg
|
||||
}
|
||||
|
||||
void dumpQMakeAssignments(const QList<QMakeAssignment> &list)
|
||||
{
|
||||
foreach (const QMakeAssignment &qa, list) {
|
||||
qCDebug(MakeFileParse::logging()) << " " << qa.variable << qa.op << qa.value;
|
||||
}
|
||||
}
|
||||
|
||||
void MakeFileParse::parseAssignments(QList<QMakeAssignment> *assignments)
|
||||
{
|
||||
bool foundSeparateDebugInfo = false;
|
||||
bool foundForceDebugInfo = false;
|
||||
QList<QMakeAssignment> oldAssignments = *assignments;
|
||||
assignments->clear();
|
||||
foreach (const QMakeAssignment &qa, oldAssignments) {
|
||||
if (qa.variable == QLatin1String("CONFIG")) {
|
||||
QStringList values = qa.value.split(QLatin1Char(' '));
|
||||
QStringList newValues;
|
||||
foreach (const QString &value, values) {
|
||||
if (value == QLatin1String("debug")) {
|
||||
if (qa.op == QLatin1String("+=")) {
|
||||
m_qmakeBuildConfig.explicitDebug = true;
|
||||
m_qmakeBuildConfig.explicitRelease = false;
|
||||
} else {
|
||||
m_qmakeBuildConfig.explicitDebug = false;
|
||||
m_qmakeBuildConfig.explicitRelease = true;
|
||||
}
|
||||
} else if (value == QLatin1String("release")) {
|
||||
if (qa.op == QLatin1String("+=")) {
|
||||
m_qmakeBuildConfig.explicitDebug = false;
|
||||
m_qmakeBuildConfig.explicitRelease = true;
|
||||
} else {
|
||||
m_qmakeBuildConfig.explicitDebug = true;
|
||||
m_qmakeBuildConfig.explicitRelease = false;
|
||||
}
|
||||
} else if (value == QLatin1String("debug_and_release")) {
|
||||
if (qa.op == QLatin1String("+=")) {
|
||||
m_qmakeBuildConfig.explicitBuildAll = true;
|
||||
m_qmakeBuildConfig.explicitNoBuildAll = false;
|
||||
} else {
|
||||
m_qmakeBuildConfig.explicitBuildAll = false;
|
||||
m_qmakeBuildConfig.explicitNoBuildAll = true;
|
||||
}
|
||||
} else if (value == QLatin1String("x86")) {
|
||||
if (qa.op == QLatin1String("+="))
|
||||
m_config.archConfig = QMakeStepConfig::X86;
|
||||
else
|
||||
m_config.archConfig = QMakeStepConfig::NoArch;
|
||||
} else if (value == QLatin1String("x86_64")) {
|
||||
if (qa.op == QLatin1String("+="))
|
||||
m_config.archConfig = QMakeStepConfig::X86_64;
|
||||
else
|
||||
m_config.archConfig = QMakeStepConfig::NoArch;
|
||||
} else if (value == QLatin1String("ppc")) {
|
||||
if (qa.op == QLatin1String("+="))
|
||||
m_config.archConfig = QMakeStepConfig::PPC;
|
||||
else
|
||||
m_config.archConfig = QMakeStepConfig::NoArch;
|
||||
} else if (value == QLatin1String("ppc64")) {
|
||||
if (qa.op == QLatin1String("+="))
|
||||
m_config.archConfig = QMakeStepConfig::PPC64;
|
||||
else
|
||||
m_config.archConfig = QMakeStepConfig::NoArch;
|
||||
} else if (value == QLatin1String("iphonesimulator")) {
|
||||
if (qa.op == QLatin1String("+="))
|
||||
m_config.osType = QMakeStepConfig::IphoneSimulator;
|
||||
else
|
||||
m_config.osType = QMakeStepConfig::NoOsType;
|
||||
} else if (value == QLatin1String("iphoneos")) {
|
||||
if (qa.op == QLatin1String("+="))
|
||||
m_config.osType = QMakeStepConfig::IphoneOS;
|
||||
else
|
||||
m_config.osType = QMakeStepConfig::NoOsType;
|
||||
} else if (value == QLatin1String("declarative_debug")) {
|
||||
if (qa.op == QLatin1String("+="))
|
||||
m_config.linkQmlDebuggingQQ1 = true;
|
||||
else
|
||||
m_config.linkQmlDebuggingQQ1 = false;
|
||||
} else if (value == QLatin1String("qml_debug")) {
|
||||
if (qa.op == QLatin1String("+="))
|
||||
m_config.linkQmlDebuggingQQ2 = true;
|
||||
else
|
||||
m_config.linkQmlDebuggingQQ2 = false;
|
||||
} else if (value == QLatin1String("qtquickcompiler")) {
|
||||
if (qa.op == QLatin1String("+="))
|
||||
m_config.useQtQuickCompiler = true;
|
||||
else
|
||||
m_config.useQtQuickCompiler = false;
|
||||
} else if (value == QLatin1String("force_debug_info")) {
|
||||
if (qa.op == QLatin1String("+="))
|
||||
foundForceDebugInfo = true;
|
||||
else
|
||||
foundForceDebugInfo = false;
|
||||
} else if (value == QLatin1String("separate_debug_info")) {
|
||||
if (qa.op == QLatin1String("+="))
|
||||
foundSeparateDebugInfo = true;
|
||||
else
|
||||
foundSeparateDebugInfo = false;
|
||||
} else {
|
||||
newValues.append(value);
|
||||
}
|
||||
QMakeAssignment newQA = qa;
|
||||
newQA.value = newValues.join(QLatin1Char(' '));
|
||||
if (!newValues.isEmpty())
|
||||
assignments->append(newQA);
|
||||
}
|
||||
} else {
|
||||
assignments->append(qa);
|
||||
}
|
||||
}
|
||||
|
||||
if (foundForceDebugInfo && foundSeparateDebugInfo) {
|
||||
m_config.separateDebugInfo = true;
|
||||
} else if (foundForceDebugInfo) {
|
||||
// Found only force_debug_info, so readd it
|
||||
QMakeAssignment newQA;
|
||||
newQA.variable = QLatin1String("CONFIG");
|
||||
newQA.op = QLatin1String("+=");
|
||||
newQA.value = QLatin1String("force_debug_info");
|
||||
assignments->append(newQA);
|
||||
} else if (foundSeparateDebugInfo) {
|
||||
// Found only separate_debug_info, so readd it
|
||||
QMakeAssignment newQA;
|
||||
newQA.variable = QLatin1String("CONFIG");
|
||||
newQA.op = QLatin1String("+=");
|
||||
newQA.value = QLatin1String("separate_debug_info");
|
||||
assignments->append(newQA);
|
||||
}
|
||||
}
|
||||
|
||||
static FileName findQMakeBinaryFromMakefile(const QString &makefile)
|
||||
{
|
||||
bool debugAdding = false;
|
||||
QFile fi(makefile);
|
||||
if (fi.exists() && fi.open(QFile::ReadOnly)) {
|
||||
QTextStream ts(&fi);
|
||||
QRegExp r1(QLatin1String("QMAKE\\s*=(.*)"));
|
||||
while (!ts.atEnd()) {
|
||||
QString line = ts.readLine();
|
||||
if (r1.exactMatch(line)) {
|
||||
if (debugAdding)
|
||||
qDebug()<<"#~~ QMAKE is:"<<r1.cap(1).trimmed();
|
||||
QFileInfo qmake(r1.cap(1).trimmed());
|
||||
QString qmakePath = qmake.filePath();
|
||||
if (!QString::fromLatin1(QTC_HOST_EXE_SUFFIX).isEmpty()
|
||||
&& !qmakePath.endsWith(QLatin1String(QTC_HOST_EXE_SUFFIX))) {
|
||||
qmakePath.append(QLatin1String(QTC_HOST_EXE_SUFFIX));
|
||||
}
|
||||
// Is qmake still installed?
|
||||
QFileInfo fi(qmakePath);
|
||||
if (fi.exists())
|
||||
return FileName(fi);
|
||||
}
|
||||
}
|
||||
}
|
||||
return FileName();
|
||||
}
|
||||
|
||||
MakeFileParse::MakeFileParse(const QString &makefile)
|
||||
{
|
||||
qCDebug(logging()) << "Parsing makefile" << makefile;
|
||||
if (!QFileInfo::exists(makefile)) {
|
||||
qCDebug(logging()) << "**doesn't exist";
|
||||
m_state = MakefileMissing;
|
||||
return;
|
||||
}
|
||||
|
||||
// Qt Version!
|
||||
m_qmakePath = findQMakeBinaryFromMakefile(makefile);
|
||||
qCDebug(logging()) << " qmake:" << m_qmakePath;
|
||||
|
||||
QString line = findQMakeLine(makefile, QLatin1String("# Project:")).trimmed();
|
||||
if (line.isEmpty()) {
|
||||
m_state = CouldNotParse;
|
||||
qCDebug(logging()) << "**No Project line";
|
||||
return;
|
||||
}
|
||||
|
||||
line.remove(0, line.indexOf(QLatin1Char(':')) + 1);
|
||||
line = line.trimmed();
|
||||
|
||||
// Src Pro file
|
||||
m_srcProFile = QDir::cleanPath(QFileInfo(makefile).absoluteDir().filePath(line));
|
||||
qCDebug(logging()) << " source .pro file:" << m_srcProFile;
|
||||
|
||||
line = findQMakeLine(makefile, QLatin1String("# Command:"));
|
||||
if (line.trimmed().isEmpty()) {
|
||||
m_state = CouldNotParse;
|
||||
qCDebug(logging()) << "**No Command line found";
|
||||
return;
|
||||
}
|
||||
|
||||
line = trimLine(line);
|
||||
|
||||
QList<QMakeAssignment> assignments;
|
||||
QList<QMakeAssignment> afterAssignments;
|
||||
// Split up args into assignments and other arguments, writes m_unparsedArguments
|
||||
parseArgs(line, &assignments, &afterAssignments);
|
||||
qCDebug(logging()) << " Initial assignments:";
|
||||
dumpQMakeAssignments(assignments);
|
||||
|
||||
// Filter out CONFIG arguments we know into m_qmakeBuildConfig and m_config
|
||||
parseAssignments(&assignments);
|
||||
qCDebug(logging()) << " After parsing";
|
||||
dumpQMakeAssignments(assignments);
|
||||
|
||||
qCDebug(logging()) << " Explicit Debug" << m_qmakeBuildConfig.explicitDebug;
|
||||
qCDebug(logging()) << " Explicit Release" << m_qmakeBuildConfig.explicitRelease;
|
||||
qCDebug(logging()) << " Explicit BuildAll" << m_qmakeBuildConfig.explicitBuildAll;
|
||||
qCDebug(logging()) << " Explicit NoBuildAll" << m_qmakeBuildConfig.explicitNoBuildAll;
|
||||
qCDebug(logging()) << " TargetArch" << m_config.archConfig;
|
||||
qCDebug(logging()) << " OsType" << m_config.osType;
|
||||
qCDebug(logging()) << " LinkQmlDebuggingQQ1" << m_config.linkQmlDebuggingQQ1;
|
||||
qCDebug(logging()) << " LinkQmlDebuggingQQ2" << m_config.linkQmlDebuggingQQ2;
|
||||
qCDebug(logging()) << " Qt Quick Compiler" << m_config.useQtQuickCompiler;
|
||||
qCDebug(logging()) << " Separate Debug Info" << m_config.separateDebugInfo;
|
||||
|
||||
|
||||
// Create command line of all unfiltered arguments
|
||||
foreach (const QMakeAssignment &qa, assignments)
|
||||
QtcProcess::addArg(&m_unparsedArguments, qa.variable + qa.op + qa.value);
|
||||
if (!afterAssignments.isEmpty()) {
|
||||
QtcProcess::addArg(&m_unparsedArguments, QLatin1String("-after"));
|
||||
foreach (const QMakeAssignment &qa, afterAssignments)
|
||||
QtcProcess::addArg(&m_unparsedArguments, qa.variable + qa.op + qa.value);
|
||||
}
|
||||
m_state = Okay;
|
||||
}
|
||||
|
||||
MakeFileParse::MakefileState MakeFileParse::makeFileState() const
|
||||
{
|
||||
return m_state;
|
||||
}
|
||||
|
||||
Utils::FileName MakeFileParse::qmakePath() const
|
||||
{
|
||||
return m_qmakePath;
|
||||
}
|
||||
|
||||
QString MakeFileParse::srcProFile() const
|
||||
{
|
||||
return m_srcProFile;
|
||||
}
|
||||
|
||||
QMakeStepConfig MakeFileParse::config() const
|
||||
{
|
||||
return m_config;
|
||||
}
|
||||
|
||||
|
||||
QString MakeFileParse::unparsedArguments() const
|
||||
{
|
||||
return m_unparsedArguments;
|
||||
}
|
||||
|
||||
BaseQtVersion::QmakeBuildConfigs MakeFileParse::effectiveBuildConfig(BaseQtVersion::QmakeBuildConfigs defaultBuildConfig) const
|
||||
{
|
||||
BaseQtVersion::QmakeBuildConfigs buildConfig = defaultBuildConfig;
|
||||
if (m_qmakeBuildConfig.explicitDebug)
|
||||
buildConfig = buildConfig & BaseQtVersion::DebugBuild;
|
||||
else if (m_qmakeBuildConfig.explicitRelease)
|
||||
buildConfig = buildConfig & ~BaseQtVersion::DebugBuild;
|
||||
if (m_qmakeBuildConfig.explicitBuildAll)
|
||||
buildConfig = buildConfig & BaseQtVersion::BuildAll;
|
||||
else if (m_qmakeBuildConfig.explicitNoBuildAll)
|
||||
buildConfig = buildConfig &~ BaseQtVersion::BuildAll;
|
||||
return buildConfig;
|
||||
}
|
||||
|
||||
const QLoggingCategory &MakeFileParse::logging()
|
||||
{
|
||||
static const QLoggingCategory category("qtc.qmakeprojectmanager.import");
|
||||
return category;
|
||||
}
|
||||
|
||||
103
src/plugins/qmakeprojectmanager/makefileparse.h
Normal file
103
src/plugins/qmakeprojectmanager/makefileparse.h
Normal file
@@ -0,0 +1,103 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2015 The Qt Company Ltd.
|
||||
** Contact: http://www.qt.io/licensing
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms and
|
||||
** conditions see http://www.qt.io/terms-conditions. For further information
|
||||
** use the contact form at http://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 or version 3 as published by the Free
|
||||
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
||||
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
||||
** following information to ensure the GNU Lesser General Public License
|
||||
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, The Qt Company gives you certain additional
|
||||
** rights. These rights are described in The Qt Company LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef MAKEFILEPARSE_H
|
||||
#define MAKEFILEPARSE_H
|
||||
|
||||
#include <utils/fileutils.h>
|
||||
#include <qtsupport/baseqtversion.h>
|
||||
#include <qmakeprojectmanager/qmakestep.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QLogggingCategory;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace QmakeProjectManager {
|
||||
namespace Internal {
|
||||
|
||||
struct QMakeAssignment
|
||||
{
|
||||
QString variable;
|
||||
QString op;
|
||||
QString value;
|
||||
};
|
||||
|
||||
class MakeFileParse
|
||||
{
|
||||
public:
|
||||
MakeFileParse(const QString &makefile);
|
||||
|
||||
enum MakefileState { MakefileMissing, CouldNotParse, Okay };
|
||||
|
||||
MakefileState makeFileState() const;
|
||||
Utils::FileName qmakePath() const;
|
||||
QString srcProFile() const;
|
||||
QMakeStepConfig config() const;
|
||||
|
||||
QString unparsedArguments() const;
|
||||
|
||||
QtSupport::BaseQtVersion::QmakeBuildConfigs
|
||||
effectiveBuildConfig(QtSupport::BaseQtVersion::QmakeBuildConfigs defaultBuildConfig) const;
|
||||
|
||||
static const QLoggingCategory &logging();
|
||||
|
||||
private:
|
||||
void parseArgs(const QString &args, QList<QMakeAssignment> *assignments, QList<QMakeAssignment> *afterAssignments);
|
||||
void parseAssignments(QList<QMakeAssignment> *assignments);
|
||||
|
||||
class QmakeBuildConfig
|
||||
{
|
||||
public:
|
||||
QmakeBuildConfig()
|
||||
: explicitDebug(false),
|
||||
explicitRelease(false),
|
||||
explicitBuildAll(false),
|
||||
explicitNoBuildAll(false)
|
||||
{}
|
||||
bool explicitDebug;
|
||||
bool explicitRelease;
|
||||
bool explicitBuildAll;
|
||||
bool explicitNoBuildAll;
|
||||
};
|
||||
|
||||
MakefileState m_state;
|
||||
Utils::FileName m_qmakePath;
|
||||
QString m_srcProFile;
|
||||
|
||||
QmakeBuildConfig m_qmakeBuildConfig;
|
||||
QMakeStepConfig m_config;
|
||||
QString m_unparsedArguments;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace QmakeProjectManager
|
||||
|
||||
|
||||
#endif // MAKEFILEPARSE_H
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "qmakenodes.h"
|
||||
#include "qmakestep.h"
|
||||
#include "makestep.h"
|
||||
#include "makefileparse.h"
|
||||
|
||||
#include <coreplugin/documentmanager.h>
|
||||
#include <coreplugin/icore.h>
|
||||
@@ -59,6 +60,7 @@
|
||||
|
||||
#include <QDebug>
|
||||
#include <QInputDialog>
|
||||
#include <QLoggingCategory>
|
||||
|
||||
#include <limits>
|
||||
|
||||
@@ -329,25 +331,52 @@ MakeStep *QmakeBuildConfiguration::makeStep() const
|
||||
// Returns true if both are equal.
|
||||
QmakeBuildConfiguration::MakefileState QmakeBuildConfiguration::compareToImportFrom(const QString &makefile)
|
||||
{
|
||||
const QLoggingCategory &logs = MakeFileParse::logging();
|
||||
qCDebug(logs) << "QMakeBuildConfiguration::compareToImport";
|
||||
|
||||
QMakeStep *qs = qmakeStep();
|
||||
if (QFileInfo::exists(makefile) && qs) {
|
||||
FileName qmakePath = QtVersionManager::findQMakeBinaryFromMakefile(makefile);
|
||||
BaseQtVersion *version = QtKitInformation::qtVersion(target()->kit());
|
||||
if (!version)
|
||||
return MakefileForWrongProject;
|
||||
if (QtSupport::QtVersionManager::makefileIsFor(makefile, qs->project()->projectFilePath().toString())
|
||||
!= QtSupport::QtVersionManager::SameProject) {
|
||||
if (debug) {
|
||||
qDebug() << "different profile used to generate the Makefile:"
|
||||
<< makefile << " expected profile:" << qs->project()->projectFilePath();
|
||||
MakeFileParse parse(makefile);
|
||||
|
||||
if (parse.makeFileState() == MakeFileParse::MakefileMissing) {
|
||||
qCDebug(logs) << "**Makefile missing";
|
||||
return MakefileMissing;
|
||||
}
|
||||
if (parse.makeFileState() == MakeFileParse::CouldNotParse) {
|
||||
qCDebug(logs) << "**Makefile incompatible";
|
||||
return MakefileIncompatible;
|
||||
}
|
||||
if (version->qmakeCommand() == qmakePath) {
|
||||
|
||||
if (!qs) {
|
||||
qCDebug(logs) << "**No qmake step";
|
||||
return MakefileMissing;
|
||||
}
|
||||
|
||||
BaseQtVersion *version = QtKitInformation::qtVersion(target()->kit());
|
||||
if (!version) {
|
||||
qCDebug(logs) << "**No qt version in kit";
|
||||
return MakefileForWrongProject;
|
||||
}
|
||||
|
||||
if (parse.srcProFile() != qs->project()->projectFilePath().toString()) {
|
||||
qCDebug(logs) << "**Different profile used to generate the Makefile:"
|
||||
<< parse.srcProFile() << " expected profile:" << qs->project()->projectFilePath();
|
||||
return MakefileIncompatible;
|
||||
}
|
||||
|
||||
if (version->qmakeCommand() != parse.qmakePath()) {
|
||||
qCDebug(logs) << "**Different Qt versions, buildconfiguration:" << version->qmakeCommand().toString()
|
||||
<< " Makefile:"<< parse.qmakePath().toString();
|
||||
return MakefileForWrongProject;
|
||||
}
|
||||
|
||||
// same qtversion
|
||||
QPair<BaseQtVersion::QmakeBuildConfigs, QString> result =
|
||||
QtVersionManager::scanMakeFile(makefile, version->defaultBuildConfig());
|
||||
if (qmakeBuildConfiguration() == result.first) {
|
||||
BaseQtVersion::QmakeBuildConfigs buildConfig = parse.effectiveBuildConfig(version->defaultBuildConfig());
|
||||
if (qmakeBuildConfiguration() != buildConfig) {
|
||||
qCDebug(logs) << "**Different qmake buildconfigurations buildconfiguration:"
|
||||
<< qmakeBuildConfiguration() << " Makefile:" << buildConfig;
|
||||
return MakefileIncompatible;
|
||||
}
|
||||
|
||||
// The qmake Build Configuration are the same,
|
||||
// now compare arguments lists
|
||||
// we have to compare without the spec/platform cmd argument
|
||||
@@ -358,19 +387,18 @@ QmakeBuildConfiguration::MakefileState QmakeBuildConfiguration::compareToImportF
|
||||
// This copies the settings from userArgs to actualArgs (minus some we
|
||||
// are not interested in), splitting them up into individual strings:
|
||||
extractSpecFromArguments(&userArgs, workingDirectory, version, &actualArgs);
|
||||
actualArgs = qs->deducedArguments() + actualArgs;
|
||||
FileName actualSpec = qs->mkspec();
|
||||
|
||||
QString qmakeArgs = result.second;
|
||||
QString qmakeArgs = parse.unparsedArguments();
|
||||
QStringList parsedArgs;
|
||||
FileName parsedSpec = extractSpecFromArguments(&qmakeArgs, workingDirectory, version, &parsedArgs);
|
||||
|
||||
if (debug) {
|
||||
qDebug() << "Actual args:" << actualArgs;
|
||||
qDebug() << "Parsed args:" << parsedArgs;
|
||||
qDebug() << "Actual spec:" << actualSpec.toString();
|
||||
qDebug() << "Parsed spec:" << parsedSpec.toString();
|
||||
}
|
||||
qCDebug(logs) << " Actual args:" << actualArgs;
|
||||
qCDebug(logs) << " Parsed args:" << parsedArgs;
|
||||
qCDebug(logs) << " Actual spec:" << actualSpec.toString();
|
||||
qCDebug(logs) << " Parsed spec:" << parsedSpec.toString();
|
||||
qCDebug(logs) << " Actual config:" << qs->deducedArguments();
|
||||
qCDebug(logs) << " Parsed config:" << parse.config();
|
||||
|
||||
// Comparing the sorted list is obviously wrong
|
||||
// Though haven written a more complete version
|
||||
@@ -388,46 +416,31 @@ QmakeBuildConfiguration::MakefileState QmakeBuildConfiguration::compareToImportF
|
||||
// -norecursive vs. recursive
|
||||
actualArgs.sort();
|
||||
parsedArgs.sort();
|
||||
if (actualArgs == parsedArgs) {
|
||||
if (actualArgs != parsedArgs) {
|
||||
qCDebug(logs) << "**Mismateched args";
|
||||
return MakefileIncompatible;
|
||||
}
|
||||
|
||||
if (parse.config() != qs->deducedArguments()) {
|
||||
qCDebug(logs) << "**Mismatched config";
|
||||
return MakefileIncompatible;
|
||||
}
|
||||
|
||||
// Specs match exactly
|
||||
if (actualSpec == parsedSpec)
|
||||
if (actualSpec == parsedSpec) {
|
||||
qCDebug(logs) << "**Matched specs (1)";
|
||||
return MakefileMatches;
|
||||
}
|
||||
// Actual spec is the default one
|
||||
// qDebug() << "AS vs VS" << actualSpec << version->mkspec();
|
||||
if ((actualSpec == version->mkspec() || actualSpec == FileName::fromLatin1("default"))
|
||||
&& (parsedSpec == version->mkspec() || parsedSpec == FileName::fromLatin1("default") || parsedSpec.isEmpty()))
|
||||
&& (parsedSpec == version->mkspec() || parsedSpec == FileName::fromLatin1("default") || parsedSpec.isEmpty())) {
|
||||
qCDebug(logs) << "**Matched specs (2)";
|
||||
return MakefileMatches;
|
||||
}
|
||||
return MakefileIncompatible;
|
||||
} else {
|
||||
if (debug)
|
||||
qDebug() << "different qmake buildconfigurations buildconfiguration:"
|
||||
<< qmakeBuildConfiguration() << " Makefile:" << result.first;
|
||||
return MakefileIncompatible;
|
||||
}
|
||||
} else {
|
||||
if (debug)
|
||||
qDebug() << "different Qt versions, buildconfiguration:" << version->qmakeCommand().toString()
|
||||
<< " Makefile:"<< qmakePath.toString();
|
||||
return MakefileForWrongProject;
|
||||
}
|
||||
}
|
||||
return MakefileMissing;
|
||||
}
|
||||
|
||||
bool QmakeBuildConfiguration::removeQMLInspectorFromArguments(QString *args)
|
||||
{
|
||||
bool removedArgument = false;
|
||||
for (QtcProcess::ArgIterator ait(args); ait.next(); ) {
|
||||
const QString arg = ait.value();
|
||||
if (arg.contains(QLatin1String(Constants::QMAKEVAR_QMLJSDEBUGGER_PATH))
|
||||
|| arg.contains(QLatin1String(Constants::QMAKEVAR_QUICK1_DEBUG))
|
||||
|| arg.contains(QLatin1String(Constants::QMAKEVAR_QUICK2_DEBUG))) {
|
||||
ait.deleteArg();
|
||||
removedArgument = true;
|
||||
}
|
||||
}
|
||||
return removedArgument;
|
||||
qCDebug(logs) << "**Incompatible specs";
|
||||
return MakefileIncompatible;
|
||||
}
|
||||
|
||||
FileName QmakeBuildConfiguration::extractSpecFromArguments(QString *args,
|
||||
@@ -499,52 +512,6 @@ FileName QmakeBuildConfiguration::extractSpecFromArguments(QString *args,
|
||||
return parsedSpec;
|
||||
}
|
||||
|
||||
QStringList QmakeBuildConfiguration::extractDeducedArguments(QString *args)
|
||||
{
|
||||
QStringList allPossibleDeducedArguments;
|
||||
allPossibleDeducedArguments << QLatin1String("CONFIG+=x86")
|
||||
<< QLatin1String("CONFIG+=x86_64")
|
||||
<< QLatin1String("CONFIG+=iphonesimulator")
|
||||
<< QLatin1String("CONFIG+=ppc")
|
||||
<< QLatin1String("CONFIG+=ppc64")
|
||||
<< QLatin1String("CONFIG+=iphoneos");
|
||||
QStringList result;
|
||||
for (QtcProcess::ArgIterator ait(args); ait.next(); ) {
|
||||
QString arg = ait.value();
|
||||
if (allPossibleDeducedArguments.contains(arg)) {
|
||||
result << arg;
|
||||
ait.deleteArg();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
QStringList QmakeBuildConfiguration::deduceArgumentsForTargetAbi(const ProjectExplorer::Abi &targetAbi, const BaseQtVersion *version)
|
||||
{
|
||||
QStringList arguments;
|
||||
if ((targetAbi.os() == ProjectExplorer::Abi::MacOS)
|
||||
&& (targetAbi.binaryFormat() == ProjectExplorer::Abi::MachOFormat)) {
|
||||
if (targetAbi.architecture() == ProjectExplorer::Abi::X86Architecture) {
|
||||
if (targetAbi.wordWidth() == 32)
|
||||
arguments << QLatin1String("CONFIG+=x86");
|
||||
else if (targetAbi.wordWidth() == 64)
|
||||
arguments << QLatin1String("CONFIG+=x86_64");
|
||||
|
||||
const char IOSQT[] = "Qt4ProjectManager.QtVersion.Ios";
|
||||
if (version && version->type() == QLatin1String(IOSQT)) // ugly, we can't distinguish between ios and mac toolchains
|
||||
arguments << QLatin1String("CONFIG+=iphonesimulator");
|
||||
} else if (targetAbi.architecture() == ProjectExplorer::Abi::PowerPCArchitecture) {
|
||||
if (targetAbi.wordWidth() == 32)
|
||||
arguments << QLatin1String("CONFIG+=ppc");
|
||||
else if (targetAbi.wordWidth() == 64)
|
||||
arguments << QLatin1String("CONFIG+=ppc64");
|
||||
} else if (targetAbi.architecture() == ProjectExplorer::Abi::ArmArchitecture) {
|
||||
arguments << QLatin1String("CONFIG+=iphoneos");
|
||||
}
|
||||
}
|
||||
return arguments;
|
||||
}
|
||||
|
||||
bool QmakeBuildConfiguration::isEnabled() const
|
||||
{
|
||||
return m_isEnabled;
|
||||
@@ -702,13 +669,13 @@ void QmakeBuildConfigurationFactory::configureBuildConfiguration(Target *parent,
|
||||
cleanSteps->insertStep(0, cleanStep);
|
||||
|
||||
QString additionalArguments = qmakeInfo->additionalArguments;
|
||||
|
||||
bool enableQmlDebugger
|
||||
= QmakeBuildConfiguration::removeQMLInspectorFromArguments(&additionalArguments);
|
||||
if (!additionalArguments.isEmpty())
|
||||
qmakeStep->setUserArguments(additionalArguments);
|
||||
if (!qmakeInfo->makefile.isEmpty())
|
||||
qmakeStep->setLinkQmlDebuggingLibrary(enableQmlDebugger);
|
||||
qmakeStep->setLinkQmlDebuggingLibrary(qmakeInfo->config.linkQmlDebuggingQQ1
|
||||
|| qmakeInfo->config.linkQmlDebuggingQQ2);
|
||||
qmakeStep->setSeparateDebugInfo(qmakeInfo->config.separateDebugInfo);
|
||||
qmakeStep->setUseQtQuickCompiler(qmakeInfo->config.useQtQuickCompiler);
|
||||
|
||||
bc->setQMakeBuildConfiguration(config);
|
||||
|
||||
|
||||
@@ -92,12 +92,9 @@ public:
|
||||
|
||||
enum MakefileState { MakefileMatches, MakefileForWrongProject, MakefileIncompatible, MakefileMissing };
|
||||
MakefileState compareToImportFrom(const QString &makefile);
|
||||
static bool removeQMLInspectorFromArguments(QString *args);
|
||||
static Utils::FileName extractSpecFromArguments(QString *arguments,
|
||||
const QString &directory, const QtSupport::BaseQtVersion *version,
|
||||
QStringList *outArgs = 0);
|
||||
static QStringList extractDeducedArguments(QString *args);
|
||||
static QStringList deduceArgumentsForTargetAbi(const ProjectExplorer::Abi &targetAbi, const QtSupport::BaseQtVersion *version);
|
||||
|
||||
QVariantMap toMap() const;
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#define QMAKEBUILDINFO_H
|
||||
|
||||
#include "qmakebuildconfiguration.h"
|
||||
#include "qmakestep.h"
|
||||
|
||||
#include <projectexplorer/buildinfo.h>
|
||||
#include <projectexplorer/kitmanager.h>
|
||||
@@ -48,6 +49,7 @@ public:
|
||||
ProjectExplorer::BuildConfiguration::BuildType type;
|
||||
QString additionalArguments;
|
||||
QString makefile;
|
||||
QMakeStepConfig config;
|
||||
|
||||
bool operator==(const QmakeBuildInfo &o) {
|
||||
return displayName == o.displayName
|
||||
@@ -55,7 +57,8 @@ public:
|
||||
&& buildDirectory == o.buildDirectory
|
||||
&& kitId == o.kitId
|
||||
&& type == o.type
|
||||
&& additionalArguments == o.additionalArguments;
|
||||
&& additionalArguments == o.additionalArguments
|
||||
&& config == o.config;
|
||||
}
|
||||
|
||||
QList<ProjectExplorer::Task> reportIssues(const QString &projectPath,
|
||||
|
||||
@@ -34,6 +34,8 @@
|
||||
#include "qmakekitinformation.h"
|
||||
#include "qmakebuildconfiguration.h"
|
||||
#include "qmakeproject.h"
|
||||
#include "makefileparse.h"
|
||||
#include "qmakestep.h"
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
#include <coreplugin/idocument.h>
|
||||
@@ -52,6 +54,7 @@
|
||||
#include <QFileInfo>
|
||||
#include <QMessageBox>
|
||||
#include <QStringList>
|
||||
#include <QLoggingCategory>
|
||||
|
||||
using namespace ProjectExplorer;
|
||||
using namespace QtSupport;
|
||||
@@ -61,6 +64,7 @@ namespace QmakeProjectManager {
|
||||
namespace Internal {
|
||||
|
||||
const Core::Id QT_IS_TEMPORARY("Qmake.TempQt");
|
||||
const char IOSQT[] = "Qt4ProjectManager.QtVersion.Ios"; // ugly
|
||||
|
||||
QmakeProjectImporter::QmakeProjectImporter(const QString &path) :
|
||||
ProjectImporter(path)
|
||||
@@ -68,36 +72,46 @@ QmakeProjectImporter::QmakeProjectImporter(const QString &path) :
|
||||
|
||||
QList<BuildInfo *> QmakeProjectImporter::import(const FileName &importPath, bool silent)
|
||||
{
|
||||
const auto &logs = MakeFileParse::logging();
|
||||
qCDebug(logs) << "QmakeProjectImporter::import" << importPath << silent;
|
||||
|
||||
QList<BuildInfo *> result;
|
||||
QFileInfo fi = importPath.toFileInfo();
|
||||
if (!fi.exists() && !fi.isDir())
|
||||
if (!fi.exists() && !fi.isDir()) {
|
||||
qCDebug(logs) << "**doesn't exist";
|
||||
return result;
|
||||
}
|
||||
|
||||
QStringList makefiles = QDir(importPath.toString()).entryList(QStringList(QLatin1String("Makefile*")));
|
||||
qCDebug(logs) << " Makefiles:" << makefiles;
|
||||
|
||||
BaseQtVersion *version = 0;
|
||||
bool temporaryVersion = false;
|
||||
|
||||
foreach (const QString &file, makefiles) {
|
||||
qCDebug(logs) << " Parsing makefile" << file;
|
||||
// find interesting makefiles
|
||||
QString makefile = importPath.toString() + QLatin1Char('/') + file;
|
||||
FileName qmakeBinary = QtVersionManager::findQMakeBinaryFromMakefile(makefile);
|
||||
QFileInfo qmakeFi = qmakeBinary.toFileInfo();
|
||||
MakeFileParse parse(makefile);
|
||||
QFileInfo qmakeFi = parse.qmakePath().toFileInfo();
|
||||
FileName canonicalQmakeBinary = FileName::fromString(qmakeFi.canonicalFilePath());
|
||||
if (canonicalQmakeBinary.isEmpty())
|
||||
if (canonicalQmakeBinary.isEmpty()) {
|
||||
qCDebug(logs) << " " << parse.qmakePath() << "doesn't exist anymore";
|
||||
continue;
|
||||
if (QtVersionManager::makefileIsFor(makefile, projectFilePath()) != QtVersionManager::SameProject)
|
||||
}
|
||||
if (parse.srcProFile() != projectFilePath()) {
|
||||
qCDebug(logs) << " pro files doesn't match" << parse.srcProFile() << projectFilePath();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Find version:
|
||||
foreach (BaseQtVersion *v, QtVersionManager::versions()) {
|
||||
qCDebug(logs) << " QMake:" << canonicalQmakeBinary;
|
||||
|
||||
BaseQtVersion *version
|
||||
= Utils::findOrDefault(QtVersionManager::versions(),
|
||||
[&canonicalQmakeBinary](BaseQtVersion *v) {
|
||||
QFileInfo vfi = v->qmakeCommand().toFileInfo();
|
||||
FileName current = FileName::fromString(vfi.canonicalFilePath());
|
||||
if (current == canonicalQmakeBinary) {
|
||||
version = v;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return current == canonicalQmakeBinary;
|
||||
});
|
||||
|
||||
if (version) {
|
||||
// Check if version is a temporary qt
|
||||
@@ -105,10 +119,11 @@ QList<BuildInfo *> QmakeProjectImporter::import(const FileName &importPath, bool
|
||||
temporaryVersion = Utils::anyOf(KitManager::kits(), [&qtId](Kit *k){
|
||||
return k->value(QT_IS_TEMPORARY, -1).toInt() == qtId;
|
||||
});
|
||||
qCDebug(logs) << " qt version already exist. Temporary:" << temporaryVersion;
|
||||
} else {
|
||||
// Create a new version if not found:
|
||||
// Do not use the canonical path here...
|
||||
version = QtVersionFactory::createQtVersionFromQMakePath(qmakeBinary);
|
||||
version = QtVersionFactory::createQtVersionFromQMakePath(parse.qmakePath());
|
||||
if (!version)
|
||||
continue;
|
||||
|
||||
@@ -116,28 +131,58 @@ QList<BuildInfo *> QmakeProjectImporter::import(const FileName &importPath, bool
|
||||
QtVersionManager::addVersion(version);
|
||||
setIsUpdating(oldIsUpdating);
|
||||
temporaryVersion = true;
|
||||
qCDebug(logs) << " created new qt version";
|
||||
}
|
||||
|
||||
// find qmake arguments and mkspec
|
||||
QPair<BaseQtVersion::QmakeBuildConfigs, QString> makefileBuildConfig =
|
||||
QtVersionManager::scanMakeFile(makefile, version->defaultBuildConfig());
|
||||
QMakeStepConfig::TargetArchConfig archConfig = parse.config().archConfig;
|
||||
QMakeStepConfig::OsType osType = parse.config().osType;
|
||||
qCDebug(logs) << " archConfig:" << archConfig;
|
||||
qCDebug(logs) << " osType: " << osType;
|
||||
if (version->type() == QLatin1String(IOSQT)
|
||||
&& osType == QMakeStepConfig::NoOsType) {
|
||||
osType = QMakeStepConfig::IphoneOS;
|
||||
qCDebug(logs) << " IOS found without osType, adjusting osType" << osType;
|
||||
}
|
||||
|
||||
QString additionalArguments = makefileBuildConfig.second;
|
||||
if (version->type() == QLatin1String(Constants::DESKTOPQT)) {
|
||||
QList<ProjectExplorer::Abi> abis = version->qtAbis();
|
||||
if (!abis.isEmpty()) {
|
||||
ProjectExplorer::Abi abi = abis.first();
|
||||
if (abi.os() == ProjectExplorer::Abi::MacOS) {
|
||||
if (abi.wordWidth() == 64)
|
||||
archConfig = QMakeStepConfig::X86_64;
|
||||
else
|
||||
archConfig = QMakeStepConfig::X86;
|
||||
qCDebug(logs) << " OS X found without targetarch, adjusting archType" << archConfig;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// find qmake arguments and mkspec
|
||||
QString additionalArguments = parse.unparsedArguments();
|
||||
qCDebug(logs) << " Unparsed arguments:" << additionalArguments;
|
||||
FileName parsedSpec =
|
||||
QmakeBuildConfiguration::extractSpecFromArguments(&additionalArguments, importPath.toString(), version);
|
||||
QStringList deducedArguments =
|
||||
QmakeBuildConfiguration::extractDeducedArguments(&additionalArguments);
|
||||
qCDebug(logs) << " Extracted spec:" << parsedSpec;
|
||||
qCDebug(logs) << " Arguments now:" << additionalArguments;
|
||||
|
||||
FileName versionSpec = version->mkspec();
|
||||
if (parsedSpec.isEmpty() || parsedSpec == FileName::fromLatin1("default"))
|
||||
if (parsedSpec.isEmpty() || parsedSpec == FileName::fromLatin1("default")) {
|
||||
parsedSpec = versionSpec;
|
||||
qCDebug(logs) << " No parsed spec or default spec => parsed spec now:" << parsedSpec;
|
||||
}
|
||||
|
||||
QString specArgument;
|
||||
// Compare mkspecs and add to additional arguments
|
||||
if (parsedSpec != versionSpec)
|
||||
if (parsedSpec != versionSpec) {
|
||||
specArgument = QLatin1String("-spec ") + QtcProcess::quoteArg(parsedSpec.toUserOutput());
|
||||
QtcProcess::addArgs(&specArgument, additionalArguments);
|
||||
qCDebug(logs) << " custom spec added to additionalArguments:" << additionalArguments;
|
||||
}
|
||||
|
||||
qCDebug(logs) << "*******************";
|
||||
qCDebug(logs) << "* Looking for kits";
|
||||
// Find kits (can be more than one, e.g. (Linux-)Desktop and embedded linux):
|
||||
QList<Kit *> kitList;
|
||||
foreach (Kit *k, KitManager::kits()) {
|
||||
@@ -146,17 +191,23 @@ QList<BuildInfo *> QmakeProjectImporter::import(const FileName &importPath, bool
|
||||
ToolChain *tc = ToolChainKitInformation::toolChain(k);
|
||||
if (kitSpec.isEmpty() && kitVersion)
|
||||
kitSpec = kitVersion->mkspecFor(tc);
|
||||
QStringList kitDeducedArguments;
|
||||
if (tc)
|
||||
kitDeducedArguments = QmakeBuildConfiguration::deduceArgumentsForTargetAbi(tc->targetAbi(), kitVersion);
|
||||
|
||||
QMakeStepConfig::TargetArchConfig kitTargetArch = QMakeStepConfig::targetArchFor(tc->targetAbi(), kitVersion);
|
||||
QMakeStepConfig::OsType kitOsType = QMakeStepConfig::osTypeFor(tc->targetAbi(), kitVersion);
|
||||
qCDebug(logs) << k->displayName()
|
||||
<< "version:" << (kitVersion == version)
|
||||
<< "spec:" << (kitSpec == parsedSpec)
|
||||
<< "targetarch:" << (kitTargetArch == archConfig)
|
||||
<< "ostype:" << (kitOsType == osType);
|
||||
if (kitVersion == version
|
||||
&& kitSpec == parsedSpec
|
||||
&& kitDeducedArguments == deducedArguments)
|
||||
&& kitTargetArch == archConfig
|
||||
&& kitOsType == osType)
|
||||
kitList.append(k);
|
||||
}
|
||||
if (kitList.isEmpty())
|
||||
kitList.append(createTemporaryKit(version, temporaryVersion, parsedSpec, deducedArguments));
|
||||
if (kitList.isEmpty()) {
|
||||
kitList.append(createTemporaryKit(version, temporaryVersion, parsedSpec, archConfig, osType));
|
||||
qCDebug(logs) << " No matching kits found, created new kit";
|
||||
}
|
||||
|
||||
foreach (Kit *k, kitList) {
|
||||
addProject(k);
|
||||
@@ -169,7 +220,8 @@ QList<BuildInfo *> QmakeProjectImporter::import(const FileName &importPath, bool
|
||||
|
||||
// create info:
|
||||
QmakeBuildInfo *info = new QmakeBuildInfo(factory);
|
||||
if (makefileBuildConfig.first & BaseQtVersion::DebugBuild) {
|
||||
BaseQtVersion::QmakeBuildConfigs buildConfig = parse.effectiveBuildConfig(version->defaultBuildConfig());
|
||||
if (buildConfig & BaseQtVersion::DebugBuild) {
|
||||
info->type = BuildConfiguration::Debug;
|
||||
info->displayName = QCoreApplication::translate("QmakeProjectManager::Internal::QmakeProjectImporter", "Debug");
|
||||
} else {
|
||||
@@ -179,6 +231,7 @@ QList<BuildInfo *> QmakeProjectImporter::import(const FileName &importPath, bool
|
||||
info->kitId = k->id();
|
||||
info->buildDirectory = FileName::fromString(fi.absoluteFilePath());
|
||||
info->additionalArguments = additionalArguments;
|
||||
info->config = parse.config();
|
||||
info->makefile = makefile;
|
||||
|
||||
bool found = false;
|
||||
@@ -289,7 +342,7 @@ void QmakeProjectImporter::makePermanent(Kit *k)
|
||||
ProjectImporter::makePermanent(k);
|
||||
}
|
||||
|
||||
static ToolChain *preferredToolChain(BaseQtVersion *qtVersion, const FileName &ms, const QStringList &deducedArguments)
|
||||
static ToolChain *preferredToolChain(BaseQtVersion *qtVersion, const FileName &ms, const QMakeStepConfig::TargetArchConfig &archConfig)
|
||||
{
|
||||
const FileName spec = ms.isEmpty() ? qtVersion->mkspec() : ms;
|
||||
|
||||
@@ -297,25 +350,27 @@ static ToolChain *preferredToolChain(BaseQtVersion *qtVersion, const FileName &m
|
||||
QList<Abi> qtAbis = qtVersion->qtAbis();
|
||||
return findOr(toolchains,
|
||||
toolchains.isEmpty() ? 0 : toolchains.first(),
|
||||
[&spec, &deducedArguments, &qtAbis](ToolChain *tc) -> bool{
|
||||
[&spec, &archConfig, &qtAbis, &qtVersion](ToolChain *tc) -> bool{
|
||||
return qtAbis.contains(tc->targetAbi())
|
||||
&& tc->suggestedMkspecList().contains(spec)
|
||||
&& QmakeBuildConfiguration::deduceArgumentsForTargetAbi(tc->targetAbi(), 0) == deducedArguments;
|
||||
&& QMakeStepConfig::targetArchFor(tc->targetAbi(), qtVersion) == archConfig;
|
||||
});
|
||||
}
|
||||
|
||||
Kit *QmakeProjectImporter::createTemporaryKit(BaseQtVersion *version,
|
||||
bool temporaryVersion,
|
||||
const FileName &parsedSpec,
|
||||
const QStringList &deducedQmakeArguments)
|
||||
const QMakeStepConfig::TargetArchConfig &archConfig,
|
||||
const QMakeStepConfig::OsType &osType)
|
||||
{
|
||||
Q_UNUSED(osType); // TODO use this to select the right toolchain?
|
||||
Kit *k = new Kit;
|
||||
bool oldIsUpdating = setIsUpdating(true);
|
||||
{
|
||||
KitGuard guard(k);
|
||||
|
||||
QtKitInformation::setQtVersion(k, version);
|
||||
ToolChainKitInformation::setToolChain(k, preferredToolChain(version, parsedSpec, deducedQmakeArguments));
|
||||
ToolChainKitInformation::setToolChain(k, preferredToolChain(version, parsedSpec, archConfig));
|
||||
QmakeKitInformation::setMkspec(k, parsedSpec);
|
||||
|
||||
markTemporary(k);
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#define QMAKEPROJECTIMPORTER_H
|
||||
|
||||
#include <projectexplorer/projectimporter.h>
|
||||
#include <qmakestep.h>
|
||||
|
||||
namespace QtSupport { class BaseQtVersion; }
|
||||
|
||||
@@ -58,7 +59,8 @@ public:
|
||||
private:
|
||||
ProjectExplorer::Kit *createTemporaryKit(QtSupport::BaseQtVersion *version,
|
||||
bool temporaryVersion,
|
||||
const Utils::FileName &parsedSpec, const QStringList &deducedQmakeArguments);
|
||||
const Utils::FileName &parsedSpec,
|
||||
const QmakeProjectManager::QMakeStepConfig::TargetArchConfig &archConfig, const QMakeStepConfig::OsType &osType);
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -51,7 +51,8 @@ HEADERS += \
|
||||
findqmakeprofiles.h \
|
||||
qmakeprojectmanager_global.h \
|
||||
desktopqmakerunconfiguration.h \
|
||||
profilecompletionassist.h
|
||||
profilecompletionassist.h \
|
||||
makefileparse.h
|
||||
|
||||
SOURCES += \
|
||||
qmakekitconfigwidget.cpp \
|
||||
@@ -98,6 +99,7 @@ SOURCES += \
|
||||
findqmakeprofiles.cpp \
|
||||
desktopqmakerunconfiguration.cpp \
|
||||
profilecompletionassist.cpp \
|
||||
makefileparse.cpp
|
||||
|
||||
FORMS += makestep.ui \
|
||||
qmakestep.ui \
|
||||
|
||||
@@ -72,11 +72,6 @@ const char QMAKEPROJECT_ID[] = "Qt4ProjectManager.Qt4Project";
|
||||
// ICONS
|
||||
const char ICON_QTQUICK_APP[] = ":/wizards/images/qtquickapp.png";
|
||||
|
||||
// Env variables
|
||||
const char QMAKEVAR_QMLJSDEBUGGER_PATH[] = "QMLJSDEBUGGER_PATH";
|
||||
const char QMAKEVAR_QUICK1_DEBUG[] = "CONFIG+=declarative_debug";
|
||||
const char QMAKEVAR_QUICK2_DEBUG[] = "CONFIG+=qml_debug";
|
||||
|
||||
} // namespace Constants
|
||||
} // namespace QmakeProjectManager
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
#include <qtsupport/debugginghelperbuildtask.h>
|
||||
#include <qtsupport/qtkitinformation.h>
|
||||
#include <qtsupport/qtversionmanager.h>
|
||||
#include <qtsupport/qtsupportconstants.h>
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/hostosinfo.h>
|
||||
#include <utils/qtcprocess.h>
|
||||
@@ -58,6 +59,7 @@
|
||||
|
||||
using namespace QmakeProjectManager;
|
||||
using namespace QmakeProjectManager::Internal;
|
||||
using namespace QtSupport;
|
||||
using namespace ProjectExplorer;
|
||||
using namespace Utils;
|
||||
|
||||
@@ -154,7 +156,7 @@ QString QMakeStep::allArguments(bool shorted)
|
||||
// Find out what flags we pass on to qmake
|
||||
arguments << bc->configCommandLineArguments();
|
||||
|
||||
arguments << deducedArguments();
|
||||
arguments << deducedArguments().toArguments();
|
||||
|
||||
QString args = QtcProcess::joinArgs(arguments);
|
||||
// User arguments
|
||||
@@ -162,40 +164,36 @@ QString QMakeStep::allArguments(bool shorted)
|
||||
return args;
|
||||
}
|
||||
|
||||
///
|
||||
/// moreArguments,
|
||||
/// iphoneos/iphonesimulator for ios
|
||||
/// QMAKE_VAR_QMLJSDEBUGGER_PATH
|
||||
QStringList QMakeStep::deducedArguments()
|
||||
QMakeStepConfig QMakeStep::deducedArguments()
|
||||
{
|
||||
QStringList arguments;
|
||||
ProjectExplorer::Kit *kit = target()->kit();
|
||||
QMakeStepConfig config;
|
||||
ProjectExplorer::ToolChain *tc
|
||||
= ProjectExplorer::ToolChainKitInformation::toolChain(target()->kit());
|
||||
= ProjectExplorer::ToolChainKitInformation::toolChain(kit);
|
||||
ProjectExplorer::Abi targetAbi;
|
||||
if (tc)
|
||||
targetAbi = tc->targetAbi();
|
||||
|
||||
// explicitly add architecture to CONFIG
|
||||
|
||||
QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(target()->kit());
|
||||
arguments << QmakeBuildConfiguration::deduceArgumentsForTargetAbi(targetAbi, version);
|
||||
|
||||
config.archConfig = QMakeStepConfig::targetArchFor(targetAbi, version);
|
||||
config.osType = QMakeStepConfig::osTypeFor(targetAbi, version);
|
||||
if (linkQmlDebuggingLibrary() && version) {
|
||||
arguments << QLatin1String(Constants::QMAKEVAR_QUICK1_DEBUG);
|
||||
config.linkQmlDebuggingQQ1 = true;
|
||||
if (version->qtVersion().majorVersion >= 5)
|
||||
arguments << QLatin1String(Constants::QMAKEVAR_QUICK2_DEBUG);
|
||||
config.linkQmlDebuggingQQ2 = true;
|
||||
}
|
||||
|
||||
if (useQtQuickCompiler() && version)
|
||||
arguments << QLatin1String("CONFIG+=qtquickcompiler");
|
||||
config.useQtQuickCompiler = true;
|
||||
|
||||
if (separateDebugInfo()) {
|
||||
arguments << QLatin1String("CONFIG+=force_debug_info")
|
||||
<< QLatin1String("CONFIG+=separate_debug_info");
|
||||
}
|
||||
if (separateDebugInfo())
|
||||
config.separateDebugInfo = true;
|
||||
|
||||
return arguments;
|
||||
return config;
|
||||
}
|
||||
|
||||
|
||||
bool QMakeStep::init()
|
||||
{
|
||||
QmakeBuildConfiguration *qt4bc = qmakeBuildConfiguration();
|
||||
@@ -822,3 +820,76 @@ QString QMakeStepFactory::displayNameForId(Core::Id id) const
|
||||
return tr("qmake");
|
||||
return QString();
|
||||
}
|
||||
|
||||
|
||||
QMakeStepConfig::TargetArchConfig QMakeStepConfig::targetArchFor(const Abi &targetAbi, const BaseQtVersion *version)
|
||||
{
|
||||
QMakeStepConfig::TargetArchConfig arch = QMakeStepConfig::NoArch;
|
||||
if (!version || version->type() != QLatin1String(QtSupport::Constants::DESKTOPQT))
|
||||
return arch;
|
||||
if ((targetAbi.os() == ProjectExplorer::Abi::MacOS)
|
||||
&& (targetAbi.binaryFormat() == ProjectExplorer::Abi::MachOFormat)) {
|
||||
if (targetAbi.architecture() == ProjectExplorer::Abi::X86Architecture) {
|
||||
if (targetAbi.wordWidth() == 32)
|
||||
arch = QMakeStepConfig::X86;
|
||||
else if (targetAbi.wordWidth() == 64)
|
||||
arch = QMakeStepConfig::X86_64;
|
||||
} else if (targetAbi.architecture() == ProjectExplorer::Abi::PowerPCArchitecture) {
|
||||
if (targetAbi.wordWidth() == 32)
|
||||
arch = QMakeStepConfig::PPC;
|
||||
else if (targetAbi.wordWidth() == 64)
|
||||
arch = QMakeStepConfig::PPC64;
|
||||
}
|
||||
}
|
||||
return arch;
|
||||
}
|
||||
|
||||
QMakeStepConfig::OsType QMakeStepConfig::osTypeFor(const ProjectExplorer::Abi &targetAbi, const BaseQtVersion *version)
|
||||
{
|
||||
QMakeStepConfig::OsType os = QMakeStepConfig::NoOsType;
|
||||
const char IOSQT[] = "Qt4ProjectManager.QtVersion.Ios";
|
||||
if (!version || version->type() != QLatin1String(IOSQT))
|
||||
return os;
|
||||
if ((targetAbi.os() == ProjectExplorer::Abi::MacOS)
|
||||
&& (targetAbi.binaryFormat() == ProjectExplorer::Abi::MachOFormat)) {
|
||||
if (targetAbi.architecture() == ProjectExplorer::Abi::X86Architecture) {
|
||||
os = QMakeStepConfig::IphoneSimulator;
|
||||
} else if (targetAbi.architecture() == ProjectExplorer::Abi::ArmArchitecture) {
|
||||
os = QMakeStepConfig::IphoneOS;
|
||||
}
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
QStringList QMakeStepConfig::toArguments() const
|
||||
{
|
||||
QStringList arguments;
|
||||
if (archConfig == X86)
|
||||
arguments << QLatin1String("CONFIG+=x86");
|
||||
else if (archConfig == X86_64)
|
||||
arguments << QLatin1String("CONFIG+=x86_64");
|
||||
else if (archConfig == PPC)
|
||||
arguments << QLatin1String("CONFIG+=ppc");
|
||||
else if (archConfig == PPC64)
|
||||
arguments << QLatin1String("CONFIG+=ppc64");
|
||||
|
||||
if (osType == IphoneSimulator)
|
||||
arguments << QLatin1String("CONFIG+=iphonesimulator");
|
||||
else if (osType == IphoneOS)
|
||||
arguments << QLatin1String("CONFIG+=iphoneos");
|
||||
|
||||
if (linkQmlDebuggingQQ1)
|
||||
arguments << QLatin1String("CONFIG+=declarative_debug");
|
||||
if (linkQmlDebuggingQQ2)
|
||||
arguments << QLatin1String("CONFIG+=qml_debug");
|
||||
|
||||
if (useQtQuickCompiler)
|
||||
arguments << QLatin1String("CONFIG+=qtquickcompiler");
|
||||
|
||||
if (separateDebugInfo)
|
||||
arguments << QLatin1String("CONFIG+=force_debug_info")
|
||||
<< QLatin1String("CONFIG+=separate_debug_info");
|
||||
|
||||
return arguments;
|
||||
}
|
||||
|
||||
|
||||
@@ -39,11 +39,15 @@
|
||||
namespace Utils { class FileName; }
|
||||
|
||||
namespace ProjectExplorer {
|
||||
class Abi;
|
||||
class BuildStep;
|
||||
class IBuildStepFactory;
|
||||
class Project;
|
||||
class Kit;
|
||||
}
|
||||
|
||||
namespace QtSupport { class BaseQtVersion; }
|
||||
|
||||
namespace QmakeProjectManager {
|
||||
class QmakeBuildConfiguration;
|
||||
class QmakeProject;
|
||||
@@ -71,6 +75,56 @@ public:
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
class QMAKEPROJECTMANAGER_EXPORT QMakeStepConfig
|
||||
{
|
||||
public:
|
||||
enum TargetArchConfig {
|
||||
NoArch, X86, X86_64, PPC, PPC64
|
||||
};
|
||||
|
||||
enum OsType {
|
||||
NoOsType, IphoneSimulator, IphoneOS
|
||||
};
|
||||
|
||||
static TargetArchConfig targetArchFor(const ProjectExplorer::Abi &targetAbi, const QtSupport::BaseQtVersion *version);
|
||||
static OsType osTypeFor(const ProjectExplorer::Abi &targetAbi, const QtSupport::BaseQtVersion *version);
|
||||
|
||||
|
||||
QMakeStepConfig()
|
||||
: archConfig(NoArch),
|
||||
osType(NoOsType),
|
||||
linkQmlDebuggingQQ1(false),
|
||||
linkQmlDebuggingQQ2(false),
|
||||
useQtQuickCompiler(false),
|
||||
separateDebugInfo(false)
|
||||
{}
|
||||
|
||||
QStringList toArguments() const;
|
||||
|
||||
// Actual data
|
||||
TargetArchConfig archConfig;
|
||||
OsType osType;
|
||||
bool linkQmlDebuggingQQ1;
|
||||
bool linkQmlDebuggingQQ2;
|
||||
bool useQtQuickCompiler;
|
||||
bool separateDebugInfo;
|
||||
};
|
||||
|
||||
|
||||
inline bool operator ==(const QMakeStepConfig &a, const QMakeStepConfig &b) {
|
||||
return std::tie(a.archConfig, a.osType, a.linkQmlDebuggingQQ1, a.linkQmlDebuggingQQ2, a.useQtQuickCompiler, a.separateDebugInfo)
|
||||
== std::tie(b.archConfig, b.osType, b.linkQmlDebuggingQQ1, b.linkQmlDebuggingQQ2, b.useQtQuickCompiler, b.separateDebugInfo);
|
||||
}
|
||||
|
||||
inline bool operator !=(const QMakeStepConfig &a, const QMakeStepConfig &b) {
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
inline QDebug operator<<(QDebug dbg, const QMakeStepConfig &c)
|
||||
{
|
||||
dbg << c.archConfig << c.osType << c.linkQmlDebuggingQQ1 << c.linkQmlDebuggingQQ2 << c.useQtQuickCompiler << c.separateDebugInfo;
|
||||
return dbg;
|
||||
}
|
||||
|
||||
class QMAKEPROJECTMANAGER_EXPORT QMakeStep : public ProjectExplorer::AbstractProcessStep
|
||||
{
|
||||
@@ -100,8 +154,7 @@ public:
|
||||
|
||||
// the complete argument line
|
||||
QString allArguments(bool shorted = false);
|
||||
// deduced arguments e.g. qmljs debugging
|
||||
QStringList deducedArguments();
|
||||
QMakeStepConfig deducedArguments();
|
||||
// arguments passed to the pro file parser
|
||||
QStringList parserArguments();
|
||||
// arguments set by the user
|
||||
|
||||
@@ -64,13 +64,6 @@ namespace QtSupport {
|
||||
|
||||
using namespace Internal;
|
||||
|
||||
struct QMakeAssignment
|
||||
{
|
||||
QString variable;
|
||||
QString op;
|
||||
QString value;
|
||||
};
|
||||
|
||||
const char QTVERSION_DATA_KEY[] = "QtVersion.";
|
||||
const char QTVERSION_TYPE_KEY[] = "QtVersion.Type";
|
||||
const char QTVERSION_FILE_VERSION_KEY[] = "Version";
|
||||
@@ -107,36 +100,6 @@ bool qtVersionNumberCompare(BaseQtVersion *a, BaseQtVersion *b)
|
||||
{
|
||||
return a->qtVersion() > b->qtVersion() || (a->qtVersion() == b->qtVersion() && a->uniqueId() < b->uniqueId());
|
||||
}
|
||||
|
||||
static QString findQMakeLine(const QString &makefile, const QString &key)
|
||||
{
|
||||
QFile fi(makefile);
|
||||
if (fi.exists() && fi.open(QFile::ReadOnly)) {
|
||||
QTextStream ts(&fi);
|
||||
while (!ts.atEnd()) {
|
||||
const QString line = ts.readLine();
|
||||
if (line.startsWith(key))
|
||||
return line;
|
||||
}
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
/// This function trims the "#Command /path/to/qmake" from the line
|
||||
static QString trimLine(const QString &line)
|
||||
{
|
||||
|
||||
// Actually the first space after #Command: /path/to/qmake
|
||||
const int firstSpace = line.indexOf(QLatin1Char(' '), 11);
|
||||
return line.mid(firstSpace).trimmed();
|
||||
}
|
||||
|
||||
static void parseArgs(const QString &args,
|
||||
QList<QMakeAssignment> *assignments,
|
||||
QList<QMakeAssignment> *afterAssignments,
|
||||
QString *additionalArguments);
|
||||
static BaseQtVersion::QmakeBuildConfigs qmakeBuildConfigFromCmdArgs(QList<QMakeAssignment> *assignments,
|
||||
BaseQtVersion::QmakeBuildConfigs defaultBuildConfig);
|
||||
static bool restoreQtVersions();
|
||||
static void findSystemQt();
|
||||
static void saveQtVersions();
|
||||
@@ -608,210 +571,9 @@ void QtVersionManager::setNewQtVersions(QList<BaseQtVersion *> newVersions)
|
||||
emit m_instance->qtVersionsChanged(addedVersions, removedVersions, changedVersions);
|
||||
}
|
||||
|
||||
// Returns the version that was used to build the project in that directory
|
||||
// That is returns the directory
|
||||
// To find out whether we already have a qtversion for that directory call
|
||||
// QtVersion *QtVersionManager::qtVersionForDirectory(const QString directory);
|
||||
FileName QtVersionManager::findQMakeBinaryFromMakefile(const QString &makefile)
|
||||
{
|
||||
bool debugAdding = false;
|
||||
QFile fi(makefile);
|
||||
if (fi.exists() && fi.open(QFile::ReadOnly)) {
|
||||
QTextStream ts(&fi);
|
||||
QRegExp r1(QLatin1String("QMAKE\\s*=(.*)"));
|
||||
while (!ts.atEnd()) {
|
||||
QString line = ts.readLine();
|
||||
if (r1.exactMatch(line)) {
|
||||
if (debugAdding)
|
||||
qDebug()<<"#~~ QMAKE is:"<<r1.cap(1).trimmed();
|
||||
QFileInfo qmake(r1.cap(1).trimmed());
|
||||
QString qmakePath = qmake.filePath();
|
||||
if (!QString::fromLatin1(QTC_HOST_EXE_SUFFIX).isEmpty()
|
||||
&& !qmakePath.endsWith(QLatin1String(QTC_HOST_EXE_SUFFIX))) {
|
||||
qmakePath.append(QLatin1String(QTC_HOST_EXE_SUFFIX));
|
||||
}
|
||||
// Is qmake still installed?
|
||||
QFileInfo fi(qmakePath);
|
||||
if (fi.exists())
|
||||
return FileName(fi);
|
||||
}
|
||||
}
|
||||
}
|
||||
return FileName();
|
||||
}
|
||||
|
||||
BaseQtVersion *QtVersionManager::qtVersionForQMakeBinary(const FileName &qmakePath)
|
||||
{
|
||||
return Utils::findOrDefault(versions(), Utils::equal(&BaseQtVersion::qmakeCommand, qmakePath));
|
||||
}
|
||||
|
||||
void dumpQMakeAssignments(const QList<QMakeAssignment> &list)
|
||||
{
|
||||
foreach (const QMakeAssignment &qa, list) {
|
||||
qDebug()<<qa.variable<<qa.op<<qa.value;
|
||||
}
|
||||
}
|
||||
|
||||
QtVersionManager::MakefileCompatible QtVersionManager::makefileIsFor(const QString &makefile, const QString &proFile)
|
||||
{
|
||||
if (proFile.isEmpty())
|
||||
return CouldNotParse;
|
||||
|
||||
// The Makefile.Debug / Makefile.Release lack a # Command: line
|
||||
if (findQMakeLine(makefile, QLatin1String("# Command:")).trimmed().isEmpty())
|
||||
return CouldNotParse;
|
||||
|
||||
QString line = findQMakeLine(makefile, QLatin1String("# Project:")).trimmed();
|
||||
if (line.isEmpty())
|
||||
return CouldNotParse;
|
||||
|
||||
line.remove(0, line.indexOf(QLatin1Char(':')) + 1);
|
||||
line = line.trimmed();
|
||||
|
||||
QFileInfo srcFileInfo(QFileInfo(makefile).absoluteDir(), line);
|
||||
QFileInfo proFileInfo(proFile);
|
||||
return (srcFileInfo == proFileInfo) ? SameProject : DifferentProject;
|
||||
}
|
||||
|
||||
QPair<BaseQtVersion::QmakeBuildConfigs, QString> QtVersionManager::scanMakeFile(const QString &makefile, BaseQtVersion::QmakeBuildConfigs defaultBuildConfig)
|
||||
{
|
||||
if (debug)
|
||||
qDebug()<<"ScanMakeFile, the gory details:";
|
||||
BaseQtVersion::QmakeBuildConfigs result = defaultBuildConfig;
|
||||
QString result2;
|
||||
|
||||
QString line = findQMakeLine(makefile, QLatin1String("# Command:"));
|
||||
if (!line.isEmpty()) {
|
||||
if (debug)
|
||||
qDebug()<<"Found line"<<line;
|
||||
line = trimLine(line);
|
||||
QList<QMakeAssignment> assignments;
|
||||
QList<QMakeAssignment> afterAssignments;
|
||||
parseArgs(line, &assignments, &afterAssignments, &result2);
|
||||
|
||||
if (debug) {
|
||||
dumpQMakeAssignments(assignments);
|
||||
if (!afterAssignments.isEmpty())
|
||||
qDebug()<<"-after";
|
||||
dumpQMakeAssignments(afterAssignments);
|
||||
}
|
||||
|
||||
// Search in assignments for CONFIG(+=,-=,=)(debug,release,debug_and_release)
|
||||
// Also remove them from the list
|
||||
result = qmakeBuildConfigFromCmdArgs(&assignments, defaultBuildConfig);
|
||||
|
||||
if (debug)
|
||||
dumpQMakeAssignments(assignments);
|
||||
|
||||
foreach (const QMakeAssignment &qa, assignments)
|
||||
QtcProcess::addArg(&result2, qa.variable + qa.op + qa.value);
|
||||
if (!afterAssignments.isEmpty()) {
|
||||
QtcProcess::addArg(&result2, QLatin1String("-after"));
|
||||
foreach (const QMakeAssignment &qa, afterAssignments)
|
||||
QtcProcess::addArg(&result2, qa.variable + qa.op + qa.value);
|
||||
}
|
||||
}
|
||||
|
||||
// Dump the gathered information:
|
||||
if (debug) {
|
||||
qDebug()<<"\n\nDumping information from scanMakeFile";
|
||||
qDebug()<<"QMake CONFIG variable parsing";
|
||||
qDebug()<<" "<< (result & BaseQtVersion::NoBuild ? QByteArray("No Build") : QByteArray::number(int(result)));
|
||||
qDebug()<<" "<< (result & BaseQtVersion::DebugBuild ? "debug" : "release");
|
||||
qDebug()<<" "<< (result & BaseQtVersion::BuildAll ? "debug_and_release" : "no debug_and_release");
|
||||
qDebug()<<"\nAddtional Arguments";
|
||||
qDebug()<<result2;
|
||||
qDebug()<<"\n\n";
|
||||
}
|
||||
return qMakePair(result, result2);
|
||||
}
|
||||
|
||||
static void parseArgs(const QString &args, QList<QMakeAssignment> *assignments, QList<QMakeAssignment> *afterAssignments, QString *additionalArguments)
|
||||
{
|
||||
QRegExp regExp(QLatin1String("([^\\s\\+-]*)\\s*(\\+=|=|-=|~=)(.*)"));
|
||||
bool after = false;
|
||||
bool ignoreNext = false;
|
||||
*additionalArguments = args;
|
||||
QtcProcess::ArgIterator ait(additionalArguments);
|
||||
while (ait.next()) {
|
||||
if (ignoreNext) {
|
||||
// Ignoring
|
||||
ignoreNext = false;
|
||||
ait.deleteArg();
|
||||
} else if (ait.value() == QLatin1String("-after")) {
|
||||
after = true;
|
||||
ait.deleteArg();
|
||||
} else if (ait.value().contains(QLatin1Char('='))) {
|
||||
if (regExp.exactMatch(ait.value())) {
|
||||
QMakeAssignment qa;
|
||||
qa.variable = regExp.cap(1);
|
||||
qa.op = regExp.cap(2);
|
||||
qa.value = regExp.cap(3).trimmed();
|
||||
if (after)
|
||||
afterAssignments->append(qa);
|
||||
else
|
||||
assignments->append(qa);
|
||||
} else {
|
||||
qDebug()<<"regexp did not match";
|
||||
}
|
||||
ait.deleteArg();
|
||||
} else if (ait.value() == QLatin1String("-o")) {
|
||||
ignoreNext = true;
|
||||
ait.deleteArg();
|
||||
#if defined(Q_OS_WIN32)
|
||||
} else if (ait.value() == QLatin1String("-win32")) {
|
||||
#elif defined(Q_OS_MAC)
|
||||
} else if (ait.value() == QLatin1String("-macx")) {
|
||||
#elif defined(Q_OS_QNX6)
|
||||
} else if (ait.value() == QLatin1String("-qnx6")) {
|
||||
#else
|
||||
} else if (ait.value() == QLatin1String("-unix")) {
|
||||
#endif
|
||||
ait.deleteArg();
|
||||
}
|
||||
}
|
||||
ait.deleteArg(); // The .pro file is always the last arg
|
||||
}
|
||||
|
||||
/// This function extracts all the CONFIG+=debug, CONFIG+=release
|
||||
static BaseQtVersion::QmakeBuildConfigs qmakeBuildConfigFromCmdArgs(QList<QMakeAssignment> *assignments, BaseQtVersion::QmakeBuildConfigs defaultBuildConfig)
|
||||
{
|
||||
BaseQtVersion::QmakeBuildConfigs result = defaultBuildConfig;
|
||||
QList<QMakeAssignment> oldAssignments = *assignments;
|
||||
assignments->clear();
|
||||
foreach (const QMakeAssignment &qa, oldAssignments) {
|
||||
if (qa.variable == QLatin1String("CONFIG")) {
|
||||
QStringList values = qa.value.split(QLatin1Char(' '));
|
||||
QStringList newValues;
|
||||
foreach (const QString &value, values) {
|
||||
if (value == QLatin1String("debug")) {
|
||||
if (qa.op == QLatin1String("+="))
|
||||
result = result | BaseQtVersion::DebugBuild;
|
||||
else
|
||||
result = result & ~BaseQtVersion::DebugBuild;
|
||||
} else if (value == QLatin1String("release")) {
|
||||
if (qa.op == QLatin1String("+="))
|
||||
result = result & ~BaseQtVersion::DebugBuild;
|
||||
else
|
||||
result = result | BaseQtVersion::DebugBuild;
|
||||
} else if (value == QLatin1String("debug_and_release")) {
|
||||
if (qa.op == QLatin1String("+="))
|
||||
result = result | BaseQtVersion::BuildAll;
|
||||
else
|
||||
result = result & ~BaseQtVersion::BuildAll;
|
||||
} else {
|
||||
newValues.append(value);
|
||||
}
|
||||
QMakeAssignment newQA = qa;
|
||||
newQA.value = newValues.join(QLatin1Char(' '));
|
||||
if (!newValues.isEmpty())
|
||||
assignments->append(newQA);
|
||||
}
|
||||
} else {
|
||||
assignments->append(qa);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace QtVersion
|
||||
|
||||
@@ -66,11 +66,6 @@ public:
|
||||
static void addVersion(BaseQtVersion *version);
|
||||
static void removeVersion(BaseQtVersion *version);
|
||||
|
||||
enum MakefileCompatible { CouldNotParse, DifferentProject, SameProject };
|
||||
static MakefileCompatible makefileIsFor(const QString &makefile, const QString &proFile);
|
||||
static QPair<BaseQtVersion::QmakeBuildConfigs, QString> scanMakeFile(const QString &makefile,
|
||||
BaseQtVersion::QmakeBuildConfigs defaultBuildConfig);
|
||||
static Utils::FileName findQMakeBinaryFromMakefile(const QString &directory);
|
||||
static bool isValidId(int id);
|
||||
|
||||
signals:
|
||||
|
||||
Reference in New Issue
Block a user