[clang-tools-extra] Add --project-root to clangd (PR #155905)
Dominicentek wrote: Yeah thanks, I'm aware. I'll get to it in a couple of days when I'm not busy. https://github.com/llvm/llvm-project/pull/155905 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] Add --project-root to clangd (PR #155905)
HighCommander4 wrote: Ah, I see, so it's actually a UBSan error, and it's complaining at the read of `ClangdServer::Options::StrongWorkspaceMode` in `ClangdLSPServer::onInitialize()` that we're reading a value of 49 from a bool, which suggests that bool was not initialized. Should be a simple fix, just need to give this field a class member initializer. @Dominicentek heads up that this has been reverted and you'll need to resubmit with this fix to move forward with this change https://github.com/llvm/llvm-project/pull/155905 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] Add --project-root to clangd (PR #155905)
boomanaiden154 wrote:
Seeing the same thing with ASan at -O1:
```
<<< initialize: {}
<-- initialize(0)
third_party/llvm/llvm-project/clang-tools-extra/clangd/ClangdLSPServer.cpp:557:14:
runtime error: load of value 112, which is not a valid value for type 'bool'
```
Only `--gtest_filter="LSPTest*:GlobalCompilationDatabaseTest*"` is needed to
reproduce this.
I've reverted this in 01c4eb5b9b0690692638e8be353e1c6cf2da5d9a.
https://github.com/llvm/llvm-project/pull/155905
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] Add --project-root to clangd (PR #155905)
fmayer wrote: This might have caused buildbot errors. Running some builds to confirm, but in case it looks familiar posting it now: https://lab.llvm.org/buildbot/#/builders/164/builds/16465/steps/11/logs/stdio ``` [ RUN ] LSPTest.CDBConfigIntegration #0 0x580ed5359812 ___interceptor_backtrace /home/b/sanitizer-x86_64-linux-bootstrap-msan/build/llvm-project/compiler-rt/lib/msan/../sanitizer_common/sanitizer_common_interceptors.inc:4556:13 #1 0x580ed6d2028f llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) /home/b/sanitizer-x86_64-linux-bootstrap-msan/build/llvm-project/llvm/lib/Support/Unix/Signals.inc:0:13 #2 0x580ed6d19648 llvm::sys::RunSignalHandlers() /home/b/sanitizer-x86_64-linux-bootstrap-msan/build/llvm-project/llvm/lib/Support/Signals.cpp:0:5 #3 0x580ed6d2278a SignalHandler(int, siginfo_t*, void*) /home/b/sanitizer-x86_64-linux-bootstrap-msan/build/llvm-project/llvm/lib/Support/Unix/Signals.inc:426:38 #4 0x580ed538d58e IsInInterceptorScope /home/b/sanitizer-x86_64-linux-bootstrap-msan/build/llvm-project/compiler-rt/lib/msan/msan_interceptors.cpp:78:10 #5 0x580ed538d58e SignalAction(int, void*, void*) /home/b/sanitizer-x86_64-linux-bootstrap-msan/build/llvm-project/compiler-rt/lib/msan/msan_interceptors.cpp:1167:3 #6 0x7ec17a4458d0 (/lib/x86_64-linux-gnu/libc.so.6+0x458d0) #7 0x7ec17a4a49bc pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0xa49bc) #8 0x7ec17a44579e raise (/lib/x86_64-linux-gnu/libc.so.6+0x4579e) #9 0x7ec17a4288cd abort (/lib/x86_64-linux-gnu/libc.so.6+0x288cd) #10 0x580ed531addc (/home/b/sanitizer-x86_64-linux-bootstrap-msan/build/llvm_build_msan/tools/clang/tools/extra/clangd/unittests/./ClangdTests+0x1666ddc) #11 0x580ed531986e __sanitizer::Die() /home/b/sanitizer-x86_64-linux-bootstrap-msan/build/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_termination.cpp:52:5 #12 0x580ed532ceb3 (/home/b/sanitizer-x86_64-linux-bootstrap-msan/build/llvm_build_msan/tools/clang/tools/extra/clangd/unittests/./ClangdTests+0x1678eb3) #13 0x580edad88299 reset /home/b/sanitizer-x86_64-linux-bootstrap-msan/build/libcxx_install_msan/include/c++/v1/__memory/unique_ptr.h:287:9 #14 0x580edad88299 operator=, void, void> /home/b/sanitizer-x86_64-linux-bootstrap-msan/build/libcxx_install_msan/include/c++/v1/__memory/unique_ptr.h:235:5 #15 0x580edad88299 clang::clangd::ClangdLSPServer::onInitialize(clang::clangd::InitializeParams const&, llvm::unique_function)>) /home/b/sanitizer-x86_64-linux-bootstrap-msan/build/llvm-project/clang-tools-extra/clangd/ClangdLSPServer.cpp:559:13 #16 0x580edae002b8 asInt /home/b/sanitizer-x86_64-linux-bootstrap-msan/build/llvm-project/llvm/include/llvm/ADT/PointerIntPair.h:41:5 #17 0x580edae002b8 operator long /home/b/sanitizer-x86_64-linux-bootstrap-msan/build/llvm-project/llvm/include/llvm/ADT/PointerIntPair.h:45:48 #18 0x580edae002b8 getPointer /home/b/sanitizer-x86_64-linux-bootstrap-msan/build/llvm-project/llvm/include/llvm/ADT/PointerIntPair.h:94:58 #19 0x580edae002b8 ~UniqueFunctionBase /home/b/sanitizer-x86_64-linux-bootstrap-msan/build/llvm-project/llvm/include/llvm/ADT/FunctionExtras.h:274:32 #20 0x580edae002b8 void clang::clangd::LSPBinder::method(llvm::StringLiteral, clang::clangd::ClangdLSPServer*, void (clang::clangd::ClangdLSPServer::*)(clang::clangd::InitializeParams const&, llvm::unique_function)>))::'lambda'(llvm::json::Value, llvm::unique_function)>)::operator()(llvm::json::Value, llvm::unique_function)>) const /home/b/sanitizer-x86_64-linux-bootstrap-msan/build/llvm-project/clang-tools-extra/clangd/LSPBinder.h:141:5 #21 0x580edadffc12 asInt /home/b/sanitizer-x86_64-linux-bootstrap-msan/build/llvm-project/llvm/include/llvm/ADT/PointerIntPair.h:41:5 #22 0x580edadffc12 operator long /home/b/sanitizer-x86_64-linux-bootstrap-msan/build/llvm-project/llvm/include/llvm/ADT/PointerIntPair.h:45:48 #23 0x580edadffc12 getPointer /home/b/sanitizer-x86_64-linux-bootstrap-msan/build/llvm-project/llvm/include/llvm/ADT/PointerIntPair.h:94:58 #24 0x580edadffc12 ~UniqueFunctionBase /home/b/sanitizer-x86_64-linux-bootstrap-msan/build/llvm-project/llvm/include/llvm/ADT/FunctionExtras.h:274:32 #25 0x580edadffc12 void llvm::detail::UniqueFunctionBase)>>::CallImpl(llvm::StringLiteral, clang::clangd::ClangdLSPServer*, void (clang::clangd::ClangdLSPServer::*)(clang::clangd::InitializeParams const&, llvm::unique_function)>))::'lambda'(llvm::json::Value, llvm::unique_function)>)>(void*, llvm::json::Value&, llvm::unique_function)>&) /home/b/sanitizer-x86_64-linux-bootstrap-msan/build/llvm-project/llvm/include/llvm/ADT/FunctionExtras.h:212:5 #26 0x580edadc328a asInt /home/b/sanitizer-x86_64-linux-bootstrap-msan/build/llvm-project/llvm/include/llvm/ADT/PointerIntPair.h:41:5 #27 0x580edadc328a operator long /home/b/sanitizer-x86_64-linux-bootstrap-msan/build/llvm-project/llvm/include/llvm/ADT/PointerIntPair.h:45:48
[clang-tools-extra] Add --project-root to clangd (PR #155905)
github-actions[bot] wrote: @Dominicentek Congratulations on having your first Pull Request (PR) merged into the LLVM Project! Your changes will be combined with recent changes from other authors, then tested by our [build bots](https://lab.llvm.org/buildbot/). If there is a problem with a build, you may receive a report in an email or a comment on this PR. Please check whether problems have been caused by your change specifically, as the builds can include changes from many authors. It is not uncommon for your change to be included in a build that fails due to someone else's changes, or infrastructure issues. How to do this, and the rest of the post-merge process, is covered in detail [here](https://llvm.org/docs/MyFirstTypoFix.html#myfirsttypofix-issues-after-landing-your-pr). If your change does cause a problem, it may be reverted, or you can revert it yourself. This is a normal part of [LLVM development](https://llvm.org/docs/DeveloperPolicy.html#patch-reversion-policy). You can fix your changes and open a new PR to merge them again. If you don't get any reports, no action is required from you. Your changes are working as expected, well done! https://github.com/llvm/llvm-project/pull/155905 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] Add --project-root to clangd (PR #155905)
https://github.com/HighCommander4 closed https://github.com/llvm/llvm-project/pull/155905 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] Add --project-root to clangd (PR #155905)
https://github.com/HighCommander4 auto_merge_enabled https://github.com/llvm/llvm-project/pull/155905 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] Add --project-root to clangd (PR #155905)
https://github.com/HighCommander4 auto_merge_disabled https://github.com/llvm/llvm-project/pull/155905 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] Add --project-root to clangd (PR #155905)
https://github.com/HighCommander4 auto_merge_enabled https://github.com/llvm/llvm-project/pull/155905 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] Add --project-root to clangd (PR #155905)
https://github.com/HighCommander4 edited https://github.com/llvm/llvm-project/pull/155905 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] Add --project-root to clangd (PR #155905)
@@ -460,6 +462,17 @@ DirectoryBasedGlobalCompilationDatabase::lookupCDB(
return Result;
}
+void DirectoryBasedGlobalCompilationDatabase::Options::applyWorkingDirectory(
+const std::optional &&WorkingDirectory) {
+ if (WorkingDirectory)
+this->WorkingDirectory = *WorkingDirectory;
+ else {
+SmallString<256> CWD;
HighCommander4 wrote:
I tweaked the comment wording a bit here. I think it's important to mention
that it's the LSP client not providing a workspace path that necessitates a
fallback (or error) here, i.e. something we as the server can't control.
https://github.com/llvm/llvm-project/pull/155905
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] Add --project-root to clangd (PR #155905)
https://github.com/HighCommander4 approved this pull request. Thanks! LGTM with some minor tweaks which I went ahead and made. https://github.com/llvm/llvm-project/pull/155905 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] Add --project-root to clangd (PR #155905)
https://github.com/HighCommander4 updated
https://github.com/llvm/llvm-project/pull/155905
>From 9a30c2b92be357deac5a65e2fa0952d91634de70 Mon Sep 17 00:00:00 2001
From: Dominicentek
Date: Thu, 28 Aug 2025 20:46:35 +0200
Subject: [PATCH 01/12] Add --project-root to clangd
---
clang-tools-extra/clangd/ClangdServer.cpp | 1 +
clang-tools-extra/clangd/ClangdServer.h| 4
.../clangd/GlobalCompilationDatabase.cpp | 14 +++---
.../clangd/GlobalCompilationDatabase.h | 6 +++---
clang-tools-extra/clangd/TUScheduler.cpp | 6 --
clang-tools-extra/clangd/TUScheduler.h | 4
clang-tools-extra/clangd/tool/Check.cpp| 4 ++--
clang-tools-extra/clangd/tool/ClangdMain.cpp | 10 ++
8 files changed, 35 insertions(+), 14 deletions(-)
diff --git a/clang-tools-extra/clangd/ClangdServer.cpp
b/clang-tools-extra/clangd/ClangdServer.cpp
index ac1e9aa5f0ff1..51230b4506b1a 100644
--- a/clang-tools-extra/clangd/ClangdServer.cpp
+++ b/clang-tools-extra/clangd/ClangdServer.cpp
@@ -208,6 +208,7 @@ ClangdServer::Options::operator TUScheduler::Options()
const {
Opts.UpdateDebounce = UpdateDebounce;
Opts.ContextProvider = ContextProvider;
Opts.PreambleThrottler = PreambleThrottler;
+ Opts.FallbackProjectRoot = FallbackProjectRoot;
return Opts;
}
diff --git a/clang-tools-extra/clangd/ClangdServer.h
b/clang-tools-extra/clangd/ClangdServer.h
index 4a1eae188f7eb..2c56d6f7e6d6c 100644
--- a/clang-tools-extra/clangd/ClangdServer.h
+++ b/clang-tools-extra/clangd/ClangdServer.h
@@ -152,6 +152,10 @@ class ClangdServer {
/// FIXME: If not set, should use the current working directory.
std::optional WorkspaceRoot;
+/// If set, fallback command uses this path as its current working
directory
+/// instead of the file's parent path.
+std::optional FallbackProjectRoot;
+
/// The resource directory is used to find internal headers, overriding
/// defaults and -resource-dir compiler flag).
/// If std::nullopt, ClangdServer calls
diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
index c6afd0bc07cbd..b73697d4ee7e5 100644
--- a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
+++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
@@ -55,7 +55,7 @@ void actOnAllParentDirectories(PathRef FileName,
} // namespace
tooling::CompileCommand
-GlobalCompilationDatabase::getFallbackCommand(PathRef File) const {
+GlobalCompilationDatabase::getFallbackCommand(PathRef File,
std::optional ProjectRoot) const {
std::vector Argv = {"clang"};
// Clang treats .h files as C by default and files without extension as
linker
// input, resulting in unhelpful diagnostics.
@@ -64,7 +64,7 @@ GlobalCompilationDatabase::getFallbackCommand(PathRef File)
const {
if (FileExtension.empty() || FileExtension == ".h")
Argv.push_back("-xobjective-c++-header");
Argv.push_back(std::string(File));
- tooling::CompileCommand Cmd(llvm::sys::path::parent_path(File),
+ tooling::CompileCommand Cmd(ProjectRoot ? *ProjectRoot :
llvm::sys::path::parent_path(File),
llvm::sys::path::filename(File), std::move(Argv),
/*Output=*/"");
Cmd.Heuristic = "clangd fallback";
@@ -797,8 +797,8 @@ OverlayCDB::getCompileCommand(PathRef File) const {
return Cmd;
}
-tooling::CompileCommand OverlayCDB::getFallbackCommand(PathRef File) const {
- auto Cmd = DelegatingCDB::getFallbackCommand(File);
+tooling::CompileCommand OverlayCDB::getFallbackCommand(PathRef File,
std::optional ProjectRoot) const {
+ auto Cmd = DelegatingCDB::getFallbackCommand(File, ProjectRoot);
std::lock_guard Lock(Mutex);
Cmd.CommandLine.insert(Cmd.CommandLine.end(), FallbackFlags.begin(),
FallbackFlags.end());
@@ -877,10 +877,10 @@ DelegatingCDB::getProjectModules(PathRef File) const {
return Base->getProjectModules(File);
}
-tooling::CompileCommand DelegatingCDB::getFallbackCommand(PathRef File) const {
+tooling::CompileCommand DelegatingCDB::getFallbackCommand(PathRef File,
std::optional ProjectRoot) const {
if (!Base)
-return GlobalCompilationDatabase::getFallbackCommand(File);
- return Base->getFallbackCommand(File);
+return GlobalCompilationDatabase::getFallbackCommand(File, ProjectRoot);
+ return Base->getFallbackCommand(File, ProjectRoot);
}
bool DelegatingCDB::blockUntilIdle(Deadline D) const {
diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.h
b/clang-tools-extra/clangd/GlobalCompilationDatabase.h
index 1d636d73664be..5d1b5cb632154 100644
--- a/clang-tools-extra/clangd/GlobalCompilationDatabase.h
+++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.h
@@ -55,7 +55,7 @@ class GlobalCompilationDatabase {
/// Makes a guess at how to build a file.
/// The default implementation just runs clang on the fil
[clang-tools-extra] Add --project-root to clangd (PR #155905)
https://github.com/HighCommander4 updated
https://github.com/llvm/llvm-project/pull/155905
>From 9a30c2b92be357deac5a65e2fa0952d91634de70 Mon Sep 17 00:00:00 2001
From: Dominicentek
Date: Thu, 28 Aug 2025 20:46:35 +0200
Subject: [PATCH 01/11] Add --project-root to clangd
---
clang-tools-extra/clangd/ClangdServer.cpp | 1 +
clang-tools-extra/clangd/ClangdServer.h| 4
.../clangd/GlobalCompilationDatabase.cpp | 14 +++---
.../clangd/GlobalCompilationDatabase.h | 6 +++---
clang-tools-extra/clangd/TUScheduler.cpp | 6 --
clang-tools-extra/clangd/TUScheduler.h | 4
clang-tools-extra/clangd/tool/Check.cpp| 4 ++--
clang-tools-extra/clangd/tool/ClangdMain.cpp | 10 ++
8 files changed, 35 insertions(+), 14 deletions(-)
diff --git a/clang-tools-extra/clangd/ClangdServer.cpp
b/clang-tools-extra/clangd/ClangdServer.cpp
index ac1e9aa5f0ff1..51230b4506b1a 100644
--- a/clang-tools-extra/clangd/ClangdServer.cpp
+++ b/clang-tools-extra/clangd/ClangdServer.cpp
@@ -208,6 +208,7 @@ ClangdServer::Options::operator TUScheduler::Options()
const {
Opts.UpdateDebounce = UpdateDebounce;
Opts.ContextProvider = ContextProvider;
Opts.PreambleThrottler = PreambleThrottler;
+ Opts.FallbackProjectRoot = FallbackProjectRoot;
return Opts;
}
diff --git a/clang-tools-extra/clangd/ClangdServer.h
b/clang-tools-extra/clangd/ClangdServer.h
index 4a1eae188f7eb..2c56d6f7e6d6c 100644
--- a/clang-tools-extra/clangd/ClangdServer.h
+++ b/clang-tools-extra/clangd/ClangdServer.h
@@ -152,6 +152,10 @@ class ClangdServer {
/// FIXME: If not set, should use the current working directory.
std::optional WorkspaceRoot;
+/// If set, fallback command uses this path as its current working
directory
+/// instead of the file's parent path.
+std::optional FallbackProjectRoot;
+
/// The resource directory is used to find internal headers, overriding
/// defaults and -resource-dir compiler flag).
/// If std::nullopt, ClangdServer calls
diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
index c6afd0bc07cbd..b73697d4ee7e5 100644
--- a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
+++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
@@ -55,7 +55,7 @@ void actOnAllParentDirectories(PathRef FileName,
} // namespace
tooling::CompileCommand
-GlobalCompilationDatabase::getFallbackCommand(PathRef File) const {
+GlobalCompilationDatabase::getFallbackCommand(PathRef File,
std::optional ProjectRoot) const {
std::vector Argv = {"clang"};
// Clang treats .h files as C by default and files without extension as
linker
// input, resulting in unhelpful diagnostics.
@@ -64,7 +64,7 @@ GlobalCompilationDatabase::getFallbackCommand(PathRef File)
const {
if (FileExtension.empty() || FileExtension == ".h")
Argv.push_back("-xobjective-c++-header");
Argv.push_back(std::string(File));
- tooling::CompileCommand Cmd(llvm::sys::path::parent_path(File),
+ tooling::CompileCommand Cmd(ProjectRoot ? *ProjectRoot :
llvm::sys::path::parent_path(File),
llvm::sys::path::filename(File), std::move(Argv),
/*Output=*/"");
Cmd.Heuristic = "clangd fallback";
@@ -797,8 +797,8 @@ OverlayCDB::getCompileCommand(PathRef File) const {
return Cmd;
}
-tooling::CompileCommand OverlayCDB::getFallbackCommand(PathRef File) const {
- auto Cmd = DelegatingCDB::getFallbackCommand(File);
+tooling::CompileCommand OverlayCDB::getFallbackCommand(PathRef File,
std::optional ProjectRoot) const {
+ auto Cmd = DelegatingCDB::getFallbackCommand(File, ProjectRoot);
std::lock_guard Lock(Mutex);
Cmd.CommandLine.insert(Cmd.CommandLine.end(), FallbackFlags.begin(),
FallbackFlags.end());
@@ -877,10 +877,10 @@ DelegatingCDB::getProjectModules(PathRef File) const {
return Base->getProjectModules(File);
}
-tooling::CompileCommand DelegatingCDB::getFallbackCommand(PathRef File) const {
+tooling::CompileCommand DelegatingCDB::getFallbackCommand(PathRef File,
std::optional ProjectRoot) const {
if (!Base)
-return GlobalCompilationDatabase::getFallbackCommand(File);
- return Base->getFallbackCommand(File);
+return GlobalCompilationDatabase::getFallbackCommand(File, ProjectRoot);
+ return Base->getFallbackCommand(File, ProjectRoot);
}
bool DelegatingCDB::blockUntilIdle(Deadline D) const {
diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.h
b/clang-tools-extra/clangd/GlobalCompilationDatabase.h
index 1d636d73664be..5d1b5cb632154 100644
--- a/clang-tools-extra/clangd/GlobalCompilationDatabase.h
+++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.h
@@ -55,7 +55,7 @@ class GlobalCompilationDatabase {
/// Makes a guess at how to build a file.
/// The default implementation just runs clang on the fil
[clang-tools-extra] Add --project-root to clangd (PR #155905)
https://github.com/HighCommander4 updated
https://github.com/llvm/llvm-project/pull/155905
>From 9a30c2b92be357deac5a65e2fa0952d91634de70 Mon Sep 17 00:00:00 2001
From: Dominicentek
Date: Thu, 28 Aug 2025 20:46:35 +0200
Subject: [PATCH 01/10] Add --project-root to clangd
---
clang-tools-extra/clangd/ClangdServer.cpp | 1 +
clang-tools-extra/clangd/ClangdServer.h| 4
.../clangd/GlobalCompilationDatabase.cpp | 14 +++---
.../clangd/GlobalCompilationDatabase.h | 6 +++---
clang-tools-extra/clangd/TUScheduler.cpp | 6 --
clang-tools-extra/clangd/TUScheduler.h | 4
clang-tools-extra/clangd/tool/Check.cpp| 4 ++--
clang-tools-extra/clangd/tool/ClangdMain.cpp | 10 ++
8 files changed, 35 insertions(+), 14 deletions(-)
diff --git a/clang-tools-extra/clangd/ClangdServer.cpp
b/clang-tools-extra/clangd/ClangdServer.cpp
index ac1e9aa5f0ff1..51230b4506b1a 100644
--- a/clang-tools-extra/clangd/ClangdServer.cpp
+++ b/clang-tools-extra/clangd/ClangdServer.cpp
@@ -208,6 +208,7 @@ ClangdServer::Options::operator TUScheduler::Options()
const {
Opts.UpdateDebounce = UpdateDebounce;
Opts.ContextProvider = ContextProvider;
Opts.PreambleThrottler = PreambleThrottler;
+ Opts.FallbackProjectRoot = FallbackProjectRoot;
return Opts;
}
diff --git a/clang-tools-extra/clangd/ClangdServer.h
b/clang-tools-extra/clangd/ClangdServer.h
index 4a1eae188f7eb..2c56d6f7e6d6c 100644
--- a/clang-tools-extra/clangd/ClangdServer.h
+++ b/clang-tools-extra/clangd/ClangdServer.h
@@ -152,6 +152,10 @@ class ClangdServer {
/// FIXME: If not set, should use the current working directory.
std::optional WorkspaceRoot;
+/// If set, fallback command uses this path as its current working
directory
+/// instead of the file's parent path.
+std::optional FallbackProjectRoot;
+
/// The resource directory is used to find internal headers, overriding
/// defaults and -resource-dir compiler flag).
/// If std::nullopt, ClangdServer calls
diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
index c6afd0bc07cbd..b73697d4ee7e5 100644
--- a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
+++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
@@ -55,7 +55,7 @@ void actOnAllParentDirectories(PathRef FileName,
} // namespace
tooling::CompileCommand
-GlobalCompilationDatabase::getFallbackCommand(PathRef File) const {
+GlobalCompilationDatabase::getFallbackCommand(PathRef File,
std::optional ProjectRoot) const {
std::vector Argv = {"clang"};
// Clang treats .h files as C by default and files without extension as
linker
// input, resulting in unhelpful diagnostics.
@@ -64,7 +64,7 @@ GlobalCompilationDatabase::getFallbackCommand(PathRef File)
const {
if (FileExtension.empty() || FileExtension == ".h")
Argv.push_back("-xobjective-c++-header");
Argv.push_back(std::string(File));
- tooling::CompileCommand Cmd(llvm::sys::path::parent_path(File),
+ tooling::CompileCommand Cmd(ProjectRoot ? *ProjectRoot :
llvm::sys::path::parent_path(File),
llvm::sys::path::filename(File), std::move(Argv),
/*Output=*/"");
Cmd.Heuristic = "clangd fallback";
@@ -797,8 +797,8 @@ OverlayCDB::getCompileCommand(PathRef File) const {
return Cmd;
}
-tooling::CompileCommand OverlayCDB::getFallbackCommand(PathRef File) const {
- auto Cmd = DelegatingCDB::getFallbackCommand(File);
+tooling::CompileCommand OverlayCDB::getFallbackCommand(PathRef File,
std::optional ProjectRoot) const {
+ auto Cmd = DelegatingCDB::getFallbackCommand(File, ProjectRoot);
std::lock_guard Lock(Mutex);
Cmd.CommandLine.insert(Cmd.CommandLine.end(), FallbackFlags.begin(),
FallbackFlags.end());
@@ -877,10 +877,10 @@ DelegatingCDB::getProjectModules(PathRef File) const {
return Base->getProjectModules(File);
}
-tooling::CompileCommand DelegatingCDB::getFallbackCommand(PathRef File) const {
+tooling::CompileCommand DelegatingCDB::getFallbackCommand(PathRef File,
std::optional ProjectRoot) const {
if (!Base)
-return GlobalCompilationDatabase::getFallbackCommand(File);
- return Base->getFallbackCommand(File);
+return GlobalCompilationDatabase::getFallbackCommand(File, ProjectRoot);
+ return Base->getFallbackCommand(File, ProjectRoot);
}
bool DelegatingCDB::blockUntilIdle(Deadline D) const {
diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.h
b/clang-tools-extra/clangd/GlobalCompilationDatabase.h
index 1d636d73664be..5d1b5cb632154 100644
--- a/clang-tools-extra/clangd/GlobalCompilationDatabase.h
+++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.h
@@ -55,7 +55,7 @@ class GlobalCompilationDatabase {
/// Makes a guess at how to build a file.
/// The default implementation just runs clang on the fil
[clang-tools-extra] Add --project-root to clangd (PR #155905)
Dominicentek wrote: Hi @HighCommander4, I apologize if you're busy, but is there any progress on this patch? https://github.com/llvm/llvm-project/pull/155905 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] Add --project-root to clangd (PR #155905)
https://github.com/Dominicentek updated
https://github.com/llvm/llvm-project/pull/155905
>From 9a30c2b92be357deac5a65e2fa0952d91634de70 Mon Sep 17 00:00:00 2001
From: Dominicentek
Date: Thu, 28 Aug 2025 20:46:35 +0200
Subject: [PATCH 1/9] Add --project-root to clangd
---
clang-tools-extra/clangd/ClangdServer.cpp | 1 +
clang-tools-extra/clangd/ClangdServer.h| 4
.../clangd/GlobalCompilationDatabase.cpp | 14 +++---
.../clangd/GlobalCompilationDatabase.h | 6 +++---
clang-tools-extra/clangd/TUScheduler.cpp | 6 --
clang-tools-extra/clangd/TUScheduler.h | 4
clang-tools-extra/clangd/tool/Check.cpp| 4 ++--
clang-tools-extra/clangd/tool/ClangdMain.cpp | 10 ++
8 files changed, 35 insertions(+), 14 deletions(-)
diff --git a/clang-tools-extra/clangd/ClangdServer.cpp
b/clang-tools-extra/clangd/ClangdServer.cpp
index ac1e9aa5f0ff1..51230b4506b1a 100644
--- a/clang-tools-extra/clangd/ClangdServer.cpp
+++ b/clang-tools-extra/clangd/ClangdServer.cpp
@@ -208,6 +208,7 @@ ClangdServer::Options::operator TUScheduler::Options()
const {
Opts.UpdateDebounce = UpdateDebounce;
Opts.ContextProvider = ContextProvider;
Opts.PreambleThrottler = PreambleThrottler;
+ Opts.FallbackProjectRoot = FallbackProjectRoot;
return Opts;
}
diff --git a/clang-tools-extra/clangd/ClangdServer.h
b/clang-tools-extra/clangd/ClangdServer.h
index 4a1eae188f7eb..2c56d6f7e6d6c 100644
--- a/clang-tools-extra/clangd/ClangdServer.h
+++ b/clang-tools-extra/clangd/ClangdServer.h
@@ -152,6 +152,10 @@ class ClangdServer {
/// FIXME: If not set, should use the current working directory.
std::optional WorkspaceRoot;
+/// If set, fallback command uses this path as its current working
directory
+/// instead of the file's parent path.
+std::optional FallbackProjectRoot;
+
/// The resource directory is used to find internal headers, overriding
/// defaults and -resource-dir compiler flag).
/// If std::nullopt, ClangdServer calls
diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
index c6afd0bc07cbd..b73697d4ee7e5 100644
--- a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
+++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
@@ -55,7 +55,7 @@ void actOnAllParentDirectories(PathRef FileName,
} // namespace
tooling::CompileCommand
-GlobalCompilationDatabase::getFallbackCommand(PathRef File) const {
+GlobalCompilationDatabase::getFallbackCommand(PathRef File,
std::optional ProjectRoot) const {
std::vector Argv = {"clang"};
// Clang treats .h files as C by default and files without extension as
linker
// input, resulting in unhelpful diagnostics.
@@ -64,7 +64,7 @@ GlobalCompilationDatabase::getFallbackCommand(PathRef File)
const {
if (FileExtension.empty() || FileExtension == ".h")
Argv.push_back("-xobjective-c++-header");
Argv.push_back(std::string(File));
- tooling::CompileCommand Cmd(llvm::sys::path::parent_path(File),
+ tooling::CompileCommand Cmd(ProjectRoot ? *ProjectRoot :
llvm::sys::path::parent_path(File),
llvm::sys::path::filename(File), std::move(Argv),
/*Output=*/"");
Cmd.Heuristic = "clangd fallback";
@@ -797,8 +797,8 @@ OverlayCDB::getCompileCommand(PathRef File) const {
return Cmd;
}
-tooling::CompileCommand OverlayCDB::getFallbackCommand(PathRef File) const {
- auto Cmd = DelegatingCDB::getFallbackCommand(File);
+tooling::CompileCommand OverlayCDB::getFallbackCommand(PathRef File,
std::optional ProjectRoot) const {
+ auto Cmd = DelegatingCDB::getFallbackCommand(File, ProjectRoot);
std::lock_guard Lock(Mutex);
Cmd.CommandLine.insert(Cmd.CommandLine.end(), FallbackFlags.begin(),
FallbackFlags.end());
@@ -877,10 +877,10 @@ DelegatingCDB::getProjectModules(PathRef File) const {
return Base->getProjectModules(File);
}
-tooling::CompileCommand DelegatingCDB::getFallbackCommand(PathRef File) const {
+tooling::CompileCommand DelegatingCDB::getFallbackCommand(PathRef File,
std::optional ProjectRoot) const {
if (!Base)
-return GlobalCompilationDatabase::getFallbackCommand(File);
- return Base->getFallbackCommand(File);
+return GlobalCompilationDatabase::getFallbackCommand(File, ProjectRoot);
+ return Base->getFallbackCommand(File, ProjectRoot);
}
bool DelegatingCDB::blockUntilIdle(Deadline D) const {
diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.h
b/clang-tools-extra/clangd/GlobalCompilationDatabase.h
index 1d636d73664be..5d1b5cb632154 100644
--- a/clang-tools-extra/clangd/GlobalCompilationDatabase.h
+++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.h
@@ -55,7 +55,7 @@ class GlobalCompilationDatabase {
/// Makes a guess at how to build a file.
/// The default implementation just runs clang on the file.
[clang-tools-extra] Add --project-root to clangd (PR #155905)
https://github.com/Dominicentek updated
https://github.com/llvm/llvm-project/pull/155905
>From 9a30c2b92be357deac5a65e2fa0952d91634de70 Mon Sep 17 00:00:00 2001
From: Dominicentek
Date: Thu, 28 Aug 2025 20:46:35 +0200
Subject: [PATCH 1/8] Add --project-root to clangd
---
clang-tools-extra/clangd/ClangdServer.cpp | 1 +
clang-tools-extra/clangd/ClangdServer.h| 4
.../clangd/GlobalCompilationDatabase.cpp | 14 +++---
.../clangd/GlobalCompilationDatabase.h | 6 +++---
clang-tools-extra/clangd/TUScheduler.cpp | 6 --
clang-tools-extra/clangd/TUScheduler.h | 4
clang-tools-extra/clangd/tool/Check.cpp| 4 ++--
clang-tools-extra/clangd/tool/ClangdMain.cpp | 10 ++
8 files changed, 35 insertions(+), 14 deletions(-)
diff --git a/clang-tools-extra/clangd/ClangdServer.cpp
b/clang-tools-extra/clangd/ClangdServer.cpp
index ac1e9aa5f0ff1..51230b4506b1a 100644
--- a/clang-tools-extra/clangd/ClangdServer.cpp
+++ b/clang-tools-extra/clangd/ClangdServer.cpp
@@ -208,6 +208,7 @@ ClangdServer::Options::operator TUScheduler::Options()
const {
Opts.UpdateDebounce = UpdateDebounce;
Opts.ContextProvider = ContextProvider;
Opts.PreambleThrottler = PreambleThrottler;
+ Opts.FallbackProjectRoot = FallbackProjectRoot;
return Opts;
}
diff --git a/clang-tools-extra/clangd/ClangdServer.h
b/clang-tools-extra/clangd/ClangdServer.h
index 4a1eae188f7eb..2c56d6f7e6d6c 100644
--- a/clang-tools-extra/clangd/ClangdServer.h
+++ b/clang-tools-extra/clangd/ClangdServer.h
@@ -152,6 +152,10 @@ class ClangdServer {
/// FIXME: If not set, should use the current working directory.
std::optional WorkspaceRoot;
+/// If set, fallback command uses this path as its current working
directory
+/// instead of the file's parent path.
+std::optional FallbackProjectRoot;
+
/// The resource directory is used to find internal headers, overriding
/// defaults and -resource-dir compiler flag).
/// If std::nullopt, ClangdServer calls
diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
index c6afd0bc07cbd..b73697d4ee7e5 100644
--- a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
+++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
@@ -55,7 +55,7 @@ void actOnAllParentDirectories(PathRef FileName,
} // namespace
tooling::CompileCommand
-GlobalCompilationDatabase::getFallbackCommand(PathRef File) const {
+GlobalCompilationDatabase::getFallbackCommand(PathRef File,
std::optional ProjectRoot) const {
std::vector Argv = {"clang"};
// Clang treats .h files as C by default and files without extension as
linker
// input, resulting in unhelpful diagnostics.
@@ -64,7 +64,7 @@ GlobalCompilationDatabase::getFallbackCommand(PathRef File)
const {
if (FileExtension.empty() || FileExtension == ".h")
Argv.push_back("-xobjective-c++-header");
Argv.push_back(std::string(File));
- tooling::CompileCommand Cmd(llvm::sys::path::parent_path(File),
+ tooling::CompileCommand Cmd(ProjectRoot ? *ProjectRoot :
llvm::sys::path::parent_path(File),
llvm::sys::path::filename(File), std::move(Argv),
/*Output=*/"");
Cmd.Heuristic = "clangd fallback";
@@ -797,8 +797,8 @@ OverlayCDB::getCompileCommand(PathRef File) const {
return Cmd;
}
-tooling::CompileCommand OverlayCDB::getFallbackCommand(PathRef File) const {
- auto Cmd = DelegatingCDB::getFallbackCommand(File);
+tooling::CompileCommand OverlayCDB::getFallbackCommand(PathRef File,
std::optional ProjectRoot) const {
+ auto Cmd = DelegatingCDB::getFallbackCommand(File, ProjectRoot);
std::lock_guard Lock(Mutex);
Cmd.CommandLine.insert(Cmd.CommandLine.end(), FallbackFlags.begin(),
FallbackFlags.end());
@@ -877,10 +877,10 @@ DelegatingCDB::getProjectModules(PathRef File) const {
return Base->getProjectModules(File);
}
-tooling::CompileCommand DelegatingCDB::getFallbackCommand(PathRef File) const {
+tooling::CompileCommand DelegatingCDB::getFallbackCommand(PathRef File,
std::optional ProjectRoot) const {
if (!Base)
-return GlobalCompilationDatabase::getFallbackCommand(File);
- return Base->getFallbackCommand(File);
+return GlobalCompilationDatabase::getFallbackCommand(File, ProjectRoot);
+ return Base->getFallbackCommand(File, ProjectRoot);
}
bool DelegatingCDB::blockUntilIdle(Deadline D) const {
diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.h
b/clang-tools-extra/clangd/GlobalCompilationDatabase.h
index 1d636d73664be..5d1b5cb632154 100644
--- a/clang-tools-extra/clangd/GlobalCompilationDatabase.h
+++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.h
@@ -55,7 +55,7 @@ class GlobalCompilationDatabase {
/// Makes a guess at how to build a file.
/// The default implementation just runs clang on the file.
[clang-tools-extra] Add --project-root to clangd (PR #155905)
https://github.com/HighCommander4 commented: The patch updates look good to me, just one final nit: can we use the terminology `FallbackWorkingDirectory` consistently, i.e. in the name of the `CDBOpts` field, the name of the `applyWorkingDirectory` method, the various constructor parameters etc.? https://github.com/llvm/llvm-project/pull/155905 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] Add --project-root to clangd (PR #155905)
https://github.com/HighCommander4 edited https://github.com/llvm/llvm-project/pull/155905 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] Add --project-root to clangd (PR #155905)
@@ -460,6 +462,17 @@ DirectoryBasedGlobalCompilationDatabase::lookupCDB(
return Result;
}
+void DirectoryBasedGlobalCompilationDatabase::Options::applyWorkingDirectory(
+const std::optional &&WorkingDirectory) {
+ if (WorkingDirectory)
+this->WorkingDirectory = *WorkingDirectory;
+ else {
+SmallString<256> CWD;
HighCommander4 wrote:
I could go either way on this. The advantage of a fallback is that it can help
workaround a client that's unhelpfully failing to set `rootUri`, for which you
as a user may not have much other recourse.
https://github.com/llvm/llvm-project/pull/155905
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] Add --project-root to clangd (PR #155905)
@@ -460,6 +462,17 @@ DirectoryBasedGlobalCompilationDatabase::lookupCDB(
return Result;
}
+void DirectoryBasedGlobalCompilationDatabase::Options::applyWorkingDirectory(
+const std::optional &&WorkingDirectory) {
+ if (WorkingDirectory)
+this->WorkingDirectory = *WorkingDirectory;
+ else {
+SmallString<256> CWD;
MythreyaK wrote:
I was wondering if an error instead of a silent fallback helps with immediate
user feedback, since this is an opt-in feature. Strong workspace's precondition
is that a the directory should be set anyway.
https://github.com/llvm/llvm-project/pull/155905
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] Add --project-root to clangd (PR #155905)
HighCommander4 wrote: > > the new behaviour that clangd looks for such a file there even for files > > outside the workspace directory is basically a no-op. > > Does this impact indexing files located outside of the projects but are > `#include`ed in the project? I think clangd today stores index data for such files in `$HOME/.cache/clangd/index`, which is not very intuitive in my opinion. With strong workspace mode, it would store them in `/.cache/clangd/index`. > > the new behaviour that clangd looks for such a file there even for files > > outside the workspace directory is basically a no-op. Clangd will continue > > using the sub-project compile_commands.json files based on > > ancestor-directory lookup just as it did before. > > So as long as an open file is in one of these `compile_commands.json`, clangd > will use that for indexing, correct? How will indexing for included files > (from outside of the project) be handled? For example, one subproject's > macros (say, `USE_WAYLAND` vs `USE_XCB`) could expose symbols differently > when including a system header. Other than the index storage location being `/.cache/clangd/index`, I would expect it to work the same as it does today without strong workspace mode. https://github.com/llvm/llvm-project/pull/155905 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] Add --project-root to clangd (PR #155905)
HighCommander4 wrote: > If you don't have a `compile_commands.json` file in your workspace's root > directory, the new behaviour that clangd looks for such a file there even for > files outside the workspace directory is basically a no-op. Clangd will > continue using the sub-project `compile_commands.json` files based on > ancestor-directory lookup just as it did before. I guess in retrospect this is not an obvious choice, e.g. it's not how `--compile-commands-dir` works (if you specify `--compile-commands-dir=` but your `compile_commands.json` files are actually in subdirectories, clangd won't use those even for source file inside the subdirectories). So we could say `--strong-workspace-mode`'s behaviours are a strict superset of `--compile-commands-dir=`, and in that case the guidance would be "don't use strong workspace mode for projects of the sort you describe". But I think it would more user-friendly for strong workspace mode to use `/compile_commands.json` _if it exists_ and fall back to ancestor-directory lookup otherwise. This would make it usable with a wider variety of workflows (and maybe even leave room for someday making it the default for some editors like vscode). https://github.com/llvm/llvm-project/pull/155905 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] Add --project-root to clangd (PR #155905)
https://github.com/Dominicentek updated
https://github.com/llvm/llvm-project/pull/155905
>From 9a30c2b92be357deac5a65e2fa0952d91634de70 Mon Sep 17 00:00:00 2001
From: Dominicentek
Date: Thu, 28 Aug 2025 20:46:35 +0200
Subject: [PATCH 1/7] Add --project-root to clangd
---
clang-tools-extra/clangd/ClangdServer.cpp | 1 +
clang-tools-extra/clangd/ClangdServer.h| 4
.../clangd/GlobalCompilationDatabase.cpp | 14 +++---
.../clangd/GlobalCompilationDatabase.h | 6 +++---
clang-tools-extra/clangd/TUScheduler.cpp | 6 --
clang-tools-extra/clangd/TUScheduler.h | 4
clang-tools-extra/clangd/tool/Check.cpp| 4 ++--
clang-tools-extra/clangd/tool/ClangdMain.cpp | 10 ++
8 files changed, 35 insertions(+), 14 deletions(-)
diff --git a/clang-tools-extra/clangd/ClangdServer.cpp
b/clang-tools-extra/clangd/ClangdServer.cpp
index ac1e9aa5f0ff1..51230b4506b1a 100644
--- a/clang-tools-extra/clangd/ClangdServer.cpp
+++ b/clang-tools-extra/clangd/ClangdServer.cpp
@@ -208,6 +208,7 @@ ClangdServer::Options::operator TUScheduler::Options()
const {
Opts.UpdateDebounce = UpdateDebounce;
Opts.ContextProvider = ContextProvider;
Opts.PreambleThrottler = PreambleThrottler;
+ Opts.FallbackProjectRoot = FallbackProjectRoot;
return Opts;
}
diff --git a/clang-tools-extra/clangd/ClangdServer.h
b/clang-tools-extra/clangd/ClangdServer.h
index 4a1eae188f7eb..2c56d6f7e6d6c 100644
--- a/clang-tools-extra/clangd/ClangdServer.h
+++ b/clang-tools-extra/clangd/ClangdServer.h
@@ -152,6 +152,10 @@ class ClangdServer {
/// FIXME: If not set, should use the current working directory.
std::optional WorkspaceRoot;
+/// If set, fallback command uses this path as its current working
directory
+/// instead of the file's parent path.
+std::optional FallbackProjectRoot;
+
/// The resource directory is used to find internal headers, overriding
/// defaults and -resource-dir compiler flag).
/// If std::nullopt, ClangdServer calls
diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
index c6afd0bc07cbd..b73697d4ee7e5 100644
--- a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
+++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
@@ -55,7 +55,7 @@ void actOnAllParentDirectories(PathRef FileName,
} // namespace
tooling::CompileCommand
-GlobalCompilationDatabase::getFallbackCommand(PathRef File) const {
+GlobalCompilationDatabase::getFallbackCommand(PathRef File,
std::optional ProjectRoot) const {
std::vector Argv = {"clang"};
// Clang treats .h files as C by default and files without extension as
linker
// input, resulting in unhelpful diagnostics.
@@ -64,7 +64,7 @@ GlobalCompilationDatabase::getFallbackCommand(PathRef File)
const {
if (FileExtension.empty() || FileExtension == ".h")
Argv.push_back("-xobjective-c++-header");
Argv.push_back(std::string(File));
- tooling::CompileCommand Cmd(llvm::sys::path::parent_path(File),
+ tooling::CompileCommand Cmd(ProjectRoot ? *ProjectRoot :
llvm::sys::path::parent_path(File),
llvm::sys::path::filename(File), std::move(Argv),
/*Output=*/"");
Cmd.Heuristic = "clangd fallback";
@@ -797,8 +797,8 @@ OverlayCDB::getCompileCommand(PathRef File) const {
return Cmd;
}
-tooling::CompileCommand OverlayCDB::getFallbackCommand(PathRef File) const {
- auto Cmd = DelegatingCDB::getFallbackCommand(File);
+tooling::CompileCommand OverlayCDB::getFallbackCommand(PathRef File,
std::optional ProjectRoot) const {
+ auto Cmd = DelegatingCDB::getFallbackCommand(File, ProjectRoot);
std::lock_guard Lock(Mutex);
Cmd.CommandLine.insert(Cmd.CommandLine.end(), FallbackFlags.begin(),
FallbackFlags.end());
@@ -877,10 +877,10 @@ DelegatingCDB::getProjectModules(PathRef File) const {
return Base->getProjectModules(File);
}
-tooling::CompileCommand DelegatingCDB::getFallbackCommand(PathRef File) const {
+tooling::CompileCommand DelegatingCDB::getFallbackCommand(PathRef File,
std::optional ProjectRoot) const {
if (!Base)
-return GlobalCompilationDatabase::getFallbackCommand(File);
- return Base->getFallbackCommand(File);
+return GlobalCompilationDatabase::getFallbackCommand(File, ProjectRoot);
+ return Base->getFallbackCommand(File, ProjectRoot);
}
bool DelegatingCDB::blockUntilIdle(Deadline D) const {
diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.h
b/clang-tools-extra/clangd/GlobalCompilationDatabase.h
index 1d636d73664be..5d1b5cb632154 100644
--- a/clang-tools-extra/clangd/GlobalCompilationDatabase.h
+++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.h
@@ -55,7 +55,7 @@ class GlobalCompilationDatabase {
/// Makes a guess at how to build a file.
/// The default implementation just runs clang on the file.
[clang-tools-extra] Add --project-root to clangd (PR #155905)
MythreyaK wrote: That sounds reasonable, thank you! Two more questions, > If you don't have a compile_commands.json file in your workspace's root > directory For the example I was suggesting, only the subprojects have the compilation database, but `--project-root` would point to the parent directory. My understanding is that a single index is generated across all subprojects, with their respective `compile_commands.json`, allowing for cross-referencing, which is really handy! > the new behaviour that clangd looks for such a file there even for files > outside the workspace directory is basically a no-op. Clangd will continue > using the sub-project compile_commands.json files based on ancestor-directory > lookup just as it did before. So as long as an open file is in one of these `compile_commands.json`, clangd will use that for indexing, correct? How will indexing for included files (from outside of the project) be handled? For example, one subproject's macros (say, `USE_WAYLAND` vs `USE_XCB`) could expose symbols differently when including a system header. https://github.com/llvm/llvm-project/pull/155905 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] Add --project-root to clangd (PR #155905)
HighCommander4 wrote:
> For multi-workspace (not vscode workspace) projects, say a monorepo where
> each subproject is built individually (and therefore separate build dirs and
> compile_commands.json), is the idea that each subproject will (should?) now
> have its own clangd instance running?
I would say this patch doesn't make any changes to how clangd works on, or
should be used with, such projects.
This patch is adding (the beginnings of) a non-default mode of operation
("strong workspace mode") that users need to opt into. If you don't opt into
it, everything will work just as it did before.
For a project of the sort you describe, even if you opt into "strong workspace
mode" (and after the remaining behaviours described in [this
comment](https://github.com/llvm/llvm-project/pull/155905#issuecomment-3549683238))
are implemented, not a lot is likely to change:
* If you don't have a `compile_commands.json` file in your workspace's root
directory, the new behaviour that clangd looks for such a file there even for
files outside the workspace directory is basically a no-op. Clangd will
continue using the sub-project `compile_commands.json` based on
ancestor-directory lookup just as it did before.
* Clangd will also look at a `.clangd` file in the workspace root, even for
files outside the workspace directory. That might be convenient (you can stash
some extra flags there that you want to apply for any file you open while
working on this project), but shouldn't make a big difference.
* The change to the working directory for fallback commands is probably not
relevant if you have `compile_comands.json` files.
> is the idea that each subproject will (should?) now have its own clangd
> instance running?
It has separately been proposed that clients like vscode-clangd gain the
ability to manager multiple clangd instances and launch one per "workspace
root" (in the sense of vscode's multi-root workspaces). For example, one such
proposal is being pursued in https://github.com/clangd/vscode-clangd/pull/810.
If such a proposal is accepted, then using it for a project of the sort you
describe (i.e. making each sub-project a "workspace root") would be a separate
knob you can opt into. I think it would come with both advantages and
disadvantages. (For example, clangd's index would no longer be able to
cross-reference symbols between sub-projects. Depending on how your
sub-projects are related, this may be a desirable change or an undesirable one.)
If you do opt into such a hypothetical multi-root workspace feature, you could
then _also_ opt into "strong workspace mode" for each sub-project, and that may
bring more benefits than using "strong workspace mode" with a single workspace
root for your overall project would have. (For example, if you have an ARM
sub-project and an x86 sub-project, and you open a system header from a source
file in your ARM sub-project, clangd will automatically use a compile command
from one of your ARM source files, more reliably than it does today.)
https://github.com/llvm/llvm-project/pull/155905
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] Add --project-root to clangd (PR #155905)
MythreyaK wrote: For multi-workspace (not vscode workspace) projects, say a monorepo where each subproject is built individually (and therefore separate build dirs and compile_commands.json), is the idea that each subproject will (should?) now have its own clangd instance running? It mostly just worked in my experience so far, but wanted to understand this better. I am not completely sure how this might interact with vscode workspaces. https://github.com/llvm/llvm-project/pull/155905 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] Add --project-root to clangd (PR #155905)
@@ -460,6 +462,17 @@ DirectoryBasedGlobalCompilationDatabase::lookupCDB(
return Result;
}
+void DirectoryBasedGlobalCompilationDatabase::Options::applyWorkingDirectory(
+const std::optional &&WorkingDirectory) {
+ if (WorkingDirectory)
+this->WorkingDirectory = *WorkingDirectory;
+ else {
+SmallString<256> CWD;
HighCommander4 wrote:
It's worth a comment explaining why we need a fallback here. Something like
"the user asked for strong workspace mode, but the client didn't provide a
workspace path, so use the working directory as a fallback".
https://github.com/llvm/llvm-project/pull/155905
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] Add --project-root to clangd (PR #155905)
@@ -500,6 +500,16 @@ opt EnableConfig{
init(true),
};
+opt StrongWorkspaceMode{
+"strong-workspace-mode",
+cat(Features),
+desc("An alternate mode of operation for clangd, operating more closely to
"
HighCommander4 wrote:
Suggested reword: "operating more closely to the workspace" --> "where the
clangd instance is used to edit a single workspace".
https://github.com/llvm/llvm-project/pull/155905
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] Add --project-root to clangd (PR #155905)
@@ -35,6 +35,8 @@ struct ProjectInfo {
/// Provides compilation arguments used for parsing C and C++ files.
class GlobalCompilationDatabase {
public:
+ GlobalCompilationDatabase(std::optional WorkingDirectory)
HighCommander4 wrote:
I would give this parameter a default to minimize the disruption caused by this
change. (I'm not just talking about test code in this repo; I think this class
has out-of-tree subclasses as well.)
https://github.com/llvm/llvm-project/pull/155905
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] Add --project-root to clangd (PR #155905)
@@ -117,6 +122,12 @@ class DirectoryBasedGlobalCompilationDatabase // Only look for a compilation database in this one fixed directory. // FIXME: fold this into config/context mechanism. std::optional CompileCommandsDir; +// Working directory for fallback commands +// If unset, parent directory of file should be used +std::optional WorkingDirectory; + +void +applyWorkingDirectory(const std::optional &&WorkingDirectory); HighCommander4 wrote: What is the purpose of using `const &&` here? https://github.com/llvm/llvm-project/pull/155905 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] Add --project-root to clangd (PR #155905)
https://github.com/HighCommander4 requested changes to this pull request. Thanks, I think the general shape of the patch looks pretty good now. https://github.com/llvm/llvm-project/pull/155905 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] Add --project-root to clangd (PR #155905)
@@ -69,14 +71,17 @@ class GlobalCompilationDatabase {
}
protected:
+ std::optional WorkingDirectory;
mutable CommandChanged OnCommandChanged;
};
// Helper class for implementing GlobalCompilationDatabases that wrap others.
class DelegatingCDB : public GlobalCompilationDatabase {
public:
- DelegatingCDB(const GlobalCompilationDatabase *Base);
- DelegatingCDB(std::unique_ptr Base);
+ DelegatingCDB(const GlobalCompilationDatabase *Base,
HighCommander4 wrote:
Likewise here, we may want to give these added parameters a default
https://github.com/llvm/llvm-project/pull/155905
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] Add --project-root to clangd (PR #155905)
@@ -500,6 +500,16 @@ opt EnableConfig{
init(true),
};
+opt StrongWorkspaceMode{
+"strong-workspace-mode",
+cat(Features),
+desc("An alternate mode of operation for clangd, operating more closely to
"
+ "the workspace.\n"
+ "When enabled, fallback commands use the workspace directory as their
"
+ "working directory instead of the parent folder."),
+init(false),
HighCommander4 wrote:
Let's make this option hidden for now
([example](https://searchfox.org/llvm/rev/bd95a74a2c548867c004ec991defe276f9cbbf40/clang-tools-extra/clangd/tool/ClangdMain.cpp#134)),
until the feature is more fleshed out with other behaviours. (This just means
it won't show up in `clangd --help`, only in `clangd --help-hidden`.)
https://github.com/llvm/llvm-project/pull/155905
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] Add --project-root to clangd (PR #155905)
@@ -69,14 +71,17 @@ class GlobalCompilationDatabase {
}
protected:
+ std::optional WorkingDirectory;
HighCommander4 wrote:
Since this only applies to fallback commands, let's call it
`FallbackWorkingDirectory`. Likewise for the field in
`DirectoryBasedGlobalCompilationDatabase::Options`, the method that sets it,
etc.
https://github.com/llvm/llvm-project/pull/155905
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] Add --project-root to clangd (PR #155905)
https://github.com/HighCommander4 edited https://github.com/llvm/llvm-project/pull/155905 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] Add --project-root to clangd (PR #155905)
@@ -236,6 +236,8 @@ class TUScheduler {
/// Typically to inject per-file configuration.
/// If the path is empty, context sholud be "generic".
std::function ContextProvider;
+
+bool test;
HighCommander4 wrote:
Leftover debug code?
https://github.com/llvm/llvm-project/pull/155905
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] Add --project-root to clangd (PR #155905)
https://github.com/Dominicentek updated
https://github.com/llvm/llvm-project/pull/155905
>From 9a30c2b92be357deac5a65e2fa0952d91634de70 Mon Sep 17 00:00:00 2001
From: Dominicentek
Date: Thu, 28 Aug 2025 20:46:35 +0200
Subject: [PATCH 1/6] Add --project-root to clangd
---
clang-tools-extra/clangd/ClangdServer.cpp | 1 +
clang-tools-extra/clangd/ClangdServer.h| 4
.../clangd/GlobalCompilationDatabase.cpp | 14 +++---
.../clangd/GlobalCompilationDatabase.h | 6 +++---
clang-tools-extra/clangd/TUScheduler.cpp | 6 --
clang-tools-extra/clangd/TUScheduler.h | 4
clang-tools-extra/clangd/tool/Check.cpp| 4 ++--
clang-tools-extra/clangd/tool/ClangdMain.cpp | 10 ++
8 files changed, 35 insertions(+), 14 deletions(-)
diff --git a/clang-tools-extra/clangd/ClangdServer.cpp
b/clang-tools-extra/clangd/ClangdServer.cpp
index ac1e9aa5f0ff1..51230b4506b1a 100644
--- a/clang-tools-extra/clangd/ClangdServer.cpp
+++ b/clang-tools-extra/clangd/ClangdServer.cpp
@@ -208,6 +208,7 @@ ClangdServer::Options::operator TUScheduler::Options()
const {
Opts.UpdateDebounce = UpdateDebounce;
Opts.ContextProvider = ContextProvider;
Opts.PreambleThrottler = PreambleThrottler;
+ Opts.FallbackProjectRoot = FallbackProjectRoot;
return Opts;
}
diff --git a/clang-tools-extra/clangd/ClangdServer.h
b/clang-tools-extra/clangd/ClangdServer.h
index 4a1eae188f7eb..2c56d6f7e6d6c 100644
--- a/clang-tools-extra/clangd/ClangdServer.h
+++ b/clang-tools-extra/clangd/ClangdServer.h
@@ -152,6 +152,10 @@ class ClangdServer {
/// FIXME: If not set, should use the current working directory.
std::optional WorkspaceRoot;
+/// If set, fallback command uses this path as its current working
directory
+/// instead of the file's parent path.
+std::optional FallbackProjectRoot;
+
/// The resource directory is used to find internal headers, overriding
/// defaults and -resource-dir compiler flag).
/// If std::nullopt, ClangdServer calls
diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
index c6afd0bc07cbd..b73697d4ee7e5 100644
--- a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
+++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
@@ -55,7 +55,7 @@ void actOnAllParentDirectories(PathRef FileName,
} // namespace
tooling::CompileCommand
-GlobalCompilationDatabase::getFallbackCommand(PathRef File) const {
+GlobalCompilationDatabase::getFallbackCommand(PathRef File,
std::optional ProjectRoot) const {
std::vector Argv = {"clang"};
// Clang treats .h files as C by default and files without extension as
linker
// input, resulting in unhelpful diagnostics.
@@ -64,7 +64,7 @@ GlobalCompilationDatabase::getFallbackCommand(PathRef File)
const {
if (FileExtension.empty() || FileExtension == ".h")
Argv.push_back("-xobjective-c++-header");
Argv.push_back(std::string(File));
- tooling::CompileCommand Cmd(llvm::sys::path::parent_path(File),
+ tooling::CompileCommand Cmd(ProjectRoot ? *ProjectRoot :
llvm::sys::path::parent_path(File),
llvm::sys::path::filename(File), std::move(Argv),
/*Output=*/"");
Cmd.Heuristic = "clangd fallback";
@@ -797,8 +797,8 @@ OverlayCDB::getCompileCommand(PathRef File) const {
return Cmd;
}
-tooling::CompileCommand OverlayCDB::getFallbackCommand(PathRef File) const {
- auto Cmd = DelegatingCDB::getFallbackCommand(File);
+tooling::CompileCommand OverlayCDB::getFallbackCommand(PathRef File,
std::optional ProjectRoot) const {
+ auto Cmd = DelegatingCDB::getFallbackCommand(File, ProjectRoot);
std::lock_guard Lock(Mutex);
Cmd.CommandLine.insert(Cmd.CommandLine.end(), FallbackFlags.begin(),
FallbackFlags.end());
@@ -877,10 +877,10 @@ DelegatingCDB::getProjectModules(PathRef File) const {
return Base->getProjectModules(File);
}
-tooling::CompileCommand DelegatingCDB::getFallbackCommand(PathRef File) const {
+tooling::CompileCommand DelegatingCDB::getFallbackCommand(PathRef File,
std::optional ProjectRoot) const {
if (!Base)
-return GlobalCompilationDatabase::getFallbackCommand(File);
- return Base->getFallbackCommand(File);
+return GlobalCompilationDatabase::getFallbackCommand(File, ProjectRoot);
+ return Base->getFallbackCommand(File, ProjectRoot);
}
bool DelegatingCDB::blockUntilIdle(Deadline D) const {
diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.h
b/clang-tools-extra/clangd/GlobalCompilationDatabase.h
index 1d636d73664be..5d1b5cb632154 100644
--- a/clang-tools-extra/clangd/GlobalCompilationDatabase.h
+++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.h
@@ -55,7 +55,7 @@ class GlobalCompilationDatabase {
/// Makes a guess at how to build a file.
/// The default implementation just runs clang on the file.
[clang-tools-extra] Add --project-root to clangd (PR #155905)
https://github.com/Dominicentek updated
https://github.com/llvm/llvm-project/pull/155905
>From 9a30c2b92be357deac5a65e2fa0952d91634de70 Mon Sep 17 00:00:00 2001
From: Dominicentek
Date: Thu, 28 Aug 2025 20:46:35 +0200
Subject: [PATCH 1/5] Add --project-root to clangd
---
clang-tools-extra/clangd/ClangdServer.cpp | 1 +
clang-tools-extra/clangd/ClangdServer.h| 4
.../clangd/GlobalCompilationDatabase.cpp | 14 +++---
.../clangd/GlobalCompilationDatabase.h | 6 +++---
clang-tools-extra/clangd/TUScheduler.cpp | 6 --
clang-tools-extra/clangd/TUScheduler.h | 4
clang-tools-extra/clangd/tool/Check.cpp| 4 ++--
clang-tools-extra/clangd/tool/ClangdMain.cpp | 10 ++
8 files changed, 35 insertions(+), 14 deletions(-)
diff --git a/clang-tools-extra/clangd/ClangdServer.cpp
b/clang-tools-extra/clangd/ClangdServer.cpp
index ac1e9aa5f0ff1..51230b4506b1a 100644
--- a/clang-tools-extra/clangd/ClangdServer.cpp
+++ b/clang-tools-extra/clangd/ClangdServer.cpp
@@ -208,6 +208,7 @@ ClangdServer::Options::operator TUScheduler::Options()
const {
Opts.UpdateDebounce = UpdateDebounce;
Opts.ContextProvider = ContextProvider;
Opts.PreambleThrottler = PreambleThrottler;
+ Opts.FallbackProjectRoot = FallbackProjectRoot;
return Opts;
}
diff --git a/clang-tools-extra/clangd/ClangdServer.h
b/clang-tools-extra/clangd/ClangdServer.h
index 4a1eae188f7eb..2c56d6f7e6d6c 100644
--- a/clang-tools-extra/clangd/ClangdServer.h
+++ b/clang-tools-extra/clangd/ClangdServer.h
@@ -152,6 +152,10 @@ class ClangdServer {
/// FIXME: If not set, should use the current working directory.
std::optional WorkspaceRoot;
+/// If set, fallback command uses this path as its current working
directory
+/// instead of the file's parent path.
+std::optional FallbackProjectRoot;
+
/// The resource directory is used to find internal headers, overriding
/// defaults and -resource-dir compiler flag).
/// If std::nullopt, ClangdServer calls
diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
index c6afd0bc07cbd..b73697d4ee7e5 100644
--- a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
+++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
@@ -55,7 +55,7 @@ void actOnAllParentDirectories(PathRef FileName,
} // namespace
tooling::CompileCommand
-GlobalCompilationDatabase::getFallbackCommand(PathRef File) const {
+GlobalCompilationDatabase::getFallbackCommand(PathRef File,
std::optional ProjectRoot) const {
std::vector Argv = {"clang"};
// Clang treats .h files as C by default and files without extension as
linker
// input, resulting in unhelpful diagnostics.
@@ -64,7 +64,7 @@ GlobalCompilationDatabase::getFallbackCommand(PathRef File)
const {
if (FileExtension.empty() || FileExtension == ".h")
Argv.push_back("-xobjective-c++-header");
Argv.push_back(std::string(File));
- tooling::CompileCommand Cmd(llvm::sys::path::parent_path(File),
+ tooling::CompileCommand Cmd(ProjectRoot ? *ProjectRoot :
llvm::sys::path::parent_path(File),
llvm::sys::path::filename(File), std::move(Argv),
/*Output=*/"");
Cmd.Heuristic = "clangd fallback";
@@ -797,8 +797,8 @@ OverlayCDB::getCompileCommand(PathRef File) const {
return Cmd;
}
-tooling::CompileCommand OverlayCDB::getFallbackCommand(PathRef File) const {
- auto Cmd = DelegatingCDB::getFallbackCommand(File);
+tooling::CompileCommand OverlayCDB::getFallbackCommand(PathRef File,
std::optional ProjectRoot) const {
+ auto Cmd = DelegatingCDB::getFallbackCommand(File, ProjectRoot);
std::lock_guard Lock(Mutex);
Cmd.CommandLine.insert(Cmd.CommandLine.end(), FallbackFlags.begin(),
FallbackFlags.end());
@@ -877,10 +877,10 @@ DelegatingCDB::getProjectModules(PathRef File) const {
return Base->getProjectModules(File);
}
-tooling::CompileCommand DelegatingCDB::getFallbackCommand(PathRef File) const {
+tooling::CompileCommand DelegatingCDB::getFallbackCommand(PathRef File,
std::optional ProjectRoot) const {
if (!Base)
-return GlobalCompilationDatabase::getFallbackCommand(File);
- return Base->getFallbackCommand(File);
+return GlobalCompilationDatabase::getFallbackCommand(File, ProjectRoot);
+ return Base->getFallbackCommand(File, ProjectRoot);
}
bool DelegatingCDB::blockUntilIdle(Deadline D) const {
diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.h
b/clang-tools-extra/clangd/GlobalCompilationDatabase.h
index 1d636d73664be..5d1b5cb632154 100644
--- a/clang-tools-extra/clangd/GlobalCompilationDatabase.h
+++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.h
@@ -55,7 +55,7 @@ class GlobalCompilationDatabase {
/// Makes a guess at how to build a file.
/// The default implementation just runs clang on the file.
[clang-tools-extra] Add --project-root to clangd (PR #155905)
https://github.com/Dominicentek updated
https://github.com/llvm/llvm-project/pull/155905
>From 9a30c2b92be357deac5a65e2fa0952d91634de70 Mon Sep 17 00:00:00 2001
From: Dominicentek
Date: Thu, 28 Aug 2025 20:46:35 +0200
Subject: [PATCH 1/3] Add --project-root to clangd
---
clang-tools-extra/clangd/ClangdServer.cpp | 1 +
clang-tools-extra/clangd/ClangdServer.h| 4
.../clangd/GlobalCompilationDatabase.cpp | 14 +++---
.../clangd/GlobalCompilationDatabase.h | 6 +++---
clang-tools-extra/clangd/TUScheduler.cpp | 6 --
clang-tools-extra/clangd/TUScheduler.h | 4
clang-tools-extra/clangd/tool/Check.cpp| 4 ++--
clang-tools-extra/clangd/tool/ClangdMain.cpp | 10 ++
8 files changed, 35 insertions(+), 14 deletions(-)
diff --git a/clang-tools-extra/clangd/ClangdServer.cpp
b/clang-tools-extra/clangd/ClangdServer.cpp
index ac1e9aa5f0ff1..51230b4506b1a 100644
--- a/clang-tools-extra/clangd/ClangdServer.cpp
+++ b/clang-tools-extra/clangd/ClangdServer.cpp
@@ -208,6 +208,7 @@ ClangdServer::Options::operator TUScheduler::Options()
const {
Opts.UpdateDebounce = UpdateDebounce;
Opts.ContextProvider = ContextProvider;
Opts.PreambleThrottler = PreambleThrottler;
+ Opts.FallbackProjectRoot = FallbackProjectRoot;
return Opts;
}
diff --git a/clang-tools-extra/clangd/ClangdServer.h
b/clang-tools-extra/clangd/ClangdServer.h
index 4a1eae188f7eb..2c56d6f7e6d6c 100644
--- a/clang-tools-extra/clangd/ClangdServer.h
+++ b/clang-tools-extra/clangd/ClangdServer.h
@@ -152,6 +152,10 @@ class ClangdServer {
/// FIXME: If not set, should use the current working directory.
std::optional WorkspaceRoot;
+/// If set, fallback command uses this path as its current working
directory
+/// instead of the file's parent path.
+std::optional FallbackProjectRoot;
+
/// The resource directory is used to find internal headers, overriding
/// defaults and -resource-dir compiler flag).
/// If std::nullopt, ClangdServer calls
diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
index c6afd0bc07cbd..b73697d4ee7e5 100644
--- a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
+++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
@@ -55,7 +55,7 @@ void actOnAllParentDirectories(PathRef FileName,
} // namespace
tooling::CompileCommand
-GlobalCompilationDatabase::getFallbackCommand(PathRef File) const {
+GlobalCompilationDatabase::getFallbackCommand(PathRef File,
std::optional ProjectRoot) const {
std::vector Argv = {"clang"};
// Clang treats .h files as C by default and files without extension as
linker
// input, resulting in unhelpful diagnostics.
@@ -64,7 +64,7 @@ GlobalCompilationDatabase::getFallbackCommand(PathRef File)
const {
if (FileExtension.empty() || FileExtension == ".h")
Argv.push_back("-xobjective-c++-header");
Argv.push_back(std::string(File));
- tooling::CompileCommand Cmd(llvm::sys::path::parent_path(File),
+ tooling::CompileCommand Cmd(ProjectRoot ? *ProjectRoot :
llvm::sys::path::parent_path(File),
llvm::sys::path::filename(File), std::move(Argv),
/*Output=*/"");
Cmd.Heuristic = "clangd fallback";
@@ -797,8 +797,8 @@ OverlayCDB::getCompileCommand(PathRef File) const {
return Cmd;
}
-tooling::CompileCommand OverlayCDB::getFallbackCommand(PathRef File) const {
- auto Cmd = DelegatingCDB::getFallbackCommand(File);
+tooling::CompileCommand OverlayCDB::getFallbackCommand(PathRef File,
std::optional ProjectRoot) const {
+ auto Cmd = DelegatingCDB::getFallbackCommand(File, ProjectRoot);
std::lock_guard Lock(Mutex);
Cmd.CommandLine.insert(Cmd.CommandLine.end(), FallbackFlags.begin(),
FallbackFlags.end());
@@ -877,10 +877,10 @@ DelegatingCDB::getProjectModules(PathRef File) const {
return Base->getProjectModules(File);
}
-tooling::CompileCommand DelegatingCDB::getFallbackCommand(PathRef File) const {
+tooling::CompileCommand DelegatingCDB::getFallbackCommand(PathRef File,
std::optional ProjectRoot) const {
if (!Base)
-return GlobalCompilationDatabase::getFallbackCommand(File);
- return Base->getFallbackCommand(File);
+return GlobalCompilationDatabase::getFallbackCommand(File, ProjectRoot);
+ return Base->getFallbackCommand(File, ProjectRoot);
}
bool DelegatingCDB::blockUntilIdle(Deadline D) const {
diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.h
b/clang-tools-extra/clangd/GlobalCompilationDatabase.h
index 1d636d73664be..5d1b5cb632154 100644
--- a/clang-tools-extra/clangd/GlobalCompilationDatabase.h
+++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.h
@@ -55,7 +55,7 @@ class GlobalCompilationDatabase {
/// Makes a guess at how to build a file.
/// The default implementation just runs clang on the file.
[clang-tools-extra] Add --project-root to clangd (PR #155905)
https://github.com/HighCommander4 requested changes to this pull request. I haven't had a chance to take a very detailed look, but some high-level feedback: * We shouldn't assume the current working directory (`current_path`) will be the workspace root, even if that happens to be the case today. Instead, let's propagate the `rootUri` (or `rootPath`) that the client sent in the `initialize` request to the place where we need it. We already propagate it into [`Opts.WorkspaceRoot`](https://searchfox.org/llvm/rev/d90bc3bc609d3ef2254e85cfcd435a99eb2b019b/clang-tools-extra/clangd/ClangdLSPServer.cpp#511-514), we can plumb it further from there into `GlobalCompilationDatabase`. * Rather than changing the `GlobalCompilationDatabase::getFallbackCommand` signature, let's provide the flag to the `GlobalCompilationDatabase` via its constructor (and derived classes' constructors). * In fact, since we need to tell it both the bool and the path, maybe we can group them into an `optional`, which would contain the path in strong workspace mode, and be empty in the default mode. * We should add some sort of test coverage. We can add a unit test similar to [`GlobalCompilationDatabaseTest.FallbackCommand`](https://searchfox.org/llvm/rev/d90bc3bc609d3ef2254e85cfcd435a99eb2b019b/clang-tools-extra/clangd/unittests/GlobalCompilationDatabaseTests.cpp#41-56) which makes assertions about `Cmd.Directory`. https://github.com/llvm/llvm-project/pull/155905 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] Add --project-root to clangd (PR #155905)
github-actions[bot] wrote:
:warning: C/C++ code formatter, clang-format found issues in your code.
:warning:
You can test this locally with the following command:
``bash
git-clang-format --diff origin/main HEAD --extensions h,cpp --
clang-tools-extra/clangd/ClangdServer.cpp
clang-tools-extra/clangd/ClangdServer.h
clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
clang-tools-extra/clangd/GlobalCompilationDatabase.h
clang-tools-extra/clangd/TUScheduler.cpp clang-tools-extra/clangd/TUScheduler.h
clang-tools-extra/clangd/tool/Check.cpp
clang-tools-extra/clangd/tool/ClangdMain.cpp --diff_from_common_commit
``
:warning:
The reproduction instructions above might return results for more than one PR
in a stack if you are using a stacked PR workflow. You can limit the results by
changing `origin/main` to the base branch/commit you want to compare against.
:warning:
View the diff from clang-format here.
``diff
diff --git a/clang-tools-extra/clangd/ClangdServer.h
b/clang-tools-extra/clangd/ClangdServer.h
index 3f3eaf411..6ed5db517 100644
--- a/clang-tools-extra/clangd/ClangdServer.h
+++ b/clang-tools-extra/clangd/ClangdServer.h
@@ -153,7 +153,8 @@ public:
std::optional WorkspaceRoot;
/// Sets an alterante mode of operation. Current effects are:
-/// - Using the current working directory as the working directory for
fallback commands
+/// - Using the current working directory as the working directory for
+/// fallback commands
bool StrongWorkspaceMode;
/// The resource directory is used to find internal headers, overriding
diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
index 4f161b38d..916fb1892 100644
--- a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
+++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
@@ -55,7 +55,8 @@ void actOnAllParentDirectories(PathRef FileName,
} // namespace
tooling::CompileCommand
-GlobalCompilationDatabase::getFallbackCommand(PathRef File, bool
StrongWorkspaceMode) const {
+GlobalCompilationDatabase::getFallbackCommand(PathRef File,
+ bool StrongWorkspaceMode) const {
std::vector Argv = {"clang"};
// Clang treats .h files as C by default and files without extension as
linker
// input, resulting in unhelpful diagnostics.
@@ -69,8 +70,8 @@ GlobalCompilationDatabase::getFallbackCommand(PathRef File,
bool StrongWorkspace
llvm::sys::fs::current_path(WorkingDir);
else
WorkingDir = llvm::sys::path::parent_path(File);
- tooling::CompileCommand Cmd(WorkingDir,
- llvm::sys::path::filename(File), std::move(Argv),
+ tooling::CompileCommand Cmd(WorkingDir, llvm::sys::path::filename(File),
+ std::move(Argv),
/*Output=*/"");
Cmd.Heuristic = "clangd fallback";
return Cmd;
@@ -802,7 +803,8 @@ OverlayCDB::getCompileCommand(PathRef File) const {
return Cmd;
}
-tooling::CompileCommand OverlayCDB::getFallbackCommand(PathRef File, bool
StrongWorkspaceMode) const {
+tooling::CompileCommand
+OverlayCDB::getFallbackCommand(PathRef File, bool StrongWorkspaceMode) const {
auto Cmd = DelegatingCDB::getFallbackCommand(File, StrongWorkspaceMode);
std::lock_guard Lock(Mutex);
Cmd.CommandLine.insert(Cmd.CommandLine.end(), FallbackFlags.begin(),
@@ -882,9 +884,12 @@ DelegatingCDB::getProjectModules(PathRef File) const {
return Base->getProjectModules(File);
}
-tooling::CompileCommand DelegatingCDB::getFallbackCommand(PathRef File, bool
StrongWorkspaceMode) const {
+tooling::CompileCommand
+DelegatingCDB::getFallbackCommand(PathRef File,
+ bool StrongWorkspaceMode) const {
if (!Base)
-return GlobalCompilationDatabase::getFallbackCommand(File,
StrongWorkspaceMode);
+return GlobalCompilationDatabase::getFallbackCommand(File,
+ StrongWorkspaceMode);
return Base->getFallbackCommand(File, StrongWorkspaceMode);
}
diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.h
b/clang-tools-extra/clangd/GlobalCompilationDatabase.h
index a23e8cc16..d8376b617 100644
--- a/clang-tools-extra/clangd/GlobalCompilationDatabase.h
+++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.h
@@ -55,7 +55,8 @@ public:
/// Makes a guess at how to build a file.
/// The default implementation just runs clang on the file.
/// Clangd should treat the results as unreliable.
- virtual tooling::CompileCommand getFallbackCommand(PathRef File, bool
StrongWorkspaceMode = false) const;
+ virtual tooling::CompileCommand
+ getFallbackCommand(PathRef File, bool StrongWorkspaceMode = false) const;
/// If the CDB does any asynchronous work, wait for it to complete.
/// For use in tests.
@@ -86,7 +87,9 @@ public:
std::unique_ptr
getProjectModules(Pat
[clang-tools-extra] Add --project-root to clangd (PR #155905)
https://github.com/Dominicentek updated
https://github.com/llvm/llvm-project/pull/155905
>From 9a30c2b92be357deac5a65e2fa0952d91634de70 Mon Sep 17 00:00:00 2001
From: Dominicentek
Date: Thu, 28 Aug 2025 20:46:35 +0200
Subject: [PATCH 1/2] Add --project-root to clangd
---
clang-tools-extra/clangd/ClangdServer.cpp | 1 +
clang-tools-extra/clangd/ClangdServer.h| 4
.../clangd/GlobalCompilationDatabase.cpp | 14 +++---
.../clangd/GlobalCompilationDatabase.h | 6 +++---
clang-tools-extra/clangd/TUScheduler.cpp | 6 --
clang-tools-extra/clangd/TUScheduler.h | 4
clang-tools-extra/clangd/tool/Check.cpp| 4 ++--
clang-tools-extra/clangd/tool/ClangdMain.cpp | 10 ++
8 files changed, 35 insertions(+), 14 deletions(-)
diff --git a/clang-tools-extra/clangd/ClangdServer.cpp
b/clang-tools-extra/clangd/ClangdServer.cpp
index ac1e9aa5f0ff1..51230b4506b1a 100644
--- a/clang-tools-extra/clangd/ClangdServer.cpp
+++ b/clang-tools-extra/clangd/ClangdServer.cpp
@@ -208,6 +208,7 @@ ClangdServer::Options::operator TUScheduler::Options()
const {
Opts.UpdateDebounce = UpdateDebounce;
Opts.ContextProvider = ContextProvider;
Opts.PreambleThrottler = PreambleThrottler;
+ Opts.FallbackProjectRoot = FallbackProjectRoot;
return Opts;
}
diff --git a/clang-tools-extra/clangd/ClangdServer.h
b/clang-tools-extra/clangd/ClangdServer.h
index 4a1eae188f7eb..2c56d6f7e6d6c 100644
--- a/clang-tools-extra/clangd/ClangdServer.h
+++ b/clang-tools-extra/clangd/ClangdServer.h
@@ -152,6 +152,10 @@ class ClangdServer {
/// FIXME: If not set, should use the current working directory.
std::optional WorkspaceRoot;
+/// If set, fallback command uses this path as its current working
directory
+/// instead of the file's parent path.
+std::optional FallbackProjectRoot;
+
/// The resource directory is used to find internal headers, overriding
/// defaults and -resource-dir compiler flag).
/// If std::nullopt, ClangdServer calls
diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
index c6afd0bc07cbd..b73697d4ee7e5 100644
--- a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
+++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
@@ -55,7 +55,7 @@ void actOnAllParentDirectories(PathRef FileName,
} // namespace
tooling::CompileCommand
-GlobalCompilationDatabase::getFallbackCommand(PathRef File) const {
+GlobalCompilationDatabase::getFallbackCommand(PathRef File,
std::optional ProjectRoot) const {
std::vector Argv = {"clang"};
// Clang treats .h files as C by default and files without extension as
linker
// input, resulting in unhelpful diagnostics.
@@ -64,7 +64,7 @@ GlobalCompilationDatabase::getFallbackCommand(PathRef File)
const {
if (FileExtension.empty() || FileExtension == ".h")
Argv.push_back("-xobjective-c++-header");
Argv.push_back(std::string(File));
- tooling::CompileCommand Cmd(llvm::sys::path::parent_path(File),
+ tooling::CompileCommand Cmd(ProjectRoot ? *ProjectRoot :
llvm::sys::path::parent_path(File),
llvm::sys::path::filename(File), std::move(Argv),
/*Output=*/"");
Cmd.Heuristic = "clangd fallback";
@@ -797,8 +797,8 @@ OverlayCDB::getCompileCommand(PathRef File) const {
return Cmd;
}
-tooling::CompileCommand OverlayCDB::getFallbackCommand(PathRef File) const {
- auto Cmd = DelegatingCDB::getFallbackCommand(File);
+tooling::CompileCommand OverlayCDB::getFallbackCommand(PathRef File,
std::optional ProjectRoot) const {
+ auto Cmd = DelegatingCDB::getFallbackCommand(File, ProjectRoot);
std::lock_guard Lock(Mutex);
Cmd.CommandLine.insert(Cmd.CommandLine.end(), FallbackFlags.begin(),
FallbackFlags.end());
@@ -877,10 +877,10 @@ DelegatingCDB::getProjectModules(PathRef File) const {
return Base->getProjectModules(File);
}
-tooling::CompileCommand DelegatingCDB::getFallbackCommand(PathRef File) const {
+tooling::CompileCommand DelegatingCDB::getFallbackCommand(PathRef File,
std::optional ProjectRoot) const {
if (!Base)
-return GlobalCompilationDatabase::getFallbackCommand(File);
- return Base->getFallbackCommand(File);
+return GlobalCompilationDatabase::getFallbackCommand(File, ProjectRoot);
+ return Base->getFallbackCommand(File, ProjectRoot);
}
bool DelegatingCDB::blockUntilIdle(Deadline D) const {
diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.h
b/clang-tools-extra/clangd/GlobalCompilationDatabase.h
index 1d636d73664be..5d1b5cb632154 100644
--- a/clang-tools-extra/clangd/GlobalCompilationDatabase.h
+++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.h
@@ -55,7 +55,7 @@ class GlobalCompilationDatabase {
/// Makes a guess at how to build a file.
/// The default implementation just runs clang on the file.
[clang-tools-extra] Add --project-root to clangd (PR #155905)
Dominicentek wrote: Alright, I've made the changes. https://github.com/llvm/llvm-project/pull/155905 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] Add --project-root to clangd (PR #155905)
HighCommander4 wrote: > Yep, sounds great! Ok, cool. Would you like to update this PR to implement this revised approach? I'd be happy to review and (if no one else objects) approve it. https://github.com/llvm/llvm-project/pull/155905 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] Add --project-root to clangd (PR #155905)
Dominicentek wrote: Yep, sounds great! https://github.com/llvm/llvm-project/pull/155905 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] Add --project-root to clangd (PR #155905)
HighCommander4 wrote: > 1. I've attached my clangd log below. I'm seeing the client include `"rootUri":"file:///home/dominicentek/Desktop/project"` in the `initialize` request. I take it this is the same directory you were envisioning passing to `--project-root`? > 2. Zed only lets you configure CLI options, environment variables and path to > the binary. I'm using `~/.config/clangd/config.yaml` to configure the > fallback flags. Ok, thanks for checking. So given all that, what do you think about the following approach: * Introduce a command-line flag `--strong-workspace-mode` which is boolean-valued rather than taking a string argument. * If set to true, this flag would currently have the effect of using the `rootUri` sent by the client as the working directory for fallback commands. * In the future, the effect of this flag would be extended to have the other effects described in [this comment](https://github.com/llvm/llvm-project/pull/155905#issuecomment-3549683238). https://github.com/llvm/llvm-project/pull/155905 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] Add --project-root to clangd (PR #155905)
Dominicentek wrote: 1. I've attached my clangd log below. 2. Zed only lets you configure CLI options, environment variables and path to the binary. I'm using `~/.config/clangd/config.yaml` to configure the fallback flags. [clangd.log](https://github.com/user-attachments/files/23695777/clangd.log) https://github.com/llvm/llvm-project/pull/155905 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] Add --project-root to clangd (PR #155905)
HighCommander4 wrote: Thanks for the clarification. I have a couple of follow-up questions about using clangd with Zed, with a view to understanding what sort of constraints we have on how to configure this behaviour: 1. Does Zed send a suitable workspace path in [`InitializeParams`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#initializeParams), in any of the `rootPath`, `rootUri`, or `workspaceFolders` fields? (If unsure, feel free to post [clangd logs](https://clangd.llvm.org/troubleshooting.html#gathering-logs) taken with `--log=verbose`, which will include the entire contents of the client's `initialize` request.) I'm trying to understand whether we have the potential option of using this directory, rather than specifying an additional (possibly conflicting) directory as the value of a command-line argument such as `--project-root`. 2. Does Zed provide some way of customizing the `initialize` request, such as injecting additional fields into it? (E.g. neovim allows this, with a short piece of Lua script.) If it does, and the way to activate this feature would be to inject e.g. `strongWorkspaceMode: true` or some such, would you consider that a sufficiently usable alternative to a command line option? https://github.com/llvm/llvm-project/pull/155905 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] Add --project-root to clangd (PR #155905)
Dominicentek wrote:
Ah I apologize, I was misremembering.
I used `-I${workspaceFolder}/include` in my VSCode configuration, not
`-Iinclude`.
https://github.com/llvm/llvm-project/pull/155905
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] Add --project-root to clangd (PR #155905)
HighCommander4 wrote: > > my editor's (Zed) built-in clangd client doesn't set the project root > > directory as the working directory for fallback commands. VSCode does > > actually have this behavior. > > Do you know how VSCode does this? I tried to reproduce the described behaviour in VSCode, and I haven't been able to. Here's what I tried specifically: * Created `/tmp/workspace` with the directory structure: . ├── include │ └── foo.hpp └── src └── test.cpp ``` * Gave `src/test.cpp` the contents `#include "include/foo.hpp"` * Added the vscode setting `"clangd.fallbackFlags": ["-Iinclude"]` * Opened `src/test.cpp` The clangd logs are showing: ``` I[02:12:28.500] ASTWorker building file /tmp/workspace/src/test.cpp version 1 with command clangd fallback [/tmp/workspace/src] /usr/bin/clang -Iinclude -resource-dir=/usr/lib/llvm-21/lib/clang/21 -- /tmp/workspace/src/test.cpp ``` indicating that it's using the source file's containing directory (`/tmp/workspace/src`), and not the project root directory (`/tmp/workspace`) as the working directory for the command (and indeed, the include in the opened file is not resolved). Could you elaborate on what VSCode behaviour you were observing? https://github.com/llvm/llvm-project/pull/155905 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] Add --project-root to clangd (PR #155905)
https://github.com/Dominicentek updated
https://github.com/llvm/llvm-project/pull/155905
>From 9a30c2b92be357deac5a65e2fa0952d91634de70 Mon Sep 17 00:00:00 2001
From: Dominicentek
Date: Thu, 28 Aug 2025 20:46:35 +0200
Subject: [PATCH] Add --project-root to clangd
---
clang-tools-extra/clangd/ClangdServer.cpp | 1 +
clang-tools-extra/clangd/ClangdServer.h| 4
.../clangd/GlobalCompilationDatabase.cpp | 14 +++---
.../clangd/GlobalCompilationDatabase.h | 6 +++---
clang-tools-extra/clangd/TUScheduler.cpp | 6 --
clang-tools-extra/clangd/TUScheduler.h | 4
clang-tools-extra/clangd/tool/Check.cpp| 4 ++--
clang-tools-extra/clangd/tool/ClangdMain.cpp | 10 ++
8 files changed, 35 insertions(+), 14 deletions(-)
diff --git a/clang-tools-extra/clangd/ClangdServer.cpp
b/clang-tools-extra/clangd/ClangdServer.cpp
index ac1e9aa5f0ff1..51230b4506b1a 100644
--- a/clang-tools-extra/clangd/ClangdServer.cpp
+++ b/clang-tools-extra/clangd/ClangdServer.cpp
@@ -208,6 +208,7 @@ ClangdServer::Options::operator TUScheduler::Options()
const {
Opts.UpdateDebounce = UpdateDebounce;
Opts.ContextProvider = ContextProvider;
Opts.PreambleThrottler = PreambleThrottler;
+ Opts.FallbackProjectRoot = FallbackProjectRoot;
return Opts;
}
diff --git a/clang-tools-extra/clangd/ClangdServer.h
b/clang-tools-extra/clangd/ClangdServer.h
index 4a1eae188f7eb..2c56d6f7e6d6c 100644
--- a/clang-tools-extra/clangd/ClangdServer.h
+++ b/clang-tools-extra/clangd/ClangdServer.h
@@ -152,6 +152,10 @@ class ClangdServer {
/// FIXME: If not set, should use the current working directory.
std::optional WorkspaceRoot;
+/// If set, fallback command uses this path as its current working
directory
+/// instead of the file's parent path.
+std::optional FallbackProjectRoot;
+
/// The resource directory is used to find internal headers, overriding
/// defaults and -resource-dir compiler flag).
/// If std::nullopt, ClangdServer calls
diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
index c6afd0bc07cbd..b73697d4ee7e5 100644
--- a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
+++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
@@ -55,7 +55,7 @@ void actOnAllParentDirectories(PathRef FileName,
} // namespace
tooling::CompileCommand
-GlobalCompilationDatabase::getFallbackCommand(PathRef File) const {
+GlobalCompilationDatabase::getFallbackCommand(PathRef File,
std::optional ProjectRoot) const {
std::vector Argv = {"clang"};
// Clang treats .h files as C by default and files without extension as
linker
// input, resulting in unhelpful diagnostics.
@@ -64,7 +64,7 @@ GlobalCompilationDatabase::getFallbackCommand(PathRef File)
const {
if (FileExtension.empty() || FileExtension == ".h")
Argv.push_back("-xobjective-c++-header");
Argv.push_back(std::string(File));
- tooling::CompileCommand Cmd(llvm::sys::path::parent_path(File),
+ tooling::CompileCommand Cmd(ProjectRoot ? *ProjectRoot :
llvm::sys::path::parent_path(File),
llvm::sys::path::filename(File), std::move(Argv),
/*Output=*/"");
Cmd.Heuristic = "clangd fallback";
@@ -797,8 +797,8 @@ OverlayCDB::getCompileCommand(PathRef File) const {
return Cmd;
}
-tooling::CompileCommand OverlayCDB::getFallbackCommand(PathRef File) const {
- auto Cmd = DelegatingCDB::getFallbackCommand(File);
+tooling::CompileCommand OverlayCDB::getFallbackCommand(PathRef File,
std::optional ProjectRoot) const {
+ auto Cmd = DelegatingCDB::getFallbackCommand(File, ProjectRoot);
std::lock_guard Lock(Mutex);
Cmd.CommandLine.insert(Cmd.CommandLine.end(), FallbackFlags.begin(),
FallbackFlags.end());
@@ -877,10 +877,10 @@ DelegatingCDB::getProjectModules(PathRef File) const {
return Base->getProjectModules(File);
}
-tooling::CompileCommand DelegatingCDB::getFallbackCommand(PathRef File) const {
+tooling::CompileCommand DelegatingCDB::getFallbackCommand(PathRef File,
std::optional ProjectRoot) const {
if (!Base)
-return GlobalCompilationDatabase::getFallbackCommand(File);
- return Base->getFallbackCommand(File);
+return GlobalCompilationDatabase::getFallbackCommand(File, ProjectRoot);
+ return Base->getFallbackCommand(File, ProjectRoot);
}
bool DelegatingCDB::blockUntilIdle(Deadline D) const {
diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.h
b/clang-tools-extra/clangd/GlobalCompilationDatabase.h
index 1d636d73664be..5d1b5cb632154 100644
--- a/clang-tools-extra/clangd/GlobalCompilationDatabase.h
+++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.h
@@ -55,7 +55,7 @@ class GlobalCompilationDatabase {
/// Makes a guess at how to build a file.
/// The default implementation just runs clang on the file.
//
[clang-tools-extra] Add --project-root to clangd (PR #155905)
Dominicentek wrote: No, I'm not entirely sure. https://github.com/llvm/llvm-project/pull/155905 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] Add --project-root to clangd (PR #155905)
HighCommander4 wrote: > my editor's (Zed) built-in clangd client doesn't set the project root > directory as the working directory for fallback commands. VSCode does > actually have this behavior. Do you know how VSCode does this? https://github.com/llvm/llvm-project/pull/155905 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] Add --project-root to clangd (PR #155905)
https://github.com/Dominicentek updated
https://github.com/llvm/llvm-project/pull/155905
>From 9a30c2b92be357deac5a65e2fa0952d91634de70 Mon Sep 17 00:00:00 2001
From: Dominicentek
Date: Thu, 28 Aug 2025 20:46:35 +0200
Subject: [PATCH] Add --project-root to clangd
---
clang-tools-extra/clangd/ClangdServer.cpp | 1 +
clang-tools-extra/clangd/ClangdServer.h| 4
.../clangd/GlobalCompilationDatabase.cpp | 14 +++---
.../clangd/GlobalCompilationDatabase.h | 6 +++---
clang-tools-extra/clangd/TUScheduler.cpp | 6 --
clang-tools-extra/clangd/TUScheduler.h | 4
clang-tools-extra/clangd/tool/Check.cpp| 4 ++--
clang-tools-extra/clangd/tool/ClangdMain.cpp | 10 ++
8 files changed, 35 insertions(+), 14 deletions(-)
diff --git a/clang-tools-extra/clangd/ClangdServer.cpp
b/clang-tools-extra/clangd/ClangdServer.cpp
index ac1e9aa5f0ff1..51230b4506b1a 100644
--- a/clang-tools-extra/clangd/ClangdServer.cpp
+++ b/clang-tools-extra/clangd/ClangdServer.cpp
@@ -208,6 +208,7 @@ ClangdServer::Options::operator TUScheduler::Options()
const {
Opts.UpdateDebounce = UpdateDebounce;
Opts.ContextProvider = ContextProvider;
Opts.PreambleThrottler = PreambleThrottler;
+ Opts.FallbackProjectRoot = FallbackProjectRoot;
return Opts;
}
diff --git a/clang-tools-extra/clangd/ClangdServer.h
b/clang-tools-extra/clangd/ClangdServer.h
index 4a1eae188f7eb..2c56d6f7e6d6c 100644
--- a/clang-tools-extra/clangd/ClangdServer.h
+++ b/clang-tools-extra/clangd/ClangdServer.h
@@ -152,6 +152,10 @@ class ClangdServer {
/// FIXME: If not set, should use the current working directory.
std::optional WorkspaceRoot;
+/// If set, fallback command uses this path as its current working
directory
+/// instead of the file's parent path.
+std::optional FallbackProjectRoot;
+
/// The resource directory is used to find internal headers, overriding
/// defaults and -resource-dir compiler flag).
/// If std::nullopt, ClangdServer calls
diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
index c6afd0bc07cbd..b73697d4ee7e5 100644
--- a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
+++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
@@ -55,7 +55,7 @@ void actOnAllParentDirectories(PathRef FileName,
} // namespace
tooling::CompileCommand
-GlobalCompilationDatabase::getFallbackCommand(PathRef File) const {
+GlobalCompilationDatabase::getFallbackCommand(PathRef File,
std::optional ProjectRoot) const {
std::vector Argv = {"clang"};
// Clang treats .h files as C by default and files without extension as
linker
// input, resulting in unhelpful diagnostics.
@@ -64,7 +64,7 @@ GlobalCompilationDatabase::getFallbackCommand(PathRef File)
const {
if (FileExtension.empty() || FileExtension == ".h")
Argv.push_back("-xobjective-c++-header");
Argv.push_back(std::string(File));
- tooling::CompileCommand Cmd(llvm::sys::path::parent_path(File),
+ tooling::CompileCommand Cmd(ProjectRoot ? *ProjectRoot :
llvm::sys::path::parent_path(File),
llvm::sys::path::filename(File), std::move(Argv),
/*Output=*/"");
Cmd.Heuristic = "clangd fallback";
@@ -797,8 +797,8 @@ OverlayCDB::getCompileCommand(PathRef File) const {
return Cmd;
}
-tooling::CompileCommand OverlayCDB::getFallbackCommand(PathRef File) const {
- auto Cmd = DelegatingCDB::getFallbackCommand(File);
+tooling::CompileCommand OverlayCDB::getFallbackCommand(PathRef File,
std::optional ProjectRoot) const {
+ auto Cmd = DelegatingCDB::getFallbackCommand(File, ProjectRoot);
std::lock_guard Lock(Mutex);
Cmd.CommandLine.insert(Cmd.CommandLine.end(), FallbackFlags.begin(),
FallbackFlags.end());
@@ -877,10 +877,10 @@ DelegatingCDB::getProjectModules(PathRef File) const {
return Base->getProjectModules(File);
}
-tooling::CompileCommand DelegatingCDB::getFallbackCommand(PathRef File) const {
+tooling::CompileCommand DelegatingCDB::getFallbackCommand(PathRef File,
std::optional ProjectRoot) const {
if (!Base)
-return GlobalCompilationDatabase::getFallbackCommand(File);
- return Base->getFallbackCommand(File);
+return GlobalCompilationDatabase::getFallbackCommand(File, ProjectRoot);
+ return Base->getFallbackCommand(File, ProjectRoot);
}
bool DelegatingCDB::blockUntilIdle(Deadline D) const {
diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.h
b/clang-tools-extra/clangd/GlobalCompilationDatabase.h
index 1d636d73664be..5d1b5cb632154 100644
--- a/clang-tools-extra/clangd/GlobalCompilationDatabase.h
+++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.h
@@ -55,7 +55,7 @@ class GlobalCompilationDatabase {
/// Makes a guess at how to build a file.
/// The default implementation just runs clang on the file.
//
[clang-tools-extra] Add --project-root to clangd (PR #155905)
https://github.com/Dominicentek updated
https://github.com/llvm/llvm-project/pull/155905
>From 9a30c2b92be357deac5a65e2fa0952d91634de70 Mon Sep 17 00:00:00 2001
From: Dominicentek
Date: Thu, 28 Aug 2025 20:46:35 +0200
Subject: [PATCH] Add --project-root to clangd
---
clang-tools-extra/clangd/ClangdServer.cpp | 1 +
clang-tools-extra/clangd/ClangdServer.h| 4
.../clangd/GlobalCompilationDatabase.cpp | 14 +++---
.../clangd/GlobalCompilationDatabase.h | 6 +++---
clang-tools-extra/clangd/TUScheduler.cpp | 6 --
clang-tools-extra/clangd/TUScheduler.h | 4
clang-tools-extra/clangd/tool/Check.cpp| 4 ++--
clang-tools-extra/clangd/tool/ClangdMain.cpp | 10 ++
8 files changed, 35 insertions(+), 14 deletions(-)
diff --git a/clang-tools-extra/clangd/ClangdServer.cpp
b/clang-tools-extra/clangd/ClangdServer.cpp
index ac1e9aa5f0ff1..51230b4506b1a 100644
--- a/clang-tools-extra/clangd/ClangdServer.cpp
+++ b/clang-tools-extra/clangd/ClangdServer.cpp
@@ -208,6 +208,7 @@ ClangdServer::Options::operator TUScheduler::Options()
const {
Opts.UpdateDebounce = UpdateDebounce;
Opts.ContextProvider = ContextProvider;
Opts.PreambleThrottler = PreambleThrottler;
+ Opts.FallbackProjectRoot = FallbackProjectRoot;
return Opts;
}
diff --git a/clang-tools-extra/clangd/ClangdServer.h
b/clang-tools-extra/clangd/ClangdServer.h
index 4a1eae188f7eb..2c56d6f7e6d6c 100644
--- a/clang-tools-extra/clangd/ClangdServer.h
+++ b/clang-tools-extra/clangd/ClangdServer.h
@@ -152,6 +152,10 @@ class ClangdServer {
/// FIXME: If not set, should use the current working directory.
std::optional WorkspaceRoot;
+/// If set, fallback command uses this path as its current working
directory
+/// instead of the file's parent path.
+std::optional FallbackProjectRoot;
+
/// The resource directory is used to find internal headers, overriding
/// defaults and -resource-dir compiler flag).
/// If std::nullopt, ClangdServer calls
diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
index c6afd0bc07cbd..b73697d4ee7e5 100644
--- a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
+++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
@@ -55,7 +55,7 @@ void actOnAllParentDirectories(PathRef FileName,
} // namespace
tooling::CompileCommand
-GlobalCompilationDatabase::getFallbackCommand(PathRef File) const {
+GlobalCompilationDatabase::getFallbackCommand(PathRef File,
std::optional ProjectRoot) const {
std::vector Argv = {"clang"};
// Clang treats .h files as C by default and files without extension as
linker
// input, resulting in unhelpful diagnostics.
@@ -64,7 +64,7 @@ GlobalCompilationDatabase::getFallbackCommand(PathRef File)
const {
if (FileExtension.empty() || FileExtension == ".h")
Argv.push_back("-xobjective-c++-header");
Argv.push_back(std::string(File));
- tooling::CompileCommand Cmd(llvm::sys::path::parent_path(File),
+ tooling::CompileCommand Cmd(ProjectRoot ? *ProjectRoot :
llvm::sys::path::parent_path(File),
llvm::sys::path::filename(File), std::move(Argv),
/*Output=*/"");
Cmd.Heuristic = "clangd fallback";
@@ -797,8 +797,8 @@ OverlayCDB::getCompileCommand(PathRef File) const {
return Cmd;
}
-tooling::CompileCommand OverlayCDB::getFallbackCommand(PathRef File) const {
- auto Cmd = DelegatingCDB::getFallbackCommand(File);
+tooling::CompileCommand OverlayCDB::getFallbackCommand(PathRef File,
std::optional ProjectRoot) const {
+ auto Cmd = DelegatingCDB::getFallbackCommand(File, ProjectRoot);
std::lock_guard Lock(Mutex);
Cmd.CommandLine.insert(Cmd.CommandLine.end(), FallbackFlags.begin(),
FallbackFlags.end());
@@ -877,10 +877,10 @@ DelegatingCDB::getProjectModules(PathRef File) const {
return Base->getProjectModules(File);
}
-tooling::CompileCommand DelegatingCDB::getFallbackCommand(PathRef File) const {
+tooling::CompileCommand DelegatingCDB::getFallbackCommand(PathRef File,
std::optional ProjectRoot) const {
if (!Base)
-return GlobalCompilationDatabase::getFallbackCommand(File);
- return Base->getFallbackCommand(File);
+return GlobalCompilationDatabase::getFallbackCommand(File, ProjectRoot);
+ return Base->getFallbackCommand(File, ProjectRoot);
}
bool DelegatingCDB::blockUntilIdle(Deadline D) const {
diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.h
b/clang-tools-extra/clangd/GlobalCompilationDatabase.h
index 1d636d73664be..5d1b5cb632154 100644
--- a/clang-tools-extra/clangd/GlobalCompilationDatabase.h
+++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.h
@@ -55,7 +55,7 @@ class GlobalCompilationDatabase {
/// Makes a guess at how to build a file.
/// The default implementation just runs clang on the file.
//
[clang-tools-extra] Add --project-root to clangd (PR #155905)
llvmbot wrote:
@llvm/pr-subscribers-clang-tools-extra
Author: Dominicentek (Dominicentek)
Changes
Adds an ability to change the current working directory for fallback commands.
---
Full diff: https://github.com/llvm/llvm-project/pull/155905.diff
8 Files Affected:
- (modified) clang-tools-extra/clangd/ClangdServer.cpp (+1)
- (modified) clang-tools-extra/clangd/ClangdServer.h (+4)
- (modified) clang-tools-extra/clangd/GlobalCompilationDatabase.cpp (+7-7)
- (modified) clang-tools-extra/clangd/GlobalCompilationDatabase.h (+3-3)
- (modified) clang-tools-extra/clangd/TUScheduler.cpp (+4-2)
- (modified) clang-tools-extra/clangd/TUScheduler.h (+4)
- (modified) clang-tools-extra/clangd/tool/Check.cpp (+2-2)
- (modified) clang-tools-extra/clangd/tool/ClangdMain.cpp (+10)
``diff
diff --git a/clang-tools-extra/clangd/ClangdServer.cpp
b/clang-tools-extra/clangd/ClangdServer.cpp
index ac1e9aa5f0ff1..51230b4506b1a 100644
--- a/clang-tools-extra/clangd/ClangdServer.cpp
+++ b/clang-tools-extra/clangd/ClangdServer.cpp
@@ -208,6 +208,7 @@ ClangdServer::Options::operator TUScheduler::Options()
const {
Opts.UpdateDebounce = UpdateDebounce;
Opts.ContextProvider = ContextProvider;
Opts.PreambleThrottler = PreambleThrottler;
+ Opts.FallbackProjectRoot = FallbackProjectRoot;
return Opts;
}
diff --git a/clang-tools-extra/clangd/ClangdServer.h
b/clang-tools-extra/clangd/ClangdServer.h
index 4a1eae188f7eb..2c56d6f7e6d6c 100644
--- a/clang-tools-extra/clangd/ClangdServer.h
+++ b/clang-tools-extra/clangd/ClangdServer.h
@@ -152,6 +152,10 @@ class ClangdServer {
/// FIXME: If not set, should use the current working directory.
std::optional WorkspaceRoot;
+/// If set, fallback command uses this path as its current working
directory
+/// instead of the file's parent path.
+std::optional FallbackProjectRoot;
+
/// The resource directory is used to find internal headers, overriding
/// defaults and -resource-dir compiler flag).
/// If std::nullopt, ClangdServer calls
diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
index c6afd0bc07cbd..b73697d4ee7e5 100644
--- a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
+++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
@@ -55,7 +55,7 @@ void actOnAllParentDirectories(PathRef FileName,
} // namespace
tooling::CompileCommand
-GlobalCompilationDatabase::getFallbackCommand(PathRef File) const {
+GlobalCompilationDatabase::getFallbackCommand(PathRef File,
std::optional ProjectRoot) const {
std::vector Argv = {"clang"};
// Clang treats .h files as C by default and files without extension as
linker
// input, resulting in unhelpful diagnostics.
@@ -64,7 +64,7 @@ GlobalCompilationDatabase::getFallbackCommand(PathRef File)
const {
if (FileExtension.empty() || FileExtension == ".h")
Argv.push_back("-xobjective-c++-header");
Argv.push_back(std::string(File));
- tooling::CompileCommand Cmd(llvm::sys::path::parent_path(File),
+ tooling::CompileCommand Cmd(ProjectRoot ? *ProjectRoot :
llvm::sys::path::parent_path(File),
llvm::sys::path::filename(File), std::move(Argv),
/*Output=*/"");
Cmd.Heuristic = "clangd fallback";
@@ -797,8 +797,8 @@ OverlayCDB::getCompileCommand(PathRef File) const {
return Cmd;
}
-tooling::CompileCommand OverlayCDB::getFallbackCommand(PathRef File) const {
- auto Cmd = DelegatingCDB::getFallbackCommand(File);
+tooling::CompileCommand OverlayCDB::getFallbackCommand(PathRef File,
std::optional ProjectRoot) const {
+ auto Cmd = DelegatingCDB::getFallbackCommand(File, ProjectRoot);
std::lock_guard Lock(Mutex);
Cmd.CommandLine.insert(Cmd.CommandLine.end(), FallbackFlags.begin(),
FallbackFlags.end());
@@ -877,10 +877,10 @@ DelegatingCDB::getProjectModules(PathRef File) const {
return Base->getProjectModules(File);
}
-tooling::CompileCommand DelegatingCDB::getFallbackCommand(PathRef File) const {
+tooling::CompileCommand DelegatingCDB::getFallbackCommand(PathRef File,
std::optional ProjectRoot) const {
if (!Base)
-return GlobalCompilationDatabase::getFallbackCommand(File);
- return Base->getFallbackCommand(File);
+return GlobalCompilationDatabase::getFallbackCommand(File, ProjectRoot);
+ return Base->getFallbackCommand(File, ProjectRoot);
}
bool DelegatingCDB::blockUntilIdle(Deadline D) const {
diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.h
b/clang-tools-extra/clangd/GlobalCompilationDatabase.h
index 1d636d73664be..5d1b5cb632154 100644
--- a/clang-tools-extra/clangd/GlobalCompilationDatabase.h
+++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.h
@@ -55,7 +55,7 @@ class GlobalCompilationDatabase {
/// Makes a guess at how to build a file.
/// The default implementation just runs clang on the file.
/// Clangd should treat the res
[clang-tools-extra] Add --project-root to clangd (PR #155905)
github-actions[bot] wrote: Thank you for submitting a Pull Request (PR) to the LLVM Project! This PR will be automatically labeled and the relevant teams will be notified. If you wish to, you can add reviewers by using the "Reviewers" section on this page. If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using `@` followed by their GitHub username. If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers. If you have further questions, they may be answered by the [LLVM GitHub User Guide](https://llvm.org/docs/GitHub.html). You can also ask questions in a comment on this PR, on the [LLVM Discord](https://discord.com/invite/xS7Z362) or on the [forums](https://discourse.llvm.org/). https://github.com/llvm/llvm-project/pull/155905 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] Add --project-root to clangd (PR #155905)
https://github.com/Dominicentek created
https://github.com/llvm/llvm-project/pull/155905
Adds an ability to change the current working directory for fallback commands.
>From 9a30c2b92be357deac5a65e2fa0952d91634de70 Mon Sep 17 00:00:00 2001
From: Dominicentek
Date: Thu, 28 Aug 2025 20:46:35 +0200
Subject: [PATCH] Add --project-root to clangd
---
clang-tools-extra/clangd/ClangdServer.cpp | 1 +
clang-tools-extra/clangd/ClangdServer.h| 4
.../clangd/GlobalCompilationDatabase.cpp | 14 +++---
.../clangd/GlobalCompilationDatabase.h | 6 +++---
clang-tools-extra/clangd/TUScheduler.cpp | 6 --
clang-tools-extra/clangd/TUScheduler.h | 4
clang-tools-extra/clangd/tool/Check.cpp| 4 ++--
clang-tools-extra/clangd/tool/ClangdMain.cpp | 10 ++
8 files changed, 35 insertions(+), 14 deletions(-)
diff --git a/clang-tools-extra/clangd/ClangdServer.cpp
b/clang-tools-extra/clangd/ClangdServer.cpp
index ac1e9aa5f0ff1..51230b4506b1a 100644
--- a/clang-tools-extra/clangd/ClangdServer.cpp
+++ b/clang-tools-extra/clangd/ClangdServer.cpp
@@ -208,6 +208,7 @@ ClangdServer::Options::operator TUScheduler::Options()
const {
Opts.UpdateDebounce = UpdateDebounce;
Opts.ContextProvider = ContextProvider;
Opts.PreambleThrottler = PreambleThrottler;
+ Opts.FallbackProjectRoot = FallbackProjectRoot;
return Opts;
}
diff --git a/clang-tools-extra/clangd/ClangdServer.h
b/clang-tools-extra/clangd/ClangdServer.h
index 4a1eae188f7eb..2c56d6f7e6d6c 100644
--- a/clang-tools-extra/clangd/ClangdServer.h
+++ b/clang-tools-extra/clangd/ClangdServer.h
@@ -152,6 +152,10 @@ class ClangdServer {
/// FIXME: If not set, should use the current working directory.
std::optional WorkspaceRoot;
+/// If set, fallback command uses this path as its current working
directory
+/// instead of the file's parent path.
+std::optional FallbackProjectRoot;
+
/// The resource directory is used to find internal headers, overriding
/// defaults and -resource-dir compiler flag).
/// If std::nullopt, ClangdServer calls
diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
index c6afd0bc07cbd..b73697d4ee7e5 100644
--- a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
+++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
@@ -55,7 +55,7 @@ void actOnAllParentDirectories(PathRef FileName,
} // namespace
tooling::CompileCommand
-GlobalCompilationDatabase::getFallbackCommand(PathRef File) const {
+GlobalCompilationDatabase::getFallbackCommand(PathRef File,
std::optional ProjectRoot) const {
std::vector Argv = {"clang"};
// Clang treats .h files as C by default and files without extension as
linker
// input, resulting in unhelpful diagnostics.
@@ -64,7 +64,7 @@ GlobalCompilationDatabase::getFallbackCommand(PathRef File)
const {
if (FileExtension.empty() || FileExtension == ".h")
Argv.push_back("-xobjective-c++-header");
Argv.push_back(std::string(File));
- tooling::CompileCommand Cmd(llvm::sys::path::parent_path(File),
+ tooling::CompileCommand Cmd(ProjectRoot ? *ProjectRoot :
llvm::sys::path::parent_path(File),
llvm::sys::path::filename(File), std::move(Argv),
/*Output=*/"");
Cmd.Heuristic = "clangd fallback";
@@ -797,8 +797,8 @@ OverlayCDB::getCompileCommand(PathRef File) const {
return Cmd;
}
-tooling::CompileCommand OverlayCDB::getFallbackCommand(PathRef File) const {
- auto Cmd = DelegatingCDB::getFallbackCommand(File);
+tooling::CompileCommand OverlayCDB::getFallbackCommand(PathRef File,
std::optional ProjectRoot) const {
+ auto Cmd = DelegatingCDB::getFallbackCommand(File, ProjectRoot);
std::lock_guard Lock(Mutex);
Cmd.CommandLine.insert(Cmd.CommandLine.end(), FallbackFlags.begin(),
FallbackFlags.end());
@@ -877,10 +877,10 @@ DelegatingCDB::getProjectModules(PathRef File) const {
return Base->getProjectModules(File);
}
-tooling::CompileCommand DelegatingCDB::getFallbackCommand(PathRef File) const {
+tooling::CompileCommand DelegatingCDB::getFallbackCommand(PathRef File,
std::optional ProjectRoot) const {
if (!Base)
-return GlobalCompilationDatabase::getFallbackCommand(File);
- return Base->getFallbackCommand(File);
+return GlobalCompilationDatabase::getFallbackCommand(File, ProjectRoot);
+ return Base->getFallbackCommand(File, ProjectRoot);
}
bool DelegatingCDB::blockUntilIdle(Deadline D) const {
diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.h
b/clang-tools-extra/clangd/GlobalCompilationDatabase.h
index 1d636d73664be..5d1b5cb632154 100644
--- a/clang-tools-extra/clangd/GlobalCompilationDatabase.h
+++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.h
@@ -55,7 +55,7 @@ class GlobalCompilationDatabase {
/// Makes a guess at how to bu
