ccls
ccls copied to clipboard
CCLS jumps to host libs instead of the target cross-platform libs
Observed behavior
I'm using CCLS as a LSP (with coc-nvim) as the auto-complete framework for embedded development.
Using platformio or makefiles, I'm generating the compile_commands.json
file with bear make
.
It works nicely for the most part. Problem is, for stdio functions (printf, sprintf, etc), goto-definition jumps to /usr/include
instead of the corresponding path in the cross-compiler's own libs. This causes the linter to show errors and warnings erroneously (as if the source is to be compiled for the host(Intel x86 CPU) not the target (Arm Cortex-M MCU).
I've observed this behavior when the cross-compiler was arm-none-eabi-gcc (stm32f103, nrf52832) and xtensa (esp8266).
For example here is the compile_commands.json
for nRF52832 generated with bear
with PIO-ArduinoHAL framework.
https://dpaste.com/2GTYHLNF4
GIF
https://user-images.githubusercontent.com/1058151/106142907-4cafc900-6187-11eb-8dc7-32864a97d30a.mp4
System information
$ ccls --version
ccls version <unknown>
clang version 10.0.0-4ubuntu1~18.04.2
- OS: Xubuntu 18.04
- Editor: vim (coc-nvim)
ccls doesn't use GCC, at all. It uses clang/llvm. So, there's no way for ccls to know (on its own) that the GCC variant you're using is a cross-compiler and where to find the system headers.
You can set ccls options that force the compiler to look in alternate locations for system headers: this is what I do. Unfortunately I don't know how to configure vim so all I can do is provide my Emacs setup that does this:
(setq ccls-initialization-options
`(:clang (:extraArgs ["--gcc-toolchain=/path/to/gcc/install" "--sysroot=/path/to/target/sysroot"])))
I'm not sure if you can add these in the .ccls
file, or not. If so that might be simpler.
@madscientist For vim/CoC, we use a .vim/coc-settings.json
in project dir which is like this:
{
"clangd.enabled": false,
"languageserver": {
"ccls": {
"command": "ccls",
"filetypes": ["c", "cpp", "cuda", "objc", "objcpp"],
"rootPatterns": [".ccls", ".ccls-root", "compile_commands.json"],
"initializationOptions": {
"cache": {
"directory": ".ccls-cache"
},
"client": {
"snippetSupport": true
},
"highlight": { "lsRanges" : true }
}
}
}
}
But I didn't think that I should change this. Doesn't bear
tool figure out that a cross-compiler is used and sets up the proper paths in the compile_commands.json
automatically? I mean shouldn't system libs and all paths relevant to the project be inside that compile_commands.json
?
Well, you can look in compile_commands.json
and see what's there.
Tools like bear
can only track the options that you invoke the compiler with. However, usually those options are not provided explicitly on the command line: usually cross-compilers know intuitively where to look for system headers etc. So, you just run arm-none-eabi-gcc -o armexe armexe.c
and you get an ARM executable, and you don't have to add a bunch of specialized command-line options to tell arm-non-eabi-gcc
where to find system headers and libraries. Of course there are almost as many different subtle difference in cross-compilation systems as there are people cross-compiling so YMMV.
If that's the way your cross-compilers work, then the magical paths are embedded into the cross-compiler front-end and external tools like make, bear, ccls, etc. never see them, and they won't appear in compile_commands.json
.
You'll have to add them yourself, as I've described above.
I have not done much cross compiling, but. Can one not ask the compiler et al which directories they use to find header files and libraries? Then it will also adjust to the arguments the user gives to be used by the compiler. Certainly these tools have to know where they look for files? And the proper way would then be to ask the tools, and just by telling ccls which tools to use should be enough to get it right? Am I missing something here? Yours A Jackson
I use cmake tool, compile my project, has the same questions.