Index: plugins/cmake/cmakecommitchangesjob.cpp =================================================================== --- plugins/cmake/cmakecommitchangesjob.cpp +++ plugins/cmake/cmakecommitchangesjob.cpp @@ -160,7 +160,7 @@ QString dir = m_path.toLocalFile(); if(data.vm.value("CMAKE_INCLUDE_CURRENT_DIR")==QStringList("ON")) { m_directories += dir; - m_directories += CMakeParserUtils::binaryPath(dir, m_project->path().toLocalFile(), CMake::currentBuildDir(m_project).toLocalFile(QUrl::RemoveTrailingSlash)); + m_directories += CMakeParserUtils::binaryPath(dir, m_project->path().toLocalFile(), CMake::currentCanonicalBuildDir(m_project).toLocalFile(QUrl::RemoveTrailingSlash)); } m_directories += resolvePaths(m_path, data.properties[DirectoryProperty][dir]["INCLUDE_DIRECTORIES"]); m_directories.removeAll(QString()); Index: plugins/cmake/cmakeimportjsonjob.cpp =================================================================== --- plugins/cmake/cmakeimportjsonjob.cpp +++ plugins/cmake/cmakeimportjsonjob.cpp @@ -94,8 +94,11 @@ ret.includes = kTransform(result.paths, convert); ret.frameworkDirectories = kTransform(result.frameworkDirectories, convert); ret.defines = result.defines; - const Path path(rt->pathInHost(Path(entry[KEY_FILE].toString()))); - qCDebug(CMAKE) << "entering..." << path << entry[KEY_FILE]; + const auto entryFile = entry[KEY_FILE].toString(); + const auto entryInfo = QFileInfo(entryFile); + const auto entryPath = Path(entryInfo.exists() ? entryInfo.canonicalFilePath() : entryFile); + const Path path(rt->pathInHost(entryPath)); + qCDebug(CMAKE) << "entering..." << path << entryFile; data.files[path] = ret; } @@ -142,7 +145,7 @@ return; } - const Path currentBuildDir = CMake::currentBuildDir(m_project); + const Path currentBuildDir = CMake::currentCanonicalBuildDir(m_project); Q_ASSERT (!currentBuildDir.isEmpty()); const Path targetsFilePath = CMake::targetDirectoriesFile(m_project); Index: plugins/cmake/cmakemanager.cpp =================================================================== --- plugins/cmake/cmakemanager.cpp +++ plugins/cmake/cmakemanager.cpp @@ -127,7 +127,7 @@ // if(fi) // ret.addPath(fi->buildDir()); // return ret; - return Path(CMake::currentBuildDir(item->project())); + return Path(CMake::currentCanonicalBuildDir(item->project())); } KDevelop::ProjectFolderItem* CMakeManager::import( KDevelop::IProject *project ) Index: plugins/cmake/cmakemodelitems.cpp =================================================================== --- plugins/cmake/cmakemodelitems.cpp +++ plugins/cmake/cmakemodelitems.cpp @@ -32,7 +32,7 @@ if (!m_builtUrl.isEmpty()) return m_builtUrl.toUrl(); - const KDevelop::Path buildDir = CMake::currentBuildDir(project()); + const KDevelop::Path buildDir = CMake::currentCanonicalBuildDir(project()); if (buildDir.isEmpty()) return QUrl(); Index: plugins/cmake/cmakeserverimportjob.cpp =================================================================== --- plugins/cmake/cmakeserverimportjob.cpp +++ plugins/cmake/cmakeserverimportjob.cpp @@ -176,7 +176,7 @@ { connect(m_server.data(), &CMakeServer::response, this, &CMakeServerImportJob::processResponse); - m_server->handshake(m_project->path(), CMake::currentBuildDir(m_project)); + m_server->handshake(m_project->path(), CMake::currentCanonicalBuildDir(m_project)); } void CMakeServerImportJob::processResponse(const QJsonObject& response) Index: plugins/cmake/cmakeutils.h =================================================================== --- plugins/cmake/cmakeutils.h +++ plugins/cmake/cmakeutils.h @@ -88,6 +88,12 @@ */ KDEVCMAKECOMMON_EXPORT KDevelop::Path currentBuildDir( KDevelop::IProject* project, int builddir = -1 ); + /** + * @returns the current canonical builddir for the given project or an empty url if none + * has been set by the user. See QFileInfo::canonicalFilePath() + */ + KDEVCMAKECOMMON_EXPORT KDevelop::Path currentCanonicalBuildDir( KDevelop::IProject* project, int builddir = -1 ); + /** * @returns the path to the 'compile_commands.json' file in the current builddir for the given project * or an empty url if none has been set by the user. @@ -190,6 +196,11 @@ */ KDEVCMAKECOMMON_EXPORT QStringList allBuildDirs(KDevelop::IProject* project); + /** + * Retrieves the canonical form of the configured build directories for @p project. + */ + KDEVCMAKECOMMON_EXPORT QStringList allCanonicalBuildDirs(KDevelop::IProject* project); + /** * Attempts to migrate the CMake configuration to per-builddir format. * Silently returns if the migration has already been performed. Index: plugins/cmake/cmakeutils.cpp =================================================================== --- plugins/cmake/cmakeutils.cpp +++ plugins/cmake/cmakeutils.cpp @@ -165,7 +165,7 @@ KDevelop::Path::List resolveSystemDirs(KDevelop::IProject* project, const QStringList& dirs) { - const KDevelop::Path buildDir(CMake::currentBuildDir(project)); + const KDevelop::Path buildDir(CMake::currentCanonicalBuildDir(project)); const KDevelop::Path installDir(CMake::currentInstallDir(project)); KDevelop::Path::List newList; @@ -199,15 +199,15 @@ bool checkForNeedingConfigure( KDevelop::IProject* project ) { const QString currentRuntime = ICore::self()->runtimeController()->currentRuntime()->name(); - const KDevelop::Path builddir = currentBuildDir(project); + const KDevelop::Path builddir = currentCanonicalBuildDir(project); const bool isValid = (buildDirRuntime(project, -1) == currentRuntime || buildDirRuntime(project, -1).isEmpty()) && builddir.isValid(); if( !isValid ) { CMakeBuildDirChooser bd; bd.setProject( project ); - const auto builddirs = CMake::allBuildDirs(project); + const auto builddirs = CMake::allCanonicalBuildDirs(project); bd.setAlreadyUsed( builddirs ); bd.setShowAvailableBuildDirs(!builddirs.isEmpty()); bd.setCMakeExecutable(currentCMakeExecutable(project)); @@ -295,6 +295,17 @@ return KDevelop::Path(readBuildDirParameter( project, Config::Specific::buildDirPathKey, QString(), builddir )); } +KDevelop::Path currentCanonicalBuildDir( KDevelop::IProject* project, int builddir ) +{ + const QString buildDir(readBuildDirParameter( project, Config::Specific::buildDirPathKey, QString(), builddir )); + const auto info = QFileInfo(buildDir); + if (info.exists()) { + return KDevelop::Path(info.canonicalFilePath()); + } else { + return KDevelop::Path(buildDir); + } +} + KDevelop::Path commandsFile(KDevelop::IProject* project) { auto currentBuildDir = CMake::currentBuildDir(project); @@ -631,6 +642,22 @@ return result; } +QStringList allCanonicalBuildDirs(KDevelop::IProject* project) +{ + QStringList result; + int bdCount = buildDirCount(project); + for (int i = 0; i < bdCount; ++i) { + QString buildDir = buildDirGroup( project, i ).readEntry( Config::Specific::buildDirPathKey ); + const auto info = QFileInfo(buildDir); + if (info.exists()) { + result += info.canonicalFilePath(); + } else { + result += buildDir; + } + } + return result; +} + QString executeProcess(const QString& execName, const QStringList& args) { Q_ASSERT(!execName.isEmpty()); Index: plugins/cmake/settings/cmakepreferences.cpp =================================================================== --- plugins/cmake/settings/cmakepreferences.cpp +++ plugins/cmake/settings/cmakepreferences.cpp @@ -332,7 +332,7 @@ if(curr < 0) return; - Path removedPath = CMake::currentBuildDir( m_project ); + Path removedPath = CMake::currentCanonicalBuildDir( m_project ); QString removed = removedPath.toLocalFile(); if(QDir(removed).exists()) { Index: plugins/cmakebuilder/cmakebuilder.cpp =================================================================== --- plugins/cmakebuilder/cmakebuilder.cpp +++ plugins/cmakebuilder/cmakebuilder.cpp @@ -233,7 +233,7 @@ KDevelop::IProjectBuilder* CMakeBuilder::builderForProject(KDevelop::IProject* p) const { - QString builddir = CMake::currentBuildDir( p ).toLocalFile(); + QString builddir = CMake::currentCanonicalBuildDir( p ).toLocalFile(); QMap::const_iterator it = m_builders.constBegin(), itEnd = m_builders.constEnd(); for(; it!=itEnd; ++it) { if (QFile::exists(builddir+QLatin1Char('/')+it.key())) Index: plugins/cmakebuilder/cmakejob.cpp =================================================================== --- plugins/cmakebuilder/cmakejob.cpp +++ plugins/cmakebuilder/cmakejob.cpp @@ -72,7 +72,7 @@ QUrl CMakeJob::workingDirectory() const { - KDevelop::Path path = CMake::currentBuildDir( m_project ); + KDevelop::Path path = CMake::currentCanonicalBuildDir( m_project ); qCDebug(KDEV_CMAKEBUILDER) << "builddir: " << path; Q_ASSERT(path.isValid()); //We cannot get the project folder as a build directory! return path.toUrl(); @@ -102,7 +102,7 @@ auto rt = ICore::self()->runtimeController()->currentRuntime(); //if we are creating a new build directory, we'll want to specify the generator - QDir builddir(rt->pathInRuntime(CMake::currentBuildDir( m_project )).toLocalFile()); + QDir builddir(rt->pathInRuntime(CMake::currentCanonicalBuildDir( m_project )).toLocalFile()); if(!builddir.exists() || !builddir.exists(QStringLiteral("CMakeCache.txt"))) { CMakeBuilderSettings::self()->load(); args << QStringLiteral("-G") << CMake::defaultGenerator();