Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
petr-tik opened this issue Oct 21, 2020 · 16 comments
Open

Comments

@petr-tik
Copy link
Contributor

petr-tik commented Oct 21, 2020

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.

@laurynas-biveinis
Copy link
Contributor

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

@petr-tik
Copy link
Contributor Author

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.

@yyoncho
Copy link
Member

yyoncho commented Oct 22, 2020

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.

@petr-tik
Copy link
Contributor Author

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
Copy link
Contributor Author

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

@yyoncho
Copy link
Member

yyoncho commented Oct 22, 2020

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.

@petr-tik
Copy link
Contributor Author

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

@yyoncho
Copy link
Member

yyoncho commented Oct 22, 2020

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

@petr-tik
Copy link
Contributor Author

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

@yyoncho
Copy link
Member

yyoncho commented Oct 22, 2020

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.

@petr-tik
Copy link
Contributor Author

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 added a commit to petr-tik/lsp-mode that referenced this issue Oct 23, 2020
Fix emacs-lsp#2278

Depends on fixing lsp-workspace-root to be available
when opening a new workspace

Tested locally on projects with and without a compile_commands.json
file.
petr-tik added a commit to petr-tik/lsp-mode that referenced this issue Oct 23, 2020
Fix emacs-lsp#2278

Depends on fixing lsp-workspace-root to be available
when opening a new workspace

Tested locally on projects with and without a compile_commands.json
file.
petr-tik added a commit to petr-tik/lsp-mode that referenced this issue Nov 11, 2020
Fix emacs-lsp#2278

Depends on fixing lsp-workspace-root to be available
when opening a new workspace

Tested locally on projects with and without a compile_commands.json
file.
@petr-tik
Copy link
Contributor Author

petr-tik commented Dec 7, 2020

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

@garyo
Copy link

garyo commented Dec 13, 2022

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

@jkordani
Copy link

Also interested in how this should be managed

@dabrahams
Copy link

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.

@createyourpersonalaccount
Copy link

createyourpersonalaccount commented Aug 18, 2024

@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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants