diff --git a/kdevplatform/project/interfaces/ibuildsystemmanager.h b/kdevplatform/project/interfaces/ibuildsystemmanager.h --- a/kdevplatform/project/interfaces/ibuildsystemmanager.h +++ b/kdevplatform/project/interfaces/ibuildsystemmanager.h @@ -130,6 +130,11 @@ * @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 findCompiler(KDevelop::ProjectTargetItem* p) const { Q_UNUSED(p); return {}; }; }; } diff --git a/plugins/cmake/cmakemanager.h b/plugins/cmake/cmakemanager.h --- a/plugins/cmake/cmakemanager.h +++ b/plugins/cmake/cmakemanager.h @@ -137,6 +137,8 @@ void integrateData(const CMakeProjectData &data, KDevelop::IProject* project); + KDevelop::Path findCompiler(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: void reloadProjects(); CMakeFile fileInformation(KDevelop::ProjectBaseItem* item) const; + CMakeTarget targetInformation(KDevelop::ProjectTargetItem* item) const; void folderAdded(KDevelop::ProjectFolderItem* folder); diff --git a/plugins/cmake/cmakemanager.cpp b/plugins/cmake/cmakemanager.cpp --- a/plugins/cmake/cmakemanager.cpp +++ b/plugins/cmake/cmakemanager.cpp @@ -984,4 +984,35 @@ } } +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::findCompiler(KDevelop::ProjectTargetItem* item) const +{ + const auto targetInfo = targetInformation(item); + if (targetInfo.sources.isEmpty()) { + qDebug() << "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()) { + qDebug() << "no lang for..." << item << item->text() << info.defines << targetInfo.sources.constFirst(); + return {}; + } + const QString var = QStringLiteral("CMAKE_") + lang + QStringLiteral("_COMPILER"); + const auto ret = CMake::readCacheValues(KDevelop::Path(buildDirectory(item), QStringLiteral("CMakeCache.txt")), {var}); + qDebug() << "compiler for" << lang << var << ret; + return KDevelop::Path(ret.value(var)); +} + #include "cmakemanager.moc" diff --git a/plugins/cmake/cmakeprojectdata.h b/plugins/cmake/cmakeprojectdata.h --- a/plugins/cmake/cmakeprojectdata.h +++ b/plugins/cmake/cmakeprojectdata.h @@ -40,11 +40,12 @@ KDevelop::Path::List includes; KDevelop::Path::List frameworkDirectories; QString compileFlags; + QString language; QHash defines; }; 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(); } diff --git a/plugins/cmake/cmakeserverimportjob.cpp b/plugins/cmake/cmakeserverimportjob.cpp --- a/plugins/cmake/cmakeserverimportjob.cpp +++ b/plugins/cmake/cmakeserverimportjob.cpp @@ -115,6 +115,7 @@ CMakeFile file; file.includes = kTransform(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()); diff --git a/plugins/custom-definesandincludes/compilerprovider/compilerprovider.cpp b/plugins/custom-definesandincludes/compilerprovider/compilerprovider.cpp --- a/plugins/custom-definesandincludes/compilerprovider/compilerprovider.cpp +++ b/plugins/custom-definesandincludes/compilerprovider/compilerprovider.cpp @@ -36,6 +36,8 @@ #include #include #include +#include +#include using namespace KDevelop; @@ -101,6 +103,22 @@ } } +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) @@ -126,7 +144,38 @@ registerCompiler(createDummyCompiler()); retrieveUserDefinedCompilers(); - connect(ICore::self()->runtimeController(), &IRuntimeController::currentRuntimeChanged, this, [this]() { m_defaultProvider.clear(); }); + connect(ICore::self()->runtimeController(), &IRuntimeController::currentRuntimeChanged, this, [this]() { + m_defaultProvider.clear(); + + for (auto p : ICore::self()->projectController()->projects()) { + const auto target = findCompiledTarget(p->projectItem()); + if (!target) + continue; + + auto path = p->buildSystemManager()->findCompiler(target); + qCDebug(DEFINESANDINCLUDES) << "found compiler" << path; + if (!path.isEmpty() || !QDir::isAbsolutePath(path.toLocalFile())) + continue; + + const auto pathString = path.toLocalFile(); + bool alreadyPresent = false; + for ( const CompilerPointer& compiler : m_compilers ) { + if (compiler->path() == pathString) { + alreadyPresent = true; + break; + } + } + if (alreadyPresent) + continue; + //we need to search, sdk compiler names are weird: arm-linux-androideabi-g++ + int factory = path.lastPathSegment().contains(QLatin1String("clang")) ? 1 : 0; + auto compiler = m_factories[factory]->createCompiler(path.lastPathSegment(), pathString); + registerCompiler(compiler); + + qCDebug(DEFINESANDINCLUDES) << "using compiler" << compiler; + m_defaultProvider = compiler; + } + }, Qt::QueuedConnection); } CompilerProvider::~CompilerProvider() = default;