lsp-mode icon indicating copy to clipboard operation
lsp-mode copied to clipboard

Try auto-finding the directory with compile_commands.json for lsp-clangd

Open petr-tik opened this issue 5 years ago • 16 comments

Running current version of lsp-clangd with a cmake based out-of-source builds, I set set(CMAKE_EXPORT_COMPILE_COMMANDS ON), which results in a compile_commands.json file in my build directory.

After that I need to copy or symlink it to project root every time I re-configure top-level CML (add a new file, new dependency etc) for clangd to pick up info about my includes and successfully resolve goto-def queries. Symlinking doesn't work when I use Docker for Desktop with a WSL volume mounted to Docker, so I have to manually copy it every time.

I noticed from clangd-10 --help that it takes the following flag to specify a directory for clangd to find compile_commands.json.

clangd compilation flags options:

  --compile-commands-dir=<string> - Specify a path to look for compile_commands.json. If path is invalid, clangd will look in the current directory and parent paths of each source file

The heuristic used by clangd

If path is invalid, clangd will look in the current directory and parent paths of each source file

seems quite useless in out-of-source builds.

I wanted to suggest running a 1-level deep search for a compile_commands.json file from the project root and setting this flag with the directory name for this flag eg. "--compile-commands-dir=build/".

I don't know if lsp currently has hooks for lsp-server specific project initialisation routines, but I think it would help. Happy to take a crack at it, if it's possible with the current API and is in line with what you have in mind about easy to use default options.

Amazing work - i appreciate your efforts.

petr-tik avatar Oct 21 '20 22:10 petr-tik

Perhaps https://github.com/rpav/cmake-build.el would help for your use case too, as it manages symlinking compile-commands.json

laurynas-biveinis avatar Oct 22 '20 11:10 laurynas-biveinis

Thanks for your swift reply. cmake-build.el looks good, however, i actually build in a separate terminal, so care less about cmake integration and more about clangd finding compile_commands.json out of the box. lsp-mode has been brilliant at working OOTB so far and I thought this might be a worthy addition.

I was driving at adding "--compile-commands-dir=my_esoteric_build_dir/" to clangd arguments when you start clangd in a given workspace by running a quick search (could even use bash for it) for compile_commands.json instead of making users symlink or copy the file to project root every time it changes.

Additionally, symlinks don't seem to work between Docker for Desktop and WSL1, so I would like to avoid them.

petr-tik avatar Oct 22 '20 12:10 petr-tik

I don't know if lsp currently has hooks for lsp-server specific project initialisation routines, but I think it would help. Happy to take a crack at it, if it's possible with the current API and is in line with what you have in mind about easy to use default options.

This is supported. The core framework supports passing a function which returns the program to start.

Thanks for your swift reply. cmake-build.el looks good, however, i actually build in a separate terminal, so care less about cmake integration and more about clangd finding compile_commands.json out of the box. lsp-mode has been brilliant at working OOTB so far and I thought this might be a worthy addition.

Supporting this makes sense to me. We should support disabling this feature and log that we have automatically found the compile_commands when automatic discovery works out.

yyoncho avatar Oct 22 '20 15:10 yyoncho

Are you ok with me taking a crack at this?

From my looking around at the code, clangd currently doesn't use the :initialization-options property instead creating the whole command with the following snippet, where clangd args are set through a variable.

https://github.com/emacs-lsp/lsp-mode/blob/master/clients/lsp-clangd.el#L175-L193

What I don't quite understand is how to force the evaluation of my potential lsp-clangd--find-compile-commands-dir function before starting a connection.

petr-tik avatar Oct 22 '20 18:10 petr-tik

aha, realising initialisation-options is unnecessary here, we can do everything in the lsp-clients--clangd-command

petr-tik avatar Oct 22 '20 19:10 petr-tik

aha, realising initialisation-options is unnecessary here, we can do everything in the lsp-clients--clangd-command

Yes. The tricky part is that workspace root is not available in the initial import of the project but we will change that.

yyoncho avatar Oct 22 '20 19:10 yyoncho

I was experimenting with using lsp--suggest-project-root - is that bad?

petr-tik avatar Oct 22 '20 19:10 petr-tik

you should use lsp-workspace-root but it will return nil before you have imported the project. But again, this will change.

yyoncho avatar Oct 22 '20 19:10 yyoncho

how far in the future is this change? It sounds like I should wait until it lands and proceed after that?

petr-tik avatar Oct 22 '20 20:10 petr-tik

how far in the future is this change? It sounds like I should wait until it lands and proceed after that?

I can't tell - I will be inactive for some time. You can implement your feature and it will be merged once lsp-workspace-root is fixed to work all the time.

yyoncho avatar Oct 22 '20 20:10 yyoncho

hope you are ok in these interesting times.

I have mostly been testing my function in an already loaded project, so I would have not noticed this chronological dependency had you not mentioned it.

petr-tik avatar Oct 22 '20 20:10 petr-tik

after clangd-11, we’ll also be looking for directories named build to find compile_commands.json from https://llvm.discourse.group/t/clangd-lsp-with-emacs-external-library/1593/4

I guess we could replicate this heuristic

petr-tik avatar Dec 07 '20 18:12 petr-tik

Just found this by googling... did this ever happen?

garyo avatar Dec 13 '22 22:12 garyo

Also interested in how this should be managed

jkordani avatar Mar 31 '23 16:03 jkordani

Just found this by googling... did this ever happen?

I can confirm that if you call your cmake build directory build then clangd will look there for compile_commands.json.

dabrahams avatar May 03 '24 23:05 dabrahams

@dabrahams However this will not work if you are using cmake-presets with various configurePresets, because now compile_commands.json is under e.g. build/debug. In that case you do have to use a symlink with:

ln -s build/debug/compile_commands.json .

Also make sure to restart lsp with M-x lsp-workspace-restart.