forked from qt-creator/qt-creator
QmakeProjectImporter: Split up import method
Split up the import method into several smaller methods. Call these from ProjectImporter::import, which now contains the build system independent parts, moving all the build system dependent code into the smaller methods. This will allow to reuse logic for cmake project import. Change-Id: Idcd1d1daaab18ebcc581cc5aff3f20c7757c639b Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
@@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include "projectimporter.h"
|
#include "projectimporter.h"
|
||||||
|
|
||||||
|
#include "buildinfo.h"
|
||||||
#include "kit.h"
|
#include "kit.h"
|
||||||
#include "kitinformation.h"
|
#include "kitinformation.h"
|
||||||
#include "kitmanager.h"
|
#include "kitmanager.h"
|
||||||
@@ -32,10 +33,14 @@
|
|||||||
#include "projectexplorerconstants.h"
|
#include "projectexplorerconstants.h"
|
||||||
#include "target.h"
|
#include "target.h"
|
||||||
|
|
||||||
#include <coreplugin/idocument.h>
|
#include <coreplugin/icore.h>
|
||||||
|
|
||||||
|
#include <utils/algorithm.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
|
#include <QLoggingCategory>
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
namespace ProjectExplorer {
|
namespace ProjectExplorer {
|
||||||
|
|
||||||
static const Core::Id KIT_IS_TEMPORARY("PE.TempKit");
|
static const Core::Id KIT_IS_TEMPORARY("PE.TempKit");
|
||||||
@@ -52,6 +57,70 @@ ProjectImporter::~ProjectImporter()
|
|||||||
removeProject(k);
|
removeProject(k);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QList<BuildInfo *> ProjectImporter::import(const Utils::FileName &importPath, bool silent)
|
||||||
|
{
|
||||||
|
QList<BuildInfo *> result;
|
||||||
|
|
||||||
|
const QLoggingCategory log("qtc.projectexplorer.import");
|
||||||
|
qCDebug(log) << "ProjectImporter::import" << importPath << silent;
|
||||||
|
|
||||||
|
QFileInfo fi = importPath.toFileInfo();
|
||||||
|
if (!fi.exists() && !fi.isDir()) {
|
||||||
|
qCDebug(log) << "**doesn't exist";
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Utils::FileName absoluteImportPath = Utils::FileName::fromString(fi.absoluteFilePath());
|
||||||
|
|
||||||
|
qCDebug(log) << "Examining directory" << absoluteImportPath.toString();
|
||||||
|
QList<void *> dataList = examineDirectory(absoluteImportPath);
|
||||||
|
if (dataList.isEmpty()) {
|
||||||
|
qCDebug(log) << "Nothing to import found in" << absoluteImportPath.toString();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
qCDebug(log) << "Looking for kits";
|
||||||
|
foreach (void *data, dataList) {
|
||||||
|
QTC_ASSERT(data, continue);
|
||||||
|
QList<Kit *> kitList;
|
||||||
|
const QList<Kit *> tmp
|
||||||
|
= Utils::filtered(KitManager::kits(), [this, data](Kit *k) { return matchKit(data, k); });
|
||||||
|
if (tmp.isEmpty()) {
|
||||||
|
kitList += createKit(data);
|
||||||
|
qCDebug(log) << " no matching kit found, temporary kit created.";
|
||||||
|
} else {
|
||||||
|
kitList += tmp;
|
||||||
|
qCDebug(log) << " " << tmp.count() << "matching kits found.";
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (Kit *k, kitList) {
|
||||||
|
qCDebug(log) << "Creating buildinfos for kit" << k->displayName();
|
||||||
|
QList<BuildInfo *> infoList = buildInfoListForKit(k, data);
|
||||||
|
if (infoList.isEmpty()) {
|
||||||
|
qCDebug(log) << "No build infos for kit" << k->displayName();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
addProject(k);
|
||||||
|
|
||||||
|
foreach (BuildInfo *i, infoList) {
|
||||||
|
if (!Utils::contains(result, [i](const BuildInfo *o) { return (*i) == (*o); }))
|
||||||
|
result += i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
qDeleteAll(dataList);
|
||||||
|
|
||||||
|
if (result.isEmpty() && !silent)
|
||||||
|
QMessageBox::critical(Core::ICore::mainWindow(),
|
||||||
|
QCoreApplication::translate("ProjectExplorer::ProjectImporter", "No Build Found"),
|
||||||
|
QCoreApplication::translate("ProjectExplorer::ProjectImporter", "No build found in %1 matching project %2.")
|
||||||
|
.arg(importPath.toUserOutput()).arg(QDir::toNativeSeparators(projectFilePath())));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
Target *ProjectImporter::preferredTarget(const QList<Target *> &possibleTargets)
|
Target *ProjectImporter::preferredTarget(const QList<Target *> &possibleTargets)
|
||||||
{
|
{
|
||||||
// Select active target
|
// Select active target
|
||||||
@@ -77,7 +146,7 @@ Target *ProjectImporter::preferredTarget(const QList<Target *> &possibleTargets)
|
|||||||
return activeTarget;
|
return activeTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProjectImporter::markTemporary(Kit *k)
|
void ProjectImporter::markTemporary(Kit *k) const
|
||||||
{
|
{
|
||||||
QTC_ASSERT(!k->hasValue(KIT_IS_TEMPORARY), return);
|
QTC_ASSERT(!k->hasValue(KIT_IS_TEMPORARY), return);
|
||||||
|
|
||||||
@@ -92,7 +161,7 @@ void ProjectImporter::markTemporary(Kit *k)
|
|||||||
k->setValue(KIT_IS_TEMPORARY, true);
|
k->setValue(KIT_IS_TEMPORARY, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProjectImporter::makePermanent(Kit *k)
|
void ProjectImporter::makePermanent(Kit *k) const
|
||||||
{
|
{
|
||||||
if (!k->hasValue(KIT_IS_TEMPORARY))
|
if (!k->hasValue(KIT_IS_TEMPORARY))
|
||||||
return;
|
return;
|
||||||
@@ -144,7 +213,7 @@ bool ProjectImporter::isTemporaryKit(Kit *k) const
|
|||||||
return k->hasValue(KIT_IS_TEMPORARY);
|
return k->hasValue(KIT_IS_TEMPORARY);
|
||||||
}
|
}
|
||||||
|
|
||||||
Kit *ProjectImporter::createTemporaryKit(const KitSetupFunction &setup)
|
Kit *ProjectImporter::createTemporaryKit(const KitSetupFunction &setup) const
|
||||||
{
|
{
|
||||||
Kit *k = new Kit;
|
Kit *k = new Kit;
|
||||||
UpdateGuard guard(*this);
|
UpdateGuard guard(*this);
|
||||||
|
|||||||
@@ -45,13 +45,13 @@ public:
|
|||||||
|
|
||||||
const QString projectFilePath() const { return m_projectPath; }
|
const QString projectFilePath() const { return m_projectPath; }
|
||||||
|
|
||||||
virtual QList<BuildInfo *> import(const Utils::FileName &importPath, bool silent = false) = 0;
|
virtual QList<BuildInfo *> import(const Utils::FileName &importPath, bool silent = false);
|
||||||
virtual QStringList importCandidates() = 0;
|
virtual QStringList importCandidates() = 0;
|
||||||
virtual Target *preferredTarget(const QList<Target *> &possibleTargets);
|
virtual Target *preferredTarget(const QList<Target *> &possibleTargets);
|
||||||
|
|
||||||
bool isUpdating() const { return m_isUpdating; }
|
bool isUpdating() const { return m_isUpdating; }
|
||||||
|
|
||||||
virtual void makePermanent(Kit *k);
|
virtual void makePermanent(Kit *k) const;
|
||||||
|
|
||||||
// Additional cleanup that has to happen when kits are removed
|
// Additional cleanup that has to happen when kits are removed
|
||||||
virtual void cleanupKit(Kit *k);
|
virtual void cleanupKit(Kit *k);
|
||||||
@@ -65,7 +65,7 @@ protected:
|
|||||||
class UpdateGuard
|
class UpdateGuard
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
UpdateGuard(ProjectImporter &i) : m_importer(i)
|
UpdateGuard(const ProjectImporter &i) : m_importer(i)
|
||||||
{
|
{
|
||||||
m_wasUpdating = m_importer.isUpdating();
|
m_wasUpdating = m_importer.isUpdating();
|
||||||
m_importer.m_isUpdating = true;
|
m_importer.m_isUpdating = true;
|
||||||
@@ -73,19 +73,27 @@ protected:
|
|||||||
~UpdateGuard() { m_importer.m_isUpdating = m_wasUpdating; }
|
~UpdateGuard() { m_importer.m_isUpdating = m_wasUpdating; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ProjectImporter &m_importer;
|
const ProjectImporter &m_importer;
|
||||||
bool m_wasUpdating;
|
bool m_wasUpdating;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// importPath is an existing directory at this point!
|
||||||
|
virtual QList<void *> examineDirectory(const Utils::FileName &importPath) const = 0;
|
||||||
|
// will get one of the results from examineDirectory
|
||||||
|
virtual bool matchKit(void *directoryData, const Kit *k) const = 0;
|
||||||
|
// will get one of the results from examineDirectory
|
||||||
|
virtual Kit *createKit(void *directoryData) const = 0;
|
||||||
|
// will get one of the results from examineDirectory
|
||||||
|
virtual QList<BuildInfo *> buildInfoListForKit(const Kit *k, void *directoryData) const = 0;
|
||||||
|
|
||||||
using KitSetupFunction = std::function<void(Kit *)>;
|
using KitSetupFunction = std::function<void(Kit *)>;
|
||||||
ProjectExplorer::Kit *createTemporaryKit(const KitSetupFunction &setup);
|
ProjectExplorer::Kit *createTemporaryKit(const KitSetupFunction &setup) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void markTemporary(Kit *k);
|
void markTemporary(Kit *k) const;
|
||||||
|
|
||||||
const QString m_projectPath;
|
const QString m_projectPath;
|
||||||
bool m_isUpdating = false;
|
mutable bool m_isUpdating = false;
|
||||||
|
|
||||||
friend class UpdateGuard;
|
friend class UpdateGuard;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -32,7 +32,6 @@
|
|||||||
#include "makefileparse.h"
|
#include "makefileparse.h"
|
||||||
#include "qmakestep.h"
|
#include "qmakestep.h"
|
||||||
|
|
||||||
#include <coreplugin/icore.h>
|
|
||||||
#include <projectexplorer/kitmanager.h>
|
#include <projectexplorer/kitmanager.h>
|
||||||
#include <projectexplorer/toolchain.h>
|
#include <projectexplorer/toolchain.h>
|
||||||
#include <projectexplorer/toolchainmanager.h>
|
#include <projectexplorer/toolchainmanager.h>
|
||||||
@@ -47,14 +46,34 @@
|
|||||||
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QMessageBox>
|
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QLoggingCategory>
|
#include <QLoggingCategory>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
using namespace ProjectExplorer;
|
using namespace ProjectExplorer;
|
||||||
|
using namespace QmakeProjectManager;
|
||||||
using namespace QtSupport;
|
using namespace QtSupport;
|
||||||
using namespace Utils;
|
using namespace Utils;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
struct DirectoryData
|
||||||
|
{
|
||||||
|
QString makefile;
|
||||||
|
Utils::FileName buildDirectory;
|
||||||
|
Utils::FileName canonicalQmakeBinary;
|
||||||
|
QtProjectImporter::QtVersionData qtVersionData;
|
||||||
|
FileName parsedSpec;
|
||||||
|
BaseQtVersion::QmakeBuildConfigs buildConfig;
|
||||||
|
QString additionalArguments;
|
||||||
|
QMakeStepConfig config;
|
||||||
|
QMakeStepConfig::TargetArchConfig archConfig;
|
||||||
|
QMakeStepConfig::OsType osType;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
namespace QmakeProjectManager {
|
namespace QmakeProjectManager {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
@@ -65,166 +84,6 @@ QmakeProjectImporter::QmakeProjectImporter(const QString &path) :
|
|||||||
QtProjectImporter(path)
|
QtProjectImporter(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()) {
|
|
||||||
qCDebug(logs) << "**doesn't exist";
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
QStringList makefiles = QDir(importPath.toString()).entryList(QStringList(QLatin1String("Makefile*")));
|
|
||||||
qCDebug(logs) << " Makefiles:" << makefiles;
|
|
||||||
|
|
||||||
foreach (const QString &file, makefiles) {
|
|
||||||
qCDebug(logs) << " Parsing makefile" << file;
|
|
||||||
// find interesting makefiles
|
|
||||||
QString makefile = importPath.toString() + QLatin1Char('/') + file;
|
|
||||||
MakeFileParse parse(makefile);
|
|
||||||
if (parse.makeFileState() != MakeFileParse::Okay)
|
|
||||||
continue;
|
|
||||||
QFileInfo qmakeFi = parse.qmakePath().toFileInfo();
|
|
||||||
FileName canonicalQmakeBinary = FileName::fromString(qmakeFi.canonicalFilePath());
|
|
||||||
if (canonicalQmakeBinary.isEmpty()) {
|
|
||||||
qCDebug(logs) << " " << parse.qmakePath() << "doesn't exist anymore";
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (parse.srcProFile() != projectFilePath()) {
|
|
||||||
qCDebug(logs) << " pro files doesn't match" << parse.srcProFile() << projectFilePath();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
qCDebug(logs) << " QMake:" << canonicalQmakeBinary;
|
|
||||||
|
|
||||||
QtProjectImporter::QtVersionData data
|
|
||||||
= QtProjectImporter::findOrCreateQtVersion(canonicalQmakeBinary);
|
|
||||||
QTC_ASSERT(data.version, continue);
|
|
||||||
qCDebug(logs) << " qt version:" << data.version->displayName()
|
|
||||||
<< " temporary:" << data.isTemporaryVersion;
|
|
||||||
|
|
||||||
QMakeStepConfig::TargetArchConfig archConfig = parse.config().archConfig;
|
|
||||||
QMakeStepConfig::OsType osType = parse.config().osType;
|
|
||||||
qCDebug(logs) << " archConfig:" << archConfig;
|
|
||||||
qCDebug(logs) << " osType: " << osType;
|
|
||||||
if (data.version->type() == QLatin1String(IOSQT)
|
|
||||||
&& osType == QMakeStepConfig::NoOsType) {
|
|
||||||
osType = QMakeStepConfig::IphoneOS;
|
|
||||||
qCDebug(logs) << " IOS found without osType, adjusting osType" << osType;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.version->type() == QLatin1String(Constants::DESKTOPQT)) {
|
|
||||||
QList<ProjectExplorer::Abi> abis = data.version->qtAbis();
|
|
||||||
if (!abis.isEmpty()) {
|
|
||||||
ProjectExplorer::Abi abi = abis.first();
|
|
||||||
if (abi.os() == ProjectExplorer::Abi::DarwinOS) {
|
|
||||||
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(), data.version);
|
|
||||||
qCDebug(logs) << " Extracted spec:" << parsedSpec;
|
|
||||||
qCDebug(logs) << " Arguments now:" << additionalArguments;
|
|
||||||
|
|
||||||
FileName versionSpec = data.version->mkspec();
|
|
||||||
if (parsedSpec.isEmpty() || parsedSpec == FileName::fromLatin1("default")) {
|
|
||||||
parsedSpec = versionSpec;
|
|
||||||
qCDebug(logs) << " No parsed spec or default spec => parsed spec now:" << parsedSpec;
|
|
||||||
}
|
|
||||||
|
|
||||||
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()) {
|
|
||||||
BaseQtVersion *kitVersion = QtKitInformation::qtVersion(k);
|
|
||||||
FileName kitSpec = QmakeKitInformation::mkspec(k);
|
|
||||||
ToolChain *tc = ToolChainKitInformation::toolChain(k, ToolChain::Language::Cxx);
|
|
||||||
if (kitSpec.isEmpty() && kitVersion)
|
|
||||||
kitSpec = kitVersion->mkspecFor(tc);
|
|
||||||
QMakeStepConfig::TargetArchConfig kitTargetArch = QMakeStepConfig::NoArch;
|
|
||||||
QMakeStepConfig::OsType kitOsType = QMakeStepConfig::NoOsType;
|
|
||||||
if (tc) {
|
|
||||||
kitTargetArch = QMakeStepConfig::targetArchFor(tc->targetAbi(), kitVersion);
|
|
||||||
kitOsType = QMakeStepConfig::osTypeFor(tc->targetAbi(), kitVersion);
|
|
||||||
}
|
|
||||||
qCDebug(logs) << k->displayName()
|
|
||||||
<< "version:" << (kitVersion == data.version)
|
|
||||||
<< "spec:" << (kitSpec == parsedSpec)
|
|
||||||
<< "targetarch:" << (kitTargetArch == archConfig)
|
|
||||||
<< "ostype:" << (kitOsType == osType);
|
|
||||||
if (kitVersion == data.version
|
|
||||||
&& kitSpec == parsedSpec
|
|
||||||
&& kitTargetArch == archConfig
|
|
||||||
&& kitOsType == osType)
|
|
||||||
kitList.append(k);
|
|
||||||
}
|
|
||||||
if (kitList.isEmpty()) {
|
|
||||||
kitList.append(createTemporaryKit(data, parsedSpec, archConfig, osType));
|
|
||||||
qCDebug(logs) << " No matching kits found, created new kit";
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (Kit *k, kitList) {
|
|
||||||
addProject(k);
|
|
||||||
|
|
||||||
auto factory = qobject_cast<QmakeBuildConfigurationFactory *>(
|
|
||||||
IBuildConfigurationFactory::find(k, projectFilePath()));
|
|
||||||
|
|
||||||
if (!factory)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// create info:
|
|
||||||
QmakeBuildInfo *info = new QmakeBuildInfo(factory);
|
|
||||||
BaseQtVersion::QmakeBuildConfigs buildConfig = parse.effectiveBuildConfig(data.version->defaultBuildConfig());
|
|
||||||
if (buildConfig & BaseQtVersion::DebugBuild) {
|
|
||||||
info->buildType = BuildConfiguration::Debug;
|
|
||||||
info->displayName = QCoreApplication::translate("QmakeProjectManager::Internal::QmakeProjectImporter", "Debug");
|
|
||||||
} else {
|
|
||||||
info->buildType = BuildConfiguration::Release;
|
|
||||||
info->displayName = QCoreApplication::translate("QmakeProjectManager::Internal::QmakeProjectImporter", "Release");
|
|
||||||
}
|
|
||||||
info->kitId = k->id();
|
|
||||||
info->buildDirectory = FileName::fromString(fi.absoluteFilePath());
|
|
||||||
info->additionalArguments = additionalArguments;
|
|
||||||
info->config = parse.config();
|
|
||||||
info->makefile = makefile;
|
|
||||||
|
|
||||||
bool found = false;
|
|
||||||
foreach (BuildInfo *bInfo, result) {
|
|
||||||
if (*static_cast<QmakeBuildInfo *>(bInfo) == *info) {
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (found)
|
|
||||||
delete info;
|
|
||||||
else
|
|
||||||
result << info;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result.isEmpty() && !silent)
|
|
||||||
QMessageBox::critical(Core::ICore::mainWindow(),
|
|
||||||
QCoreApplication::translate("QmakeProjectManager::Internal::QmakeProjectImporter", "No Build Found"),
|
|
||||||
QCoreApplication::translate("QmakeProjectManager::Internal::QmakeProjectImporter", "No build found in %1 matching project %2.")
|
|
||||||
.arg(importPath.toUserOutput()).arg(QDir::toNativeSeparators(projectFilePath())));
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
QStringList QmakeProjectImporter::importCandidates()
|
QStringList QmakeProjectImporter::importCandidates()
|
||||||
{
|
{
|
||||||
QStringList candidates;
|
QStringList candidates;
|
||||||
@@ -247,7 +106,167 @@ QStringList QmakeProjectImporter::importCandidates()
|
|||||||
return candidates;
|
return candidates;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ToolChain *preferredToolChain(BaseQtVersion *qtVersion, const FileName &ms, const QMakeStepConfig::TargetArchConfig &archConfig)
|
QList<void *> QmakeProjectImporter::examineDirectory(const FileName &importPath) const
|
||||||
|
{
|
||||||
|
QList<void *> result;
|
||||||
|
const QLoggingCategory &logs = MakeFileParse::logging();
|
||||||
|
|
||||||
|
QStringList makefiles = QDir(importPath.toString()).entryList(QStringList(QLatin1String("Makefile*")));
|
||||||
|
qCDebug(logs) << " Makefiles:" << makefiles;
|
||||||
|
|
||||||
|
foreach (const QString &file, makefiles) {
|
||||||
|
std::unique_ptr<DirectoryData> data(new DirectoryData);
|
||||||
|
data->makefile = file;
|
||||||
|
data->buildDirectory = importPath;
|
||||||
|
|
||||||
|
qCDebug(logs) << " Parsing makefile" << file;
|
||||||
|
// find interesting makefiles
|
||||||
|
QString makefile = importPath.toString() + QLatin1Char('/') + file;
|
||||||
|
MakeFileParse parse(makefile);
|
||||||
|
if (parse.makeFileState() != MakeFileParse::Okay) {
|
||||||
|
qCDebug(logs) << " Parsing the makefile failed" << makefile;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (parse.srcProFile() != projectFilePath()) {
|
||||||
|
qCDebug(logs) << " pro files doesn't match" << parse.srcProFile() << projectFilePath();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
QFileInfo qmakeFi = parse.qmakePath().toFileInfo();
|
||||||
|
data->canonicalQmakeBinary = FileName::fromString(qmakeFi.canonicalFilePath());
|
||||||
|
if (data->canonicalQmakeBinary.isEmpty()) {
|
||||||
|
qCDebug(logs) << " " << parse.qmakePath() << "doesn't exist anymore";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
qCDebug(logs) << " QMake:" << data->canonicalQmakeBinary;
|
||||||
|
|
||||||
|
data->qtVersionData = QtProjectImporter::findOrCreateQtVersion(data->canonicalQmakeBinary);
|
||||||
|
BaseQtVersion *version = data->qtVersionData.qt;
|
||||||
|
bool isTemporaryVersion = data->qtVersionData.isTemporary;
|
||||||
|
|
||||||
|
QTC_ASSERT(version, continue);
|
||||||
|
|
||||||
|
qCDebug(logs) << " qt version:" << version->displayName() << " temporary:" << isTemporaryVersion;
|
||||||
|
|
||||||
|
data->archConfig = parse.config().archConfig;
|
||||||
|
data->osType = parse.config().osType;
|
||||||
|
|
||||||
|
qCDebug(logs) << " archConfig:" << data->archConfig;
|
||||||
|
qCDebug(logs) << " osType: " << data->osType;
|
||||||
|
if (version->type() == QLatin1String(IOSQT)
|
||||||
|
&& data->osType == QMakeStepConfig::NoOsType) {
|
||||||
|
data->osType = QMakeStepConfig::IphoneOS;
|
||||||
|
qCDebug(logs) << " IOS found without osType, adjusting osType" << data->osType;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version->type() == Constants::DESKTOPQT) {
|
||||||
|
const QList<ProjectExplorer::Abi> abis = version->qtAbis();
|
||||||
|
if (!abis.isEmpty()) {
|
||||||
|
ProjectExplorer::Abi abi = abis.first();
|
||||||
|
if (abi.os() == ProjectExplorer::Abi::DarwinOS) {
|
||||||
|
if (abi.wordWidth() == 64)
|
||||||
|
data->archConfig = QMakeStepConfig::X86_64;
|
||||||
|
else
|
||||||
|
data->archConfig = QMakeStepConfig::X86;
|
||||||
|
qCDebug(logs) << " OS X found without targetarch, adjusting archType" << data->archConfig;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// find qmake arguments and mkspec
|
||||||
|
data->additionalArguments = parse.unparsedArguments();
|
||||||
|
qCDebug(logs) << " Unparsed arguments:" << data->additionalArguments;
|
||||||
|
data->parsedSpec =
|
||||||
|
QmakeBuildConfiguration::extractSpecFromArguments(&(data->additionalArguments), importPath.toString(), version);
|
||||||
|
qCDebug(logs) << " Extracted spec:" << data->parsedSpec;
|
||||||
|
qCDebug(logs) << " Arguments now:" << data->additionalArguments;
|
||||||
|
|
||||||
|
FileName versionSpec = version->mkspec();
|
||||||
|
if (data->parsedSpec.isEmpty() || data->parsedSpec == FileName::fromLatin1("default")) {
|
||||||
|
data->parsedSpec = versionSpec;
|
||||||
|
qCDebug(logs) << " No parsed spec or default spec => parsed spec now:" << data->parsedSpec;
|
||||||
|
}
|
||||||
|
data->buildConfig = parse.effectiveBuildConfig(data->qtVersionData.qt->defaultBuildConfig());
|
||||||
|
data->config = parse.config();
|
||||||
|
|
||||||
|
result.append(data.release());
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QmakeProjectImporter::matchKit(void *directoryData, const Kit *k) const
|
||||||
|
{
|
||||||
|
DirectoryData *data = static_cast<DirectoryData *>(directoryData);
|
||||||
|
const QLoggingCategory &logs = MakeFileParse::logging();
|
||||||
|
|
||||||
|
BaseQtVersion *kitVersion = QtKitInformation::qtVersion(k);
|
||||||
|
FileName kitSpec = QmakeKitInformation::mkspec(k);
|
||||||
|
ToolChain *tc = ToolChainKitInformation::toolChain(k, ToolChain::Language::Cxx);
|
||||||
|
if (kitSpec.isEmpty() && kitVersion)
|
||||||
|
kitSpec = kitVersion->mkspecFor(tc);
|
||||||
|
QMakeStepConfig::TargetArchConfig kitTargetArch = QMakeStepConfig::NoArch;
|
||||||
|
QMakeStepConfig::OsType kitOsType = QMakeStepConfig::NoOsType;
|
||||||
|
if (tc) {
|
||||||
|
kitTargetArch = QMakeStepConfig::targetArchFor(tc->targetAbi(), kitVersion);
|
||||||
|
kitOsType = QMakeStepConfig::osTypeFor(tc->targetAbi(), kitVersion);
|
||||||
|
}
|
||||||
|
qCDebug(logs) << k->displayName()
|
||||||
|
<< "version:" << (kitVersion == data->qtVersionData.qt)
|
||||||
|
<< "spec:" << (kitSpec == data->parsedSpec)
|
||||||
|
<< "targetarch:" << (kitTargetArch == data->archConfig)
|
||||||
|
<< "ostype:" << (kitOsType == data->osType);
|
||||||
|
return kitVersion == data->qtVersionData.qt
|
||||||
|
&& kitSpec == data->parsedSpec
|
||||||
|
&& kitTargetArch == data->archConfig
|
||||||
|
&& kitOsType == data->osType;
|
||||||
|
}
|
||||||
|
|
||||||
|
Kit *QmakeProjectImporter::createKit(void *directoryData) const
|
||||||
|
{
|
||||||
|
DirectoryData *data = static_cast<DirectoryData *>(directoryData);
|
||||||
|
return createTemporaryKit(data->qtVersionData, data->parsedSpec, data->archConfig, data->osType);
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<BuildInfo *> QmakeProjectImporter::buildInfoListForKit(const Kit *k, void *directoryData) const
|
||||||
|
{
|
||||||
|
QList<BuildInfo *> result;
|
||||||
|
DirectoryData *data = static_cast<DirectoryData *>(directoryData);
|
||||||
|
auto factory = qobject_cast<QmakeBuildConfigurationFactory *>(
|
||||||
|
IBuildConfigurationFactory::find(k, projectFilePath()));
|
||||||
|
if (!factory)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
// create info:
|
||||||
|
std::unique_ptr<QmakeBuildInfo> info(new QmakeBuildInfo(factory));
|
||||||
|
if (data->buildConfig & BaseQtVersion::DebugBuild) {
|
||||||
|
info->buildType = BuildConfiguration::Debug;
|
||||||
|
info->displayName = QCoreApplication::translate("QmakeProjectManager::Internal::QmakeProjectImporter", "Debug");
|
||||||
|
} else {
|
||||||
|
info->buildType = BuildConfiguration::Release;
|
||||||
|
info->displayName = QCoreApplication::translate("QmakeProjectManager::Internal::QmakeProjectImporter", "Release");
|
||||||
|
}
|
||||||
|
info->kitId = k->id();
|
||||||
|
info->buildDirectory = data->buildDirectory;
|
||||||
|
info->additionalArguments = data->additionalArguments;
|
||||||
|
info->config = data->config;
|
||||||
|
info->makefile = data->makefile;
|
||||||
|
|
||||||
|
bool found = false;
|
||||||
|
foreach (BuildInfo *bInfo, result) {
|
||||||
|
if (*static_cast<QmakeBuildInfo *>(bInfo) == *info) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found)
|
||||||
|
result << info.release();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ToolChain *preferredToolChain(BaseQtVersion *qtVersion, const FileName &ms,
|
||||||
|
const QMakeStepConfig::TargetArchConfig &archConfig)
|
||||||
{
|
{
|
||||||
const FileName spec = ms.isEmpty() ? qtVersion->mkspec() : ms;
|
const FileName spec = ms.isEmpty() ? qtVersion->mkspec() : ms;
|
||||||
|
|
||||||
@@ -265,13 +284,13 @@ static ToolChain *preferredToolChain(BaseQtVersion *qtVersion, const FileName &m
|
|||||||
Kit *QmakeProjectImporter::createTemporaryKit(const QtProjectImporter::QtVersionData &data,
|
Kit *QmakeProjectImporter::createTemporaryKit(const QtProjectImporter::QtVersionData &data,
|
||||||
const FileName &parsedSpec,
|
const FileName &parsedSpec,
|
||||||
const QMakeStepConfig::TargetArchConfig &archConfig,
|
const QMakeStepConfig::TargetArchConfig &archConfig,
|
||||||
const QMakeStepConfig::OsType &osType)
|
const QMakeStepConfig::OsType &osType) const
|
||||||
{
|
{
|
||||||
Q_UNUSED(osType); // TODO use this to select the right toolchain?
|
Q_UNUSED(osType); // TODO use this to select the right toolchain?
|
||||||
return QtProjectImporter::createTemporaryKit(data,
|
return QtProjectImporter::createTemporaryKit(data,
|
||||||
[&data, parsedSpec, archConfig](Kit *k) -> void {
|
[&data, parsedSpec, archConfig](Kit *k) -> void {
|
||||||
ToolChainKitInformation::setToolChain(k, preferredToolChain(data.version, parsedSpec, archConfig));
|
ToolChainKitInformation::setToolChain(k, preferredToolChain(data.qt, parsedSpec, archConfig));
|
||||||
if (parsedSpec != data.version->mkspec())
|
if (parsedSpec != data.qt->mkspec())
|
||||||
QmakeKitInformation::setMkspec(k, parsedSpec);
|
QmakeKitInformation::setMkspec(k, parsedSpec);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,14 +43,20 @@ class QmakeProjectImporter : public QtSupport::QtProjectImporter
|
|||||||
public:
|
public:
|
||||||
QmakeProjectImporter(const QString &path);
|
QmakeProjectImporter(const QString &path);
|
||||||
|
|
||||||
QList<ProjectExplorer::BuildInfo *> import(const Utils::FileName &importPath, bool silent = false) final;
|
|
||||||
QStringList importCandidates() final;
|
QStringList importCandidates() final;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
QList<void *> examineDirectory(const Utils::FileName &importPath) const final;
|
||||||
|
bool matchKit(void *directoryData, const ProjectExplorer::Kit *k) const final;
|
||||||
|
ProjectExplorer::Kit *createKit(void *directoryData) const final;
|
||||||
|
QList<ProjectExplorer::BuildInfo *> buildInfoListForKit(const ProjectExplorer::Kit *k,
|
||||||
|
void *directoryData) const final;
|
||||||
|
|
||||||
|
|
||||||
ProjectExplorer::Kit *createTemporaryKit(const QtProjectImporter::QtVersionData &data,
|
ProjectExplorer::Kit *createTemporaryKit(const QtProjectImporter::QtVersionData &data,
|
||||||
const Utils::FileName &parsedSpec,
|
const Utils::FileName &parsedSpec,
|
||||||
const QmakeProjectManager::QMakeStepConfig::TargetArchConfig &archConfig,
|
const QmakeProjectManager::QMakeStepConfig::TargetArchConfig &archConfig,
|
||||||
const QMakeStepConfig::OsType &osType);
|
const QMakeStepConfig::OsType &osType) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
|||||||
@@ -59,17 +59,7 @@ static void cleanTemporaryVersion(BaseQtVersion *version) {
|
|||||||
QtVersionManager::removeVersion(version);
|
QtVersionManager::removeVersion(version);
|
||||||
}
|
}
|
||||||
|
|
||||||
QtProjectImporter::QtProjectImporter(const QString &path) : ProjectImporter(path)
|
void QtProjectImporter::makePermanent(Kit *k) const
|
||||||
{ }
|
|
||||||
|
|
||||||
void QtProjectImporter::cleanupKit(Kit *k)
|
|
||||||
{
|
|
||||||
const int tempId = k->value(QT_IS_TEMPORARY, -1).toInt();
|
|
||||||
k->removeKeySilently(QT_IS_TEMPORARY);
|
|
||||||
cleanTemporaryVersion(QtVersionManager::version(tempId));
|
|
||||||
}
|
|
||||||
|
|
||||||
void QtProjectImporter::makePermanent(Kit *k)
|
|
||||||
{
|
{
|
||||||
if (!isTemporaryKit(k))
|
if (!isTemporaryKit(k))
|
||||||
return;
|
return;
|
||||||
@@ -88,10 +78,10 @@ void QtProjectImporter::makePermanent(Kit *k)
|
|||||||
}
|
}
|
||||||
|
|
||||||
QtProjectImporter::QtVersionData
|
QtProjectImporter::QtVersionData
|
||||||
QtProjectImporter::findOrCreateQtVersion(const Utils::FileName &qmakePath)
|
QtProjectImporter::findOrCreateQtVersion(const Utils::FileName &qmakePath) const
|
||||||
{
|
{
|
||||||
QtVersionData result;
|
QtVersionData result;
|
||||||
result.version
|
result.qt
|
||||||
= Utils::findOrDefault(QtVersionManager::unsortedVersions(),
|
= Utils::findOrDefault(QtVersionManager::unsortedVersions(),
|
||||||
[&qmakePath](BaseQtVersion *v) -> bool {
|
[&qmakePath](BaseQtVersion *v) -> bool {
|
||||||
QFileInfo vfi = v->qmakeCommand().toFileInfo();
|
QFileInfo vfi = v->qmakeCommand().toFileInfo();
|
||||||
@@ -99,10 +89,10 @@ QtProjectImporter::findOrCreateQtVersion(const Utils::FileName &qmakePath)
|
|||||||
return current == qmakePath;
|
return current == qmakePath;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (result.version) {
|
if (result.qt) {
|
||||||
// Check if version is a temporary qt
|
// Check if version is a temporary qt
|
||||||
const int qtId = result.version->uniqueId();
|
const int qtId = result.qt->uniqueId();
|
||||||
result.isTemporaryVersion = Utils::anyOf(KitManager::kits(), [&qtId](Kit *k) {
|
result.isTemporary = Utils::anyOf(KitManager::kits(), [&qtId](Kit *k) {
|
||||||
return k->value(QT_IS_TEMPORARY, -1).toInt() == qtId;
|
return k->value(QT_IS_TEMPORARY, -1).toInt() == qtId;
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
@@ -110,25 +100,25 @@ QtProjectImporter::findOrCreateQtVersion(const Utils::FileName &qmakePath)
|
|||||||
|
|
||||||
// Create a new version if not found:
|
// Create a new version if not found:
|
||||||
// Do not use the canonical path here...
|
// Do not use the canonical path here...
|
||||||
result.version = QtVersionFactory::createQtVersionFromQMakePath(qmakePath);
|
result.qt = QtVersionFactory::createQtVersionFromQMakePath(qmakePath);
|
||||||
result.isTemporaryVersion = true;
|
result.isTemporary = true;
|
||||||
if (result.version) {
|
if (result.qt) {
|
||||||
UpdateGuard guard(*this);
|
UpdateGuard guard(*this);
|
||||||
QtVersionManager::addVersion(result.version);
|
QtVersionManager::addVersion(result.qt);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Kit *QtProjectImporter::createTemporaryKit(const QtVersionData &versionData,
|
Kit *QtProjectImporter::createTemporaryKit(const QtVersionData &versionData,
|
||||||
const ProjectImporter::KitSetupFunction &setup)
|
const ProjectImporter::KitSetupFunction &setup) const
|
||||||
{
|
{
|
||||||
return ProjectImporter::createTemporaryKit([&setup, &versionData](Kit *k) -> void {
|
return ProjectImporter::createTemporaryKit([&setup, &versionData](Kit *k) -> void {
|
||||||
QtKitInformation::setQtVersion(k, versionData.version);
|
QtKitInformation::setQtVersion(k, versionData.qt);
|
||||||
if (versionData.isTemporaryVersion)
|
if (versionData.isTemporary)
|
||||||
k->setValue(QT_IS_TEMPORARY, versionData.version->uniqueId());
|
k->setValue(QT_IS_TEMPORARY, versionData.qt->uniqueId());
|
||||||
|
|
||||||
k->setUnexpandedDisplayName(versionData.version->displayName());;
|
k->setUnexpandedDisplayName(versionData.qt->displayName());;
|
||||||
|
|
||||||
setup(k);
|
setup(k);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -42,19 +42,19 @@ public:
|
|||||||
QtProjectImporter(const QString &path);
|
QtProjectImporter(const QString &path);
|
||||||
|
|
||||||
void cleanupKit(ProjectExplorer::Kit *k) override;
|
void cleanupKit(ProjectExplorer::Kit *k) override;
|
||||||
void makePermanent(ProjectExplorer::Kit *k) override;
|
void makePermanent(ProjectExplorer::Kit *k) const override;
|
||||||
|
|
||||||
protected:
|
|
||||||
class QtVersionData
|
class QtVersionData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BaseQtVersion *version = nullptr;
|
BaseQtVersion *qt = nullptr;
|
||||||
bool isTemporaryVersion = true;
|
bool isTemporary = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
QtVersionData findOrCreateQtVersion(const Utils::FileName &qmakePath);
|
protected:
|
||||||
|
QtVersionData findOrCreateQtVersion(const Utils::FileName &qmakePath) const;
|
||||||
ProjectExplorer::Kit *createTemporaryKit(const QtVersionData &versionData,
|
ProjectExplorer::Kit *createTemporaryKit(const QtVersionData &versionData,
|
||||||
const KitSetupFunction &setup);
|
const KitSetupFunction &setup) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace QmakeProjectManager
|
} // namespace QmakeProjectManager
|
||||||
|
|||||||
Reference in New Issue
Block a user