Commit 62ae1929 authored by Aleix Pol Gonzalez's avatar Aleix Pol Gonzalez 🐧

Make sure we use the same compiler settings as the project is by default

Summary:
Instead of trusting the user to configure it beforehand, make it
possible to check which compiler is being used in the build manager and
uses it to figure out the initial compilation settings.
This includes a QStringList IBSM::findCompiler(item) method to get the
path to the used compiler. I wonder if we should be providing the
sysroot as well.

Test Plan:
Been playing around with the androidqt branch that uses docker
to implement the SDK instead of just expecting the user to install it himself.

Reviewers: #kdevelop, mwolff

Reviewed By: #kdevelop, mwolff

Subscribers: mschwarz, aaronpuchert, mwolff, kdevelop-devel

Differential Revision: https://phabricator.kde.org/D11136
parent 02b042a9
......@@ -130,6 +130,11 @@ public:
* @returns the extra arguments that will be passed to the compiler when building @p item
*/
virtual QString extraArguments(ProjectBaseItem* item) const = 0;
/**
* @returns the absolute path to the tool that will be used or an empty path if unknown
*/
virtual Path compiler(KDevelop::ProjectTargetItem* p) const = 0;
};
}
......
......@@ -313,6 +313,8 @@ bool CMakeManager::reload(KDevelop::ProjectFolderItem* folder)
connect(job, &KJob::finished, this, [project](KJob* job) {
if (job->error())
return;
KDevelop::ICore::self()->projectController()->projectConfigurationChanged(project);
KDevelop::ICore::self()->projectController()->reparseProject(project, true);
});
}
......@@ -1025,4 +1027,35 @@ void CMakeManager::reloadProjects()
}
}
CMakeTarget CMakeManager::targetInformation(KDevelop::ProjectTargetItem* item) const
{
const auto targets = m_projects[item->project()].targets[item->parent()->path()];
for (auto target: targets) {
if (item->text() == target.name) {
return target;
}
}
return {};
}
KDevelop::Path CMakeManager::compiler(KDevelop::ProjectTargetItem* item) const
{
const auto targetInfo = targetInformation(item);
if (targetInfo.sources.isEmpty()) {
qCDebug(CMAKE) << "could not find target" << item->text();
return {};
}
const auto info = m_projects[item->project()].compilationData.files[targetInfo.sources.constFirst()];
const auto lang = info.language;
if (lang.isEmpty()) {
qCDebug(CMAKE) << "no language for" << item << item->text() << info.defines << targetInfo.sources.constFirst();
return {};
}
const QString var = QLatin1String("CMAKE_") + lang + QLatin1String("_COMPILER");
const auto ret = CMake::readCacheValues(KDevelop::Path(buildDirectory(item), QStringLiteral("CMakeCache.txt")), {var});
qCDebug(CMAKE) << "compiler for" << lang << var << ret;
return KDevelop::Path(ret.value(var));
}
#include "cmakemanager.moc"
......@@ -137,6 +137,8 @@ public:
void integrateData(const CMakeProjectData &data, KDevelop::IProject* project);
KDevelop::Path compiler(KDevelop::ProjectTargetItem * p) const override;
Q_SIGNALS:
void folderRenamed(const KDevelop::Path& oldFolder, KDevelop::ProjectFolderItem* newFolder);
void fileRenamed(const KDevelop::Path& oldFile, KDevelop::ProjectFileItem* newFile);
......@@ -154,6 +156,7 @@ private Q_SLOTS:
private:
void reloadProjects();
CMakeFile fileInformation(KDevelop::ProjectBaseItem* item) const;
CMakeTarget targetInformation(KDevelop::ProjectTargetItem* item) const;
void folderAdded(KDevelop::ProjectFolderItem* folder);
KTextEditor::Range termRangeAtPosition(const KTextEditor::Document* textDocument,
......
......@@ -40,6 +40,7 @@ struct CMakeFile
KDevelop::Path::List includes;
KDevelop::Path::List frameworkDirectories;
QString compileFlags;
QString language;
QHash<QString, QString> defines;
bool isEmpty() const
......@@ -50,7 +51,7 @@ struct CMakeFile
};
inline QDebug &operator<<(QDebug debug, const CMakeFile& file)
{
debug << "CMakeFile(-I" << file.includes << ", -F" << file.frameworkDirectories << ", -D" << file.defines << ")";
debug << "CMakeFile(-I" << file.includes << ", -F" << file.frameworkDirectories << ", -D" << file.defines << ", " << file.language << ")";
return debug.maybeSpace();
}
......
......@@ -115,6 +115,7 @@ void CMakeServerImportJob::processCodeModel(const QJsonObject &response, CMakePr
CMakeFile file;
file.includes = kTransform<KDevelop::Path::List>(fileGroup.value(QStringLiteral("includePath")).toArray(), [](const QJsonValue& val) { return KDevelop::Path(val.toObject().value(QStringLiteral("path")).toString()); });
file.language = fileGroup.value(QStringLiteral("language")).toString(),
file.compileFlags = fileGroup.value(QStringLiteral("compileFlags")).toString();
file.defines = processDefines(file.compileFlags, fileGroup.value(QStringLiteral("defines")).toArray());
......
......@@ -195,4 +195,9 @@ KDevelop::ConfigPage* CustomBuildSystem::perProjectConfigPage(int number, const
return nullptr;
}
KDevelop::Path CustomBuildSystem::compiler(KDevelop::ProjectTargetItem* item) const
{
return {};
}
#include "custombuildsystemplugin.moc"
......@@ -52,6 +52,9 @@ public:
/// @p installPrefix will be passed as DESTDIR environment variable
KJob* install( KDevelop::ProjectBaseItem* item, const QUrl &installPrefix ) override;
KJob* configure( KDevelop::IProject* ) override;
KDevelop::Path compiler(KDevelop::ProjectTargetItem * p) const override;
Q_SIGNALS:
void built( KDevelop::ProjectBaseItem *dom );
void installed( KDevelop::ProjectBaseItem* );
......
......@@ -32,6 +32,12 @@ QString ClangFactory::name() const
return QStringLiteral("Clang");
}
bool ClangFactory::isSupported(const KDevelop::Path& path) const
{
const auto filename = path.lastPathSegment();
return filename.contains(QLatin1String("clang")) && !filename.contains(QLatin1String("clang-cl"));
}
CompilerPointer ClangFactory::createCompiler(const QString& name, const QString& path, bool editable ) const
{
return CompilerPointer(new GccLikeCompiler(name, path, editable, this->name()));
......@@ -50,6 +56,11 @@ QString GccFactory::name() const
return QStringLiteral("GCC");
}
bool GccFactory::isSupported(const KDevelop::Path& path) const
{
return path.lastPathSegment().contains(QLatin1String("gcc")) || path.lastPathSegment().contains(QLatin1String("g++"));
}
CompilerPointer GccFactory::createCompiler(const QString& name, const QString& path, bool editable ) const
{
return CompilerPointer(new GccLikeCompiler(name, path, editable, this->name()));
......@@ -77,3 +88,8 @@ void MsvcFactory::registerDefaultCompilers(CompilerProvider* provider) const
{
provider->registerCompiler(createCompiler(name(), QStringLiteral("cl.exe"), false));
}
bool MsvcFactory::isSupported(const KDevelop::Path& path) const
{
return path.lastPathSegment() == QLatin1String("cl.exe") || path.lastPathSegment().contains(QLatin1String("clang-cl"));
}
......@@ -32,6 +32,7 @@ public:
CompilerPointer createCompiler( const QString& name, const QString& path, bool editable = true ) const override;
QString name() const override;
bool isSupported(const KDevelop::Path& path) const override;
void registerDefaultCompilers(CompilerProvider* provider) const override;
};
......@@ -42,6 +43,7 @@ public:
CompilerPointer createCompiler( const QString& name, const QString& path, bool editable = true ) const override;
QString name() const override;
bool isSupported(const KDevelop::Path& path) const override;
void registerDefaultCompilers(CompilerProvider* provider) const override;
};
......@@ -52,6 +54,7 @@ public:
CompilerPointer createCompiler( const QString& name, const QString& path, bool editable = true ) const override;
QString name() const override;
bool isSupported(const KDevelop::Path& path) const override;
void registerDefaultCompilers(CompilerProvider* provider) const override;
};
......
......@@ -30,6 +30,8 @@
#include <interfaces/iruntime.h>
#include <interfaces/iruntimecontroller.h>
#include <interfaces/iproject.h>
#include <interfaces/iprojectcontroller.h>
#include <interfaces/ibuildsystemmanager.h>
#include <project/projectmodel.h>
#include <KLocalizedString>
......@@ -100,6 +102,22 @@ ConfigEntry configForItem(KDevelop::ProjectBaseItem* item)
}
}
ProjectTargetItem* findCompiledTarget(ProjectBaseItem* item)
{
for(auto item: item->targetList()) {
if (item->type() == ProjectBaseItem::ExecutableTarget || item->type() == ProjectBaseItem::LibraryTarget) {
return item;
}
}
for(auto folder: item->folderList()) {
auto target = findCompiledTarget(folder);
if (target)
return target;
}
return nullptr;
}
CompilerProvider::CompilerProvider( SettingsManager* settings, QObject* parent )
: QObject( parent )
, m_settings(settings)
......@@ -128,10 +146,44 @@ CompilerProvider::CompilerProvider( SettingsManager* settings, QObject* parent )
retrieveUserDefinedCompilers();
connect(ICore::self()->runtimeController(), &IRuntimeController::currentRuntimeChanged, this, [this]() { m_defaultProvider.clear(); });
connect(ICore::self()->projectController(), &IProjectController::projectConfigurationChanged, this, &CompilerProvider::projectChanged);
connect(ICore::self()->projectController(), &IProjectController::projectOpened, this, &CompilerProvider::projectChanged);
}
CompilerProvider::~CompilerProvider() = default;
void CompilerProvider::projectChanged(KDevelop::IProject* p)
{
const auto target = findCompiledTarget(p->projectItem());
if (!target)
return;
auto path = p->buildSystemManager()->compiler(target);
qCDebug(DEFINESANDINCLUDES) << "found compiler" << path;
if (path.isEmpty())
return;
Q_ASSERT(QDir::isAbsolutePath(path.toLocalFile()));
const auto pathString = path.toLocalFile();
auto it = std::find_if(m_compilers.begin(), m_compilers.end(),
[pathString](const CompilerPointer& compiler) { return compiler->path() == pathString; });
if (it != m_compilers.end()) {
m_defaultProvider = *it;
return;
}
//we need to search, sdk compiler names are weird: arm-linux-androideabi-g++
for (auto factory : m_factories) {
if (factory->isSupported(path)) {
auto compiler = factory->createCompiler(path.lastPathSegment(), pathString);
const auto registered = registerCompiler(compiler);
m_defaultProvider = compiler;
}
}
qCDebug(DEFINESANDINCLUDES) << "using compiler" << m_defaultProvider << path;
}
QHash<QString, QString> CompilerProvider::defines( const QString& path ) const
{
auto config = configForItem(nullptr);
......
......@@ -67,6 +67,7 @@ public:
private Q_SLOTS:
void retrieveUserDefinedCompilers();
void projectChanged(KDevelop::IProject* p);
private:
mutable CompilerPointer m_defaultProvider;
......
......@@ -44,6 +44,9 @@ public:
*/
virtual void registerDefaultCompilers(CompilerProvider* provider) const = 0;
/** @returns whether @p path is a compiler supported by the factory */
virtual bool isSupported(const KDevelop::Path &path) const = 0;
virtual ~ICompilerFactory() = default;
};
......
......@@ -324,5 +324,9 @@ void CustomMakeManager::unload()
IDefinesAndIncludesManager::manager()->unregisterBackgroundProvider(m_provider.data());
}
#include "custommakemanager.moc"
KDevelop::Path CustomMakeManager::compiler(KDevelop::ProjectTargetItem* item) const
{
return {};
}
#include "custommakemanager.moc"
......@@ -113,6 +113,8 @@ public:
*/
QList<KDevelop::ProjectTargetItem*> targets(KDevelop::ProjectFolderItem*) const override;
KDevelop::Path compiler(KDevelop::ProjectTargetItem * p) const override;
protected:
KDevelop::ProjectFileItem* createFileItem(KDevelop::IProject* project,
const KDevelop::Path& path,
......
......@@ -510,4 +510,9 @@ void QMakeProjectManager::slotRunQMake()
KDevelop::ICore::self()->runController()->registerJob(job);
}
KDevelop::Path QMakeProjectManager::compiler(KDevelop::ProjectTargetItem* p) const
{
return {};
}
#include "qmakemanager.moc"
......@@ -82,6 +82,8 @@ public:
}
QList<KDevelop::ProjectTargetItem*> targets(KDevelop::ProjectFolderItem*) const override;
KDevelop::Path compiler(KDevelop::ProjectTargetItem* item) const override;
//END IBuildSystemManager
private Q_SLOTS:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment