hedronvision / bazel-compile-commands-extractor

Goal: Enable awesome tooling for Bazel users of the C language family.
Other
659 stars 109 forks source link

clangd failed to find compilation database for dependency code #175

Open modatwork opened 5 months ago

modatwork commented 5 months ago

Thanks for the tool. I have succeed to generate compilation database for envoy and it works great.

But when using envoy as a library to build my customized proxy, clangd failed to parse the code in dependency. The usage is similar to the way istio/proxy https://github.com/istio/proxy/blob/e7c2818121f5bb3a3cb2cb11894652a9d9b0328b/WORKSPACE#L36 uses envoy.

The envoy project is too huge to built so I created a simple demo which has an external dependency and it has the same problem. Here is the steps to reproduce the issue with the demo project.

The following steps are tested on macOS 13.5.2, clangd 18.1.1 and bazel 6.3.2. I also tested with the latest bazel version 7.1.0 and the issue remains.

# get the source code
git clone https://github.com/modatwork/bazel-example.git
cd bazel-example
git checkout v0.1.0

# first build the project
bazel build bar

# generate the compile_commands.json
bazel run :refresh_compile_commands

vim bar.cc

After jumping to the definition of add function the LSP server complains:

Failed to find compilation database for /Users/moda/.cache/bazel/b92409a607afcdd077412f77b2f754f6/external/foo/foo.h\n".

There is a compile_commands.json file in the bazel-example directory which has compile command for "external/foo/foo". But it's not used by clangd.

modatwork commented 5 months ago

Adding a specific compilation database config does not fix the issue.

> cat .clangd
CompileFlags:
  CompilationDatabase: /path/to/bazel-example

https://clangd.llvm.org/faq#how-do-i-fix-errors-i-get-when-opening-headers-outside-of-my-project-directory

modatwork commented 5 months ago

But if adds a command line option --compile-commands-dir=/path/to/bazel-example it started working. So it seems to be related to clangd itself.

https://github.com/clangd/clangd/issues/413

modatwork commented 5 months ago

https://github.com/clangd/clangd/issues/649#issuecomment-1021946005 explains why .clangd not works.

The part about a config file being scoped to its directory is not a security measure, it's just how clangd searches for config files. When opening a file, it looks for a .clangd config file to apply in the directory containing the file and its ancestor directories; additionally, it looks at the user config (~/.config/clangd/config.yaml).

So, if you're opening a file in ~/.cache/bazel/bazel/f428e7e9652043d7b22f6d4c02d3b711/external/, then {workspaceFolder}/.clangd is not a config file it encounters during the search.

cpsauer commented 5 months ago

Hey @modatwork! Just seeing this.

I really wish clangd had designed their behavior the other way. All is exactly as you determined--that's why we encourage --compile-commands-dir in the README. As far as I know, it's the only way to have the compile_command.json apply to all the files.

Is there anything you think we should add to the README to help others get through this more easily--and if so, would you be down to make a quick edit? Additionally, it might be worth chiming in on those clangd issues, so they're more likely to factor in these (common) use cases.

Hope this means it's back to being useful for you! Chris

modatwork commented 5 months ago

Hi cpsauer, thanks for replying. I'm still trying to find the best way to set the clangd config for Neovim because Neovim created another LSP client for the code in Bazel's outputBase. After that I'd like to share my finding.

cpsauer commented 5 months ago

I think the move is to set configuration via flags instead--but please do lmk if you find a way to do otherwise.